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>
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/stl_util.h"
15 #include "crypto/openssl_util.h"
21 const EVP_MD
* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg
) {
23 case SignatureVerifier::SHA1
:
25 case SignatureVerifier::SHA256
:
33 struct SignatureVerifier::VerifyContext
{
34 ScopedOpenSSL
<EVP_MD_CTX
, EVP_MD_CTX_destroy
> ctx
;
37 SignatureVerifier::SignatureVerifier()
38 : verify_context_(NULL
) {
41 SignatureVerifier::~SignatureVerifier() {
45 bool SignatureVerifier::VerifyInit(const uint8
* signature_algorithm
,
46 int signature_algorithm_len
,
47 const uint8
* signature
,
49 const uint8
* public_key_info
,
50 int public_key_info_len
) {
51 OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
52 ScopedOpenSSL
<X509_ALGOR
, X509_ALGOR_free
> algorithm(
53 d2i_X509_ALGOR(NULL
, &signature_algorithm
, signature_algorithm_len
));
56 int nid
= OBJ_obj2nid(algorithm
.get()->algorithm
);
58 if (nid
== NID_ecdsa_with_SHA1
) {
60 } else if (nid
== NID_ecdsa_with_SHA256
) {
61 digest
= EVP_sha256();
63 // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA
65 digest
= EVP_get_digestbyobj(algorithm
.get()->algorithm
);
70 return CommonInit(digest
, signature
, signature_len
, public_key_info
,
71 public_key_info_len
, NULL
);
74 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg
,
75 HashAlgorithm mask_hash_alg
,
77 const uint8
* signature
,
79 const uint8
* public_key_info
,
80 int public_key_info_len
) {
81 OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
82 const EVP_MD
* digest
= ToOpenSSLDigest(hash_alg
);
85 EVP_PKEY_CTX
* pkey_ctx
;
86 if (!CommonInit(digest
, signature
, signature_len
, public_key_info
,
87 public_key_info_len
, &pkey_ctx
)) {
91 int rv
= EVP_PKEY_CTX_set_rsa_padding(pkey_ctx
, RSA_PKCS1_PSS_PADDING
);
94 rv
= EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx
,
95 ToOpenSSLDigest(mask_hash_alg
));
98 rv
= EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx
, salt_len
);
102 void SignatureVerifier::VerifyUpdate(const uint8
* data_part
,
104 DCHECK(verify_context_
);
105 OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
106 int rv
= EVP_DigestVerifyUpdate(verify_context_
->ctx
.get(),
107 data_part
, data_part_len
);
111 bool SignatureVerifier::VerifyFinal() {
112 DCHECK(verify_context_
);
113 OpenSSLErrStackTracer
err_tracer(FROM_HERE
);
114 int rv
= EVP_DigestVerifyFinal(verify_context_
->ctx
.get(),
115 vector_as_array(&signature_
),
117 // rv is -1 if a DER-encoded ECDSA signature cannot be decoded correctly.
123 bool SignatureVerifier::CommonInit(const EVP_MD
* digest
,
124 const uint8
* signature
,
126 const uint8
* public_key_info
,
127 int public_key_info_len
,
128 EVP_PKEY_CTX
** pkey_ctx
) {
132 verify_context_
= new VerifyContext
;
134 signature_
.assign(signature
, signature
+ signature_len
);
136 // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
137 char* data
= reinterpret_cast<char*>(const_cast<uint8
*>(public_key_info
));
138 ScopedOpenSSL
<BIO
, BIO_free_all
> bio(BIO_new_mem_buf(data
,
139 public_key_info_len
));
143 ScopedOpenSSL
<EVP_PKEY
, EVP_PKEY_free
> public_key(
144 d2i_PUBKEY_bio(bio
.get(), NULL
));
145 if (!public_key
.get())
148 verify_context_
->ctx
.reset(EVP_MD_CTX_create());
149 int rv
= EVP_DigestVerifyInit(verify_context_
->ctx
.get(), pkey_ctx
,
150 digest
, NULL
, public_key
.get());
154 void SignatureVerifier::Reset() {
155 delete verify_context_
;
156 verify_context_
= NULL
;
160 } // namespace crypto