OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "crypto/signature_verifier.h" | |
6 | |
7 #include <cryptohi.h> | |
8 #include <keyhi.h> | |
9 #include <pk11pub.h> | |
10 #include <secerr.h> | |
11 #include <sechash.h> | |
12 #include <stdint.h> | |
13 #include <stdlib.h> | |
14 | |
15 #include "base/logging.h" | |
16 #include "crypto/nss_util.h" | |
17 #include "crypto/third_party/nss/chromium-nss.h" | |
18 | |
19 namespace crypto { | |
20 | |
21 namespace { | |
22 | |
23 HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { | |
24 switch (hash_alg) { | |
25 case SignatureVerifier::SHA1: | |
26 return HASH_AlgSHA1; | |
27 case SignatureVerifier::SHA256: | |
28 return HASH_AlgSHA256; | |
29 } | |
30 return HASH_AlgNULL; | |
31 } | |
32 | |
33 SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) { | |
34 switch (sig_alg) { | |
35 case SignatureVerifier::RSA_PKCS1_SHA1: | |
36 return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | |
37 case SignatureVerifier::RSA_PKCS1_SHA256: | |
38 return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | |
39 case SignatureVerifier::ECDSA_SHA256: | |
40 return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; | |
41 } | |
42 return SEC_OID_UNKNOWN; | |
43 } | |
44 | |
45 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, | |
46 HASHContext* hash_context, | |
47 HASH_HashType mask_hash_alg, | |
48 unsigned int salt_len, | |
49 const unsigned char* signature, | |
50 unsigned int signature_len) { | |
51 unsigned int hash_len = HASH_ResultLenContext(hash_context); | |
52 std::vector<unsigned char> hash(hash_len); | |
53 HASH_End(hash_context, &hash[0], &hash_len, hash.size()); | |
54 | |
55 unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); | |
56 if (signature_len != modulus_len) { | |
57 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
58 return SECFailure; | |
59 } | |
60 std::vector<unsigned char> enc(signature_len); | |
61 SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], | |
62 const_cast<unsigned char*>(signature), | |
63 signature_len, NULL); | |
64 if (rv != SECSuccess) { | |
65 LOG(WARNING) << "PK11_PubEncryptRaw failed"; | |
66 return rv; | |
67 } | |
68 return emsa_pss_verify(&hash[0], &enc[0], enc.size(), | |
69 HASH_GetType(hash_context), mask_hash_alg, | |
70 salt_len); | |
71 } | |
72 | |
73 } // namespace | |
74 | |
75 SignatureVerifier::SignatureVerifier() | |
76 : vfy_context_(NULL), | |
77 hash_alg_(SHA1), | |
78 mask_hash_alg_(SHA1), | |
79 salt_len_(0), | |
80 public_key_(NULL), | |
81 hash_context_(NULL) { | |
82 EnsureNSSInit(); | |
83 } | |
84 | |
85 SignatureVerifier::~SignatureVerifier() { | |
86 Reset(); | |
87 } | |
88 | |
89 bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, | |
90 const uint8_t* signature, | |
91 int signature_len, | |
92 const uint8_t* public_key_info, | |
93 int public_key_info_len) { | |
94 if (vfy_context_ || hash_context_) | |
95 return false; | |
96 | |
97 signature_.assign(signature, signature + signature_len); | |
98 | |
99 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, | |
100 public_key_info_len); | |
101 if (!public_key) | |
102 return false; | |
103 | |
104 SECItem sig; | |
105 sig.type = siBuffer; | |
106 sig.data = const_cast<uint8_t*>(signature); | |
107 sig.len = signature_len; | |
108 vfy_context_ = VFY_CreateContext( | |
109 public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr); | |
110 SECKEY_DestroyPublicKey(public_key); // Done with public_key. | |
111 if (!vfy_context_) { | |
112 // A corrupted RSA signature could be detected without the data, so | |
113 // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE | |
114 // (-8182). | |
115 return false; | |
116 } | |
117 | |
118 if (VFY_Begin(vfy_context_) != SECSuccess) { | |
119 NOTREACHED(); | |
120 return false; | |
121 } | |
122 return true; | |
123 } | |
124 | |
125 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, | |
126 HashAlgorithm mask_hash_alg, | |
127 int salt_len, | |
128 const uint8_t* signature, | |
129 int signature_len, | |
130 const uint8_t* public_key_info, | |
131 int public_key_info_len) { | |
132 if (vfy_context_ || hash_context_) | |
133 return false; | |
134 | |
135 signature_.assign(signature, signature + signature_len); | |
136 | |
137 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, | |
138 public_key_info_len); | |
139 if (!public_key) | |
140 return false; | |
141 | |
142 public_key_ = public_key; | |
143 hash_alg_ = hash_alg; | |
144 mask_hash_alg_ = mask_hash_alg; | |
145 salt_len_ = salt_len; | |
146 hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); | |
147 if (!hash_context_) | |
148 return false; | |
149 HASH_Begin(hash_context_); | |
150 return true; | |
151 } | |
152 | |
153 void SignatureVerifier::VerifyUpdate(const uint8_t* data_part, | |
154 int data_part_len) { | |
155 if (vfy_context_) { | |
156 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); | |
157 DCHECK_EQ(SECSuccess, rv); | |
158 } else { | |
159 HASH_Update(hash_context_, data_part, data_part_len); | |
160 } | |
161 } | |
162 | |
163 bool SignatureVerifier::VerifyFinal() { | |
164 SECStatus rv; | |
165 if (vfy_context_) { | |
166 rv = VFY_End(vfy_context_); | |
167 } else { | |
168 rv = VerifyRSAPSS_End(public_key_, hash_context_, | |
169 ToNSSHashType(mask_hash_alg_), salt_len_, | |
170 signature_.data(), | |
171 signature_.size()); | |
172 } | |
173 Reset(); | |
174 | |
175 // If signature verification fails, the error code is | |
176 // SEC_ERROR_BAD_SIGNATURE (-8182). | |
177 return (rv == SECSuccess); | |
178 } | |
179 | |
180 // static | |
181 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( | |
182 const uint8_t* public_key_info, | |
183 int public_key_info_len) { | |
184 CERTSubjectPublicKeyInfo* spki = NULL; | |
185 SECItem spki_der; | |
186 spki_der.type = siBuffer; | |
187 spki_der.data = const_cast<uint8_t*>(public_key_info); | |
188 spki_der.len = public_key_info_len; | |
189 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); | |
190 if (!spki) | |
191 return NULL; | |
192 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); | |
193 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. | |
194 return public_key; | |
195 } | |
196 | |
197 void SignatureVerifier::Reset() { | |
198 if (vfy_context_) { | |
199 VFY_DestroyContext(vfy_context_, PR_TRUE); | |
200 vfy_context_ = NULL; | |
201 } | |
202 if (hash_context_) { | |
203 HASH_Destroy(hash_context_); | |
204 hash_context_ = NULL; | |
205 } | |
206 if (public_key_) { | |
207 SECKEY_DestroyPublicKey(public_key_); | |
208 public_key_ = NULL; | |
209 } | |
210 signature_.clear(); | |
211 } | |
212 | |
213 } // namespace crypto | |
OLD | NEW |