comparison nss/lib/cryptohi/secvfy.c @ 0:1e5118fa0cb1

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