Back to index

lightning-sunbird  0.9+nobinonly
secvfy.c
Go to the documentation of this file.
00001 /*
00002  * Verification stuff.
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is the Netscape security libraries.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 /* $Id: secvfy.c,v 1.16.2.5 2006/09/09 22:14:56 wtchang%redhat.com Exp $ */
00041 
00042 #include <stdio.h>
00043 #include "cryptohi.h"
00044 #include "sechash.h"
00045 #include "keyhi.h"
00046 #include "secasn1.h"
00047 #include "secoid.h"
00048 #include "pk11func.h"
00049 #include "secdig.h"
00050 #include "secerr.h"
00051 #include "secport.h"
00052 
00053 /*
00054 ** Decrypt signature block using public key
00055 ** Store the hash algorithm oid tag in *tagp
00056 ** Store the digest in the digest buffer
00057 ** Store the digest length in *digestlen
00058 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
00059 */
00060 static SECStatus
00061 DecryptSigBlock(SECOidTag *tagp, unsigned char *digest,
00062               unsigned int *digestlen, unsigned int maxdigestlen,
00063               SECKEYPublicKey *key, const SECItem *sig, char *wincx)
00064 {
00065     SGNDigestInfo *di   = NULL;
00066     unsigned char *buf  = NULL;
00067     SECStatus      rv;
00068     SECOidTag      tag;
00069     SECItem        it;
00070 
00071     if (key == NULL) goto loser;
00072 
00073     it.len  = SECKEY_PublicKeyStrength(key);
00074     if (!it.len) goto loser;
00075     it.data = buf = (unsigned char *)PORT_Alloc(it.len);
00076     if (!buf) goto loser;
00077 
00078     /* decrypt the block */
00079     rv = PK11_VerifyRecover(key, (SECItem *)sig, &it, wincx);
00080     if (rv != SECSuccess) goto loser;
00081 
00082     di = SGN_DecodeDigestInfo(&it);
00083     if (di == NULL) goto sigloser;
00084 
00085     /*
00086     ** Finally we have the digest info; now we can extract the algorithm
00087     ** ID and the signature block
00088     */
00089     tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
00090     /* Check that tag is an appropriate algorithm */
00091     if (tag == SEC_OID_UNKNOWN) {
00092        goto sigloser;
00093     }
00094     /* make sure the "parameters" are not too bogus. */
00095     if (di->digestAlgorithm.parameters.len > 2) {
00096        goto sigloser;
00097     }
00098     if (di->digest.len > maxdigestlen) {
00099        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
00100        goto loser;
00101     }
00102     PORT_Memcpy(digest, di->digest.data, di->digest.len);
00103     *tagp = tag;
00104     *digestlen = di->digest.len;
00105     goto done;
00106 
00107   sigloser:
00108     PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00109 
00110   loser:
00111     rv = SECFailure;
00112 
00113   done:
00114     if (di   != NULL) SGN_DestroyDigestInfo(di);
00115     if (buf  != NULL) PORT_Free(buf);
00116     
00117     return rv;
00118 }
00119 
00120 typedef enum { VFY_RSA, VFY_DSA, VFY_ECDSA } VerifyType;
00121 
00122 struct VFYContextStr {
00123     SECOidTag alg;  /* the hash algorithm */
00124     VerifyType type;
00125     SECKEYPublicKey *key;
00126     /*
00127      * This buffer holds either the digest or the full signature
00128      * depending on the type of the signature.  It is defined as a
00129      * union to make sure it always has enough space.
00130      *
00131      * Use the "buffer" union member to reference the buffer.
00132      * Note: do not take the size of the "buffer" union member.  Take
00133      * the size of the union or some other union member instead.
00134      */
00135     union {
00136        unsigned char buffer[1];
00137 
00138        /* the digest in the decrypted RSA signature */
00139        unsigned char rsadigest[HASH_LENGTH_MAX];
00140        /* the full DSA signature... 40 bytes */
00141        unsigned char dsasig[DSA_SIGNATURE_LEN];
00142        /* the full ECDSA signature */
00143        unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
00144     } u;
00145     unsigned int rsadigestlen;
00146     void * wincx;
00147     void *hashcx;
00148     const SECHashObject *hashobj;
00149     SECOidTag sigAlg;  /* the (composite) signature algorithm */
00150     PRBool hasSignature;  /* true if the signature was provided in the
00151                            * VFY_CreateContext call.  If false, the
00152                            * signature must be provided with a
00153                            * VFY_EndWithSignature call. */
00154 };
00155 
00156 /*
00157  * decode the ECDSA or DSA signature from it's DER wrapping.
00158  * The unwrapped/raw signature is placed in the buffer pointed
00159  * to by dsig and has enough room for len bytes.
00160  */
00161 static SECStatus
00162 decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *dsig,
00163                      unsigned int len) {
00164     SECItem *dsasig = NULL; /* also used for ECDSA */
00165     SECStatus rv=SECSuccess;
00166 
00167     switch (algid) {
00168     case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
00169     case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
00170     case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
00171     case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
00172     case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
00173     case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
00174        if (len > MAX_ECKEY_LEN * 2) {
00175            PORT_SetError(SEC_ERROR_BAD_DER);
00176            return SECFailure;
00177        }
00178        /* fall through */
00179     case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
00180     case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
00181     case SEC_OID_ANSIX9_DSA_SIGNATURE:
00182        dsasig = DSAU_DecodeDerSigToLen(sig, len);
00183 
00184        if ((dsasig == NULL) || (dsasig->len != len)) {
00185            rv = SECFailure;
00186        } else {
00187            PORT_Memcpy(dsig, dsasig->data, dsasig->len);
00188        }
00189        break;
00190     default:
00191         if (sig->len != len) {
00192            rv = SECFailure;
00193        } else {
00194            PORT_Memcpy(dsig, sig->data, sig->len);
00195        }
00196        break;
00197     }
00198 
00199     if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
00200     if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER);
00201     return rv;
00202 }
00203 
00204 const static SEC_ASN1Template hashParameterTemplate[] =
00205 {
00206     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
00207     { SEC_ASN1_OBJECT_ID, 0 },
00208     { SEC_ASN1_SKIP_REST },
00209     { 0, }
00210 };
00211 /*
00212  * Pulls the hash algorithm, signing algorithm, and key type out of a
00213  * composite algorithm.
00214  *
00215  * alg: the composite algorithm to dissect.
00216  * hashalg: address of a SECOidTag which will be set with the hash algorithm.
00217  * params:  specific signature parameter (from the signature AlgorithmID).
00218  * key:     public key to verify against.
00219  * Returns: SECSuccess if the alg algorithm was acceptable, SECFailure if the
00220  *     algorithm was not found or was not a signing algorithm.
00221  */
00222 static SECStatus
00223 decodeSigAlg(SECOidTag alg, const SECItem *params, const SECKEYPublicKey *key, 
00224             SECOidTag *hashalg)
00225 {
00226     PRArenaPool *arena;
00227     SECStatus rv;
00228     SECItem oid;
00229     unsigned int len;
00230     PR_ASSERT(hashalg!=NULL);
00231 
00232     switch (alg) {
00233       /* We probably shouldn't be generating MD2 signatures either */
00234       case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
00235         *hashalg = SEC_OID_MD2;
00236        break;
00237       case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
00238         *hashalg = SEC_OID_MD5;
00239        break;
00240       case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
00241       case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
00242         *hashalg = SEC_OID_SHA1;
00243        break;
00244 
00245       case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
00246       case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
00247        *hashalg = SEC_OID_SHA256;
00248        break;
00249       case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
00250       case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
00251        *hashalg = SEC_OID_SHA384;
00252        break;
00253       case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
00254       case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
00255        *hashalg = SEC_OID_SHA512;
00256        break;
00257       case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
00258        /* This is an EC algorithm. Recommended means the largest
00259         * hash algorithm that is not truncated by the keysize of 
00260         * the EC algorithm. Note that key strength is in bytes and
00261         * algorithms are specified in bits. Never use an algorithm
00262         * weaker than sha1. */
00263        len = SECKEY_PublicKeyStrength((SECKEYPublicKey *)key);
00264        if (len < 28) { /* 28 bytes == 244 bits */
00265            *hashalg = SEC_OID_SHA1;
00266        } else if (len < 32) { /* 32 bytes == 256 bits */
00267            /* we don't support 244 bit hash algorithms */
00268            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00269            return SECFailure;
00270        } else if (len < 48) { /* 48 bytes == 384 bits */
00271            *hashalg = SEC_OID_SHA256;
00272        } else if (len < 64) { /* 48 bytes == 512 bits */
00273            *hashalg = SEC_OID_SHA384;
00274        } else {
00275            /* use the largest in this case */
00276            *hashalg = SEC_OID_SHA512;
00277        }
00278        break;
00279       case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
00280        if (params == NULL) {
00281            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00282            return SECFailure;
00283        }
00284        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00285        if (arena == NULL) {
00286            return SECFailure;
00287        }
00288        rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, params);
00289        if (rv != SECSuccess) {
00290            PORT_FreeArena(arena, PR_FALSE);
00291            return rv;
00292        }
00293 
00294        *hashalg = SECOID_FindOIDTag(&oid);
00295        PORT_FreeArena(arena, PR_FALSE);
00296        if (*hashalg == SEC_OID_UNKNOWN) {
00297            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00298            return SECFailure;
00299        }
00300        break;
00301 
00302       /* what about normal DSA? */
00303       case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
00304       case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
00305       case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
00306         *hashalg = SEC_OID_SHA1;
00307        break;
00308       case SEC_OID_MISSI_DSS:
00309       case SEC_OID_MISSI_KEA_DSS:
00310       case SEC_OID_MISSI_KEA_DSS_OLD:
00311       case SEC_OID_MISSI_DSS_OLD:
00312         *hashalg = SEC_OID_SHA1;
00313        break;
00314       /* we don't implement MD4 hashes */
00315       case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
00316       default:
00317        return SECFailure;
00318     }
00319     return SECSuccess;
00320 }
00321 
00322 static VFYContext *
00323 vfy_CreateContextPrivate(const SECKEYPublicKey *key, const SECItem *sig, 
00324                 SECOidTag algid, const SECItem *params, void *wincx)
00325 {
00326     VFYContext *cx;
00327     SECStatus rv;
00328     unsigned int sigLen;
00329 
00330     cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
00331     if (cx) {
00332         cx->wincx = wincx;
00333        cx->hasSignature = (sig != NULL);
00334        cx->sigAlg = algid;
00335        rv = SECSuccess;
00336        switch (key->keyType) {
00337        case rsaKey:
00338            cx->type = VFY_RSA;
00339            /* keep our own copy */
00340            cx->key = SECKEY_CopyPublicKey((SECKEYPublicKey *)key); 
00341            if (sig) {
00342               SECOidTag hashid = SEC_OID_UNKNOWN;
00343               unsigned int digestlen = 0;
00344               rv = DecryptSigBlock(&hashid, cx->u.buffer, &digestlen,
00345                      HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
00346               cx->alg = hashid;
00347               cx->rsadigestlen = digestlen;
00348            } else {
00349               rv = decodeSigAlg(algid, params, key, &cx->alg);
00350            }
00351            break;
00352        case fortezzaKey:
00353        case dsaKey:
00354        case ecKey:
00355            if (key->keyType == ecKey) {
00356                cx->type = VFY_ECDSA;
00357               /* Unlike DSA, ECDSA does not have a fixed signature length
00358                * (it depends on the key size)
00359                */
00360               sigLen = SECKEY_SignatureLen(key);
00361            } else {
00362                cx->type = VFY_DSA;
00363               sigLen = DSA_SIGNATURE_LEN;
00364            }
00365            if (sigLen == 0) {
00366               rv = SECFailure;
00367               break;
00368            }
00369            rv = decodeSigAlg(algid, params, key, &cx->alg);
00370            if (rv != SECSuccess) {
00371               break;
00372            }
00373            cx->key = SECKEY_CopyPublicKey((SECKEYPublicKey *)key);
00374            if (sig) {
00375                rv = decodeECorDSASignature(algid,sig,cx->u.buffer,sigLen);
00376            }
00377            break;
00378        default:
00379            rv = SECFailure;
00380            break;
00381        }
00382        if (rv) goto loser;
00383        switch (cx->alg) {
00384        case SEC_OID_MD2:
00385        case SEC_OID_MD5:
00386        case SEC_OID_SHA1:
00387        case SEC_OID_SHA256:
00388        case SEC_OID_SHA384:
00389        case SEC_OID_SHA512:
00390            break;
00391        default:
00392            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00393            goto loser;
00394        }
00395     }
00396     return cx;
00397 
00398   loser:
00399     VFY_DestroyContext(cx, PR_TRUE);
00400     return 0;
00401 }
00402 
00403 VFYContext *
00404 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid,
00405                 void *wincx)
00406 {
00407    return vfy_CreateContextPrivate(key, sig, algid, NULL, wincx);
00408 }
00409 
00410 void
00411 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
00412 {
00413     if (cx) {
00414        if (cx->hashcx != NULL) {
00415            (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
00416            cx->hashcx = NULL;
00417        }
00418        if (cx->key) {
00419            SECKEY_DestroyPublicKey(cx->key);
00420        }
00421        if (freeit) {
00422            PORT_ZFree(cx, sizeof(VFYContext));
00423        }
00424     }
00425 }
00426 
00427 SECStatus
00428 VFY_Begin(VFYContext *cx)
00429 {
00430     if (cx->hashcx != NULL) {
00431        (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
00432        cx->hashcx = NULL;
00433     }
00434 
00435     cx->hashobj = HASH_GetHashObjectByOidTag(cx->alg);
00436     if (!cx->hashobj) 
00437        return SECFailure;   /* error code is set */
00438 
00439     cx->hashcx = (*cx->hashobj->create)();
00440     if (cx->hashcx == NULL)
00441        return SECFailure;
00442 
00443     (*cx->hashobj->begin)(cx->hashcx);
00444     return SECSuccess;
00445 }
00446 
00447 SECStatus
00448 VFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen)
00449 {
00450     if (cx->hashcx == NULL) {
00451        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00452        return SECFailure;
00453     }
00454     (*cx->hashobj->update)(cx->hashcx, input, inputLen);
00455     return SECSuccess;
00456 }
00457 
00458 SECStatus
00459 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
00460 {
00461     unsigned char final[HASH_LENGTH_MAX];
00462     unsigned part;
00463     SECItem hash,dsasig; /* dsasig is also used for ECDSA */
00464     SECStatus rv;
00465 
00466     if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) {
00467        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00468        return SECFailure;
00469     }
00470 
00471     if (cx->hashcx == NULL) {
00472        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00473        return SECFailure;
00474     }
00475     (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
00476     switch (cx->type) {
00477       case VFY_DSA:
00478       case VFY_ECDSA:
00479        dsasig.data = cx->u.buffer;
00480        if (cx->type == VFY_DSA) {
00481            dsasig.len = DSA_SIGNATURE_LEN;
00482        } else {
00483            dsasig.len = SECKEY_SignatureLen(cx->key);
00484        }
00485        if (dsasig.len == 0) {
00486            return SECFailure;
00487        }
00488        if (sig) {
00489            rv = decodeECorDSASignature(cx->sigAlg,sig,dsasig.data,
00490                                    dsasig.len);
00491            if (rv != SECSuccess) {
00492               PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00493               return SECFailure;
00494            }
00495        } 
00496        hash.data = final;
00497        hash.len = part;
00498        if (PK11_Verify(cx->key,&dsasig,&hash,cx->wincx) != SECSuccess) {
00499               PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00500               return SECFailure;
00501        }
00502        break;
00503       case VFY_RSA:
00504        if (sig) {
00505            SECOidTag hashid = SEC_OID_UNKNOWN;
00506            rv = DecryptSigBlock(&hashid, cx->u.buffer, &cx->rsadigestlen,
00507                   HASH_LENGTH_MAX, cx->key, sig, (char*)cx->wincx);
00508            if ((rv != SECSuccess) || (hashid != cx->alg)) {
00509               PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00510               return SECFailure;
00511            }
00512        }
00513        if ((part != cx->rsadigestlen) ||
00514               PORT_Memcmp(final, cx->u.buffer, part)) {
00515            PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00516            return SECFailure;
00517        }
00518        break;
00519       default:
00520        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00521        return SECFailure; /* shouldn't happen */
00522     }
00523     return SECSuccess;
00524 }
00525 
00526 SECStatus
00527 VFY_End(VFYContext *cx)
00528 {
00529     return VFY_EndWithSignature(cx,NULL);
00530 }
00531 
00532 /************************************************************************/
00533 /*
00534  * Verify that a previously-computed digest matches a signature.
00535  * XXX This should take a parameter that specifies the digest algorithm,
00536  * and we should compare that the algorithm found in the DigestInfo
00537  * matches it!
00538  */
00539 SECStatus
00540 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
00541                SECOidTag algid, void *wincx)
00542 {
00543     SECStatus rv;
00544     VFYContext *cx;
00545     SECItem dsasig; /* also used for ECDSA */
00546 
00547     rv = SECFailure;
00548 
00549     cx = VFY_CreateContext(key, sig, algid, wincx);
00550     if (cx != NULL) {
00551        switch (key->keyType) {
00552        case rsaKey:
00553            if ((digest->len != cx->rsadigestlen) ||
00554               PORT_Memcmp(digest->data, cx->u.buffer, digest->len)) {
00555               PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00556            } else {
00557               rv = SECSuccess;
00558            }
00559            break;
00560        case fortezzaKey:
00561        case dsaKey:
00562        case ecKey:
00563            dsasig.data = cx->u.buffer;
00564            if (key->keyType == ecKey) {
00565               dsasig.len = SECKEY_SignatureLen(cx->key);
00566            } else {
00567               /* magic size of dsa signature */
00568               dsasig.len = DSA_SIGNATURE_LEN;
00569            }
00570            if (dsasig.len == 0) {
00571               break;
00572            }
00573            if (PK11_Verify(cx->key, &dsasig, digest, cx->wincx)
00574               != SECSuccess) {
00575               PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
00576            } else {
00577               rv = SECSuccess;
00578            }
00579            break;
00580        default:
00581            break;
00582        }
00583        VFY_DestroyContext(cx, PR_TRUE);
00584     }
00585     return rv;
00586 }
00587 
00588 static SECStatus
00589 vfy_VerifyDataPrivate(const unsigned char *buf, int len, 
00590               const SECKEYPublicKey *key, const SECItem *sig, 
00591               SECOidTag algid, const SECItem *params, void *wincx)
00592 {
00593     SECStatus rv;
00594     VFYContext *cx;
00595 
00596     cx = vfy_CreateContextPrivate(key, sig, algid, params, wincx);
00597     if (cx == NULL)
00598        return SECFailure;
00599 
00600     rv = VFY_Begin(cx);
00601     if (rv == SECSuccess) {
00602        rv = VFY_Update(cx, (unsigned char *)buf, len);
00603        if (rv == SECSuccess)
00604            rv = VFY_End(cx);
00605     }
00606 
00607     VFY_DestroyContext(cx, PR_TRUE);
00608     return rv;
00609 }
00610 
00611 SECStatus
00612 VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
00613               SECItem *sig, SECOidTag algid, void *wincx)
00614 {
00615     return vfy_VerifyDataPrivate(buf, len, key, sig, algid, NULL, wincx);
00616 }
00617 
00618 /*
00619  * this function is private to nss3.dll in NSS 3.11
00620  */
00621 SECStatus
00622 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
00623                               const SECKEYPublicKey *key,
00624                               const SECItem *sig,
00625                               const SECAlgorithmID *sigAlgorithm,
00626                               SECOidTag *reserved, void *wincx)
00627 {
00628     /* the hash parameter is only provided to match the NSS 3.12 signature */
00629     PORT_Assert(reserved == NULL);
00630     if (reserved) {
00631        /* shouldn't happen, This function is not exported, and the only
00632         * NSS callers pass 'NULL' */
00633        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00634        return SECFailure;
00635     }
00636     return vfy_VerifyDataPrivate(buf, len, key, sig, 
00637            SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
00638            &sigAlgorithm->parameters, wincx);
00639 }
00640