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