tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

secvfy.c (44921B)


      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 #include "nss.h"
     20 #include "prenv.h"
     21 /*
     22 ** Recover the DigestInfo from an RSA PKCS#1 signature.
     23 **
     24 ** If givenDigestAlg != SEC_OID_UNKNOWN, copy givenDigestAlg to digestAlgOut.
     25 ** Otherwise, parse the DigestInfo structure and store the decoded digest
     26 ** algorithm into digestAlgOut.
     27 **
     28 ** Store the encoded DigestInfo into digestInfo.
     29 ** Store the DigestInfo length into digestInfoLen.
     30 **
     31 ** This function does *not* verify that the AlgorithmIdentifier in the
     32 ** DigestInfo identifies givenDigestAlg or that the DigestInfo is encoded
     33 ** correctly; verifyPKCS1DigestInfo does that.
     34 **
     35 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
     36 */
     37 static SECStatus
     38 recoverPKCS1DigestInfo(SECOidTag givenDigestAlg,
     39                       /*out*/ SECOidTag *digestAlgOut,
     40                       /*out*/ unsigned char **digestInfo,
     41                       /*out*/ unsigned int *digestInfoLen,
     42                       SECKEYPublicKey *key,
     43                       const SECItem *sig, void *wincx)
     44 {
     45    SGNDigestInfo *di = NULL;
     46    SECItem it;
     47    PRBool rv = SECSuccess;
     48 
     49    PORT_Assert(digestAlgOut);
     50    PORT_Assert(digestInfo);
     51    PORT_Assert(digestInfoLen);
     52    PORT_Assert(key);
     53    PORT_Assert(key->keyType == rsaKey);
     54    PORT_Assert(sig);
     55 
     56    it.data = NULL;
     57    it.len = SECKEY_PublicKeyStrength(key);
     58    if (it.len != 0) {
     59        it.data = (unsigned char *)PORT_Alloc(it.len);
     60    }
     61    if (it.len == 0 || it.data == NULL) {
     62        rv = SECFailure;
     63    }
     64 
     65    if (rv == SECSuccess) {
     66        /* decrypt the block */
     67        rv = PK11_VerifyRecover(key, sig, &it, wincx);
     68    }
     69 
     70    if (rv == SECSuccess) {
     71        if (givenDigestAlg != SEC_OID_UNKNOWN) {
     72            /* We don't need to parse the DigestInfo if the caller gave us the
     73             * digest algorithm to use. Later verifyPKCS1DigestInfo will verify
     74             * that the DigestInfo identifies the given digest algorithm and
     75             * that the DigestInfo is encoded absolutely correctly.
     76             */
     77            *digestInfoLen = it.len;
     78            *digestInfo = (unsigned char *)it.data;
     79            *digestAlgOut = givenDigestAlg;
     80            return SECSuccess;
     81        }
     82    }
     83 
     84    if (rv == SECSuccess) {
     85        /* The caller didn't specify a digest algorithm to use, so choose the
     86         * digest algorithm by parsing the AlgorithmIdentifier within the
     87         * DigestInfo.
     88         */
     89        di = SGN_DecodeDigestInfo(&it);
     90        if (!di) {
     91            rv = SECFailure;
     92        }
     93    }
     94 
     95    if (rv == SECSuccess) {
     96        *digestAlgOut = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
     97        if (*digestAlgOut == SEC_OID_UNKNOWN) {
     98            rv = SECFailure;
     99        }
    100    }
    101 
    102    if (di) {
    103        SGN_DestroyDigestInfo(di);
    104    }
    105 
    106    if (rv == SECSuccess) {
    107        *digestInfoLen = it.len;
    108        *digestInfo = (unsigned char *)it.data;
    109    } else {
    110        if (it.data) {
    111            PORT_Free(it.data);
    112        }
    113        *digestInfo = NULL;
    114        *digestInfoLen = 0;
    115        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    116    }
    117 
    118    return rv;
    119 }
    120 
    121 struct VFYContextStr {
    122    SECOidTag hashAlg; /* the hash algorithm */
    123    SECKEYPublicKey *key;
    124    /*
    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.
    128     *
    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.
    132     */
    133    union {
    134        unsigned char buffer[1];
    135 
    136        /* the full DSA signature... 40 bytes */
    137        unsigned char dsasig[DSA_MAX_SIGNATURE_LEN];
    138        /* the full ECDSA signature */
    139        unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
    140        /* the full RSA signature, only used in RSA-PSS */
    141        unsigned char rsasig[(RSA_MAX_MODULUS_BITS + 7) / 8];
    142        unsigned char gensig[MAX_SIGNATURE_LEN];
    143    } u;
    144    unsigned int signatureLen;
    145    unsigned int pkcs1RSADigestInfoLen;
    146    /* the encoded DigestInfo from a RSA PKCS#1 signature */
    147    unsigned char *pkcs1RSADigestInfo;
    148    void *wincx;
    149    void *hashcx;
    150    const SECHashObject *hashobj;
    151    PK11Context *vfycx;
    152    SECOidTag encAlg; /* enc alg */
    153    CK_MECHANISM_TYPE mech;
    154    PRBool hasSignature; /* true if the signature was provided in the
    155                          * VFY_CreateContext call.  If false, the
    156                          * signature must be provided with a
    157                          * VFY_EndWithSignature call. */
    158    SECItem mechparams;
    159 };
    160 
    161 static SECStatus
    162 verifyPKCS1DigestInfo(const VFYContext *cx, const SECItem *digest)
    163 {
    164    SECItem pkcs1DigestInfo;
    165    pkcs1DigestInfo.data = cx->pkcs1RSADigestInfo;
    166    pkcs1DigestInfo.len = cx->pkcs1RSADigestInfoLen;
    167    return _SGN_VerifyPKCS1DigestInfo(
    168        cx->hashAlg, digest, &pkcs1DigestInfo,
    169        PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
    170 }
    171 
    172 static unsigned int
    173 checkedSignatureLen(const SECKEYPublicKey *pubk)
    174 {
    175    unsigned int sigLen = SECKEY_SignatureLen(pubk);
    176    if (sigLen == 0) {
    177        /* Error set by SECKEY_SignatureLen */
    178        return sigLen;
    179    }
    180    unsigned int maxSigLen;
    181    switch (pubk->keyType) {
    182        case rsaKey:
    183        case rsaPssKey:
    184            maxSigLen = (RSA_MAX_MODULUS_BITS + 7) / 8;
    185            break;
    186        case dsaKey:
    187            maxSigLen = DSA_MAX_SIGNATURE_LEN;
    188            break;
    189        case ecKey:
    190            maxSigLen = 2 * MAX_ECKEY_LEN;
    191            break;
    192        case mldsaKey:
    193            maxSigLen = MAX_ML_DSA_SIGNATURE_LEN;
    194            break;
    195        default:
    196            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
    197            return 0;
    198    }
    199    PORT_Assert(maxSigLen <= MAX_SIGNATURE_LEN);
    200    if (sigLen > maxSigLen) {
    201        PORT_SetError(SEC_ERROR_INVALID_KEY);
    202        return 0;
    203    }
    204    return sigLen;
    205 }
    206 
    207 /*
    208 * decode the ECDSA or DSA signature from it's DER wrapping.
    209 * The unwrapped/raw signature is placed in the buffer pointed
    210 * to by dsig and has enough room for len bytes.
    211 */
    212 static SECStatus
    213 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
    214                       unsigned int len)
    215 {
    216    SECItem *dsasig = NULL; /* also used for ECDSA */
    217 
    218    /* Safety: Ensure algId is as expected and that signature size is within maxmimums */
    219    if (algid == SEC_OID_ANSIX9_DSA_SIGNATURE) {
    220        if (len > DSA_MAX_SIGNATURE_LEN) {
    221            goto loser;
    222        }
    223    } else if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
    224        if (len > MAX_ECKEY_LEN * 2) {
    225            goto loser;
    226        }
    227    } else {
    228        goto loser;
    229    }
    230 
    231    /* Decode and pad to length */
    232    dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
    233    if (dsasig == NULL) {
    234        goto loser;
    235    }
    236    if (dsasig->len != len) {
    237        SECITEM_FreeItem(dsasig, PR_TRUE);
    238        goto loser;
    239    }
    240 
    241    PORT_Memcpy(dsig, dsasig->data, len);
    242    SECITEM_FreeItem(dsasig, PR_TRUE);
    243 
    244    return SECSuccess;
    245 
    246 loser:
    247    PORT_SetError(SEC_ERROR_BAD_DER);
    248    return SECFailure;
    249 }
    250 
    251 const SEC_ASN1Template hashParameterTemplate[] = {
    252    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
    253    { SEC_ASN1_OBJECT_ID, 0 },
    254    { SEC_ASN1_SKIP_REST },
    255    { 0 }
    256 };
    257 
    258 /*
    259 * Get just the encryption algorithm from the signature algorithm
    260 */
    261 SECOidTag
    262 sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)
    263 {
    264    /* get the "encryption" algorithm */
    265    switch (sigAlg) {
    266        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    267        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
    268        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
    269        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
    270        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
    271        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
    272        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
    273        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
    274        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
    275        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
    276            return SEC_OID_PKCS1_RSA_ENCRYPTION;
    277        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    278            return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
    279 
    280        /* what about normal DSA? */
    281        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    282        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    283        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
    284        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
    285            return SEC_OID_ANSIX9_DSA_SIGNATURE;
    286        case SEC_OID_MISSI_DSS:
    287        case SEC_OID_MISSI_KEA_DSS:
    288        case SEC_OID_MISSI_KEA_DSS_OLD:
    289        case SEC_OID_MISSI_DSS_OLD:
    290            return SEC_OID_MISSI_DSS;
    291        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
    292        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
    293        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
    294        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
    295        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
    296        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
    297        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
    298            return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
    299        case SEC_OID_ML_DSA_44:
    300        case SEC_OID_ML_DSA_65:
    301        case SEC_OID_ML_DSA_87:
    302            return sigAlg;
    303        /* we don't implement MD4 hashes */
    304        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
    305        default:
    306            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    307            break;
    308    }
    309    return SEC_OID_UNKNOWN;
    310 }
    311 static CK_MECHANISM_TYPE
    312 sec_RSAPKCS1GetCombinedMech(SECOidTag hashalg)
    313 {
    314    switch (hashalg) {
    315        case SEC_OID_MD5:
    316            return CKM_MD5_RSA_PKCS;
    317        case SEC_OID_MD2:
    318            return CKM_MD2_RSA_PKCS;
    319        case SEC_OID_SHA1:
    320            return CKM_SHA1_RSA_PKCS;
    321        case SEC_OID_SHA224:
    322            return CKM_SHA224_RSA_PKCS;
    323        case SEC_OID_SHA256:
    324            return CKM_SHA256_RSA_PKCS;
    325        case SEC_OID_SHA384:
    326            return CKM_SHA384_RSA_PKCS;
    327        case SEC_OID_SHA512:
    328            return CKM_SHA512_RSA_PKCS;
    329        default:
    330            break;
    331    }
    332    return CKM_INVALID_MECHANISM;
    333 }
    334 
    335 static CK_MECHANISM_TYPE
    336 sec_RSAPSSGetCombinedMech(SECOidTag hashalg)
    337 {
    338    switch (hashalg) {
    339        case SEC_OID_SHA1:
    340            return CKM_SHA1_RSA_PKCS_PSS;
    341        case SEC_OID_SHA224:
    342            return CKM_SHA224_RSA_PKCS_PSS;
    343        case SEC_OID_SHA256:
    344            return CKM_SHA256_RSA_PKCS_PSS;
    345        case SEC_OID_SHA384:
    346            return CKM_SHA384_RSA_PKCS_PSS;
    347        case SEC_OID_SHA512:
    348            return CKM_SHA512_RSA_PKCS_PSS;
    349        default:
    350            break;
    351    }
    352    return CKM_INVALID_MECHANISM;
    353 }
    354 
    355 static CK_MECHANISM_TYPE
    356 sec_DSAGetCombinedMech(SECOidTag hashalg)
    357 {
    358    switch (hashalg) {
    359        case SEC_OID_SHA1:
    360            return CKM_DSA_SHA1;
    361        case SEC_OID_SHA224:
    362            return CKM_DSA_SHA224;
    363        case SEC_OID_SHA256:
    364            return CKM_DSA_SHA256;
    365        case SEC_OID_SHA384:
    366            return CKM_DSA_SHA384;
    367        case SEC_OID_SHA512:
    368            return CKM_DSA_SHA512;
    369        default:
    370            break;
    371    }
    372    return CKM_INVALID_MECHANISM;
    373 }
    374 static CK_MECHANISM_TYPE
    375 sec_ECDSAGetCombinedMech(SECOidTag hashalg)
    376 {
    377    switch (hashalg) {
    378        case SEC_OID_SHA1:
    379            return CKM_ECDSA_SHA1;
    380        case SEC_OID_SHA224:
    381            return CKM_ECDSA_SHA224;
    382        case SEC_OID_SHA256:
    383            return CKM_ECDSA_SHA256;
    384        case SEC_OID_SHA384:
    385            return CKM_ECDSA_SHA384;
    386        case SEC_OID_SHA512:
    387            return CKM_ECDSA_SHA512;
    388        default:
    389            break;
    390    }
    391    return CKM_INVALID_MECHANISM;
    392 }
    393 
    394 static CK_MECHANISM_TYPE
    395 sec_GetCombinedMech(SECOidTag encalg, SECOidTag hashalg)
    396 {
    397    switch (encalg) {
    398        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    399            return sec_RSAPKCS1GetCombinedMech(hashalg);
    400        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    401            return sec_RSAPSSGetCombinedMech(hashalg);
    402        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    403            return sec_ECDSAGetCombinedMech(hashalg);
    404        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    405            return sec_DSAGetCombinedMech(hashalg);
    406        case SEC_OID_ML_DSA_44:
    407        case SEC_OID_ML_DSA_65:
    408        case SEC_OID_ML_DSA_87:
    409            /* make sure the hashAlg is rational */
    410            if ((hashalg == SEC_OID_UNKNOWN) || (hashalg == encalg)) {
    411                return CKM_ML_DSA;
    412            }
    413            break;
    414        default:
    415            break;
    416    }
    417    return CKM_INVALID_MECHANISM;
    418 }
    419 
    420 /*
    421 * Pulls the hash algorithm, signing algorithm, and key type out of a
    422 * composite algorithm.
    423 *
    424 * key: pointer to the public key. Should be NULL if called for a sign operation.
    425 * sigAlg: the composite algorithm to dissect.
    426 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
    427 * encalg: address of a SECOidTag which will be set with the signing alg.
    428 * mechp: address of a PCKS #11 Mechanism which will be set to the
    429 *  combined hash/encrypt mechanism. If set to CKM_INVALID_MECHANISM, the code
    430 *  will fall back to external hashing.
    431 * mechparams: address of a SECItem will set to the parameters for the combined
    432 *  hash/encrypt mechanism.
    433 *
    434 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
    435 *  algorithm was not found or was not a signing algorithm.
    436 */
    437 SECStatus
    438 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
    439                 const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg,
    440                 CK_MECHANISM_TYPE *mechp, SECItem *mechparamsp)
    441 {
    442    unsigned int len;
    443    PLArenaPool *arena;
    444    SECStatus rv;
    445    SECItem oid;
    446    SECOidTag encalg;
    447    PRBool comboRequired = PR_FALSE;
    448    char *evp;
    449 
    450    PR_ASSERT(hashalg != NULL);
    451    PR_ASSERT(encalgp != NULL);
    452    PR_ASSERT(mechp != NULL);
    453    /* Get the expected combined mechanism from the signature OID
    454     * We'll override it in the table below if necessary */
    455    *mechp = PK11_AlgtagToMechanism(sigAlg);
    456    if (mechparamsp) {
    457        mechparamsp->data = NULL;
    458        mechparamsp->len = 0;
    459    }
    460 
    461    switch (sigAlg) {
    462        /* We probably shouldn't be generating MD2 signatures either */
    463        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
    464            *hashalg = SEC_OID_MD2;
    465            break;
    466        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
    467            *hashalg = SEC_OID_MD5;
    468            break;
    469        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
    470        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
    471        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
    472            *hashalg = SEC_OID_SHA1;
    473            break;
    474        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    475            /* SEC_OID_PKCS1_RSA_ENCRYPTION returns the generic
    476             * CKM_RSA_PKCS mechanism, which isn't a combined mechanism.
    477             * We don't have a hash, so we need to fall back to the old
    478             * code which gets the hashalg by decoding the signature */
    479            *mechp = CKM_INVALID_MECHANISM;
    480            *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
    481            break;
    482        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    483            /* SEC_OID_PKCS1_RSA_PSS_SIGNATURE returns the generic
    484             * CKM_RSA_PSS_PKCS mechanism, which isn't a combined mechanism.
    485             * If successful, we'll select the mechanism below, set it to
    486             * invalid here incase we aren't successful */
    487            *mechp = CKM_INVALID_MECHANISM;
    488            CK_RSA_PKCS_PSS_PARAMS *rsapssmechparams = NULL;
    489            CK_RSA_PKCS_PSS_PARAMS space;
    490 
    491            /* if we don't have a mechanism parameter to put the data in
    492             * we don't need to return it, just use a stack buffer */
    493            if (mechparamsp == NULL) {
    494                rsapssmechparams = &space;
    495            } else {
    496                rsapssmechparams = PORT_ZNew(CK_RSA_PKCS_PSS_PARAMS);
    497            }
    498            if (rsapssmechparams == NULL) {
    499                return SECFailure;
    500            }
    501            if (param && param->data) {
    502                PORTCheapArenaPool tmpArena;
    503 
    504                PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
    505                rv = sec_DecodeRSAPSSParamsToMechanism(&tmpArena.arena, param,
    506                                                       rsapssmechparams, hashalg);
    507                PORT_DestroyCheapArena(&tmpArena);
    508 
    509                /* only accept hash algorithms */
    510                if (rv != SECSuccess || HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
    511                    /* error set by sec_DecodeRSAPSSParams or HASH_GetHashTypeByOidTag */
    512                    if (mechparamsp)
    513                        PORT_Free(rsapssmechparams);
    514                    return SECFailure;
    515                }
    516            } else {
    517                *hashalg = SEC_OID_SHA1; /* default, SHA-1 */
    518                rsapssmechparams->hashAlg = CKM_SHA_1;
    519                rsapssmechparams->mgf = CKG_MGF1_SHA1;
    520                rsapssmechparams->sLen = SHA1_LENGTH;
    521            }
    522            *mechp = sec_RSAPSSGetCombinedMech(*hashalg);
    523            if (mechparamsp) {
    524                mechparamsp->data = (unsigned char *)rsapssmechparams;
    525                mechparamsp->len = sizeof(*rsapssmechparams);
    526            }
    527            break;
    528 
    529        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
    530        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
    531        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
    532            *hashalg = SEC_OID_SHA224;
    533            break;
    534        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
    535        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
    536        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
    537            *hashalg = SEC_OID_SHA256;
    538            break;
    539        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
    540        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
    541            *hashalg = SEC_OID_SHA384;
    542            break;
    543        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
    544        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
    545            *hashalg = SEC_OID_SHA512;
    546            break;
    547 
    548        /* what about normal DSA? */
    549        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    550        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    551        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
    552            *hashalg = SEC_OID_SHA1;
    553            break;
    554        case SEC_OID_MISSI_DSS:
    555        case SEC_OID_MISSI_KEA_DSS:
    556        case SEC_OID_MISSI_KEA_DSS_OLD:
    557        case SEC_OID_MISSI_DSS_OLD:
    558            *mechp = CKM_DSA_SHA1;
    559            *hashalg = SEC_OID_SHA1;
    560            break;
    561        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
    562            /* This is an EC algorithm. Recommended means the largest
    563             * hash algorithm that is not reduced by the keysize of
    564             * the EC algorithm. Note that key strength is in bytes and
    565             * algorithms are specified in bits. Never use an algorithm
    566             * weaker than sha1. */
    567            len = SECKEY_PublicKeyStrength(key);
    568            if (len < 28) { /* 28 bytes == 224 bits */
    569                *hashalg = SEC_OID_SHA1;
    570            } else if (len < 32) { /* 32 bytes == 256 bits */
    571                *hashalg = SEC_OID_SHA224;
    572            } else if (len < 48) { /* 48 bytes == 384 bits */
    573                *hashalg = SEC_OID_SHA256;
    574            } else if (len < 64) { /* 48 bytes == 512 bits */
    575                *hashalg = SEC_OID_SHA384;
    576            } else {
    577                /* use the largest in this case */
    578                *hashalg = SEC_OID_SHA512;
    579            }
    580            *mechp = sec_ECDSAGetCombinedMech(*hashalg);
    581            break;
    582        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
    583            if (param == NULL) {
    584                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    585                return SECFailure;
    586            }
    587            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    588            if (arena == NULL) {
    589                return SECFailure;
    590            }
    591            rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
    592            if (rv == SECSuccess) {
    593                *hashalg = SECOID_FindOIDTag(&oid);
    594            }
    595            PORT_FreeArena(arena, PR_FALSE);
    596            if (rv != SECSuccess) {
    597                return rv;
    598            }
    599            /* only accept hash algorithms */
    600            if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
    601                /* error set by HASH_GetHashTypeByOidTag */
    602                return SECFailure;
    603            }
    604            *mechp = sec_ECDSAGetCombinedMech(*hashalg);
    605            break;
    606        case SEC_OID_ML_DSA_44:
    607        case SEC_OID_ML_DSA_65:
    608        case SEC_OID_ML_DSA_87:
    609            comboRequired = PR_TRUE;
    610            *hashalg = sigAlg;
    611            /* decode params to get the sign context and set (mechparamsp) */
    612            break;
    613        /* we don't implement MD4 hashes */
    614        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
    615        default:
    616            *mechp = CKM_INVALID_MECHANISM;
    617            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    618            return SECFailure;
    619    }
    620 
    621    encalg = sec_GetEncAlgFromSigAlg(sigAlg);
    622    if (encalg == SEC_OID_UNKNOWN) {
    623        *mechp = CKM_INVALID_MECHANISM;
    624        SECITEM_FreeItem(mechparamsp, PR_FALSE);
    625        return SECFailure;
    626    }
    627    *encalgp = encalg;
    628    /* for testing, we want to be able to turn off combo signatures to
    629     * 1) make sure the fallback code is working correctly so we know
    630     * we can handle cases where the fallback doesn't work.
    631     * 2) make sure that the combo code is compatible with the non-combo
    632     * versions.
    633     * We know if we are signing or verifying based on the value of 'key'.
    634     * Since key is a public key, then it's set to NULL for signing */
    635    evp = PR_GetEnvSecure("NSS_COMBO_SIGNATURES");
    636    if (evp && !comboRequired) {
    637        if (PORT_Strcasecmp(evp, "none") == 0) {
    638            *mechp = CKM_INVALID_MECHANISM;
    639        } else if (key && (PORT_Strcasecmp(evp, "signonly") == 0)) {
    640            *mechp = CKM_INVALID_MECHANISM;
    641        } else if (!key && (PORT_Strcasecmp(evp, "vfyonly") == 0)) {
    642            *mechp = CKM_INVALID_MECHANISM;
    643        }
    644        /* anything else we take as use combo, which is the default */
    645    }
    646    /* now enforce the combo requires requirement */
    647    if (comboRequired && (*mechp == CKM_INVALID_MECHANISM)) {
    648        SECITEM_FreeItem(mechparamsp, PR_FALSE);
    649        return SECFailure;
    650    }
    651 
    652    return SECSuccess;
    653 }
    654 
    655 SECStatus
    656 vfy_ImportPublicKey(VFYContext *cx)
    657 {
    658    PK11SlotInfo *slot;
    659    CK_OBJECT_HANDLE objID;
    660 
    661    if (cx->key->pkcs11Slot &&
    662        PK11_DoesMechanismFlag(cx->key->pkcs11Slot,
    663                               cx->mech, CKF_VERIFY)) {
    664        return SECSuccess;
    665    }
    666    slot = PK11_GetBestSlotWithAttributes(cx->mech, CKF_VERIFY, 0, cx->wincx);
    667    if (slot == NULL) {
    668        return SECFailure; /* can't find a slot, fall back to
    669                            * normal processing */
    670    }
    671    objID = PK11_ImportPublicKey(slot, cx->key, PR_FALSE);
    672    PK11_FreeSlot(slot);
    673    return objID == CK_INVALID_HANDLE ? SECFailure : SECSuccess;
    674 }
    675 
    676 /* Sometimes there are differences between how DER encodes a
    677 * signature and how it's encoded in PKCS #11. This function converts the
    678 * DER form to the PKCS #11 form. it also verify signature length based
    679 * on the key, and verifies that length will fit in our buffer. */
    680 static SECStatus
    681 vfy_SetPKCS11SigFromX509Sig(VFYContext *cx, const SECItem *sig)
    682 {
    683    unsigned int sigLen;
    684 
    685    /* skip the legacy RSA PKCS #11 case, it's always handled separately */
    686    if ((cx->key->keyType == rsaKey) && (cx->mech == CKM_INVALID_MECHANISM) &&
    687        (cx->encAlg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE)) {
    688        return SECSuccess;
    689    }
    690 
    691    sigLen = checkedSignatureLen(cx->key);
    692    /* Check signature length is within limits */
    693    if (sigLen == 0) {
    694        /* error set by checkedSignatureLen */
    695        return SECFailure;
    696    }
    697    if (sigLen > sizeof(cx->u)) {
    698        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    699        return SECFailure;
    700    }
    701    /* save the authenticated length */
    702    cx->signatureLen = sigLen;
    703    switch (cx->encAlg) {
    704        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    705        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    706            /* decodeECorDSASignature will check sigLen == sig->len after padding */
    707            return decodeECorDSASignature(cx->encAlg, sig, cx->u.buffer, sigLen);
    708        default:
    709            break;
    710    }
    711    /* all other cases, no transform needed, just copy the signature */
    712    if (sig->len != sigLen) {
    713        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    714        return SECFailure;
    715    }
    716    PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
    717    return SECSuccess;
    718 }
    719 
    720 /*
    721 * we can verify signatures that come from 2 different sources:
    722 *  one in with the signature contains a signature oid, and the other
    723 *  in which the signature is managed by a Public key (encAlg) oid
    724 *  and a hash oid. The latter is the more basic, so that's what
    725 *  our base vfyCreate function takes.
    726 *
    727 * Modern signature algorithms builds the hashing into the algorithm, and
    728 *  some tokens (like smart cards), purposefully only export hash & sign
    729 *  combo mechanisms (which gives stronger guarrentees on key type usage
    730 *  for RSA operations). If mech is set to a PKCS #11 mechanism, we assume
    731 *  we can do the combined operations, otherwise we fall back to manually
    732 *  hashing then signing.
    733 *
    734 * This function adopts the mechparamsp parameter, so if we fail before
    735 *  setting up the context, we need to free any space associated with it
    736 *  before we return.
    737 *
    738 * There is one noteworthy corner case, if we are using an RSA key, and the
    739 * signature block is provided, then the hashAlg can be specified as
    740 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
    741 * in the RSA signature block.
    742 */
    743 static VFYContext *
    744 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
    745                  SECOidTag encAlg, SECOidTag hashAlg, CK_MECHANISM_TYPE mech,
    746                  SECItem *mechparamsp, SECOidTag *hash, PRBool prehash,
    747                  void *wincx)
    748 {
    749    VFYContext *cx;
    750    SECStatus rv;
    751    KeyType type;
    752    PRUint32 policyFlags;
    753    PRInt32 optFlags;
    754 
    755    /* make sure the encryption algorithm matches the key type */
    756    /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
    757    type = seckey_GetKeyType(encAlg);
    758    if ((key->keyType != type) &&
    759        ((key->keyType != rsaKey) || (type != rsaPssKey))) {
    760        SECITEM_FreeItem(mechparamsp, PR_FALSE);
    761        PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
    762        return NULL;
    763    }
    764    if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) {
    765        if (optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) {
    766            rv = SECKEY_EnforceKeySize(key->keyType,
    767                                       SECKEY_PublicKeyStrengthInBits(key),
    768                                       SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
    769            if (rv != SECSuccess) {
    770                SECITEM_FreeItem(mechparamsp, PR_FALSE);
    771                return NULL;
    772            }
    773        }
    774    }
    775    /* check the policy on the encryption algorithm */
    776    if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) ||
    777        !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
    778        SECITEM_FreeItem(mechparamsp, PR_FALSE);
    779        PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
    780        return NULL;
    781    }
    782 
    783    cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
    784    if (cx == NULL) {
    785        /* after this point mechparamsp is 'owned' by the context and will be
    786         * freed by Destroy context for any other failures here */
    787        SECITEM_FreeItem(mechparamsp, PR_FALSE);
    788        goto loser;
    789    }
    790 
    791    cx->wincx = wincx;
    792    cx->hasSignature = (sig != NULL);
    793    cx->encAlg = encAlg;
    794    cx->hashAlg = hashAlg;
    795    cx->mech = mech;
    796    if (mechparamsp) {
    797        cx->mechparams = *mechparamsp;
    798    } else {
    799        /* probably needs to have a call to set the default
    800         * paramseters based on hashAlg and encAlg */
    801        cx->mechparams.data = NULL;
    802        cx->mechparams.len = 0;
    803    }
    804    cx->key = SECKEY_CopyPublicKey(key);
    805    cx->pkcs1RSADigestInfo = NULL;
    806    if (mech != CKM_INVALID_MECHANISM) {
    807        rv = vfy_ImportPublicKey(cx);
    808        /* if we can't import the key, then we probably can't
    809         * support the requested combined mechanism, fallback
    810         * to the non-combined method */
    811        if (rv != SECSuccess) {
    812            cx->mech = mech = CKM_INVALID_MECHANISM;
    813        }
    814    }
    815    if (sig) {
    816        /* sigh, if we are prehashing, we still need to do verifyRecover
    817         * recover for RSA PKCS #1 */
    818        if ((mech == CKM_INVALID_MECHANISM || prehash) && (type == rsaKey)) {
    819            /* in traditional rsa PKCS #1, we use verify recover to get
    820             * the encoded RSADigestInfo. In all other cases we just
    821             * stash the signature encoded in PKCS#11 in our context */
    822            rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
    823                                        &cx->pkcs1RSADigestInfo,
    824                                        &cx->pkcs1RSADigestInfoLen,
    825                                        cx->key,
    826                                        sig, wincx);
    827        } else {
    828            /* at this point hashAlg should be known. Only the RSA case
    829             * enters here with hashAlg unknown, and it's found out
    830             * above */
    831            PORT_Assert(hashAlg != SEC_OID_UNKNOWN);
    832            rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
    833        }
    834        if (rv != SECSuccess) {
    835            goto loser;
    836        }
    837    }
    838 
    839    /* check hash alg again, RSA may have changed it.*/
    840    /* combo mechs set the hash to the sigAlg */
    841    if ((cx->hashAlg != cx->encAlg) &&
    842        (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL)) {
    843        /* error set by HASH_GetHashTypeByOidTag */
    844        goto loser;
    845    }
    846    /* check the policy on the hash algorithm. Do this after
    847     * the rsa decode because some uses of this function get hash implicitly
    848     * from the RSA signature itself. */
    849    if ((NSS_GetAlgorithmPolicy(cx->hashAlg, &policyFlags) == SECFailure) ||
    850        !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
    851        PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
    852        goto loser;
    853    }
    854 
    855    if (hash) {
    856        *hash = cx->hashAlg;
    857    }
    858    return cx;
    859 
    860 loser:
    861    if (cx) {
    862        VFY_DestroyContext(cx, PR_TRUE);
    863    }
    864    return 0;
    865 }
    866 
    867 VFYContext *
    868 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
    869                  void *wincx)
    870 {
    871    SECOidTag encAlg, hashAlg;
    872    CK_MECHANISM_TYPE mech;
    873    SECItem mechparams;
    874    SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg,
    875                                    &mech, &mechparams);
    876    if (rv != SECSuccess) {
    877        return NULL;
    878    }
    879    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech,
    880                             &mechparams, NULL, PR_FALSE, wincx);
    881 }
    882 
    883 VFYContext *
    884 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
    885                        SECOidTag encAlg, SECOidTag hashAlg,
    886                        SECOidTag *hash, void *wincx)
    887 {
    888    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
    889    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, NULL,
    890                             hash, PR_FALSE, wincx);
    891 }
    892 
    893 VFYContext *
    894 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
    895                                 const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
    896 {
    897    SECOidTag encAlg, hashAlg;
    898    CK_MECHANISM_TYPE mech;
    899    SECItem mechparams;
    900    SECStatus rv = sec_DecodeSigAlg(key,
    901                                    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
    902                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
    903                                    &mech, &mechparams);
    904    if (rv != SECSuccess) {
    905        return NULL;
    906    }
    907 
    908    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, &mechparams,
    909                             hash, PR_FALSE, wincx);
    910 }
    911 
    912 void
    913 VFY_DestroyContext(VFYContext *cx, PRBool freeit)
    914 {
    915    if (cx) {
    916        if (cx->hashcx != NULL) {
    917            (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
    918            cx->hashcx = NULL;
    919        }
    920        if (cx->vfycx != NULL) {
    921            (void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
    922            cx->vfycx = NULL;
    923        }
    924        if (cx->key) {
    925            SECKEY_DestroyPublicKey(cx->key);
    926        }
    927        if (cx->pkcs1RSADigestInfo) {
    928            PORT_Free(cx->pkcs1RSADigestInfo);
    929        }
    930        SECITEM_FreeItem(&cx->mechparams, PR_FALSE);
    931        if (freeit) {
    932            PORT_ZFree(cx, sizeof(VFYContext));
    933        }
    934    }
    935 }
    936 
    937 SECStatus
    938 VFY_Begin(VFYContext *cx)
    939 {
    940    if (cx->hashcx != NULL) {
    941        (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
    942        cx->hashcx = NULL;
    943    }
    944    if (cx->vfycx != NULL) {
    945        (void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
    946        cx->vfycx = NULL;
    947    }
    948    if (cx->mech != CKM_INVALID_MECHANISM) {
    949        PK11SlotInfo *slot = cx->key->pkcs11Slot;
    950        if (cx->hasSignature &&
    951            (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE) >= 0)) {
    952            SECItem sig = { siBuffer, cx->u.gensig, cx->signatureLen };
    953            cx->vfycx = PK11_CreateSignatureContextByPubKey(cx->mech,
    954                                                            CKA_NSS_VERIFY_SIGNATURE,
    955                                                            cx->key,
    956                                                            &cx->mechparams,
    957                                                            &sig, cx->wincx);
    958        } else {
    959            cx->vfycx = PK11_CreateContextByPubKey(cx->mech, CKA_VERIFY,
    960                                                   cx->key, &cx->mechparams,
    961                                                   cx->wincx);
    962        }
    963        if (!cx->vfycx)
    964            return SECFailure;
    965        return SECSuccess;
    966    }
    967    cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
    968    if (!cx->hashobj)
    969        return SECFailure; /* error code is set */
    970 
    971    cx->hashcx = (*cx->hashobj->create)();
    972    if (cx->hashcx == NULL)
    973        return SECFailure;
    974 
    975    (*cx->hashobj->begin)(cx->hashcx);
    976    return SECSuccess;
    977 }
    978 
    979 SECStatus
    980 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
    981 {
    982    if (cx->hashcx == NULL) {
    983        if (cx->vfycx == NULL) {
    984            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    985            return SECFailure;
    986        }
    987        return PK11_DigestOp(cx->vfycx, input, inputLen);
    988    }
    989    (*cx->hashobj->update)(cx->hashcx, input, inputLen);
    990    return SECSuccess;
    991 }
    992 
    993 static SECStatus
    994 vfy_SingleShot(VFYContext *cx, const unsigned char *buf, int len)
    995 {
    996    SECStatus rv;
    997    /* if we have the combo mechanism, do a direct verify */
    998    if (cx->mech != CKM_INVALID_MECHANISM) {
    999        SECItem sig = { siBuffer, cx->u.gensig, cx->signatureLen };
   1000        SECItem data = { siBuffer, (unsigned char *)buf, len };
   1001        return PK11_VerifyWithMechanism(cx->key, cx->mech, &cx->mechparams,
   1002                                        &sig, &data, cx->wincx);
   1003    }
   1004    rv = VFY_Begin(cx);
   1005    if (rv != SECSuccess) {
   1006        return rv;
   1007    }
   1008    rv = VFY_Update(cx, (unsigned char *)buf, len);
   1009    if (rv != SECSuccess) {
   1010        return rv;
   1011    }
   1012    return VFY_End(cx);
   1013 }
   1014 
   1015 SECStatus
   1016 VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
   1017 {
   1018    unsigned char final[HASH_LENGTH_MAX];
   1019    unsigned part;
   1020    SECStatus rv;
   1021 
   1022    /* make sure our signature is set (either previously nor now) */
   1023    if (sig) {
   1024        rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
   1025        if (rv != SECSuccess) {
   1026            return SECFailure;
   1027        }
   1028    } else if (cx->hasSignature == PR_FALSE) {
   1029        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1030        return SECFailure;
   1031    }
   1032 
   1033    if (cx->hashcx == NULL) {
   1034        unsigned int dummy;
   1035        if (cx->vfycx == NULL) {
   1036            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1037            return SECFailure;
   1038        }
   1039        return PK11_DigestFinal(cx->vfycx, cx->u.gensig, &dummy,
   1040                                cx->signatureLen);
   1041    }
   1042    (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
   1043    SECItem gensig = { siBuffer, cx->u.gensig, cx->signatureLen };
   1044    SECItem hash = { siBuffer, final, part };
   1045    PORT_Assert(part <= sizeof(final));
   1046    /* handle the algorithm specific final call */
   1047    switch (cx->key->keyType) {
   1048        case ecKey:
   1049        case dsaKey:
   1050            if (PK11_Verify(cx->key, &gensig, &hash, cx->wincx) != SECSuccess) {
   1051                PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1052                return SECFailure;
   1053            }
   1054            break;
   1055        case rsaKey:
   1056            if (cx->encAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
   1057                if (PK11_VerifyWithMechanism(cx->key, CKM_RSA_PKCS_PSS,
   1058                                             &cx->mechparams, &gensig, &hash,
   1059                                             cx->wincx) != SECSuccess) {
   1060                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1061                    return SECFailure;
   1062                }
   1063            } else {
   1064                if (sig) {
   1065                    SECOidTag hashid;
   1066                    PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
   1067                    rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
   1068                                                &cx->pkcs1RSADigestInfo,
   1069                                                &cx->pkcs1RSADigestInfoLen,
   1070                                                cx->key,
   1071                                                sig, cx->wincx);
   1072                    if (rv != SECSuccess) {
   1073                        return SECFailure;
   1074                    }
   1075                    PORT_Assert(cx->hashAlg == hashid);
   1076                }
   1077                return verifyPKCS1DigestInfo(cx, &hash);
   1078            }
   1079            break;
   1080        default:
   1081            PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1082            return SECFailure; /* shouldn't happen */
   1083    }
   1084    return SECSuccess;
   1085 }
   1086 
   1087 SECStatus
   1088 VFY_End(VFYContext *cx)
   1089 {
   1090    return VFY_EndWithSignature(cx, NULL);
   1091 }
   1092 
   1093 /************************************************************************/
   1094 /*
   1095 * Verify that a previously-computed digest matches a signature.
   1096 */
   1097 static SECStatus
   1098 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
   1099                 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
   1100                 CK_MECHANISM_TYPE mech, SECItem *mechparamsp, void *wincx)
   1101 {
   1102    SECStatus rv;
   1103    VFYContext *cx;
   1104    SECItem dsasig; /* also used for ECDSA */
   1105    rv = SECFailure;
   1106 
   1107    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
   1108                           NULL, PR_TRUE, wincx);
   1109    if (cx != NULL) {
   1110        switch (key->keyType) {
   1111            case rsaKey:
   1112                /* PSS isn't handled here for VerifyDigest. SSL
   1113                 * calls PK11_Verify directly */
   1114                rv = verifyPKCS1DigestInfo(cx, digest);
   1115                /* Error (if any) set by verifyPKCS1DigestInfo */
   1116                break;
   1117            case ecKey:
   1118            case dsaKey:
   1119                dsasig.data = cx->u.buffer;
   1120                dsasig.len = checkedSignatureLen(cx->key);
   1121                if (dsasig.len == 0) {
   1122                    /* Error set by checkedSignatureLen */
   1123                    rv = SECFailure;
   1124                    break;
   1125                }
   1126                if (dsasig.len > sizeof(cx->u)) {
   1127                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1128                    rv = SECFailure;
   1129                    break;
   1130                }
   1131                rv = PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx);
   1132                if (rv != SECSuccess) {
   1133                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1134                }
   1135                break;
   1136            case mldsaKey:
   1137            default:
   1138                PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
   1139                break;
   1140        }
   1141        VFY_DestroyContext(cx, PR_TRUE);
   1142    }
   1143    return rv;
   1144 }
   1145 
   1146 SECStatus
   1147 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
   1148                       const SECItem *sig, SECOidTag encAlg,
   1149                       SECOidTag hashAlg, void *wincx)
   1150 {
   1151    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
   1152    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, mech,
   1153                            NULL, wincx);
   1154 }
   1155 
   1156 SECStatus
   1157 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
   1158                 SECOidTag algid, void *wincx)
   1159 {
   1160    SECOidTag encAlg, hashAlg;
   1161    CK_MECHANISM_TYPE mech;
   1162    SECItem mechparams;
   1163    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
   1164                                    &mech, &mechparams);
   1165    if (rv != SECSuccess) {
   1166        return SECFailure;
   1167    }
   1168    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
   1169                            mech, &mechparams, wincx);
   1170 }
   1171 
   1172 /*
   1173 * this function takes an optional hash oid, which the digest function
   1174 * will be compared with our target hash value.
   1175 */
   1176 SECStatus
   1177 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
   1178                                const SECKEYPublicKey *key, const SECItem *sig,
   1179                                const SECAlgorithmID *sigAlgorithm,
   1180                                SECOidTag hashCmp, void *wincx)
   1181 {
   1182    SECOidTag encAlg, hashAlg;
   1183    CK_MECHANISM_TYPE mech;
   1184    SECItem mechparams;
   1185    SECStatus rv = sec_DecodeSigAlg(key,
   1186                                    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
   1187                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
   1188                                    &mech, &mechparams);
   1189    if (rv != SECSuccess) {
   1190        return rv;
   1191    }
   1192    if (hashCmp != SEC_OID_UNKNOWN &&
   1193        hashAlg != SEC_OID_UNKNOWN &&
   1194        hashCmp != hashAlg) {
   1195        if (mechparams.data != NULL) {
   1196            PORT_Free(mechparams.data);
   1197        }
   1198        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1199        return SECFailure;
   1200    }
   1201    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
   1202                            mech, &mechparams, wincx);
   1203 }
   1204 
   1205 static SECStatus
   1206 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
   1207               const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
   1208               CK_MECHANISM_TYPE mech, SECItem *mechparamsp,
   1209               SECOidTag *hash, void *wincx)
   1210 {
   1211    SECStatus rv;
   1212    VFYContext *cx;
   1213 
   1214    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
   1215                           hash, PR_FALSE, wincx);
   1216    if (cx == NULL)
   1217        return SECFailure;
   1218 
   1219    rv = vfy_SingleShot(cx, buf, len);
   1220 
   1221    VFY_DestroyContext(cx, PR_TRUE);
   1222    return rv;
   1223 }
   1224 
   1225 SECStatus
   1226 VFY_VerifyDataDirect(const unsigned char *buf, int len,
   1227                     const SECKEYPublicKey *key, const SECItem *sig,
   1228                     SECOidTag encAlg, SECOidTag hashAlg,
   1229                     SECOidTag *hash, void *wincx)
   1230 {
   1231    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
   1232    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech, NULL,
   1233                          hash, wincx);
   1234 }
   1235 
   1236 SECStatus
   1237 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
   1238               const SECItem *sig, SECOidTag algid, void *wincx)
   1239 {
   1240    SECOidTag encAlg, hashAlg;
   1241    CK_MECHANISM_TYPE mech;
   1242    SECItem mechparams;
   1243    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
   1244                                    &mech, &mechparams);
   1245    if (rv != SECSuccess) {
   1246        return rv;
   1247    }
   1248    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
   1249                          mech, &mechparams, NULL, wincx);
   1250 }
   1251 
   1252 SECStatus
   1253 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
   1254                              const SECKEYPublicKey *key,
   1255                              const SECItem *sig,
   1256                              const SECAlgorithmID *sigAlgorithm,
   1257                              SECOidTag *hash, void *wincx)
   1258 {
   1259    SECOidTag encAlg, hashAlg;
   1260    SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
   1261    CK_MECHANISM_TYPE mech;
   1262    SECItem mechparams;
   1263    SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
   1264                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
   1265                                    &mech, &mechparams);
   1266    if (rv != SECSuccess) {
   1267        return rv;
   1268    }
   1269    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech,
   1270                          &mechparams, hash, wincx);
   1271 }