Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: crypto/signature_verifier_nss.cc

Issue 17776003: Add SignatureVerifier::VerifyInitRSAPSS for verifying RSA-PSS signatures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Add a unit test with RSA PSS test vectors downloaded from RSA Labs Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "crypto/signature_verifier.h" 5 #include "crypto/signature_verifier.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <keyhi.h> 8 #include <keyhi.h>
9 #include <pk11pub.h>
10 #include <secerr.h>
11 #include <sechash.h>
9 #include <stdlib.h> 12 #include <stdlib.h>
10 13
11 #include "base/logging.h" 14 #include "base/logging.h"
12 #include "crypto/nss_util.h" 15 #include "crypto/nss_util.h"
16 #include "crypto/third_party/nss/chromium-nss.h"
13 17
14 namespace crypto { 18 namespace crypto {
15 19
16 SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) { 20 namespace {
21
22 HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) {
23 switch (hash_alg) {
24 case SignatureVerifier::SHA1:
25 return HASH_AlgSHA1;
26 case SignatureVerifier::SHA256:
27 return HASH_AlgSHA256;
28 }
29 }
30
31 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
32 HASHContext* hash_context,
33 HASH_HashType mask_hash_alg,
34 unsigned int salt_len,
35 const unsigned char* signature,
36 unsigned int signature_len) {
37 unsigned int hash_len = HASH_ResultLenContext(hash_context);
38 std::vector<unsigned char> hash(hash_len);
39 HASH_End(hash_context, &hash[0], &hash_len, hash.size());
40
41 unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
42 if (signature_len != modulus_len) {
43 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
44 return SECFailure;
45 }
46 std::vector<unsigned char> enc(signature_len);
47 SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
48 const_cast<unsigned char*>(signature),
49 signature_len, NULL);
50 if (rv != SECSuccess) {
51 LOG(WARNING) << "PK11_PubEncryptRaw failed";
52 return rv;
53 }
54 return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
55 HASH_GetType(hash_context), mask_hash_alg,
56 salt_len);
57 }
58
59 } // namespace
60
61 SignatureVerifier::SignatureVerifier()
62 : vfy_context_(NULL),
63 hash_alg_(SHA1),
64 mask_hash_alg_(SHA1),
65 salt_len_(0),
66 public_key_(NULL),
67 hash_context_(NULL) {
17 EnsureNSSInit(); 68 EnsureNSSInit();
18 } 69 }
19 70
20 SignatureVerifier::~SignatureVerifier() { 71 SignatureVerifier::~SignatureVerifier() {
21 Reset(); 72 Reset();
22 } 73 }
23 74
24 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, 75 // static
25 int signature_algorithm_len, 76 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
26 const uint8* signature, 77 const uint8* public_key_info,
27 int signature_len, 78 int public_key_info_len) {
28 const uint8* public_key_info,
29 int public_key_info_len) {
30 signature_.assign(signature, signature + signature_len);
31
32 CERTSubjectPublicKeyInfo* spki = NULL; 79 CERTSubjectPublicKeyInfo* spki = NULL;
33 SECItem spki_der; 80 SECItem spki_der;
34 spki_der.type = siBuffer; 81 spki_der.type = siBuffer;
35 spki_der.data = const_cast<uint8*>(public_key_info); 82 spki_der.data = const_cast<uint8*>(public_key_info);
36 spki_der.len = public_key_info_len; 83 spki_der.len = public_key_info_len;
37 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); 84 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
38 if (!spki) 85 if (!spki)
39 return false; 86 return NULL;
40 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); 87 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
41 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. 88 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki.
89 return public_key;
90 }
91
92 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
93 int signature_algorithm_len,
94 const uint8* signature,
95 int signature_len,
96 const uint8* public_key_info,
97 int public_key_info_len) {
98 if (vfy_context_ || hash_context_)
99 return false;
100
101 signature_.assign(signature, signature + signature_len);
102
103 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
104 public_key_info_len);
42 if (!public_key) 105 if (!public_key)
43 return false; 106 return false;
44 107
45 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 108 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
46 if (!arena) { 109 if (!arena) {
47 SECKEY_DestroyPublicKey(public_key); 110 SECKEY_DestroyPublicKey(public_key);
48 return false; 111 return false;
49 } 112 }
50 113
51 SECItem sig_alg_der; 114 SECItem sig_alg_der;
(...skipping 29 matching lines...) Expand all
81 } 144 }
82 145
83 rv = VFY_Begin(vfy_context_); 146 rv = VFY_Begin(vfy_context_);
84 if (rv != SECSuccess) { 147 if (rv != SECSuccess) {
85 NOTREACHED(); 148 NOTREACHED();
86 return false; 149 return false;
87 } 150 }
88 return true; 151 return true;
89 } 152 }
90 153
154 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
155 HashAlgorithm mask_hash_alg,
156 int salt_len,
157 const uint8* signature,
158 int signature_len,
159 const uint8* public_key_info,
160 int public_key_info_len) {
161 if (vfy_context_ || hash_context_)
162 return false;
163
164 signature_.assign(signature, signature + signature_len);
165
166 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
167 public_key_info_len);
168 if (!public_key)
169 return false;
170
171 public_key_ = public_key;
172 hash_alg_ = hash_alg;
173 mask_hash_alg_ = mask_hash_alg;
174 salt_len_ = salt_len;
175 hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
176 if (!hash_context_)
177 return false;
178 HASH_Begin(hash_context_);
179 return true;
180 }
181
91 void SignatureVerifier::VerifyUpdate(const uint8* data_part, 182 void SignatureVerifier::VerifyUpdate(const uint8* data_part,
92 int data_part_len) { 183 int data_part_len) {
93 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); 184 if (vfy_context_) {
94 DCHECK_EQ(SECSuccess, rv); 185 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
186 DCHECK_EQ(SECSuccess, rv);
187 } else {
188 HASH_Update(hash_context_, data_part, data_part_len);
189 }
95 } 190 }
96 191
97 bool SignatureVerifier::VerifyFinal() { 192 bool SignatureVerifier::VerifyFinal() {
98 SECStatus rv = VFY_End(vfy_context_); 193 SECStatus rv;
194 if (vfy_context_) {
195 rv = VFY_End(vfy_context_);
196 } else {
197 rv = VerifyRSAPSS_End(public_key_, hash_context_,
198 ToNSSHashType(mask_hash_alg_), salt_len_,
199 signature_.data(),
200 signature_.size());
201 }
99 Reset(); 202 Reset();
100 203
101 // If signature verification fails, the error code is 204 // If signature verification fails, the error code is
102 // SEC_ERROR_BAD_SIGNATURE (-8182). 205 // SEC_ERROR_BAD_SIGNATURE (-8182).
103 return (rv == SECSuccess); 206 return (rv == SECSuccess);
104 } 207 }
105 208
106 void SignatureVerifier::Reset() { 209 void SignatureVerifier::Reset() {
107 if (vfy_context_) { 210 if (vfy_context_) {
108 VFY_DestroyContext(vfy_context_, PR_TRUE); 211 VFY_DestroyContext(vfy_context_, PR_TRUE);
109 vfy_context_ = NULL; 212 vfy_context_ = NULL;
110 } 213 }
214 if (hash_context_) {
215 HASH_Destroy(hash_context_);
216 hash_context_ = NULL;
217 }
218 if (public_key_) {
219 SECKEY_DestroyPublicKey(public_key_);
220 public_key_ = NULL;
221 }
111 signature_.clear(); 222 signature_.clear();
112 } 223 }
113 224
114 } // namespace crypto 225 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698