4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Netscape security libraries.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
25 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
40 /* $Id: secvfy.c,v 1.21 2007/01/09 00:37:20 alexei.volkov.bugs%sun.com Exp $ */
54 ** Decrypt signature block using public key
55 ** Store the hash algorithm oid tag in *tagp
56 ** Store the digest in the digest buffer
57 ** Store the digest length in *digestlen
58 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
61 DecryptSigBlock(SECOidTag
*tagp
, unsigned char *digest
,
62 unsigned int *digestlen
, unsigned int maxdigestlen
,
63 SECKEYPublicKey
*key
, const SECItem
*sig
, char *wincx
)
65 SGNDigestInfo
*di
= NULL
;
66 unsigned char *buf
= NULL
;
71 if (key
== NULL
) goto loser
;
73 it
.len
= SECKEY_PublicKeyStrength(key
);
74 if (!it
.len
) goto loser
;
75 it
.data
= buf
= (unsigned char *)PORT_Alloc(it
.len
);
78 /* decrypt the block */
79 rv
= PK11_VerifyRecover(key
, (SECItem
*)sig
, &it
, wincx
);
80 if (rv
!= SECSuccess
) goto loser
;
82 di
= SGN_DecodeDigestInfo(&it
);
83 if (di
== NULL
) goto sigloser
;
86 ** Finally we have the digest info; now we can extract the algorithm
87 ** ID and the signature block
89 tag
= SECOID_GetAlgorithmTag(&di
->digestAlgorithm
);
90 /* Check that tag is an appropriate algorithm */
91 if (tag
== SEC_OID_UNKNOWN
) {
94 /* make sure the "parameters" are not too bogus. */
95 if (di
->digestAlgorithm
.parameters
.len
> 2) {
98 if (di
->digest
.len
> maxdigestlen
) {
99 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
102 PORT_Memcpy(digest
, di
->digest
.data
, di
->digest
.len
);
104 *digestlen
= di
->digest
.len
;
108 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
114 if (di
!= NULL
) SGN_DestroyDigestInfo(di
);
115 if (buf
!= NULL
) PORT_Free(buf
);
121 struct VFYContextStr
{
122 SECOidTag hashAlg
; /* the hash algorithm */
123 SECKEYPublicKey
*key
;
125 * This buffer holds either the digest or the full signature
126 * depending on the type of the signature (key->keyType). It is
127 * defined as a union to make sure it always has enough space.
129 * Use the "buffer" union member to reference the buffer.
130 * Note: do not take the size of the "buffer" union member. Take
131 * the size of the union or some other union member instead.
134 unsigned char buffer
[1];
136 /* the digest in the decrypted RSA signature */
137 unsigned char rsadigest
[HASH_LENGTH_MAX
];
138 /* the full DSA signature... 40 bytes */
139 unsigned char dsasig
[DSA_SIGNATURE_LEN
];
140 /* the full ECDSA signature */
141 unsigned char ecdsasig
[2 * MAX_ECKEY_LEN
];
143 unsigned int rsadigestlen
;
146 const SECHashObject
*hashobj
;
147 SECOidTag encAlg
; /* enc alg */
148 PRBool hasSignature
; /* true if the signature was provided in the
149 * VFY_CreateContext call. If false, the
150 * signature must be provided with a
151 * VFY_EndWithSignature call. */
155 * decode the ECDSA or DSA signature from it's DER wrapping.
156 * The unwrapped/raw signature is placed in the buffer pointed
157 * to by dsig and has enough room for len bytes.
160 decodeECorDSASignature(SECOidTag algid
, const SECItem
*sig
, unsigned char *dsig
,
162 SECItem
*dsasig
= NULL
; /* also used for ECDSA */
163 SECStatus rv
=SECSuccess
;
165 if ((algid
!= SEC_OID_ANSIX9_DSA_SIGNATURE
) &&
166 (algid
!= SEC_OID_ANSIX962_EC_PUBLIC_KEY
) ) {
167 if (sig
->len
!= len
) {
168 PORT_SetError(SEC_ERROR_BAD_DER
);
172 PORT_Memcpy(dsig
, sig
->data
, sig
->len
);
176 if (algid
== SEC_OID_ANSIX962_EC_PUBLIC_KEY
) {
177 if (len
> MAX_ECKEY_LEN
* 2) {
178 PORT_SetError(SEC_ERROR_BAD_DER
);
182 dsasig
= DSAU_DecodeDerSigToLen((SECItem
*)sig
, len
);
184 if ((dsasig
== NULL
) || (dsasig
->len
!= len
)) {
187 PORT_Memcpy(dsig
, dsasig
->data
, dsasig
->len
);
190 if (dsasig
!= NULL
) SECITEM_FreeItem(dsasig
, PR_TRUE
);
191 if (rv
== SECFailure
) PORT_SetError(SEC_ERROR_BAD_DER
);
195 const SEC_ASN1Template hashParameterTemplate
[] =
197 { SEC_ASN1_SEQUENCE
, 0, NULL
, sizeof(SECItem
) },
198 { SEC_ASN1_OBJECT_ID
, 0 },
199 { SEC_ASN1_SKIP_REST
},
204 * Pulls the hash algorithm, signing algorithm, and key type out of a
205 * composite algorithm.
207 * sigAlg: the composite algorithm to dissect.
208 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
209 * encalg: address of a SECOidTag which will be set with the signing alg.
211 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
212 * algorithm was not found or was not a signing algorithm.
215 sec_DecodeSigAlg(const SECKEYPublicKey
*key
, SECOidTag sigAlg
,
216 const SECItem
*param
, SECOidTag
*encalg
, SECOidTag
*hashalg
)
223 PR_ASSERT(hashalg
!=NULL
);
224 PR_ASSERT(encalg
!=NULL
);
227 /* We probably shouldn't be generating MD2 signatures either */
228 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
:
229 *hashalg
= SEC_OID_MD2
;
231 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
:
232 *hashalg
= SEC_OID_MD5
;
234 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
:
235 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE
:
236 *hashalg
= SEC_OID_SHA1
;
238 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
239 *hashalg
= SEC_OID_UNKNOWN
; /* get it from the RSA signature */
242 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE
:
243 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
:
244 *hashalg
= SEC_OID_SHA256
;
246 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE
:
247 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
:
248 *hashalg
= SEC_OID_SHA384
;
250 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE
:
251 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
:
252 *hashalg
= SEC_OID_SHA512
;
255 /* what about normal DSA? */
256 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST
:
257 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST
:
258 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE
:
259 *hashalg
= SEC_OID_SHA1
;
261 case SEC_OID_MISSI_DSS
:
262 case SEC_OID_MISSI_KEA_DSS
:
263 case SEC_OID_MISSI_KEA_DSS_OLD
:
264 case SEC_OID_MISSI_DSS_OLD
:
265 *hashalg
= SEC_OID_SHA1
;
267 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST
:
268 /* This is an EC algorithm. Recommended means the largest
269 * hash algorithm that is not reduced by the keysize of
270 * the EC algorithm. Note that key strength is in bytes and
271 * algorithms are specified in bits. Never use an algorithm
272 * weaker than sha1. */
273 len
= SECKEY_PublicKeyStrength(key
);
274 if (len
< 28) { /* 28 bytes == 224 bits */
275 *hashalg
= SEC_OID_SHA1
;
276 } else if (len
< 32) { /* 32 bytes == 256 bits */
277 /* SHA 224 not supported in NSS */
278 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
280 } else if (len
< 48) { /* 48 bytes == 384 bits */
281 *hashalg
= SEC_OID_SHA256
;
282 } else if (len
< 64) { /* 48 bytes == 512 bits */
283 *hashalg
= SEC_OID_SHA384
;
285 /* use the largest in this case */
286 *hashalg
= SEC_OID_SHA512
;
289 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST
:
291 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
294 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
298 rv
= SEC_QuickDERDecodeItem(arena
, &oid
, hashParameterTemplate
, param
);
299 if (rv
!= SECSuccess
) {
300 PORT_FreeArena(arena
, PR_FALSE
);
303 *hashalg
= SECOID_FindOIDTag(&oid
);
304 /* only accept hash algorithms */
305 if (HASH_GetHashTypeByOidTag(*hashalg
) == HASH_AlgNULL
) {
306 /* error set by HASH_GetHashTypeByOidTag */
310 /* we don't implement MD4 hashes */
311 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
:
313 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
316 /* get the "encryption" algorithm */
318 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
319 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
:
320 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
:
321 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
:
322 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE
:
323 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
:
324 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
:
325 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
:
326 *encalg
= SEC_OID_PKCS1_RSA_ENCRYPTION
;
329 /* what about normal DSA? */
330 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST
:
331 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST
:
332 *encalg
= SEC_OID_ANSIX9_DSA_SIGNATURE
;
334 case SEC_OID_MISSI_DSS
:
335 case SEC_OID_MISSI_KEA_DSS
:
336 case SEC_OID_MISSI_KEA_DSS_OLD
:
337 case SEC_OID_MISSI_DSS_OLD
:
338 *encalg
= SEC_OID_MISSI_DSS
;
340 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE
:
341 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE
:
342 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE
:
343 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE
:
344 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST
:
345 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST
:
346 *encalg
= SEC_OID_ANSIX962_EC_PUBLIC_KEY
;
348 /* we don't implement MD4 hashes */
349 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
:
351 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
358 * we can verify signatures that come from 2 different sources:
359 * one in with the signature contains a signature oid, and the other
360 * in which the signature is managed by a Public key (encAlg) oid
361 * and a hash oid. The latter is the more basic, so that's what
362 * our base vfyCreate function takes.
364 * There is one noteworthy corner case, if we are using an RSA key, and the
365 * signature block is provided, then the hashAlg can be specified as
366 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
367 * in the RSA signature block.
370 vfy_CreateContext(const SECKEYPublicKey
*key
, const SECItem
*sig
,
371 SECOidTag encAlg
, SECOidTag hashAlg
, SECOidTag
*hash
, void *wincx
)
378 /* make sure the encryption algorithm matches the key type */
379 type
= seckey_GetKeyType(encAlg
);
380 if (key
->keyType
!= type
) {
381 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH
);
385 cx
= (VFYContext
*) PORT_ZAlloc(sizeof(VFYContext
));
391 cx
->hasSignature
= (sig
!= NULL
);
393 cx
->hashAlg
= hashAlg
;
394 cx
->key
= SECKEY_CopyPublicKey(key
);
397 switch (key
->keyType
) {
399 rv
= DecryptSigBlock(&cx
->hashAlg
, cx
->u
.buffer
, &cx
->rsadigestlen
,
400 HASH_LENGTH_MAX
, cx
->key
, sig
, (char*)wincx
);
401 if (cx
->hashAlg
!= hashAlg
&& hashAlg
!= SEC_OID_UNKNOWN
) {
402 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
408 sigLen
= SECKEY_SignatureLen(key
);
410 /* error set by SECKEY_SignatureLen */
414 rv
= decodeECorDSASignature(encAlg
, sig
, cx
->u
.buffer
, sigLen
);
418 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG
);
425 /* check hash alg again, RSA may have changed it.*/
426 if (HASH_GetHashTypeByOidTag(cx
->hashAlg
) == HASH_AlgNULL
) {
427 /* error set by HASH_GetHashTypeByOidTag */
438 VFY_DestroyContext(cx
, PR_TRUE
);
444 VFY_CreateContext(SECKEYPublicKey
*key
, SECItem
*sig
, SECOidTag sigAlg
,
447 SECOidTag encAlg
, hashAlg
;
448 SECStatus rv
= sec_DecodeSigAlg(key
, sigAlg
, NULL
, &encAlg
, &hashAlg
);
449 if (rv
!= SECSuccess
) {
452 return vfy_CreateContext(key
, sig
, encAlg
, hashAlg
, NULL
, wincx
);
456 VFY_CreateContextDirect(const SECKEYPublicKey
*key
, const SECItem
*sig
,
457 SECOidTag encAlg
, SECOidTag hashAlg
,
458 SECOidTag
*hash
, void *wincx
)
460 return vfy_CreateContext(key
, sig
, encAlg
, hashAlg
, hash
, wincx
);
464 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey
*key
, const SECItem
*sig
,
465 const SECAlgorithmID
*sigAlgorithm
, SECOidTag
*hash
, void *wincx
)
467 SECOidTag encAlg
, hashAlg
;
468 SECStatus rv
= sec_DecodeSigAlg(key
,
469 SECOID_GetAlgorithmTag((SECAlgorithmID
*)sigAlgorithm
),
470 &sigAlgorithm
->parameters
, &encAlg
, &hashAlg
);
471 if (rv
!= SECSuccess
) {
474 return vfy_CreateContext(key
, sig
, encAlg
, hashAlg
, hash
, wincx
);
478 VFY_DestroyContext(VFYContext
*cx
, PRBool freeit
)
481 if (cx
->hashcx
!= NULL
) {
482 (*cx
->hashobj
->destroy
)(cx
->hashcx
, PR_TRUE
);
486 SECKEY_DestroyPublicKey(cx
->key
);
489 PORT_ZFree(cx
, sizeof(VFYContext
));
495 VFY_Begin(VFYContext
*cx
)
497 if (cx
->hashcx
!= NULL
) {
498 (*cx
->hashobj
->destroy
)(cx
->hashcx
, PR_TRUE
);
502 cx
->hashobj
= HASH_GetHashObjectByOidTag(cx
->hashAlg
);
504 return SECFailure
; /* error code is set */
506 cx
->hashcx
= (*cx
->hashobj
->create
)();
507 if (cx
->hashcx
== NULL
)
510 (*cx
->hashobj
->begin
)(cx
->hashcx
);
515 VFY_Update(VFYContext
*cx
, const unsigned char *input
, unsigned inputLen
)
517 if (cx
->hashcx
== NULL
) {
518 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
521 (*cx
->hashobj
->update
)(cx
->hashcx
, input
, inputLen
);
526 VFY_EndWithSignature(VFYContext
*cx
, SECItem
*sig
)
528 unsigned char final
[HASH_LENGTH_MAX
];
530 SECItem hash
,dsasig
; /* dsasig is also used for ECDSA */
533 if ((cx
->hasSignature
== PR_FALSE
) && (sig
== NULL
)) {
534 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
538 if (cx
->hashcx
== NULL
) {
539 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
542 (*cx
->hashobj
->end
)(cx
->hashcx
, final
, &part
, sizeof(final
));
543 switch (cx
->key
->keyType
) {
546 dsasig
.data
= cx
->u
.buffer
;
547 dsasig
.len
= SECKEY_SignatureLen(cx
->key
);
548 if (dsasig
.len
== 0) {
552 rv
= decodeECorDSASignature(cx
->encAlg
, sig
, dsasig
.data
,
554 if (rv
!= SECSuccess
) {
555 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
561 if (PK11_Verify(cx
->key
,&dsasig
,&hash
,cx
->wincx
) != SECSuccess
) {
562 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
568 SECOidTag hashid
= SEC_OID_UNKNOWN
;
569 rv
= DecryptSigBlock(&hashid
, cx
->u
.buffer
, &cx
->rsadigestlen
,
570 HASH_LENGTH_MAX
, cx
->key
, sig
, (char*)cx
->wincx
);
571 if ((rv
!= SECSuccess
) || (hashid
!= cx
->hashAlg
)) {
572 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
576 if ((part
!= cx
->rsadigestlen
) ||
577 PORT_Memcmp(final
, cx
->u
.buffer
, part
)) {
578 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
583 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
584 return SECFailure
; /* shouldn't happen */
590 VFY_End(VFYContext
*cx
)
592 return VFY_EndWithSignature(cx
,NULL
);
595 /************************************************************************/
597 * Verify that a previously-computed digest matches a signature.
600 vfy_VerifyDigest(const SECItem
*digest
, const SECKEYPublicKey
*key
,
601 const SECItem
*sig
, SECOidTag encAlg
, SECOidTag hashAlg
,
606 SECItem dsasig
; /* also used for ECDSA */
610 cx
= vfy_CreateContext(key
, sig
, encAlg
, hashAlg
, NULL
, wincx
);
612 switch (key
->keyType
) {
614 if ((digest
->len
!= cx
->rsadigestlen
) ||
615 PORT_Memcmp(digest
->data
, cx
->u
.buffer
, digest
->len
)) {
616 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
623 dsasig
.data
= cx
->u
.buffer
;
624 dsasig
.len
= SECKEY_SignatureLen(cx
->key
);
625 if (dsasig
.len
== 0) {
628 if (PK11_Verify(cx
->key
, &dsasig
, (SECItem
*)digest
, cx
->wincx
)
630 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
638 VFY_DestroyContext(cx
, PR_TRUE
);
644 VFY_VerifyDigestDirect(const SECItem
*digest
, const SECKEYPublicKey
*key
,
645 const SECItem
*sig
, SECOidTag encAlg
,
646 SECOidTag hashAlg
, void *wincx
)
648 return vfy_VerifyDigest(digest
, key
, sig
, encAlg
, hashAlg
, wincx
);
652 VFY_VerifyDigest(SECItem
*digest
, SECKEYPublicKey
*key
, SECItem
*sig
,
653 SECOidTag algid
, void *wincx
)
655 SECOidTag encAlg
, hashAlg
;
656 SECStatus rv
= sec_DecodeSigAlg(key
, algid
, NULL
, &encAlg
, &hashAlg
);
657 if (rv
!= SECSuccess
) {
660 return vfy_VerifyDigest(digest
, key
, sig
, encAlg
, hashAlg
, wincx
);
664 * this function takes an optional hash oid, which the digest function
665 * will be compared with our target hash value.
668 VFY_VerifyDigestWithAlgorithmID(const SECItem
*digest
,
669 const SECKEYPublicKey
*key
, const SECItem
*sig
,
670 const SECAlgorithmID
*sigAlgorithm
,
671 SECOidTag hashCmp
, void *wincx
)
673 SECOidTag encAlg
, hashAlg
;
674 SECStatus rv
= sec_DecodeSigAlg(key
,
675 SECOID_GetAlgorithmTag((SECAlgorithmID
*)sigAlgorithm
),
676 &sigAlgorithm
->parameters
, &encAlg
, &hashAlg
);
677 if (rv
!= SECSuccess
) {
680 if ( hashCmp
!= SEC_OID_UNKNOWN
&&
681 hashAlg
!= SEC_OID_UNKNOWN
&&
682 hashCmp
!= hashAlg
) {
683 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
686 return vfy_VerifyDigest(digest
, key
, sig
, encAlg
, hashAlg
, wincx
);
690 vfy_VerifyData(const unsigned char *buf
, int len
, const SECKEYPublicKey
*key
,
691 const SECItem
*sig
, SECOidTag encAlg
, SECOidTag hashAlg
,
692 SECOidTag
*hash
, void *wincx
)
697 cx
= vfy_CreateContext(key
, sig
, encAlg
, hashAlg
, hash
, wincx
);
702 if (rv
== SECSuccess
) {
703 rv
= VFY_Update(cx
, (unsigned char *)buf
, len
);
704 if (rv
== SECSuccess
)
708 VFY_DestroyContext(cx
, PR_TRUE
);
713 VFY_VerifyDataDirect(const unsigned char *buf
, int len
,
714 const SECKEYPublicKey
*key
, const SECItem
*sig
,
715 SECOidTag encAlg
, SECOidTag hashAlg
,
716 SECOidTag
*hash
, void *wincx
)
718 return vfy_VerifyData(buf
, len
, key
, sig
, encAlg
, hashAlg
, hash
, wincx
);
722 VFY_VerifyData(unsigned char *buf
, int len
, SECKEYPublicKey
*key
,
723 SECItem
*sig
, SECOidTag algid
, void *wincx
)
725 SECOidTag encAlg
, hashAlg
;
726 SECStatus rv
= sec_DecodeSigAlg(key
, algid
, NULL
, &encAlg
, &hashAlg
);
727 if (rv
!= SECSuccess
) {
730 return vfy_VerifyData(buf
, len
, key
, sig
, encAlg
, hashAlg
, NULL
, wincx
);
734 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf
, int len
,
735 const SECKEYPublicKey
*key
,
737 const SECAlgorithmID
*sigAlgorithm
,
738 SECOidTag
*hash
, void *wincx
)
740 SECOidTag encAlg
, hashAlg
;
741 SECStatus rv
= sec_DecodeSigAlg(key
,
742 SECOID_GetAlgorithmTag((SECAlgorithmID
*)sigAlgorithm
),
743 &sigAlgorithm
->parameters
, &encAlg
, &hashAlg
);
744 if (rv
!= SECSuccess
) {
747 return vfy_VerifyData(buf
, len
, key
, sig
, encAlg
, hashAlg
, hash
, wincx
);