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