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