Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / cryptohi / secvfy.c
blobfc22ad6eb7afcb38ce61fc32a2c13667e8b58c37
1 /*
2 * Verification stuff.
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is the Netscape security libraries.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
25 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
40 /* $Id: secvfy.c,v 1.21 2007/01/09 00:37:20 alexei.volkov.bugs%sun.com Exp $ */
42 #include <stdio.h>
43 #include "cryptohi.h"
44 #include "sechash.h"
45 #include "keyhi.h"
46 #include "secasn1.h"
47 #include "secoid.h"
48 #include "pk11func.h"
49 #include "secdig.h"
50 #include "secerr.h"
51 #include "keyi.h"
54 ** Decrypt signature block using public key
55 ** Store the hash algorithm oid tag in *tagp
56 ** Store the digest in the digest buffer
57 ** Store the digest length in *digestlen
58 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
60 static SECStatus
61 DecryptSigBlock(SECOidTag *tagp, unsigned char *digest,
62 unsigned int *digestlen, unsigned int maxdigestlen,
63 SECKEYPublicKey *key, const SECItem *sig, char *wincx)
65 SGNDigestInfo *di = NULL;
66 unsigned char *buf = NULL;
67 SECStatus rv;
68 SECOidTag tag;
69 SECItem it;
71 if (key == NULL) goto loser;
73 it.len = SECKEY_PublicKeyStrength(key);
74 if (!it.len) goto loser;
75 it.data = buf = (unsigned char *)PORT_Alloc(it.len);
76 if (!buf) goto loser;
78 /* decrypt the block */
79 rv = PK11_VerifyRecover(key, (SECItem *)sig, &it, wincx);
80 if (rv != SECSuccess) goto loser;
82 di = SGN_DecodeDigestInfo(&it);
83 if (di == NULL) goto sigloser;
86 ** Finally we have the digest info; now we can extract the algorithm
87 ** ID and the signature block
89 tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
90 /* Check that tag is an appropriate algorithm */
91 if (tag == SEC_OID_UNKNOWN) {
92 goto sigloser;
94 /* make sure the "parameters" are not too bogus. */
95 if (di->digestAlgorithm.parameters.len > 2) {
96 goto sigloser;
98 if (di->digest.len > maxdigestlen) {
99 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
100 goto loser;
102 PORT_Memcpy(digest, di->digest.data, di->digest.len);
103 *tagp = tag;
104 *digestlen = di->digest.len;
105 goto done;
107 sigloser:
108 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
110 loser:
111 rv = SECFailure;
113 done:
114 if (di != NULL) SGN_DestroyDigestInfo(di);
115 if (buf != NULL) PORT_Free(buf);
117 return rv;
121 struct VFYContextStr {
122 SECOidTag hashAlg; /* the hash algorithm */
123 SECKEYPublicKey *key;
125 * This buffer holds either the digest or the full signature
126 * depending on the type of the signature (key->keyType). It is
127 * defined as a union to make sure it always has enough space.
129 * Use the "buffer" union member to reference the buffer.
130 * Note: do not take the size of the "buffer" union member. Take
131 * the size of the union or some other union member instead.
133 union {
134 unsigned char buffer[1];
136 /* the digest in the decrypted RSA signature */
137 unsigned char rsadigest[HASH_LENGTH_MAX];
138 /* the full DSA signature... 40 bytes */
139 unsigned char dsasig[DSA_SIGNATURE_LEN];
140 /* the full ECDSA signature */
141 unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
142 } u;
143 unsigned int rsadigestlen;
144 void * wincx;
145 void *hashcx;
146 const SECHashObject *hashobj;
147 SECOidTag encAlg; /* enc alg */
148 PRBool hasSignature; /* true if the signature was provided in the
149 * VFY_CreateContext call. If false, the
150 * signature must be provided with a
151 * VFY_EndWithSignature call. */
155 * decode the ECDSA or DSA signature from it's DER wrapping.
156 * The unwrapped/raw signature is placed in the buffer pointed
157 * to by dsig and has enough room for len bytes.
159 static SECStatus
160 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
161 unsigned int len) {
162 SECItem *dsasig = NULL; /* also used for ECDSA */
163 SECStatus rv=SECSuccess;
165 if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
166 (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
167 if (sig->len != len) {
168 PORT_SetError(SEC_ERROR_BAD_DER);
169 return SECFailure;
172 PORT_Memcpy(dsig, sig->data, sig->len);
173 return SECSuccess;
176 if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
177 if (len > MAX_ECKEY_LEN * 2) {
178 PORT_SetError(SEC_ERROR_BAD_DER);
179 return SECFailure;
182 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
184 if ((dsasig == NULL) || (dsasig->len != len)) {
185 rv = SECFailure;
186 } else {
187 PORT_Memcpy(dsig, dsasig->data, dsasig->len);
190 if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
191 if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER);
192 return rv;
195 const SEC_ASN1Template hashParameterTemplate[] =
197 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
198 { SEC_ASN1_OBJECT_ID, 0 },
199 { SEC_ASN1_SKIP_REST },
200 { 0, }
204 * Pulls the hash algorithm, signing algorithm, and key type out of a
205 * composite algorithm.
207 * sigAlg: the composite algorithm to dissect.
208 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
209 * encalg: address of a SECOidTag which will be set with the signing alg.
211 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
212 * algorithm was not found or was not a signing algorithm.
214 SECStatus
215 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
216 const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
218 int len;
219 PRArenaPool *arena;
220 SECStatus rv;
221 SECItem oid;
223 PR_ASSERT(hashalg!=NULL);
224 PR_ASSERT(encalg!=NULL);
226 switch (sigAlg) {
227 /* We probably shouldn't be generating MD2 signatures either */
228 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
229 *hashalg = SEC_OID_MD2;
230 break;
231 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
232 *hashalg = SEC_OID_MD5;
233 break;
234 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
235 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
236 *hashalg = SEC_OID_SHA1;
237 break;
238 case SEC_OID_PKCS1_RSA_ENCRYPTION:
239 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
240 break;
242 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
243 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
244 *hashalg = SEC_OID_SHA256;
245 break;
246 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
247 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
248 *hashalg = SEC_OID_SHA384;
249 break;
250 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
251 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
252 *hashalg = SEC_OID_SHA512;
253 break;
255 /* what about normal DSA? */
256 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
257 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
258 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
259 *hashalg = SEC_OID_SHA1;
260 break;
261 case SEC_OID_MISSI_DSS:
262 case SEC_OID_MISSI_KEA_DSS:
263 case SEC_OID_MISSI_KEA_DSS_OLD:
264 case SEC_OID_MISSI_DSS_OLD:
265 *hashalg = SEC_OID_SHA1;
266 break;
267 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
268 /* This is an EC algorithm. Recommended means the largest
269 * hash algorithm that is not reduced by the keysize of
270 * the EC algorithm. Note that key strength is in bytes and
271 * algorithms are specified in bits. Never use an algorithm
272 * weaker than sha1. */
273 len = SECKEY_PublicKeyStrength(key);
274 if (len < 28) { /* 28 bytes == 224 bits */
275 *hashalg = SEC_OID_SHA1;
276 } else if (len < 32) { /* 32 bytes == 256 bits */
277 /* SHA 224 not supported in NSS */
278 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
279 return SECFailure;
280 } else if (len < 48) { /* 48 bytes == 384 bits */
281 *hashalg = SEC_OID_SHA256;
282 } else if (len < 64) { /* 48 bytes == 512 bits */
283 *hashalg = SEC_OID_SHA384;
284 } else {
285 /* use the largest in this case */
286 *hashalg = SEC_OID_SHA512;
288 break;
289 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
290 if (param == NULL) {
291 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
292 return SECFailure;
294 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
295 if (arena == NULL) {
296 return SECFailure;
298 rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
299 if (rv != SECSuccess) {
300 PORT_FreeArena(arena, PR_FALSE);
301 return rv;
303 *hashalg = SECOID_FindOIDTag(&oid);
304 /* only accept hash algorithms */
305 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
306 /* error set by HASH_GetHashTypeByOidTag */
307 return SECFailure;
309 break;
310 /* we don't implement MD4 hashes */
311 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
312 default:
313 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
314 return SECFailure;
316 /* get the "encryption" algorithm */
317 switch (sigAlg) {
318 case SEC_OID_PKCS1_RSA_ENCRYPTION:
319 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
320 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
321 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
322 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
323 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
324 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
325 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
326 *encalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
327 break;
329 /* what about normal DSA? */
330 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
331 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
332 *encalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
333 break;
334 case SEC_OID_MISSI_DSS:
335 case SEC_OID_MISSI_KEA_DSS:
336 case SEC_OID_MISSI_KEA_DSS_OLD:
337 case SEC_OID_MISSI_DSS_OLD:
338 *encalg = SEC_OID_MISSI_DSS;
339 break;
340 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
341 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
342 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
343 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
344 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
345 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
346 *encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
347 break;
348 /* we don't implement MD4 hashes */
349 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
350 default:
351 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
352 return SECFailure;
354 return SECSuccess;
358 * we can verify signatures that come from 2 different sources:
359 * one in with the signature contains a signature oid, and the other
360 * in which the signature is managed by a Public key (encAlg) oid
361 * and a hash oid. The latter is the more basic, so that's what
362 * our base vfyCreate function takes.
364 * There is one noteworthy corner case, if we are using an RSA key, and the
365 * signature block is provided, then the hashAlg can be specified as
366 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
367 * in the RSA signature block.
369 static VFYContext *
370 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
371 SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
373 VFYContext *cx;
374 SECStatus rv;
375 unsigned int sigLen;
376 KeyType type;
378 /* make sure the encryption algorithm matches the key type */
379 type = seckey_GetKeyType(encAlg);
380 if (key->keyType != type) {
381 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
382 return NULL;
385 cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
386 if (cx == NULL) {
387 goto loser;
390 cx->wincx = wincx;
391 cx->hasSignature = (sig != NULL);
392 cx->encAlg = encAlg;
393 cx->hashAlg = hashAlg;
394 cx->key = SECKEY_CopyPublicKey(key);
395 rv = SECSuccess;
396 if (sig) {
397 switch (key->keyType) {
398 case rsaKey:
399 rv = DecryptSigBlock(&cx->hashAlg, cx->u.buffer, &cx->rsadigestlen,
400 HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
401 if (cx->hashAlg != hashAlg && hashAlg != SEC_OID_UNKNOWN) {
402 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
403 rv = SECFailure;
405 break;
406 case dsaKey:
407 case ecKey:
408 sigLen = SECKEY_SignatureLen(key);
409 if (sigLen == 0) {
410 /* error set by SECKEY_SignatureLen */
411 rv = SECFailure;
412 break;
414 rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
415 break;
416 default:
417 rv = SECFailure;
418 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
419 break;
423 if (rv) goto loser;
425 /* check hash alg again, RSA may have changed it.*/
426 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
427 /* error set by HASH_GetHashTypeByOidTag */
428 goto loser;
431 if (hash) {
432 *hash = cx->hashAlg;
434 return cx;
436 loser:
437 if (cx) {
438 VFY_DestroyContext(cx, PR_TRUE);
440 return 0;
443 VFYContext *
444 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
445 void *wincx)
447 SECOidTag encAlg, hashAlg;
448 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
449 if (rv != SECSuccess) {
450 return NULL;
452 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
455 VFYContext *
456 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
457 SECOidTag encAlg, SECOidTag hashAlg,
458 SECOidTag *hash, void *wincx)
460 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
463 VFYContext *
464 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
465 const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
467 SECOidTag encAlg, hashAlg;
468 SECStatus rv = sec_DecodeSigAlg(key,
469 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
470 &sigAlgorithm->parameters, &encAlg, &hashAlg);
471 if (rv != SECSuccess) {
472 return NULL;
474 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
477 void
478 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
480 if (cx) {
481 if (cx->hashcx != NULL) {
482 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
483 cx->hashcx = NULL;
485 if (cx->key) {
486 SECKEY_DestroyPublicKey(cx->key);
488 if (freeit) {
489 PORT_ZFree(cx, sizeof(VFYContext));
494 SECStatus
495 VFY_Begin(VFYContext *cx)
497 if (cx->hashcx != NULL) {
498 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
499 cx->hashcx = NULL;
502 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
503 if (!cx->hashobj)
504 return SECFailure; /* error code is set */
506 cx->hashcx = (*cx->hashobj->create)();
507 if (cx->hashcx == NULL)
508 return SECFailure;
510 (*cx->hashobj->begin)(cx->hashcx);
511 return SECSuccess;
514 SECStatus
515 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
517 if (cx->hashcx == NULL) {
518 PORT_SetError(SEC_ERROR_INVALID_ARGS);
519 return SECFailure;
521 (*cx->hashobj->update)(cx->hashcx, input, inputLen);
522 return SECSuccess;
525 SECStatus
526 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
528 unsigned char final[HASH_LENGTH_MAX];
529 unsigned part;
530 SECItem hash,dsasig; /* dsasig is also used for ECDSA */
531 SECStatus rv;
533 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
534 PORT_SetError(SEC_ERROR_INVALID_ARGS);
535 return SECFailure;
538 if (cx->hashcx == NULL) {
539 PORT_SetError(SEC_ERROR_INVALID_ARGS);
540 return SECFailure;
542 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
543 switch (cx->key->keyType) {
544 case ecKey:
545 case dsaKey:
546 dsasig.data = cx->u.buffer;
547 dsasig.len = SECKEY_SignatureLen(cx->key);
548 if (dsasig.len == 0) {
549 return SECFailure;
551 if (sig) {
552 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
553 dsasig.len);
554 if (rv != SECSuccess) {
555 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
556 return SECFailure;
559 hash.data = final;
560 hash.len = part;
561 if (PK11_Verify(cx->key,&dsasig,&hash,cx->wincx) != SECSuccess) {
562 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
563 return SECFailure;
565 break;
566 case rsaKey:
567 if (sig) {
568 SECOidTag hashid = SEC_OID_UNKNOWN;
569 rv = DecryptSigBlock(&hashid, cx->u.buffer, &cx->rsadigestlen,
570 HASH_LENGTH_MAX, cx->key, sig, (char*)cx->wincx);
571 if ((rv != SECSuccess) || (hashid != cx->hashAlg)) {
572 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
573 return SECFailure;
576 if ((part != cx->rsadigestlen) ||
577 PORT_Memcmp(final, cx->u.buffer, part)) {
578 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
579 return SECFailure;
581 break;
582 default:
583 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
584 return SECFailure; /* shouldn't happen */
586 return SECSuccess;
589 SECStatus
590 VFY_End(VFYContext *cx)
592 return VFY_EndWithSignature(cx,NULL);
595 /************************************************************************/
597 * Verify that a previously-computed digest matches a signature.
599 static SECStatus
600 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
601 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
602 void *wincx)
604 SECStatus rv;
605 VFYContext *cx;
606 SECItem dsasig; /* also used for ECDSA */
608 rv = SECFailure;
610 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
611 if (cx != NULL) {
612 switch (key->keyType) {
613 case rsaKey:
614 if ((digest->len != cx->rsadigestlen) ||
615 PORT_Memcmp(digest->data, cx->u.buffer, digest->len)) {
616 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
617 } else {
618 rv = SECSuccess;
620 break;
621 case dsaKey:
622 case ecKey:
623 dsasig.data = cx->u.buffer;
624 dsasig.len = SECKEY_SignatureLen(cx->key);
625 if (dsasig.len == 0) {
626 break;
628 if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx)
629 != SECSuccess) {
630 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
631 } else {
632 rv = SECSuccess;
634 break;
635 default:
636 break;
638 VFY_DestroyContext(cx, PR_TRUE);
640 return rv;
643 SECStatus
644 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
645 const SECItem *sig, SECOidTag encAlg,
646 SECOidTag hashAlg, void *wincx)
648 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
651 SECStatus
652 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
653 SECOidTag algid, void *wincx)
655 SECOidTag encAlg, hashAlg;
656 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
657 if (rv != SECSuccess) {
658 return SECFailure;
660 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
664 * this function takes an optional hash oid, which the digest function
665 * will be compared with our target hash value.
667 SECStatus
668 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
669 const SECKEYPublicKey *key, const SECItem *sig,
670 const SECAlgorithmID *sigAlgorithm,
671 SECOidTag hashCmp, void *wincx)
673 SECOidTag encAlg, hashAlg;
674 SECStatus rv = sec_DecodeSigAlg(key,
675 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
676 &sigAlgorithm->parameters, &encAlg, &hashAlg);
677 if (rv != SECSuccess) {
678 return rv;
680 if ( hashCmp != SEC_OID_UNKNOWN &&
681 hashAlg != SEC_OID_UNKNOWN &&
682 hashCmp != hashAlg) {
683 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
684 return SECFailure;
686 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
689 static SECStatus
690 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
691 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
692 SECOidTag *hash, void *wincx)
694 SECStatus rv;
695 VFYContext *cx;
697 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
698 if (cx == NULL)
699 return SECFailure;
701 rv = VFY_Begin(cx);
702 if (rv == SECSuccess) {
703 rv = VFY_Update(cx, (unsigned char *)buf, len);
704 if (rv == SECSuccess)
705 rv = VFY_End(cx);
708 VFY_DestroyContext(cx, PR_TRUE);
709 return rv;
712 SECStatus
713 VFY_VerifyDataDirect(const unsigned char *buf, int len,
714 const SECKEYPublicKey *key, const SECItem *sig,
715 SECOidTag encAlg, SECOidTag hashAlg,
716 SECOidTag *hash, void *wincx)
718 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
721 SECStatus
722 VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
723 SECItem *sig, SECOidTag algid, void *wincx)
725 SECOidTag encAlg, hashAlg;
726 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
727 if (rv != SECSuccess) {
728 return rv;
730 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
733 SECStatus
734 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
735 const SECKEYPublicKey *key,
736 const SECItem *sig,
737 const SECAlgorithmID *sigAlgorithm,
738 SECOidTag *hash, void *wincx)
740 SECOidTag encAlg, hashAlg;
741 SECStatus rv = sec_DecodeSigAlg(key,
742 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
743 &sigAlgorithm->parameters, &encAlg, &hashAlg);
744 if (rv != SECSuccess) {
745 return rv;
747 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);