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"
16 #include "crypto/scoped_openssl_types.h"
22 const EVP_MD
* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg
) {
24 case SignatureVerifier::SHA1
:
26 case SignatureVerifier::SHA256
:
34 struct SignatureVerifier::VerifyContext
{
38 SignatureVerifier::SignatureVerifier()
39 : verify_context_(NULL
) {
42 SignatureVerifier::~SignatureVerifier() {
46 bool SignatureVerifier::VerifyInit(const uint8
* signature_algorithm
,
47 int signature_algorithm_len
,
48 const uint8
* signature
,
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
> algorithm(
54 d2i_X509_ALGOR(NULL
, &signature_algorithm
, signature_algorithm_len
));
57 int nid
= OBJ_obj2nid(algorithm
.get()->algorithm
);
59 if (nid
== NID_ecdsa_with_SHA1
) {
61 } else if (nid
== NID_ecdsa_with_SHA256
) {
62 digest
= EVP_sha256();
64 // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA
66 digest
= EVP_get_digestbyobj(algorithm
.get()->algorithm
);
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
,
78 const uint8
* signature
,
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
);
89 EVP_PKEY_CTX
* pkey_ctx
;
90 if (!CommonInit(digest
, signature
, signature_len
, public_key_info
,
91 public_key_info_len
, &pkey_ctx
)) {
95 int rv
= EVP_PKEY_CTX_set_rsa_padding(pkey_ctx
, RSA_PKCS1_PSS_PADDING
);
98 const EVP_MD
* const mgf_digest
= ToOpenSSLDigest(mask_hash_alg
);
103 rv
= EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx
, mgf_digest
);
106 rv
= EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx
, salt_len
);
110 void SignatureVerifier::VerifyUpdate(const uint8
* data_part
,
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
);
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_
),
125 DCHECK_EQ(static_cast<int>(!!rv
), rv
);
130 bool SignatureVerifier::CommonInit(const EVP_MD
* digest
,
131 const uint8
* signature
,
133 const uint8
* public_key_info
,
134 int public_key_info_len
,
135 EVP_PKEY_CTX
** pkey_ctx
) {
139 verify_context_
= new VerifyContext
;
141 signature_
.assign(signature
, signature
+ signature_len
);
143 const uint8_t* ptr
= public_key_info
;
144 ScopedEVP_PKEY
public_key(d2i_PUBKEY(nullptr, &ptr
, public_key_info_len
));
145 if (!public_key
.get() || ptr
!= public_key_info
+ public_key_info_len
)
148 verify_context_
->ctx
.reset(EVP_MD_CTX_create());
149 int rv
= EVP_DigestVerifyInit(verify_context_
->ctx
.get(), pkey_ctx
,
150 digest
, nullptr, public_key
.get());
154 void SignatureVerifier::Reset() {
155 delete verify_context_
;
156 verify_context_
= NULL
;
160 } // namespace crypto