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"
14 #include "base/logging.h"
15 #include "crypto/nss_util.h"
16 #include "crypto/third_party/nss/chromium-nss.h"
22 HASH_HashType
ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg
) {
24 case SignatureVerifier::SHA1
:
26 case SignatureVerifier::SHA256
:
27 return HASH_AlgSHA256
;
32 SECStatus
VerifyRSAPSS_End(SECKEYPublicKey
* public_key
,
33 HASHContext
* hash_context
,
34 HASH_HashType mask_hash_alg
,
35 unsigned int salt_len
,
36 const unsigned char* signature
,
37 unsigned int signature_len
) {
38 unsigned int hash_len
= HASH_ResultLenContext(hash_context
);
39 std::vector
<unsigned char> hash(hash_len
);
40 HASH_End(hash_context
, &hash
[0], &hash_len
, hash
.size());
42 unsigned int modulus_len
= SECKEY_PublicKeyStrength(public_key
);
43 if (signature_len
!= modulus_len
) {
44 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
47 std::vector
<unsigned char> enc(signature_len
);
48 SECStatus rv
= PK11_PubEncryptRaw(public_key
, &enc
[0],
49 const_cast<unsigned char*>(signature
),
51 if (rv
!= SECSuccess
) {
52 LOG(WARNING
) << "PK11_PubEncryptRaw failed";
55 return emsa_pss_verify(&hash
[0], &enc
[0], enc
.size(),
56 HASH_GetType(hash_context
), mask_hash_alg
,
62 SignatureVerifier::SignatureVerifier()
72 SignatureVerifier::~SignatureVerifier() {
76 bool SignatureVerifier::VerifyInit(const uint8
* signature_algorithm
,
77 int signature_algorithm_len
,
78 const uint8
* signature
,
80 const uint8
* public_key_info
,
81 int public_key_info_len
) {
82 if (vfy_context_
|| hash_context_
)
85 signature_
.assign(signature
, signature
+ signature_len
);
87 SECKEYPublicKey
* public_key
= DecodePublicKeyInfo(public_key_info
,
92 PLArenaPool
* arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
94 SECKEY_DestroyPublicKey(public_key
);
99 sig_alg_der
.type
= siBuffer
;
100 sig_alg_der
.data
= const_cast<uint8
*>(signature_algorithm
);
101 sig_alg_der
.len
= signature_algorithm_len
;
102 SECAlgorithmID sig_alg_id
;
104 rv
= SEC_QuickDERDecodeItem(arena
, &sig_alg_id
,
105 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate
),
107 if (rv
!= SECSuccess
) {
108 SECKEY_DestroyPublicKey(public_key
);
109 PORT_FreeArena(arena
, PR_TRUE
);
115 sig
.data
= const_cast<uint8
*>(signature
);
116 sig
.len
= signature_len
;
117 SECOidTag hash_alg_tag
;
118 vfy_context_
= VFY_CreateContextWithAlgorithmID(public_key
, &sig
,
119 &sig_alg_id
, &hash_alg_tag
,
121 SECKEY_DestroyPublicKey(public_key
); // Done with public_key.
122 PORT_FreeArena(arena
, PR_TRUE
); // Done with sig_alg_id.
124 // A corrupted RSA signature could be detected without the data, so
125 // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
130 rv
= VFY_Begin(vfy_context_
);
131 if (rv
!= SECSuccess
) {
138 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg
,
139 HashAlgorithm mask_hash_alg
,
141 const uint8
* signature
,
143 const uint8
* public_key_info
,
144 int public_key_info_len
) {
145 if (vfy_context_
|| hash_context_
)
148 signature_
.assign(signature
, signature
+ signature_len
);
150 SECKEYPublicKey
* public_key
= DecodePublicKeyInfo(public_key_info
,
151 public_key_info_len
);
155 public_key_
= public_key
;
156 hash_alg_
= hash_alg
;
157 mask_hash_alg_
= mask_hash_alg
;
158 salt_len_
= salt_len
;
159 hash_context_
= HASH_Create(ToNSSHashType(hash_alg_
));
162 HASH_Begin(hash_context_
);
166 void SignatureVerifier::VerifyUpdate(const uint8
* data_part
,
169 SECStatus rv
= VFY_Update(vfy_context_
, data_part
, data_part_len
);
170 DCHECK_EQ(SECSuccess
, rv
);
172 HASH_Update(hash_context_
, data_part
, data_part_len
);
176 bool SignatureVerifier::VerifyFinal() {
179 rv
= VFY_End(vfy_context_
);
181 rv
= VerifyRSAPSS_End(public_key_
, hash_context_
,
182 ToNSSHashType(mask_hash_alg_
), salt_len_
,
188 // If signature verification fails, the error code is
189 // SEC_ERROR_BAD_SIGNATURE (-8182).
190 return (rv
== SECSuccess
);
194 SECKEYPublicKey
* SignatureVerifier::DecodePublicKeyInfo(
195 const uint8
* public_key_info
,
196 int public_key_info_len
) {
197 CERTSubjectPublicKeyInfo
* spki
= NULL
;
199 spki_der
.type
= siBuffer
;
200 spki_der
.data
= const_cast<uint8
*>(public_key_info
);
201 spki_der
.len
= public_key_info_len
;
202 spki
= SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der
);
205 SECKEYPublicKey
* public_key
= SECKEY_ExtractPublicKey(spki
);
206 SECKEY_DestroySubjectPublicKeyInfo(spki
); // Done with spki.
210 void SignatureVerifier::Reset() {
212 VFY_DestroyContext(vfy_context_
, PR_TRUE
);
216 HASH_Destroy(hash_context_
);
217 hash_context_
= NULL
;
220 SECKEY_DestroyPublicKey(public_key_
);
226 } // namespace crypto