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
recoverPKCS1DigestInfo(SECOidTag givenDigestAlg,SECOidTag * digestAlgOut,unsigned char ** digestInfo,unsigned int * digestInfoLen,SECKEYPublicKey * key,const SECItem * sig,void * wincx)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 /* the full RSA signature, only used in RSA-PSS */
140 unsigned char rsasig[(RSA_MAX_MODULUS_BITS + 7) / 8];
141 } u;
142 unsigned int pkcs1RSADigestInfoLen;
143 /* the encoded DigestInfo from a RSA PKCS#1 signature */
144 unsigned char *pkcs1RSADigestInfo;
145 void *wincx;
146 void *hashcx;
147 const SECHashObject *hashobj;
148 SECOidTag encAlg; /* enc alg */
149 PRBool hasSignature; /* true if the signature was provided in the
150 * VFY_CreateContext call. If false, the
151 * signature must be provided with a
152 * VFY_EndWithSignature call. */
153 SECItem *params;
154 };
155
156 static SECStatus
verifyPKCS1DigestInfo(const VFYContext * cx,const SECItem * digest)157 verifyPKCS1DigestInfo(const VFYContext *cx, const SECItem *digest)
158 {
159 SECItem pkcs1DigestInfo;
160 pkcs1DigestInfo.data = cx->pkcs1RSADigestInfo;
161 pkcs1DigestInfo.len = cx->pkcs1RSADigestInfoLen;
162 return _SGN_VerifyPKCS1DigestInfo(
163 cx->hashAlg, digest, &pkcs1DigestInfo,
164 PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
165 }
166
167 static unsigned int
checkedSignatureLen(const SECKEYPublicKey * pubk)168 checkedSignatureLen(const SECKEYPublicKey *pubk)
169 {
170 unsigned int sigLen = SECKEY_SignatureLen(pubk);
171 if (sigLen == 0) {
172 /* Error set by SECKEY_SignatureLen */
173 return sigLen;
174 }
175 unsigned int maxSigLen;
176 switch (pubk->keyType) {
177 case rsaKey:
178 case rsaPssKey:
179 maxSigLen = (RSA_MAX_MODULUS_BITS + 7) / 8;
180 break;
181 case dsaKey:
182 maxSigLen = DSA_MAX_SIGNATURE_LEN;
183 break;
184 case ecKey:
185 maxSigLen = 2 * MAX_ECKEY_LEN;
186 break;
187 default:
188 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
189 return 0;
190 }
191 if (sigLen > maxSigLen) {
192 PORT_SetError(SEC_ERROR_INVALID_KEY);
193 return 0;
194 }
195 return sigLen;
196 }
197
198 /*
199 * decode the ECDSA or DSA signature from it's DER wrapping.
200 * The unwrapped/raw signature is placed in the buffer pointed
201 * to by dsig and has enough room for len bytes.
202 */
203 static SECStatus
decodeECorDSASignature(SECOidTag algid,const SECItem * sig,unsigned char * dsig,unsigned int len)204 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
205 unsigned int len)
206 {
207 SECItem *dsasig = NULL; /* also used for ECDSA */
208
209 /* Safety: Ensure algId is as expected and that signature size is within maxmimums */
210 if (algid == SEC_OID_ANSIX9_DSA_SIGNATURE) {
211 if (len > DSA_MAX_SIGNATURE_LEN) {
212 goto loser;
213 }
214 } else if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
215 if (len > MAX_ECKEY_LEN * 2) {
216 goto loser;
217 }
218 } else {
219 goto loser;
220 }
221
222 /* Decode and pad to length */
223 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
224 if (dsasig == NULL) {
225 goto loser;
226 }
227 if (dsasig->len != len) {
228 SECITEM_FreeItem(dsasig, PR_TRUE);
229 goto loser;
230 }
231
232 PORT_Memcpy(dsig, dsasig->data, len);
233 SECITEM_FreeItem(dsasig, PR_TRUE);
234
235 return SECSuccess;
236
237 loser:
238 PORT_SetError(SEC_ERROR_BAD_DER);
239 return SECFailure;
240 }
241
242 const SEC_ASN1Template hashParameterTemplate[] =
243 {
244 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
245 { SEC_ASN1_OBJECT_ID, 0 },
246 { SEC_ASN1_SKIP_REST },
247 { 0 }
248 };
249
250 /*
251 * Get just the encryption algorithm from the signature algorithm
252 */
253 SECOidTag
sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)254 sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)
255 {
256 /* get the "encryption" algorithm */
257 switch (sigAlg) {
258 case SEC_OID_PKCS1_RSA_ENCRYPTION:
259 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
260 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
261 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
262 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
263 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
264 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
265 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
266 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
267 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
268 return SEC_OID_PKCS1_RSA_ENCRYPTION;
269 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
270 return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
271
272 /* what about normal DSA? */
273 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
274 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
275 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
276 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
277 return SEC_OID_ANSIX9_DSA_SIGNATURE;
278 case SEC_OID_MISSI_DSS:
279 case SEC_OID_MISSI_KEA_DSS:
280 case SEC_OID_MISSI_KEA_DSS_OLD:
281 case SEC_OID_MISSI_DSS_OLD:
282 return SEC_OID_MISSI_DSS;
283 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
284 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
285 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
286 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
287 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
288 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
289 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
290 return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
291 /* we don't implement MD4 hashes */
292 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
293 default:
294 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
295 break;
296 }
297 return SEC_OID_UNKNOWN;
298 }
299
300 /*
301 * Pulls the hash algorithm, signing algorithm, and key type out of a
302 * composite algorithm.
303 *
304 * sigAlg: the composite algorithm to dissect.
305 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
306 * encalg: address of a SECOidTag which will be set with the signing alg.
307 *
308 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
309 * algorithm was not found or was not a signing algorithm.
310 */
311 SECStatus
sec_DecodeSigAlg(const SECKEYPublicKey * key,SECOidTag sigAlg,const SECItem * param,SECOidTag * encalgp,SECOidTag * hashalg)312 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
313 const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg)
314 {
315 unsigned int len;
316 PLArenaPool *arena;
317 SECStatus rv;
318 SECItem oid;
319 SECOidTag encalg;
320
321 PR_ASSERT(hashalg != NULL);
322 PR_ASSERT(encalgp != NULL);
323
324 switch (sigAlg) {
325 /* We probably shouldn't be generating MD2 signatures either */
326 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
327 *hashalg = SEC_OID_MD2;
328 break;
329 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
330 *hashalg = SEC_OID_MD5;
331 break;
332 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
333 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
334 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
335 *hashalg = SEC_OID_SHA1;
336 break;
337 case SEC_OID_PKCS1_RSA_ENCRYPTION:
338 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
339 break;
340 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
341 if (param && param->data) {
342 PORTCheapArenaPool tmpArena;
343
344 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
345 rv = sec_DecodeRSAPSSParams(&tmpArena.arena, param,
346 hashalg, NULL, NULL);
347 PORT_DestroyCheapArena(&tmpArena);
348
349 /* only accept hash algorithms */
350 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
351 /* error set by HASH_GetHashTypeByOidTag */
352 return SECFailure;
353 }
354 } else {
355 *hashalg = SEC_OID_SHA1; /* default, SHA-1 */
356 }
357 break;
358
359 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
360 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
361 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
362 *hashalg = SEC_OID_SHA224;
363 break;
364 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
365 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
366 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
367 *hashalg = SEC_OID_SHA256;
368 break;
369 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
370 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
371 *hashalg = SEC_OID_SHA384;
372 break;
373 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
374 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
375 *hashalg = SEC_OID_SHA512;
376 break;
377
378 /* what about normal DSA? */
379 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
380 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
381 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
382 *hashalg = SEC_OID_SHA1;
383 break;
384 case SEC_OID_MISSI_DSS:
385 case SEC_OID_MISSI_KEA_DSS:
386 case SEC_OID_MISSI_KEA_DSS_OLD:
387 case SEC_OID_MISSI_DSS_OLD:
388 *hashalg = SEC_OID_SHA1;
389 break;
390 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
391 /* This is an EC algorithm. Recommended means the largest
392 * hash algorithm that is not reduced by the keysize of
393 * the EC algorithm. Note that key strength is in bytes and
394 * algorithms are specified in bits. Never use an algorithm
395 * weaker than sha1. */
396 len = SECKEY_PublicKeyStrength(key);
397 if (len < 28) { /* 28 bytes == 224 bits */
398 *hashalg = SEC_OID_SHA1;
399 } else if (len < 32) { /* 32 bytes == 256 bits */
400 *hashalg = SEC_OID_SHA224;
401 } else if (len < 48) { /* 48 bytes == 384 bits */
402 *hashalg = SEC_OID_SHA256;
403 } else if (len < 64) { /* 48 bytes == 512 bits */
404 *hashalg = SEC_OID_SHA384;
405 } else {
406 /* use the largest in this case */
407 *hashalg = SEC_OID_SHA512;
408 }
409 break;
410 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
411 if (param == NULL) {
412 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
413 return SECFailure;
414 }
415 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
416 if (arena == NULL) {
417 return SECFailure;
418 }
419 rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
420 if (rv == SECSuccess) {
421 *hashalg = SECOID_FindOIDTag(&oid);
422 }
423 PORT_FreeArena(arena, PR_FALSE);
424 if (rv != SECSuccess) {
425 return rv;
426 }
427 /* only accept hash algorithms */
428 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
429 /* error set by HASH_GetHashTypeByOidTag */
430 return SECFailure;
431 }
432 break;
433 /* we don't implement MD4 hashes */
434 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
435 default:
436 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
437 return SECFailure;
438 }
439
440 encalg = sec_GetEncAlgFromSigAlg(sigAlg);
441 if (encalg == SEC_OID_UNKNOWN) {
442 return SECFailure;
443 }
444 *encalgp = encalg;
445
446 return SECSuccess;
447 }
448
449 /*
450 * we can verify signatures that come from 2 different sources:
451 * one in with the signature contains a signature oid, and the other
452 * in which the signature is managed by a Public key (encAlg) oid
453 * and a hash oid. The latter is the more basic, so that's what
454 * our base vfyCreate function takes.
455 *
456 * There is one noteworthy corner case, if we are using an RSA key, and the
457 * signature block is provided, then the hashAlg can be specified as
458 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
459 * in the RSA signature block.
460 */
461 static VFYContext *
vfy_CreateContext(const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,SECOidTag * hash,void * wincx)462 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
463 SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
464 {
465 VFYContext *cx;
466 SECStatus rv;
467 unsigned int sigLen;
468 KeyType type;
469 PRUint32 policyFlags;
470
471 /* make sure the encryption algorithm matches the key type */
472 /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
473 type = seckey_GetKeyType(encAlg);
474 if ((key->keyType != type) &&
475 ((key->keyType != rsaKey) || (type != rsaPssKey))) {
476 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
477 return NULL;
478 }
479
480 /* check the policy on the encryption algorithm */
481 if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) ||
482 !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
483 PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
484 return NULL;
485 }
486
487 cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
488 if (cx == NULL) {
489 goto loser;
490 }
491
492 cx->wincx = wincx;
493 cx->hasSignature = (sig != NULL);
494 cx->encAlg = encAlg;
495 cx->hashAlg = hashAlg;
496 cx->key = SECKEY_CopyPublicKey(key);
497 cx->pkcs1RSADigestInfo = NULL;
498 rv = SECSuccess;
499 if (sig) {
500 rv = SECFailure;
501 if (type == rsaKey) {
502 rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
503 &cx->pkcs1RSADigestInfo,
504 &cx->pkcs1RSADigestInfoLen,
505 cx->key,
506 sig, wincx);
507 } else {
508 sigLen = checkedSignatureLen(key);
509 /* Check signature length is within limits */
510 if (sigLen == 0) {
511 /* error set by checkedSignatureLen */
512 rv = SECFailure;
513 goto loser;
514 }
515 if (sigLen > sizeof(cx->u)) {
516 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
517 rv = SECFailure;
518 goto loser;
519 }
520 switch (type) {
521 case rsaPssKey:
522 if (sig->len != sigLen) {
523 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
524 rv = SECFailure;
525 goto loser;
526 }
527 PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
528 rv = SECSuccess;
529 break;
530 case ecKey:
531 case dsaKey:
532 /* decodeECorDSASignature will check sigLen == sig->len after padding */
533 rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
534 break;
535 default:
536 /* Unreachable */
537 rv = SECFailure;
538 goto loser;
539 }
540 }
541 if (rv != SECSuccess) {
542 goto loser;
543 }
544 }
545
546 /* check hash alg again, RSA may have changed it.*/
547 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
548 /* error set by HASH_GetHashTypeByOidTag */
549 goto loser;
550 }
551 /* check the policy on the hash algorithm. Do this after
552 * the rsa decode because some uses of this function get hash implicitly
553 * from the RSA signature itself. */
554 if ((NSS_GetAlgorithmPolicy(cx->hashAlg, &policyFlags) == SECFailure) ||
555 !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
556 PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
557 goto loser;
558 }
559
560 if (hash) {
561 *hash = cx->hashAlg;
562 }
563 return cx;
564
565 loser:
566 if (cx) {
567 VFY_DestroyContext(cx, PR_TRUE);
568 }
569 return 0;
570 }
571
572 VFYContext *
VFY_CreateContext(SECKEYPublicKey * key,SECItem * sig,SECOidTag sigAlg,void * wincx)573 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
574 void *wincx)
575 {
576 SECOidTag encAlg, hashAlg;
577 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
578 if (rv != SECSuccess) {
579 return NULL;
580 }
581 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
582 }
583
584 VFYContext *
VFY_CreateContextDirect(const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,SECOidTag * hash,void * wincx)585 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
586 SECOidTag encAlg, SECOidTag hashAlg,
587 SECOidTag *hash, void *wincx)
588 {
589 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
590 }
591
592 VFYContext *
VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey * key,const SECItem * sig,const SECAlgorithmID * sigAlgorithm,SECOidTag * hash,void * wincx)593 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
594 const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
595 {
596 VFYContext *cx;
597 SECOidTag encAlg, hashAlg;
598 SECStatus rv = sec_DecodeSigAlg(key,
599 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
600 &sigAlgorithm->parameters, &encAlg, &hashAlg);
601 if (rv != SECSuccess) {
602 return NULL;
603 }
604
605 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
606 if (sigAlgorithm->parameters.data) {
607 cx->params = SECITEM_DupItem(&sigAlgorithm->parameters);
608 }
609
610 return cx;
611 }
612
613 void
VFY_DestroyContext(VFYContext * cx,PRBool freeit)614 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
615 {
616 if (cx) {
617 if (cx->hashcx != NULL) {
618 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
619 cx->hashcx = NULL;
620 }
621 if (cx->key) {
622 SECKEY_DestroyPublicKey(cx->key);
623 }
624 if (cx->pkcs1RSADigestInfo) {
625 PORT_Free(cx->pkcs1RSADigestInfo);
626 }
627 if (cx->params) {
628 SECITEM_FreeItem(cx->params, PR_TRUE);
629 }
630 if (freeit) {
631 PORT_ZFree(cx, sizeof(VFYContext));
632 }
633 }
634 }
635
636 SECStatus
VFY_Begin(VFYContext * cx)637 VFY_Begin(VFYContext *cx)
638 {
639 if (cx->hashcx != NULL) {
640 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
641 cx->hashcx = NULL;
642 }
643
644 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
645 if (!cx->hashobj)
646 return SECFailure; /* error code is set */
647
648 cx->hashcx = (*cx->hashobj->create)();
649 if (cx->hashcx == NULL)
650 return SECFailure;
651
652 (*cx->hashobj->begin)(cx->hashcx);
653 return SECSuccess;
654 }
655
656 SECStatus
VFY_Update(VFYContext * cx,const unsigned char * input,unsigned inputLen)657 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
658 {
659 if (cx->hashcx == NULL) {
660 PORT_SetError(SEC_ERROR_INVALID_ARGS);
661 return SECFailure;
662 }
663 (*cx->hashobj->update)(cx->hashcx, input, inputLen);
664 return SECSuccess;
665 }
666
667 SECStatus
VFY_EndWithSignature(VFYContext * cx,SECItem * sig)668 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
669 {
670 unsigned char final[HASH_LENGTH_MAX];
671 unsigned part;
672 SECItem hash, rsasig, dsasig; /* dsasig is also used for ECDSA */
673 SECStatus rv;
674
675 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
676 PORT_SetError(SEC_ERROR_INVALID_ARGS);
677 return SECFailure;
678 }
679
680 if (cx->hashcx == NULL) {
681 PORT_SetError(SEC_ERROR_INVALID_ARGS);
682 return SECFailure;
683 }
684 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
685 switch (cx->key->keyType) {
686 case ecKey:
687 case dsaKey:
688 dsasig.len = checkedSignatureLen(cx->key);
689 if (dsasig.len == 0) {
690 return SECFailure;
691 }
692 if (dsasig.len > sizeof(cx->u)) {
693 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
694 return SECFailure;
695 }
696 dsasig.data = cx->u.buffer;
697
698 if (sig) {
699 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
700 dsasig.len);
701 if (rv != SECSuccess) {
702 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
703 return SECFailure;
704 }
705 }
706 hash.data = final;
707 hash.len = part;
708 if (PK11_Verify(cx->key, &dsasig, &hash, cx->wincx) != SECSuccess) {
709 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
710 return SECFailure;
711 }
712 break;
713 case rsaKey:
714 if (cx->encAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
715 CK_RSA_PKCS_PSS_PARAMS mech;
716 SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) };
717 PORTCheapArenaPool tmpArena;
718
719 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
720 rv = sec_DecodeRSAPSSParamsToMechanism(&tmpArena.arena,
721 cx->params,
722 &mech);
723 PORT_DestroyCheapArena(&tmpArena);
724 if (rv != SECSuccess) {
725 return SECFailure;
726 }
727
728 rsasig.data = cx->u.buffer;
729 rsasig.len = checkedSignatureLen(cx->key);
730 if (rsasig.len == 0) {
731 /* Error set by checkedSignatureLen */
732 return SECFailure;
733 }
734 if (rsasig.len > sizeof(cx->u)) {
735 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
736 return SECFailure;
737 }
738 if (sig) {
739 if (sig->len != rsasig.len) {
740 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
741 return SECFailure;
742 }
743 PORT_Memcpy(rsasig.data, sig->data, rsasig.len);
744 }
745 hash.data = final;
746 hash.len = part;
747 if (PK11_VerifyWithMechanism(cx->key, CKM_RSA_PKCS_PSS, &mechItem,
748 &rsasig, &hash, cx->wincx) != SECSuccess) {
749 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
750 return SECFailure;
751 }
752 } else {
753 SECItem digest;
754 digest.data = final;
755 digest.len = part;
756 if (sig) {
757 SECOidTag hashid;
758 PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
759 rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
760 &cx->pkcs1RSADigestInfo,
761 &cx->pkcs1RSADigestInfoLen,
762 cx->key,
763 sig, cx->wincx);
764 if (rv != SECSuccess) {
765 return SECFailure;
766 }
767 PORT_Assert(cx->hashAlg == hashid);
768 }
769 return verifyPKCS1DigestInfo(cx, &digest);
770 }
771 break;
772 default:
773 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
774 return SECFailure; /* shouldn't happen */
775 }
776 return SECSuccess;
777 }
778
779 SECStatus
VFY_End(VFYContext * cx)780 VFY_End(VFYContext *cx)
781 {
782 return VFY_EndWithSignature(cx, NULL);
783 }
784
785 /************************************************************************/
786 /*
787 * Verify that a previously-computed digest matches a signature.
788 */
789 static SECStatus
vfy_VerifyDigest(const SECItem * digest,const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,void * wincx)790 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
791 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
792 void *wincx)
793 {
794 SECStatus rv;
795 VFYContext *cx;
796 SECItem dsasig; /* also used for ECDSA */
797 rv = SECFailure;
798
799 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
800 if (cx != NULL) {
801 switch (key->keyType) {
802 case rsaKey:
803 rv = verifyPKCS1DigestInfo(cx, digest);
804 /* Error (if any) set by verifyPKCS1DigestInfo */
805 break;
806 case ecKey:
807 case dsaKey:
808 dsasig.data = cx->u.buffer;
809 dsasig.len = checkedSignatureLen(cx->key);
810 if (dsasig.len == 0) {
811 /* Error set by checkedSignatureLen */
812 rv = SECFailure;
813 break;
814 }
815 if (dsasig.len > sizeof(cx->u)) {
816 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
817 rv = SECFailure;
818 break;
819 }
820 rv = PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx);
821 if (rv != SECSuccess) {
822 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
823 }
824 break;
825 default:
826 break;
827 }
828 VFY_DestroyContext(cx, PR_TRUE);
829 }
830 return rv;
831 }
832
833 SECStatus
VFY_VerifyDigestDirect(const SECItem * digest,const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,void * wincx)834 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
835 const SECItem *sig, SECOidTag encAlg,
836 SECOidTag hashAlg, void *wincx)
837 {
838 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
839 }
840
841 SECStatus
VFY_VerifyDigest(SECItem * digest,SECKEYPublicKey * key,SECItem * sig,SECOidTag algid,void * wincx)842 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
843 SECOidTag algid, void *wincx)
844 {
845 SECOidTag encAlg, hashAlg;
846 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
847 if (rv != SECSuccess) {
848 return SECFailure;
849 }
850 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
851 }
852
853 /*
854 * this function takes an optional hash oid, which the digest function
855 * will be compared with our target hash value.
856 */
857 SECStatus
VFY_VerifyDigestWithAlgorithmID(const SECItem * digest,const SECKEYPublicKey * key,const SECItem * sig,const SECAlgorithmID * sigAlgorithm,SECOidTag hashCmp,void * wincx)858 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
859 const SECKEYPublicKey *key, const SECItem *sig,
860 const SECAlgorithmID *sigAlgorithm,
861 SECOidTag hashCmp, void *wincx)
862 {
863 SECOidTag encAlg, hashAlg;
864 SECStatus rv = sec_DecodeSigAlg(key,
865 SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
866 &sigAlgorithm->parameters, &encAlg, &hashAlg);
867 if (rv != SECSuccess) {
868 return rv;
869 }
870 if (hashCmp != SEC_OID_UNKNOWN &&
871 hashAlg != SEC_OID_UNKNOWN &&
872 hashCmp != hashAlg) {
873 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
874 return SECFailure;
875 }
876 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
877 }
878
879 static SECStatus
vfy_VerifyData(const unsigned char * buf,int len,const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,const SECItem * params,SECOidTag * hash,void * wincx)880 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
881 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
882 const SECItem *params, SECOidTag *hash, void *wincx)
883 {
884 SECStatus rv;
885 VFYContext *cx;
886
887 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
888 if (cx == NULL)
889 return SECFailure;
890 if (params) {
891 cx->params = SECITEM_DupItem(params);
892 }
893
894 rv = VFY_Begin(cx);
895 if (rv == SECSuccess) {
896 rv = VFY_Update(cx, (unsigned char *)buf, len);
897 if (rv == SECSuccess)
898 rv = VFY_End(cx);
899 }
900
901 VFY_DestroyContext(cx, PR_TRUE);
902 return rv;
903 }
904
905 SECStatus
VFY_VerifyDataDirect(const unsigned char * buf,int len,const SECKEYPublicKey * key,const SECItem * sig,SECOidTag encAlg,SECOidTag hashAlg,SECOidTag * hash,void * wincx)906 VFY_VerifyDataDirect(const unsigned char *buf, int len,
907 const SECKEYPublicKey *key, const SECItem *sig,
908 SECOidTag encAlg, SECOidTag hashAlg,
909 SECOidTag *hash, void *wincx)
910 {
911 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, hash, wincx);
912 }
913
914 SECStatus
VFY_VerifyData(const unsigned char * buf,int len,const SECKEYPublicKey * key,const SECItem * sig,SECOidTag algid,void * wincx)915 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
916 const SECItem *sig, SECOidTag algid, void *wincx)
917 {
918 SECOidTag encAlg, hashAlg;
919 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
920 if (rv != SECSuccess) {
921 return rv;
922 }
923 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, NULL, wincx);
924 }
925
926 SECStatus
VFY_VerifyDataWithAlgorithmID(const unsigned char * buf,int len,const SECKEYPublicKey * key,const SECItem * sig,const SECAlgorithmID * sigAlgorithm,SECOidTag * hash,void * wincx)927 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
928 const SECKEYPublicKey *key,
929 const SECItem *sig,
930 const SECAlgorithmID *sigAlgorithm,
931 SECOidTag *hash, void *wincx)
932 {
933 SECOidTag encAlg, hashAlg;
934 SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
935 SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
936 &sigAlgorithm->parameters, &encAlg, &hashAlg);
937 if (rv != SECSuccess) {
938 return rv;
939 }
940 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
941 &sigAlgorithm->parameters, hash, wincx);
942 }
943