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

Side by Side Diff: mozilla/security/nss/lib/cryptohi/secvfy.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 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
« no previous file with comments | « mozilla/security/nss/lib/cryptohi/secsign.c ('k') | mozilla/security/nss/lib/dev/ckhelper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Verification stuff.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* $Id: secvfy.c,v 1.30 2012/06/25 21:48:39 rrelyea%redhat.com Exp $ */
8
9 #include <stdio.h>
10 #include "cryptohi.h"
11 #include "sechash.h"
12 #include "keyhi.h"
13 #include "secasn1.h"
14 #include "secoid.h"
15 #include "pk11func.h"
16 #include "secdig.h"
17 #include "secerr.h"
18 #include "keyi.h"
19
20 /*
21 ** Decrypt signature block using public key
22 ** Store the hash algorithm oid tag in *tagp
23 ** Store the digest in the digest buffer
24 ** Store the digest length in *digestlen
25 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
26 */
27 static SECStatus
28 DecryptSigBlock(SECOidTag *tagp, unsigned char *digest,
29 unsigned int *digestlen, unsigned int maxdigestlen,
30 SECKEYPublicKey *key, const SECItem *sig, char *wincx)
31 {
32 SGNDigestInfo *di = NULL;
33 unsigned char *buf = NULL;
34 SECStatus rv;
35 SECOidTag tag;
36 SECItem it;
37
38 if (key == NULL) goto loser;
39
40 it.len = SECKEY_PublicKeyStrength(key);
41 if (!it.len) goto loser;
42 it.data = buf = (unsigned char *)PORT_Alloc(it.len);
43 if (!buf) goto loser;
44
45 /* decrypt the block */
46 rv = PK11_VerifyRecover(key, (SECItem *)sig, &it, wincx);
47 if (rv != SECSuccess) goto loser;
48
49 di = SGN_DecodeDigestInfo(&it);
50 if (di == NULL) goto sigloser;
51
52 /*
53 ** Finally we have the digest info; now we can extract the algorithm
54 ** ID and the signature block
55 */
56 tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
57 /* Check that tag is an appropriate algorithm */
58 if (tag == SEC_OID_UNKNOWN) {
59 goto sigloser;
60 }
61 /* make sure the "parameters" are not too bogus. */
62 if (di->digestAlgorithm.parameters.len > 2) {
63 goto sigloser;
64 }
65 if (di->digest.len > maxdigestlen) {
66 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
67 goto loser;
68 }
69 PORT_Memcpy(digest, di->digest.data, di->digest.len);
70 *tagp = tag;
71 *digestlen = di->digest.len;
72 goto done;
73
74 sigloser:
75 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
76
77 loser:
78 rv = SECFailure;
79
80 done:
81 if (di != NULL) SGN_DestroyDigestInfo(di);
82 if (buf != NULL) PORT_Free(buf);
83
84 return rv;
85 }
86
87
88 struct VFYContextStr {
89 SECOidTag hashAlg; /* the hash algorithm */
90 SECKEYPublicKey *key;
91 /*
92 * This buffer holds either the digest or the full signature
93 * depending on the type of the signature (key->keyType). It is
94 * defined as a union to make sure it always has enough space.
95 *
96 * Use the "buffer" union member to reference the buffer.
97 * Note: do not take the size of the "buffer" union member. Take
98 * the size of the union or some other union member instead.
99 */
100 union {
101 unsigned char buffer[1];
102
103 /* the digest in the decrypted RSA signature */
104 unsigned char rsadigest[HASH_LENGTH_MAX];
105 /* the full DSA signature... 40 bytes */
106 unsigned char dsasig[DSA_MAX_SIGNATURE_LEN];
107 /* the full ECDSA signature */
108 unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
109 } u;
110 unsigned int rsadigestlen;
111 void * wincx;
112 void *hashcx;
113 const SECHashObject *hashobj;
114 SECOidTag encAlg; /* enc alg */
115 PRBool hasSignature; /* true if the signature was provided in the
116 * VFY_CreateContext call. If false, the
117 * signature must be provided with a
118 * VFY_EndWithSignature call. */
119 };
120
121 /*
122 * decode the ECDSA or DSA signature from it's DER wrapping.
123 * The unwrapped/raw signature is placed in the buffer pointed
124 * to by dsig and has enough room for len bytes.
125 */
126 static SECStatus
127 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
128 unsigned int len) {
129 SECItem *dsasig = NULL; /* also used for ECDSA */
130 SECStatus rv=SECSuccess;
131
132 if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
133 (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
134 if (sig->len != len) {
135 PORT_SetError(SEC_ERROR_BAD_DER);
136 return SECFailure;
137 }
138
139 PORT_Memcpy(dsig, sig->data, sig->len);
140 return SECSuccess;
141 }
142
143 if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
144 if (len > MAX_ECKEY_LEN * 2) {
145 PORT_SetError(SEC_ERROR_BAD_DER);
146 return SECFailure;
147 }
148 }
149 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
150
151 if ((dsasig == NULL) || (dsasig->len != len)) {
152 rv = SECFailure;
153 } else {
154 PORT_Memcpy(dsig, dsasig->data, dsasig->len);
155 }
156
157 if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
158 if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER);
159 return rv;
160 }
161
162 const SEC_ASN1Template hashParameterTemplate[] =
163 {
164 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
165 { SEC_ASN1_OBJECT_ID, 0 },
166 { SEC_ASN1_SKIP_REST },
167 { 0, }
168 };
169
170 /*
171 * Pulls the hash algorithm, signing algorithm, and key type out of a
172 * composite algorithm.
173 *
174 * sigAlg: the composite algorithm to dissect.
175 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
176 * encalg: address of a SECOidTag which will be set with the signing alg.
177 *
178 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
179 * algorithm was not found or was not a signing algorithm.
180 */
181 SECStatus
182 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
183 const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
184 {
185 int len;
186 PRArenaPool *arena;
187 SECStatus rv;
188 SECItem oid;
189
190 PR_ASSERT(hashalg!=NULL);
191 PR_ASSERT(encalg!=NULL);
192
193 switch (sigAlg) {
194 /* We probably shouldn't be generating MD2 signatures either */
195 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
196 *hashalg = SEC_OID_MD2;
197 break;
198 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
199 *hashalg = SEC_OID_MD5;
200 break;
201 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
202 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
203 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
204 *hashalg = SEC_OID_SHA1;
205 break;
206 case SEC_OID_PKCS1_RSA_ENCRYPTION:
207 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
208 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
209 break;
210
211 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
212 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
213 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
214 *hashalg = SEC_OID_SHA224;
215 break;
216 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
217 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
218 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
219 *hashalg = SEC_OID_SHA256;
220 break;
221 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
222 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
223 *hashalg = SEC_OID_SHA384;
224 break;
225 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
226 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
227 *hashalg = SEC_OID_SHA512;
228 break;
229
230 /* what about normal DSA? */
231 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
232 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
233 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
234 *hashalg = SEC_OID_SHA1;
235 break;
236 case SEC_OID_MISSI_DSS:
237 case SEC_OID_MISSI_KEA_DSS:
238 case SEC_OID_MISSI_KEA_DSS_OLD:
239 case SEC_OID_MISSI_DSS_OLD:
240 *hashalg = SEC_OID_SHA1;
241 break;
242 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
243 /* This is an EC algorithm. Recommended means the largest
244 * hash algorithm that is not reduced by the keysize of
245 * the EC algorithm. Note that key strength is in bytes and
246 * algorithms are specified in bits. Never use an algorithm
247 * weaker than sha1. */
248 len = SECKEY_PublicKeyStrength(key);
249 if (len < 28) { /* 28 bytes == 224 bits */
250 *hashalg = SEC_OID_SHA1;
251 } else if (len < 32) { /* 32 bytes == 256 bits */
252 *hashalg = SEC_OID_SHA224;
253 } else if (len < 48) { /* 48 bytes == 384 bits */
254 *hashalg = SEC_OID_SHA256;
255 } else if (len < 64) { /* 48 bytes == 512 bits */
256 *hashalg = SEC_OID_SHA384;
257 } else {
258 /* use the largest in this case */
259 *hashalg = SEC_OID_SHA512;
260 }
261 break;
262 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
263 if (param == NULL) {
264 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
265 return SECFailure;
266 }
267 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
268 if (arena == NULL) {
269 return SECFailure;
270 }
271 rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
272 if (rv == SECSuccess) {
273 *hashalg = SECOID_FindOIDTag(&oid);
274 }
275 PORT_FreeArena(arena, PR_FALSE);
276 if (rv != SECSuccess) {
277 return rv;
278 }
279 /* only accept hash algorithms */
280 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
281 /* error set by HASH_GetHashTypeByOidTag */
282 return SECFailure;
283 }
284 break;
285 /* we don't implement MD4 hashes */
286 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
287 default:
288 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
289 return SECFailure;
290 }
291 /* get the "encryption" algorithm */
292 switch (sigAlg) {
293 case SEC_OID_PKCS1_RSA_ENCRYPTION:
294 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
295 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
296 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
297 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
298 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
299 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
300 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
301 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
302 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
303 *encalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
304 break;
305 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
306 *encalg = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
307 break;
308
309 /* what about normal DSA? */
310 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
311 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
312 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
313 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
314 *encalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
315 break;
316 case SEC_OID_MISSI_DSS:
317 case SEC_OID_MISSI_KEA_DSS:
318 case SEC_OID_MISSI_KEA_DSS_OLD:
319 case SEC_OID_MISSI_DSS_OLD:
320 *encalg = SEC_OID_MISSI_DSS;
321 break;
322 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
323 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
324 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
325 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
326 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
327 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
328 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
329 *encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
330 break;
331 /* we don't implement MD4 hashes */
332 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
333 default:
334 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
335 return SECFailure;
336 }
337 return SECSuccess;
338 }
339
340 /*
341 * we can verify signatures that come from 2 different sources:
342 * one in with the signature contains a signature oid, and the other
343 * in which the signature is managed by a Public key (encAlg) oid
344 * and a hash oid. The latter is the more basic, so that's what
345 * our base vfyCreate function takes.
346 *
347 * There is one noteworthy corner case, if we are using an RSA key, and the
348 * signature block is provided, then the hashAlg can be specified as
349 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
350 * in the RSA signature block.
351 */
352 static VFYContext *
353 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
354 SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
355 {
356 VFYContext *cx;
357 SECStatus rv;
358 unsigned int sigLen;
359 KeyType type;
360
361 /* make sure the encryption algorithm matches the key type */
362 /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
363 type = seckey_GetKeyType(encAlg);
364 if ((key->keyType != type) &&
365 ((key->keyType != rsaKey) || (type != rsaPssKey))) {
366 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
367 return NULL;
368 }
369
370 cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
371 if (cx == NULL) {
372 goto loser;
373 }
374
375 cx->wincx = wincx;
376 cx->hasSignature = (sig != NULL);
377 cx->encAlg = encAlg;
378 cx->hashAlg = hashAlg;
379 cx->key = SECKEY_CopyPublicKey(key);
380 rv = SECSuccess;
381 if (sig) {
382 switch (type) {
383 case rsaKey:
384 rv = DecryptSigBlock(&cx->hashAlg, cx->u.buffer, &cx->rsadigestlen,
385 HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
386 if (cx->hashAlg != hashAlg && hashAlg != SEC_OID_UNKNOWN) {
387 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
388 rv = SECFailure;
389 }
390 break;
391 case dsaKey:
392 case ecKey:
393 sigLen = SECKEY_SignatureLen(key);
394 if (sigLen == 0) {
395 /* error set by SECKEY_SignatureLen */
396 rv = SECFailure;
397 break;
398 }
399 rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
400 break;
401 default:
402 rv = SECFailure;
403 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
404 break;
405 }
406 }
407
408 if (rv) goto loser;
409
410 /* check hash alg again, RSA may have changed it.*/
411 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
412 /* error set by HASH_GetHashTypeByOidTag */
413 goto loser;
414 }
415
416 if (hash) {
417 *hash = cx->hashAlg;
418 }
419 return cx;
420
421 loser:
422 if (cx) {
423 VFY_DestroyContext(cx, PR_TRUE);
424 }
425 return 0;
426 }
427
428 VFYContext *
429 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
430 void *wincx)
431 {
432 SECOidTag encAlg, hashAlg;
433 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
434 if (rv != SECSuccess) {
435 return NULL;
436 }
437 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
438 }
439
440 VFYContext *
441 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
442 SECOidTag encAlg, SECOidTag hashAlg,
443 SECOidTag *hash, void *wincx)
444 {
445 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
446 }
447
448 VFYContext *
449 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
450 const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
451 {
452 SECOidTag encAlg, hashAlg;
453 SECStatus rv = sec_DecodeSigAlg(key,
454 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
455 &sigAlgorithm->parameters, &encAlg, &hashAlg);
456 if (rv != SECSuccess) {
457 return NULL;
458 }
459 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
460 }
461
462 void
463 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
464 {
465 if (cx) {
466 if (cx->hashcx != NULL) {
467 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
468 cx->hashcx = NULL;
469 }
470 if (cx->key) {
471 SECKEY_DestroyPublicKey(cx->key);
472 }
473 if (freeit) {
474 PORT_ZFree(cx, sizeof(VFYContext));
475 }
476 }
477 }
478
479 SECStatus
480 VFY_Begin(VFYContext *cx)
481 {
482 if (cx->hashcx != NULL) {
483 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
484 cx->hashcx = NULL;
485 }
486
487 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
488 if (!cx->hashobj)
489 return SECFailure; /* error code is set */
490
491 cx->hashcx = (*cx->hashobj->create)();
492 if (cx->hashcx == NULL)
493 return SECFailure;
494
495 (*cx->hashobj->begin)(cx->hashcx);
496 return SECSuccess;
497 }
498
499 SECStatus
500 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
501 {
502 if (cx->hashcx == NULL) {
503 PORT_SetError(SEC_ERROR_INVALID_ARGS);
504 return SECFailure;
505 }
506 (*cx->hashobj->update)(cx->hashcx, input, inputLen);
507 return SECSuccess;
508 }
509
510 SECStatus
511 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
512 {
513 unsigned char final[HASH_LENGTH_MAX];
514 unsigned part;
515 SECItem hash,dsasig; /* dsasig is also used for ECDSA */
516 SECStatus rv;
517
518 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
519 PORT_SetError(SEC_ERROR_INVALID_ARGS);
520 return SECFailure;
521 }
522
523 if (cx->hashcx == NULL) {
524 PORT_SetError(SEC_ERROR_INVALID_ARGS);
525 return SECFailure;
526 }
527 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
528 switch (cx->key->keyType) {
529 case ecKey:
530 case dsaKey:
531 dsasig.data = cx->u.buffer;
532 dsasig.len = SECKEY_SignatureLen(cx->key);
533 if (dsasig.len == 0) {
534 return SECFailure;
535 }
536 if (sig) {
537 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
538 dsasig.len);
539 if (rv != SECSuccess) {
540 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
541 return SECFailure;
542 }
543 }
544 hash.data = final;
545 hash.len = part;
546 if (PK11_Verify(cx->key,&dsasig,&hash,cx->wincx) != SECSuccess) {
547 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
548 return SECFailure;
549 }
550 break;
551 case rsaKey:
552 if (sig) {
553 SECOidTag hashid = SEC_OID_UNKNOWN;
554 rv = DecryptSigBlock(&hashid, cx->u.buffer, &cx->rsadigestlen,
555 HASH_LENGTH_MAX, cx->key, sig, (char*)cx->wincx);
556 if ((rv != SECSuccess) || (hashid != cx->hashAlg)) {
557 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
558 return SECFailure;
559 }
560 }
561 if ((part != cx->rsadigestlen) ||
562 PORT_Memcmp(final, cx->u.buffer, part)) {
563 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
564 return SECFailure;
565 }
566 break;
567 default:
568 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
569 return SECFailure; /* shouldn't happen */
570 }
571 return SECSuccess;
572 }
573
574 SECStatus
575 VFY_End(VFYContext *cx)
576 {
577 return VFY_EndWithSignature(cx,NULL);
578 }
579
580 /************************************************************************/
581 /*
582 * Verify that a previously-computed digest matches a signature.
583 */
584 static SECStatus
585 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
586 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
587 void *wincx)
588 {
589 SECStatus rv;
590 VFYContext *cx;
591 SECItem dsasig; /* also used for ECDSA */
592
593 rv = SECFailure;
594
595 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
596 if (cx != NULL) {
597 switch (key->keyType) {
598 case rsaKey:
599 if ((digest->len != cx->rsadigestlen) ||
600 PORT_Memcmp(digest->data, cx->u.buffer, digest->len)) {
601 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
602 } else {
603 rv = SECSuccess;
604 }
605 break;
606 case dsaKey:
607 case ecKey:
608 dsasig.data = cx->u.buffer;
609 dsasig.len = SECKEY_SignatureLen(cx->key);
610 if (dsasig.len == 0) {
611 break;
612 }
613 if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx)
614 != SECSuccess) {
615 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
616 } else {
617 rv = SECSuccess;
618 }
619 break;
620 default:
621 break;
622 }
623 VFY_DestroyContext(cx, PR_TRUE);
624 }
625 return rv;
626 }
627
628 SECStatus
629 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
630 const SECItem *sig, SECOidTag encAlg,
631 SECOidTag hashAlg, void *wincx)
632 {
633 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
634 }
635
636 SECStatus
637 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
638 SECOidTag algid, void *wincx)
639 {
640 SECOidTag encAlg, hashAlg;
641 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
642 if (rv != SECSuccess) {
643 return SECFailure;
644 }
645 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
646 }
647
648 /*
649 * this function takes an optional hash oid, which the digest function
650 * will be compared with our target hash value.
651 */
652 SECStatus
653 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
654 const SECKEYPublicKey *key, const SECItem *sig,
655 const SECAlgorithmID *sigAlgorithm,
656 SECOidTag hashCmp, void *wincx)
657 {
658 SECOidTag encAlg, hashAlg;
659 SECStatus rv = sec_DecodeSigAlg(key,
660 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
661 &sigAlgorithm->parameters, &encAlg, &hashAlg);
662 if (rv != SECSuccess) {
663 return rv;
664 }
665 if ( hashCmp != SEC_OID_UNKNOWN &&
666 hashAlg != SEC_OID_UNKNOWN &&
667 hashCmp != hashAlg) {
668 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
669 return SECFailure;
670 }
671 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
672 }
673
674 static SECStatus
675 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
676 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
677 SECOidTag *hash, void *wincx)
678 {
679 SECStatus rv;
680 VFYContext *cx;
681
682 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
683 if (cx == NULL)
684 return SECFailure;
685
686 rv = VFY_Begin(cx);
687 if (rv == SECSuccess) {
688 rv = VFY_Update(cx, (unsigned char *)buf, len);
689 if (rv == SECSuccess)
690 rv = VFY_End(cx);
691 }
692
693 VFY_DestroyContext(cx, PR_TRUE);
694 return rv;
695 }
696
697 SECStatus
698 VFY_VerifyDataDirect(const unsigned char *buf, int len,
699 const SECKEYPublicKey *key, const SECItem *sig,
700 SECOidTag encAlg, SECOidTag hashAlg,
701 SECOidTag *hash, void *wincx)
702 {
703 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
704 }
705
706 SECStatus
707 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
708 const SECItem *sig, SECOidTag algid, void *wincx)
709 {
710 SECOidTag encAlg, hashAlg;
711 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
712 if (rv != SECSuccess) {
713 return rv;
714 }
715 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
716 }
717
718 SECStatus
719 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
720 const SECKEYPublicKey *key,
721 const SECItem *sig,
722 const SECAlgorithmID *sigAlgorithm,
723 SECOidTag *hash, void *wincx)
724 {
725 SECOidTag encAlg, hashAlg;
726 SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
727 SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
728 &sigAlgorithm->parameters, &encAlg, &hashAlg);
729 if (rv != SECSuccess) {
730 return rv;
731 }
732 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
733 }
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/cryptohi/secsign.c ('k') | mozilla/security/nss/lib/dev/ckhelper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698