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

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

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/cryptohi/secsign.c ('k') | 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
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"
19
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;
47
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);
54
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 }
63
64 if (rv == SECSuccess) {
65 /* decrypt the block */
66 rv = PK11_VerifyRecover(key, sig, &it, wincx);
67 }
68
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 }
82
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 }
93
94 if (rv == SECSuccess) {
95 *digestAlgOut = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
96 if (*digestAlgOut == SEC_OID_UNKNOWN) {
97 rv = SECFailure;
98 }
99 }
100
101 if (di) {
102 SGN_DestroyDigestInfo(di);
103 }
104
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 }
116
117 return rv;
118 }
119
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];
134
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 };
152
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 }
163
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 {
173 SECItem *dsasig = NULL; /* also used for ECDSA */
174 SECStatus rv = SECSuccess;
175
176 if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
177 (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
178 if (sig->len != len) {
179 PORT_SetError(SEC_ERROR_BAD_DER);
180 return SECFailure;
181 }
182
183 PORT_Memcpy(dsig, sig->data, sig->len);
184 return SECSuccess;
185 }
186
187 if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
188 if (len > MAX_ECKEY_LEN * 2) {
189 PORT_SetError(SEC_ERROR_BAD_DER);
190 return SECFailure;
191 }
192 }
193 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
194
195 if ((dsasig == NULL) || (dsasig->len != len)) {
196 rv = SECFailure;
197 } else {
198 PORT_Memcpy(dsig, dsasig->data, dsasig->len);
199 }
200
201 if (dsasig != NULL)
202 SECITEM_FreeItem(dsasig, PR_TRUE);
203 if (rv == SECFailure)
204 PORT_SetError(SEC_ERROR_BAD_DER);
205 return rv;
206 }
207
208 const SEC_ASN1Template hashParameterTemplate[] =
209 {
210 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
211 { SEC_ASN1_OBJECT_ID, 0 },
212 { SEC_ASN1_SKIP_REST },
213 { 0 }
214 };
215
216 /*
217 * Pulls the hash algorithm, signing algorithm, and key type out of a
218 * composite algorithm.
219 *
220 * sigAlg: the composite algorithm to dissect.
221 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
222 * encalg: address of a SECOidTag which will be set with the signing alg.
223 *
224 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
225 * algorithm was not found or was not a signing algorithm.
226 */
227 SECStatus
228 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
229 const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
230 {
231 int len;
232 PLArenaPool *arena;
233 SECStatus rv;
234 SECItem oid;
235
236 PR_ASSERT(hashalg != NULL);
237 PR_ASSERT(encalg != NULL);
238
239 switch (sigAlg) {
240 /* We probably shouldn't be generating MD2 signatures either */
241 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
242 *hashalg = SEC_OID_MD2;
243 break;
244 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
245 *hashalg = SEC_OID_MD5;
246 break;
247 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
248 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
249 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
250 *hashalg = SEC_OID_SHA1;
251 break;
252 case SEC_OID_PKCS1_RSA_ENCRYPTION:
253 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
254 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
255 break;
256
257 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
258 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
259 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
260 *hashalg = SEC_OID_SHA224;
261 break;
262 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
263 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
264 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
265 *hashalg = SEC_OID_SHA256;
266 break;
267 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
268 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
269 *hashalg = SEC_OID_SHA384;
270 break;
271 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
272 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
273 *hashalg = SEC_OID_SHA512;
274 break;
275
276 /* what about normal DSA? */
277 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
278 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
279 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
280 *hashalg = SEC_OID_SHA1;
281 break;
282 case SEC_OID_MISSI_DSS:
283 case SEC_OID_MISSI_KEA_DSS:
284 case SEC_OID_MISSI_KEA_DSS_OLD:
285 case SEC_OID_MISSI_DSS_OLD:
286 *hashalg = SEC_OID_SHA1;
287 break;
288 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
289 /* This is an EC algorithm. Recommended means the largest
290 * hash algorithm that is not reduced by the keysize of
291 * the EC algorithm. Note that key strength is in bytes and
292 * algorithms are specified in bits. Never use an algorithm
293 * weaker than sha1. */
294 len = SECKEY_PublicKeyStrength(key);
295 if (len < 28) { /* 28 bytes == 224 bits */
296 *hashalg = SEC_OID_SHA1;
297 } else if (len < 32) { /* 32 bytes == 256 bits */
298 *hashalg = SEC_OID_SHA224;
299 } else if (len < 48) { /* 48 bytes == 384 bits */
300 *hashalg = SEC_OID_SHA256;
301 } else if (len < 64) { /* 48 bytes == 512 bits */
302 *hashalg = SEC_OID_SHA384;
303 } else {
304 /* use the largest in this case */
305 *hashalg = SEC_OID_SHA512;
306 }
307 break;
308 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
309 if (param == NULL) {
310 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
311 return SECFailure;
312 }
313 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
314 if (arena == NULL) {
315 return SECFailure;
316 }
317 rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, para m);
318 if (rv == SECSuccess) {
319 *hashalg = SECOID_FindOIDTag(&oid);
320 }
321 PORT_FreeArena(arena, PR_FALSE);
322 if (rv != SECSuccess) {
323 return rv;
324 }
325 /* only accept hash algorithms */
326 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
327 /* error set by HASH_GetHashTypeByOidTag */
328 return SECFailure;
329 }
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 /* get the "encryption" algorithm */
338 switch (sigAlg) {
339 case SEC_OID_PKCS1_RSA_ENCRYPTION:
340 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
341 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
342 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
343 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
344 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
345 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
346 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
347 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
348 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
349 *encalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
350 break;
351 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
352 *encalg = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
353 break;
354
355 /* what about normal DSA? */
356 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
357 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
358 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
359 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
360 *encalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
361 break;
362 case SEC_OID_MISSI_DSS:
363 case SEC_OID_MISSI_KEA_DSS:
364 case SEC_OID_MISSI_KEA_DSS_OLD:
365 case SEC_OID_MISSI_DSS_OLD:
366 *encalg = SEC_OID_MISSI_DSS;
367 break;
368 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
369 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
370 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
371 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
372 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
373 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
374 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
375 *encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
376 break;
377 /* we don't implement MD4 hashes */
378 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
379 default:
380 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
381 return SECFailure;
382 }
383 return SECSuccess;
384 }
385
386 /*
387 * we can verify signatures that come from 2 different sources:
388 * one in with the signature contains a signature oid, and the other
389 * in which the signature is managed by a Public key (encAlg) oid
390 * and a hash oid. The latter is the more basic, so that's what
391 * our base vfyCreate function takes.
392 *
393 * There is one noteworthy corner case, if we are using an RSA key, and the
394 * signature block is provided, then the hashAlg can be specified as
395 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
396 * in the RSA signature block.
397 */
398 static VFYContext *
399 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
400 SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wi ncx)
401 {
402 VFYContext *cx;
403 SECStatus rv;
404 unsigned int sigLen;
405 KeyType type;
406
407 /* make sure the encryption algorithm matches the key type */
408 /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
409 type = seckey_GetKeyType(encAlg);
410 if ((key->keyType != type) &&
411 ((key->keyType != rsaKey) || (type != rsaPssKey))) {
412 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
413 return NULL;
414 }
415
416 cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
417 if (cx == NULL) {
418 goto loser;
419 }
420
421 cx->wincx = wincx;
422 cx->hasSignature = (sig != NULL);
423 cx->encAlg = encAlg;
424 cx->hashAlg = hashAlg;
425 cx->key = SECKEY_CopyPublicKey(key);
426 cx->pkcs1RSADigestInfo = NULL;
427 rv = SECSuccess;
428 if (sig) {
429 switch (type) {
430 case rsaKey:
431 rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
432 &cx->pkcs1RSADigestInfo,
433 &cx->pkcs1RSADigestInfoLen,
434 cx->key,
435 sig, wincx);
436 break;
437 case dsaKey:
438 case ecKey:
439 sigLen = SECKEY_SignatureLen(key);
440 if (sigLen == 0) {
441 /* error set by SECKEY_SignatureLen */
442 rv = SECFailure;
443 break;
444 }
445 rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
446 break;
447 default:
448 rv = SECFailure;
449 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
450 break;
451 }
452 }
453
454 if (rv)
455 goto loser;
456
457 /* check hash alg again, RSA may have changed it.*/
458 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
459 /* error set by HASH_GetHashTypeByOidTag */
460 goto loser;
461 }
462
463 if (hash) {
464 *hash = cx->hashAlg;
465 }
466 return cx;
467
468 loser:
469 if (cx) {
470 VFY_DestroyContext(cx, PR_TRUE);
471 }
472 return 0;
473 }
474
475 VFYContext *
476 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
477 void *wincx)
478 {
479 SECOidTag encAlg, hashAlg;
480 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
481 if (rv != SECSuccess) {
482 return NULL;
483 }
484 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
485 }
486
487 VFYContext *
488 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
489 SECOidTag encAlg, SECOidTag hashAlg,
490 SECOidTag *hash, void *wincx)
491 {
492 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
493 }
494
495 VFYContext *
496 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
497 const SECAlgorithmID *sigAlgorithm, SECOidTag * hash, void *wincx)
498 {
499 SECOidTag encAlg, hashAlg;
500 SECStatus rv = sec_DecodeSigAlg(key,
501 SECOID_GetAlgorithmTag((SECAlgorithmID *)sig Algorithm),
502 &sigAlgorithm->parameters, &encAlg, &hashAlg );
503 if (rv != SECSuccess) {
504 return NULL;
505 }
506 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
507 }
508
509 void
510 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
511 {
512 if (cx) {
513 if (cx->hashcx != NULL) {
514 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
515 cx->hashcx = NULL;
516 }
517 if (cx->key) {
518 SECKEY_DestroyPublicKey(cx->key);
519 }
520 if (cx->pkcs1RSADigestInfo) {
521 PORT_Free(cx->pkcs1RSADigestInfo);
522 }
523 if (freeit) {
524 PORT_ZFree(cx, sizeof(VFYContext));
525 }
526 }
527 }
528
529 SECStatus
530 VFY_Begin(VFYContext *cx)
531 {
532 if (cx->hashcx != NULL) {
533 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
534 cx->hashcx = NULL;
535 }
536
537 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
538 if (!cx->hashobj)
539 return SECFailure; /* error code is set */
540
541 cx->hashcx = (*cx->hashobj->create)();
542 if (cx->hashcx == NULL)
543 return SECFailure;
544
545 (*cx->hashobj->begin)(cx->hashcx);
546 return SECSuccess;
547 }
548
549 SECStatus
550 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
551 {
552 if (cx->hashcx == NULL) {
553 PORT_SetError(SEC_ERROR_INVALID_ARGS);
554 return SECFailure;
555 }
556 (*cx->hashobj->update)(cx->hashcx, input, inputLen);
557 return SECSuccess;
558 }
559
560 SECStatus
561 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
562 {
563 unsigned char final[HASH_LENGTH_MAX];
564 unsigned part;
565 SECItem hash, dsasig; /* dsasig is also used for ECDSA */
566 SECStatus rv;
567
568 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
569 PORT_SetError(SEC_ERROR_INVALID_ARGS);
570 return SECFailure;
571 }
572
573 if (cx->hashcx == NULL) {
574 PORT_SetError(SEC_ERROR_INVALID_ARGS);
575 return SECFailure;
576 }
577 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
578 switch (cx->key->keyType) {
579 case ecKey:
580 case dsaKey:
581 dsasig.data = cx->u.buffer;
582 dsasig.len = SECKEY_SignatureLen(cx->key);
583 if (dsasig.len == 0) {
584 return SECFailure;
585 }
586 if (sig) {
587 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
588 dsasig.len);
589 if (rv != SECSuccess) {
590 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
591 return SECFailure;
592 }
593 }
594 hash.data = final;
595 hash.len = part;
596 if (PK11_Verify(cx->key, &dsasig, &hash, cx->wincx) != SECSuccess) {
597 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
598 return SECFailure;
599 }
600 break;
601 case rsaKey: {
602 SECItem digest;
603 digest.data = final;
604 digest.len = part;
605 if (sig) {
606 SECOidTag hashid;
607 PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
608 rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
609 &cx->pkcs1RSADigestInfo,
610 &cx->pkcs1RSADigestInfoLen,
611 cx->key,
612 sig, cx->wincx);
613 PORT_Assert(cx->hashAlg == hashid);
614 if (rv != SECSuccess) {
615 return SECFailure;
616 }
617 }
618 return verifyPKCS1DigestInfo(cx, &digest);
619 }
620 default:
621 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
622 return SECFailure; /* shouldn't happen */
623 }
624 return SECSuccess;
625 }
626
627 SECStatus
628 VFY_End(VFYContext *cx)
629 {
630 return VFY_EndWithSignature(cx, NULL);
631 }
632
633 /************************************************************************/
634 /*
635 * Verify that a previously-computed digest matches a signature.
636 */
637 static SECStatus
638 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
639 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
640 void *wincx)
641 {
642 SECStatus rv;
643 VFYContext *cx;
644 SECItem dsasig; /* also used for ECDSA */
645
646 rv = SECFailure;
647
648 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
649 if (cx != NULL) {
650 switch (key->keyType) {
651 case rsaKey:
652 rv = verifyPKCS1DigestInfo(cx, digest);
653 break;
654 case dsaKey:
655 case ecKey:
656 dsasig.data = cx->u.buffer;
657 dsasig.len = SECKEY_SignatureLen(cx->key);
658 if (dsasig.len == 0) {
659 break;
660 }
661 if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx) !=
662 SECSuccess) {
663 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
664 } else {
665 rv = SECSuccess;
666 }
667 break;
668 default:
669 break;
670 }
671 VFY_DestroyContext(cx, PR_TRUE);
672 }
673 return rv;
674 }
675
676 SECStatus
677 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
678 const SECItem *sig, SECOidTag encAlg,
679 SECOidTag hashAlg, void *wincx)
680 {
681 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
682 }
683
684 SECStatus
685 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
686 SECOidTag algid, void *wincx)
687 {
688 SECOidTag encAlg, hashAlg;
689 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
690 if (rv != SECSuccess) {
691 return SECFailure;
692 }
693 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
694 }
695
696 /*
697 * this function takes an optional hash oid, which the digest function
698 * will be compared with our target hash value.
699 */
700 SECStatus
701 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
702 const SECKEYPublicKey *key, const SECItem *sig,
703 const SECAlgorithmID *sigAlgorithm,
704 SECOidTag hashCmp, void *wincx)
705 {
706 SECOidTag encAlg, hashAlg;
707 SECStatus rv = sec_DecodeSigAlg(key,
708 SECOID_GetAlgorithmTag((SECAlgorithmID *)sig Algorithm),
709 &sigAlgorithm->parameters, &encAlg, &hashAlg );
710 if (rv != SECSuccess) {
711 return rv;
712 }
713 if (hashCmp != SEC_OID_UNKNOWN &&
714 hashAlg != SEC_OID_UNKNOWN &&
715 hashCmp != hashAlg) {
716 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
717 return SECFailure;
718 }
719 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
720 }
721
722 static SECStatus
723 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
724 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
725 SECOidTag *hash, void *wincx)
726 {
727 SECStatus rv;
728 VFYContext *cx;
729
730 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
731 if (cx == NULL)
732 return SECFailure;
733
734 rv = VFY_Begin(cx);
735 if (rv == SECSuccess) {
736 rv = VFY_Update(cx, (unsigned char *)buf, len);
737 if (rv == SECSuccess)
738 rv = VFY_End(cx);
739 }
740
741 VFY_DestroyContext(cx, PR_TRUE);
742 return rv;
743 }
744
745 SECStatus
746 VFY_VerifyDataDirect(const unsigned char *buf, int len,
747 const SECKEYPublicKey *key, const SECItem *sig,
748 SECOidTag encAlg, SECOidTag hashAlg,
749 SECOidTag *hash, void *wincx)
750 {
751 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
752 }
753
754 SECStatus
755 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
756 const SECItem *sig, SECOidTag algid, void *wincx)
757 {
758 SECOidTag encAlg, hashAlg;
759 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
760 if (rv != SECSuccess) {
761 return rv;
762 }
763 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
764 }
765
766 SECStatus
767 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
768 const SECKEYPublicKey *key,
769 const SECItem *sig,
770 const SECAlgorithmID *sigAlgorithm,
771 SECOidTag *hash, void *wincx)
772 {
773 SECOidTag encAlg, hashAlg;
774 SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
775 SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
776 &sigAlgorithm->parameters, &encAlg, &hashAlg );
777 if (rv != SECSuccess) {
778 return rv;
779 }
780 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
781 }
OLDNEW
« no previous file with comments | « nss/lib/cryptohi/secsign.c ('k') | nss/lib/dev/ckhelper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698