[fsp] Buffer consecutive Write() calls.
[chromium-blink-merge.git] / crypto / signature_verifier_openssl.cc
bloba855120ef83bd233cae7b7e4be1d1ba2fce3627b
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "crypto/signature_verifier.h"
7 #include <openssl/evp.h>
8 #include <openssl/x509.h>
10 #include <vector>
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/stl_util.h"
15 #include "crypto/openssl_util.h"
16 #include "crypto/scoped_openssl_types.h"
18 namespace crypto {
20 namespace {
22 const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) {
23 switch (hash_alg) {
24 case SignatureVerifier::SHA1:
25 return EVP_sha1();
26 case SignatureVerifier::SHA256:
27 return EVP_sha256();
29 return NULL;
32 } // namespace
34 struct SignatureVerifier::VerifyContext {
35 ScopedEVP_MD_CTX ctx;
38 SignatureVerifier::SignatureVerifier()
39 : verify_context_(NULL) {
42 SignatureVerifier::~SignatureVerifier() {
43 Reset();
46 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
47 int signature_algorithm_len,
48 const uint8* signature,
49 int signature_len,
50 const uint8* public_key_info,
51 int public_key_info_len) {
52 OpenSSLErrStackTracer err_tracer(FROM_HERE);
53 ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free>::Type algorithm(
54 d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len));
55 if (!algorithm.get())
56 return false;
57 int nid = OBJ_obj2nid(algorithm.get()->algorithm);
58 const EVP_MD* digest;
59 if (nid == NID_ecdsa_with_SHA1) {
60 digest = EVP_sha1();
61 } else if (nid == NID_ecdsa_with_SHA256) {
62 digest = EVP_sha256();
63 } else {
64 // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA
65 // signatures.
66 digest = EVP_get_digestbyobj(algorithm.get()->algorithm);
68 if (!digest)
69 return false;
71 return CommonInit(digest, signature, signature_len, public_key_info,
72 public_key_info_len, NULL);
75 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
76 HashAlgorithm mask_hash_alg,
77 int salt_len,
78 const uint8* signature,
79 int signature_len,
80 const uint8* public_key_info,
81 int public_key_info_len) {
82 OpenSSLErrStackTracer err_tracer(FROM_HERE);
83 const EVP_MD* const digest = ToOpenSSLDigest(hash_alg);
84 DCHECK(digest);
85 if (!digest) {
86 return false;
89 EVP_PKEY_CTX* pkey_ctx;
90 if (!CommonInit(digest, signature, signature_len, public_key_info,
91 public_key_info_len, &pkey_ctx)) {
92 return false;
95 int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING);
96 if (rv != 1)
97 return false;
98 const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg);
99 DCHECK(mgf_digest);
100 if (!mgf_digest) {
101 return false;
103 rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest);
104 if (rv != 1)
105 return false;
106 rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len);
107 return rv == 1;
110 void SignatureVerifier::VerifyUpdate(const uint8* data_part,
111 int data_part_len) {
112 DCHECK(verify_context_);
113 OpenSSLErrStackTracer err_tracer(FROM_HERE);
114 int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(),
115 data_part, data_part_len);
116 DCHECK_EQ(rv, 1);
119 bool SignatureVerifier::VerifyFinal() {
120 DCHECK(verify_context_);
121 OpenSSLErrStackTracer err_tracer(FROM_HERE);
122 int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(),
123 vector_as_array(&signature_),
124 signature_.size());
125 // rv is -1 if a DER-encoded ECDSA signature cannot be decoded correctly.
126 DCHECK_GE(rv, -1);
127 Reset();
128 return rv == 1;
131 bool SignatureVerifier::CommonInit(const EVP_MD* digest,
132 const uint8* signature,
133 int signature_len,
134 const uint8* public_key_info,
135 int public_key_info_len,
136 EVP_PKEY_CTX** pkey_ctx) {
137 if (verify_context_)
138 return false;
140 verify_context_ = new VerifyContext;
142 signature_.assign(signature, signature + signature_len);
144 // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
145 char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info));
146 ScopedBIO bio(BIO_new_mem_buf(data, public_key_info_len));
147 if (!bio.get())
148 return false;
150 ScopedEVP_PKEY public_key(d2i_PUBKEY_bio(bio.get(), NULL));
151 if (!public_key.get())
152 return false;
154 verify_context_->ctx.reset(EVP_MD_CTX_create());
155 int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx,
156 digest, NULL, public_key.get());
157 return rv == 1;
160 void SignatureVerifier::Reset() {
161 delete verify_context_;
162 verify_context_ = NULL;
163 signature_.clear();
166 } // namespace crypto