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