tor-browser

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

pk11pbe.c (51632B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "plarena.h"
      6 
      7 #include "blapit.h"
      8 #include "seccomon.h"
      9 #include "secitem.h"
     10 #include "secport.h"
     11 #include "hasht.h"
     12 #include "pkcs11t.h"
     13 #include "sechash.h"
     14 #include "secasn1.h"
     15 #include "secder.h"
     16 #include "secoid.h"
     17 #include "secerr.h"
     18 #include "secmod.h"
     19 #include "pk11func.h"
     20 #include "secpkcs5.h"
     21 #include "secmodi.h"
     22 #include "secmodti.h"
     23 #include "pkcs11.h"
     24 #include "pk11func.h"
     25 #include "secitem.h"
     26 #include "keyhi.h"
     27 
     28 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
     29 struct SEC_PKCS5PBEParameterStr {
     30    PLArenaPool *poolp;
     31    SECItem salt;              /* octet string */
     32    SECItem iteration;         /* integer */
     33    SECItem keyLength;         /* PKCS5v2 only */
     34    SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */
     35    SECAlgorithmID prfAlgId;   /* PKCS5v2 only */
     36 };
     37 
     38 /* PKCS5 V2 has an algorithm ID for the encryption and for
     39 * the key generation. This is valid for SEC_OID_PKCS5_PBES2
     40 * and SEC_OID_PKCS5_PBMAC1
     41 */
     42 struct sec_pkcs5V2ParameterStr {
     43    PLArenaPool *poolp;
     44    SECAlgorithmID pbeAlgId;    /* real pbe algorithms */
     45    SECAlgorithmID cipherAlgId; /* encryption/mac */
     46 };
     47 
     48 typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter;
     49 
     50 /* template for PKCS 5 PBE Parameter.  This template has been expanded
     51 * based upon the additions in PKCS 12.  This should eventually be moved
     52 * if RSA updates PKCS 5.
     53 */
     54 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = {
     55    { SEC_ASN1_SEQUENCE,
     56      0, NULL, sizeof(SEC_PKCS5PBEParameter) },
     57    { SEC_ASN1_OCTET_STRING,
     58      offsetof(SEC_PKCS5PBEParameter, salt) },
     59    { SEC_ASN1_INTEGER,
     60      offsetof(SEC_PKCS5PBEParameter, iteration) },
     61    { 0 }
     62 };
     63 
     64 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = {
     65    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
     66    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
     67    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
     68    { 0 }
     69 };
     70 
     71 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
     72 
     73 /* SECOID_PKCS5_PBKDF2 */
     74 const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] = {
     75    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
     76    /* This is really a choice, but since we only understand this
     77     * choice, just inline it */
     78    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
     79    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
     80    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL,
     81      offsetof(SEC_PKCS5PBEParameter, keyLength) },
     82    { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL,
     83      offsetof(SEC_PKCS5PBEParameter, pPrfAlgId),
     84      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     85    { 0 }
     86 };
     87 
     88 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
     89 const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] = {
     90    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
     91    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId),
     92      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     93    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     94      offsetof(sec_pkcs5V2Parameter, cipherAlgId),
     95      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     96    { 0 }
     97 };
     98 
     99 /*
    100 * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1
    101 * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2.
    102 */
    103 SECOidTag
    104 sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
    105 {
    106    switch (algorithm) {
    107        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
    108        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
    109        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
    110            return SEC_OID_DES_EDE3_CBC;
    111        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
    112        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
    113        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
    114            return SEC_OID_DES_CBC;
    115        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    116        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    117        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    118        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    119            return SEC_OID_RC2_CBC;
    120        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
    121        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
    122        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
    123        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
    124            return SEC_OID_RC4;
    125        case SEC_OID_PKCS5_PBKDF2:
    126        case SEC_OID_PKCS5_PBES2:
    127        case SEC_OID_PKCS5_PBMAC1:
    128            return SEC_OID_PKCS5_PBKDF2;
    129        default:
    130            break;
    131    }
    132 
    133    return SEC_OID_UNKNOWN;
    134 }
    135 
    136 /*
    137 * only gets the tag from PKCS5v1 or PKCS12pbe.
    138 * PKCS5v2 requires the algid to get the full thing
    139 */
    140 SECOidTag
    141 SEC_PKCS5GetHashFromAlgTag(SECOidTag algtag)
    142 {
    143    switch (algtag) {
    144        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
    145        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
    146        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
    147        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
    148        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    149        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    150        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    151        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    152        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
    153        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
    154        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
    155        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
    156            return SEC_OID_SHA1;
    157        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
    158            return SEC_OID_MD5;
    159        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
    160            return SEC_OID_MD2;
    161        default:
    162            break;
    163    }
    164    return SEC_OID_UNKNOWN;
    165 }
    166 
    167 /*
    168 * get a new PKCS5 V2 Parameter from the algorithm id.
    169 *  if arena is passed in, use it, otherwise create a new arena.
    170 */
    171 sec_pkcs5V2Parameter *
    172 sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid)
    173 {
    174    PLArenaPool *localArena = NULL;
    175    sec_pkcs5V2Parameter *pbeV2_param;
    176    SECStatus rv;
    177 
    178    if (arena == NULL) {
    179        localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    180        if (arena == NULL) {
    181            return NULL;
    182        }
    183    }
    184    pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter);
    185    if (pbeV2_param == NULL) {
    186        goto loser;
    187    }
    188 
    189    rv = SEC_ASN1DecodeItem(arena, pbeV2_param,
    190                            SEC_PKCS5V2ParameterTemplate, &algid->parameters);
    191    if (rv == SECFailure) {
    192        goto loser;
    193    }
    194 
    195    pbeV2_param->poolp = arena;
    196    return pbeV2_param;
    197 loser:
    198    if (localArena) {
    199        PORT_FreeArena(arena, PR_FALSE);
    200    }
    201    return NULL;
    202 }
    203 
    204 void
    205 sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
    206 {
    207    if (param && param->poolp) {
    208        PORT_FreeArena(param->poolp, PR_TRUE);
    209    }
    210 }
    211 
    212 /* maps crypto algorithm from PBE algorithm.
    213 */
    214 SECOidTag
    215 SEC_PKCS5GetHashAlgorithm(SECAlgorithmID *algid)
    216 {
    217 
    218    SECOidTag pbeAlg;
    219    SECOidTag hashAlg = SEC_OID_UNKNOWN;
    220    PLArenaPool *arena = NULL;
    221 
    222    if (algid == NULL)
    223        return SEC_OID_UNKNOWN;
    224 
    225    pbeAlg = SECOID_GetAlgorithmTag(algid);
    226    /* if we are using a PKCS 5v2 algorithm, get the hash from the parameters */
    227    if ((pbeAlg == SEC_OID_PKCS5_PBES2) ||
    228        (pbeAlg == SEC_OID_PKCS5_PBMAC1)) {
    229        SEC_PKCS5PBEParameter p5_param;
    230        sec_pkcs5V2Parameter *pbeV2_param;
    231        SECOidTag kdfAlg;
    232        SECStatus rv;
    233 
    234        arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    235        if (arena == NULL) {
    236            goto loser;
    237        }
    238 
    239        pbeV2_param = sec_pkcs5_v2_get_v2_param(arena, algid);
    240        if (pbeV2_param == NULL) {
    241            goto loser;
    242        }
    243 
    244        kdfAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
    245        /* sanity check, they should all be PBKDF2 here */
    246        if (kdfAlg != SEC_OID_PKCS5_PBKDF2) {
    247            goto loser;
    248        }
    249 
    250        PORT_Memset(&p5_param, 0, sizeof(p5_param));
    251        rv = SEC_ASN1DecodeItem(arena, &p5_param,
    252                                SEC_PKCS5V2PBEParameterTemplate,
    253                                &pbeV2_param->pbeAlgId.parameters);
    254        if (rv != SECSuccess) {
    255            goto loser;
    256        }
    257        /* if the prf does not exist, it defaults to SHA1 */
    258        hashAlg = SEC_OID_SHA1;
    259        if (p5_param.pPrfAlgId &&
    260            p5_param.pPrfAlgId->algorithm.data != 0) {
    261            hashAlg = HASH_GetHashOidTagByHMACOidTag(
    262                SECOID_GetAlgorithmTag(p5_param.pPrfAlgId));
    263        }
    264    } else {
    265        return SEC_PKCS5GetHashFromAlgTag(pbeAlg);
    266    }
    267 loser:
    268    if (arena != NULL) {
    269        PORT_FreeArena(arena, PR_FALSE);
    270    }
    271 
    272    return hashAlg;
    273 }
    274 
    275 /* maps crypto algorithm from PBE algorithm.
    276 */
    277 SECOidTag
    278 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
    279 {
    280 
    281    SECOidTag pbeAlg;
    282    SECOidTag cipherAlg;
    283 
    284    if (algid == NULL)
    285        return SEC_OID_UNKNOWN;
    286 
    287    pbeAlg = SECOID_GetAlgorithmTag(algid);
    288    cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg);
    289    if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) &&
    290        (pbeAlg != SEC_OID_PKCS5_PBKDF2)) {
    291        sec_pkcs5V2Parameter *pbeV2_param;
    292        cipherAlg = SEC_OID_UNKNOWN;
    293 
    294        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
    295        if (pbeV2_param != NULL) {
    296            cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId);
    297            sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
    298        }
    299    }
    300 
    301    return cipherAlg;
    302 }
    303 
    304 /*
    305 * only gets the tag from PKCS5v1 or PKCS12pbe.
    306 * PKCS5v2 requires the algid to get the full thing
    307 */
    308 SECOidTag
    309 SEC_PKCS5GetCryptoFromAlgTag(SECOidTag algtag)
    310 {
    311    SECOidTag cipherAlg;
    312    cipherAlg = sec_pkcs5GetCryptoFromAlgTag(algtag);
    313    if (cipherAlg == SEC_OID_PKCS5_PBKDF2) {
    314        return SEC_OID_UNKNOWN;
    315    }
    316    return cipherAlg;
    317 }
    318 
    319 /* check to see if an oid is a pbe algorithm
    320 */
    321 PRBool
    322 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
    323 {
    324    return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
    325 }
    326 
    327 PRBool
    328 SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag)
    329 {
    330    return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN);
    331 }
    332 
    333 /*
    334 * find the most appropriate PKCS5v2 overall oid tag from a regular
    335 * cipher/hash algorithm tag.
    336 */
    337 static SECOidTag
    338 sec_pkcs5v2_get_pbe(SECOidTag algTag)
    339 {
    340    /* if it's a valid hash oid... */
    341    if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) {
    342        /* use the MAC tag */
    343        return SEC_OID_PKCS5_PBMAC1;
    344    }
    345    if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) {
    346        /* eliminate Hash algorithms */
    347        return SEC_OID_UNKNOWN;
    348    }
    349    if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) {
    350        /* it's not a hash, if it has a PKCS #11 mechanism associated
    351         * with it, assume it's a cipher. (NOTE this will generate
    352         * some false positives). */
    353        return SEC_OID_PKCS5_PBES2;
    354    }
    355    return SEC_OID_UNKNOWN;
    356 }
    357 
    358 /*
    359 * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
    360 *  input keyLen in bits.
    361 */
    362 SECOidTag
    363 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
    364 {
    365    switch (algTag) {
    366        case SEC_OID_DES_EDE3_CBC:
    367            switch (keyLen) {
    368                case 168:
    369                case 192:
    370                case 0:
    371                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
    372                case 128:
    373                case 92:
    374                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
    375                default:
    376                    break;
    377            }
    378            break;
    379        case SEC_OID_DES_CBC:
    380            return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
    381        case SEC_OID_RC2_CBC:
    382            switch (keyLen) {
    383                case 40:
    384                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
    385                case 128:
    386                case 0:
    387                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
    388                default:
    389                    break;
    390            }
    391            break;
    392        case SEC_OID_RC4:
    393            switch (keyLen) {
    394                case 40:
    395                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
    396                case 128:
    397                case 0:
    398                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
    399                default:
    400                    break;
    401            }
    402            break;
    403        default:
    404            return sec_pkcs5v2_get_pbe(algTag);
    405    }
    406 
    407    return SEC_OID_UNKNOWN;
    408 }
    409 
    410 /*
    411 * Some oids encode the key size in the oid, while the actual PKCS
    412 * PKCS #11 mechanism does not. In those cases we can't use
    413 * the PKCS #11 automated key length code to select the key size.
    414 */
    415 static int
    416 sec_pkcs5v2_key_length_by_oid(SECOidTag algorithm)
    417 {
    418    switch (algorithm) {
    419        case SEC_OID_AES_128_CBC:
    420        case SEC_OID_CAMELLIA_128_CBC:
    421            return AES_128_KEY_LENGTH;
    422        case SEC_OID_AES_192_CBC:
    423        case SEC_OID_CAMELLIA_192_CBC:
    424            return AES_192_KEY_LENGTH;
    425        case SEC_OID_AES_256_CBC:
    426        case SEC_OID_CAMELLIA_256_CBC:
    427            return AES_256_KEY_LENGTH;
    428        default:
    429            break;
    430    }
    431    return -1;
    432 }
    433 
    434 /* find the keylength from the algorithm id */
    435 static int
    436 sec_pkcs5v2_default_key_length(SECOidTag algorithm)
    437 {
    438    CK_MECHANISM_TYPE cryptoMech;
    439    int key_length = sec_pkcs5v2_key_length_by_oid(algorithm);
    440    if (key_length != -1) {
    441        return key_length;
    442    }
    443    cryptoMech = PK11_AlgtagToMechanism(algorithm);
    444    if (cryptoMech == CKM_INVALID_MECHANISM) {
    445        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    446        return -1;
    447    }
    448    return PK11_GetMaxKeyLength(cryptoMech);
    449 }
    450 
    451 /*
    452 * get the key length in bytes from a PKCS5 PBE
    453 */
    454 static int
    455 sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId)
    456 {
    457    SECOidTag algorithm;
    458    PLArenaPool *arena = NULL;
    459    SEC_PKCS5PBEParameter p5_param;
    460    SECStatus rv;
    461    int length = -1;
    462    SECOidTag cipherAlg = SEC_OID_UNKNOWN;
    463 
    464    algorithm = SECOID_GetAlgorithmTag(algid);
    465    /* sanity check, they should all be PBKDF2 here */
    466    if (algorithm != SEC_OID_PKCS5_PBKDF2) {
    467        return -1;
    468    }
    469 
    470    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    471    if (arena == NULL) {
    472        goto loser;
    473    }
    474    PORT_Memset(&p5_param, 0, sizeof(p5_param));
    475    rv = SEC_ASN1DecodeItem(arena, &p5_param,
    476                            SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
    477    if (rv != SECSuccess) {
    478        goto loser;
    479    }
    480 
    481    if (cipherAlgId)
    482        cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId);
    483 
    484    if (p5_param.keyLength.data != NULL) {
    485        /* if the length is given, accept that length. This
    486         * will allow us to decode old NSS encrypted data
    487         * where we used the MAX keysize for the algorithm,
    488         * but put an incorrect header for a different keysize.
    489         */
    490        length = DER_GetInteger(&p5_param.keyLength);
    491    } else {
    492        /* if the keylength was not specified, figure it
    493         * out from the oid */
    494        length = sec_pkcs5v2_default_key_length(cipherAlg);
    495    }
    496 
    497 loser:
    498    if (arena) {
    499        PORT_FreeArena(arena, PR_FALSE);
    500    }
    501    return length;
    502 }
    503 
    504 /*
    505 *  get the key length in bytes needed for the PBE algorithm
    506 */
    507 int
    508 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
    509 {
    510 
    511    SECOidTag algorithm;
    512 
    513    if (algid == NULL)
    514        return SEC_OID_UNKNOWN;
    515 
    516    algorithm = SECOID_GetAlgorithmTag(algid);
    517 
    518    switch (algorithm) {
    519        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
    520        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
    521        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
    522            return 24;
    523        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
    524        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
    525        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
    526            return 8;
    527        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    528        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
    529        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
    530        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    531            return 5;
    532        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    533        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
    534        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    535        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
    536            return 16;
    537        case SEC_OID_PKCS5_PBKDF2:
    538            return sec_pkcs5v2_key_length(algid, NULL);
    539        case SEC_OID_PKCS5_PBES2:
    540        case SEC_OID_PKCS5_PBMAC1: {
    541            sec_pkcs5V2Parameter *pbeV2_param;
    542            int length = -1;
    543            pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
    544            if (pbeV2_param != NULL) {
    545                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId,
    546                                                &pbeV2_param->cipherAlgId);
    547                sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
    548            }
    549            return length;
    550        }
    551 
    552        default:
    553            break;
    554    }
    555    return -1;
    556 }
    557 
    558 /* the PKCS12 V2 algorithms only encode the salt, there is no iteration
    559 * count so we need a check for V2 algorithm parameters.
    560 */
    561 static PRBool
    562 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
    563 {
    564    switch (algorithm) {
    565        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
    566        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
    567        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
    568        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
    569        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    570        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    571            return PR_TRUE;
    572        default:
    573            break;
    574    }
    575 
    576    return PR_FALSE;
    577 }
    578 
    579 static PRBool
    580 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm)
    581 {
    582    switch (algorithm) {
    583        case SEC_OID_PKCS5_PBES2:
    584        case SEC_OID_PKCS5_PBMAC1:
    585        case SEC_OID_PKCS5_PBKDF2:
    586            return PR_TRUE;
    587        default:
    588            break;
    589    }
    590 
    591    return PR_FALSE;
    592 }
    593 
    594 /* destroy a pbe parameter.  it assumes that the parameter was
    595 * generated using the appropriate create function and therefor
    596 * contains an arena pool.
    597 */
    598 static void
    599 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
    600 {
    601    if (pbe_param != NULL)
    602        PORT_FreeArena(pbe_param->poolp, PR_TRUE);
    603 }
    604 
    605 /* creates a PBE parameter based on the PBE algorithm.  the only required
    606 * parameters are algorithm and interation.  the return is a PBE parameter
    607 * which conforms to PKCS 5 parameter unless an extended parameter is needed.
    608 * this is primarily if keyLength and a variable key length algorithm are
    609 * specified.
    610 *   salt -  if null, a salt will be generated from random bytes.
    611 *   iteration - number of iterations to perform hashing.
    612 *   keyLength - only used in variable key length algorithms. if specified,
    613 *            should be in bytes.
    614 * once a parameter is allocated, it should be destroyed calling
    615 * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
    616 */
    617 #define DEFAULT_SALT_LENGTH 16
    618 static SEC_PKCS5PBEParameter *
    619 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm,
    620                               SECItem *salt,
    621                               int iteration,
    622                               int keyLength,
    623                               SECOidTag prfAlg)
    624 {
    625    PLArenaPool *poolp = NULL;
    626    SEC_PKCS5PBEParameter *pbe_param = NULL;
    627    SECStatus rv = SECSuccess;
    628    void *dummy = NULL;
    629 
    630    if (iteration < 0) {
    631        return NULL;
    632    }
    633 
    634    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    635    if (poolp == NULL)
    636        return NULL;
    637 
    638    pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
    639                                                          sizeof(SEC_PKCS5PBEParameter));
    640    if (!pbe_param) {
    641        PORT_FreeArena(poolp, PR_TRUE);
    642        return NULL;
    643    }
    644 
    645    pbe_param->poolp = poolp;
    646 
    647    rv = SECFailure;
    648    if (salt && salt->data) {
    649        rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
    650    } else {
    651        /* sigh, the old interface generated salt on the fly, so we have to
    652         * preserve the semantics */
    653        pbe_param->salt.len = DEFAULT_SALT_LENGTH;
    654        pbe_param->salt.data = PORT_ArenaZAlloc(poolp, DEFAULT_SALT_LENGTH);
    655        if (pbe_param->salt.data) {
    656            rv = PK11_GenerateRandom(pbe_param->salt.data, DEFAULT_SALT_LENGTH);
    657        }
    658    }
    659 
    660    if (rv != SECSuccess) {
    661        PORT_FreeArena(poolp, PR_TRUE);
    662        return NULL;
    663    }
    664 
    665    /* encode the integer */
    666    dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration,
    667                                  iteration);
    668    rv = (dummy) ? SECSuccess : SECFailure;
    669 
    670    if (rv != SECSuccess) {
    671        PORT_FreeArena(poolp, PR_FALSE);
    672        return NULL;
    673    }
    674 
    675    /*
    676     * for PKCS5 v2 Add the keylength and the prf
    677     */
    678    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
    679        dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength,
    680                                      keyLength);
    681        rv = (dummy) ? SECSuccess : SECFailure;
    682        if (rv != SECSuccess) {
    683            PORT_FreeArena(poolp, PR_FALSE);
    684            return NULL;
    685        }
    686        rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL);
    687        if (rv != SECSuccess) {
    688            PORT_FreeArena(poolp, PR_FALSE);
    689            return NULL;
    690        }
    691        pbe_param->pPrfAlgId = &pbe_param->prfAlgId;
    692    }
    693 
    694    return pbe_param;
    695 }
    696 
    697 /* creates a algorithm ID containing the PBE algorithm and appropriate
    698 * parameters.  the required parameter is the algorithm.  if salt is
    699 * not specified, it is generated randomly.
    700 *
    701 * the returned SECAlgorithmID should be destroyed using
    702 * SECOID_DestroyAlgorithmID
    703 */
    704 SECAlgorithmID *
    705 sec_pkcs5CreateAlgorithmID(SECOidTag algorithm,
    706                           SECOidTag cipherAlgorithm,
    707                           SECOidTag prfAlg,
    708                           SECOidTag *pPbeAlgorithm,
    709                           int keyLength,
    710                           SECItem *salt,
    711                           int iteration)
    712 {
    713    PLArenaPool *poolp = NULL;
    714    SECAlgorithmID *algid, *ret_algid = NULL;
    715    SECOidTag pbeAlgorithm = algorithm;
    716    SECItem der_param;
    717    void *dummy;
    718    SECStatus rv = SECFailure;
    719    SEC_PKCS5PBEParameter *pbe_param = NULL;
    720    sec_pkcs5V2Parameter pbeV2_param;
    721 
    722    if (iteration <= 0) {
    723        return NULL;
    724    }
    725 
    726    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    727    if (!poolp) {
    728        goto loser;
    729    }
    730 
    731    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) ||
    732        sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
    733        /* use PKCS 5 v2 */
    734        SECItem *cipherParams;
    735 
    736        /*
    737         * if we ask for pkcs5 Algorithms directly, then the
    738         * application needs to supply the cipher algorithm,
    739         * otherwise we are implicitly using pkcs5 v2 and the
    740         * passed in algorithm is the encryption algorithm.
    741         */
    742        if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
    743            if (cipherAlgorithm == SEC_OID_UNKNOWN) {
    744                goto loser;
    745            }
    746        } else {
    747            cipherAlgorithm = algorithm;
    748            /* force algorithm to be chosen below */
    749            algorithm = SEC_OID_PKCS5_PBKDF2;
    750        }
    751 
    752        pbeAlgorithm = SEC_OID_PKCS5_PBKDF2;
    753        /*
    754         * 'algorithm' is the overall algorithm oid tag used to wrap the
    755         * entire algorithm ID block. For PKCS5v1 and PKCS12, this
    756         * algorithm OID has encoded in it both the PBE KDF function
    757         * and the encryption algorithm. For PKCS 5v2, PBE KDF and
    758         * encryption/macing oids are encoded as parameters in
    759         * the algorithm ID block.
    760         *
    761         * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11
    762         * mechanism, where as in PKCS 5v2, this algorithm tag does not map
    763         * directly to a PKCS #11 mechanim, instead the 2 oids in the
    764         * algorithm ID block map the the actual PKCS #11 mechanism.
    765         * algorithm is). We use choose this algorithm oid based on the
    766         * cipherAlgorithm to determine what this should be (MAC1 or PBES2).
    767         */
    768        if (algorithm == SEC_OID_PKCS5_PBKDF2) {
    769            /* choose mac or pbes */
    770            algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
    771        }
    772 
    773        SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
    774 
    775        /* set the PKCS5v2 specific parameters */
    776        if (keyLength == 0) {
    777            if (hashAlg != SEC_OID_UNKNOWN) {
    778                keyLength = HASH_ResultLenByOidTag(hashAlg);
    779            } else {
    780                keyLength = sec_pkcs5v2_default_key_length(cipherAlgorithm);
    781            }
    782            if (keyLength <= 0) {
    783                goto loser;
    784            }
    785        }
    786        /* currently SEC_OID_HMAC_SHA1 is the default */
    787        if (prfAlg == SEC_OID_UNKNOWN) {
    788            prfAlg = SEC_OID_HMAC_SHA1;
    789        }
    790 
    791        /* build the PKCS5v2 cipher algorithm id, if cipher
    792         * is an HMAC, the cipherParams should be NULL */
    793        if (hashAlg == SEC_OID_UNKNOWN) {
    794            cipherParams = pk11_GenerateNewParamWithKeyLen(
    795                PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
    796            if (!cipherParams) {
    797                goto loser;
    798            }
    799        } else {
    800            cipherParams = NULL;
    801        }
    802 
    803        PORT_Memset(&pbeV2_param, 0, sizeof(pbeV2_param));
    804 
    805        rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams,
    806                               poolp, &pbeV2_param.cipherAlgId);
    807        if (cipherParams) {
    808            SECITEM_FreeItem(cipherParams, PR_TRUE);
    809        }
    810        if (rv != SECSuccess) {
    811            goto loser;
    812        }
    813    }
    814 
    815    /* generate the parameter */
    816    pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
    817                                               keyLength, prfAlg);
    818    if (!pbe_param) {
    819        goto loser;
    820    }
    821 
    822    /* generate the algorithm id */
    823    algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
    824    if (algid == NULL) {
    825        goto loser;
    826    }
    827 
    828    der_param.data = NULL;
    829    der_param.len = 0;
    830    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
    831        /* first encode the PBE algorithm ID */
    832        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
    833                                   SEC_PKCS5V2PBEParameterTemplate);
    834        if (dummy == NULL) {
    835            goto loser;
    836        }
    837        rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId,
    838                                   pbeAlgorithm, &der_param);
    839        if (rv != SECSuccess) {
    840            goto loser;
    841        }
    842 
    843        /* now encode the Full PKCS 5 parameter */
    844        der_param.data = NULL;
    845        der_param.len = 0;
    846        dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param,
    847                                   SEC_PKCS5V2ParameterTemplate);
    848    } else if (!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
    849        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
    850                                   SEC_PKCS5PBEParameterTemplate);
    851    } else {
    852        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
    853                                   SEC_V2PKCS12PBEParameterTemplate);
    854    }
    855    if (dummy == NULL) {
    856        goto loser;
    857    }
    858 
    859    rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
    860    if (rv != SECSuccess) {
    861        goto loser;
    862    }
    863 
    864    ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
    865    if (ret_algid == NULL) {
    866        goto loser;
    867    }
    868 
    869    rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
    870    if (rv != SECSuccess) {
    871        SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
    872        ret_algid = NULL;
    873    } else if (pPbeAlgorithm) {
    874        *pPbeAlgorithm = pbeAlgorithm;
    875    }
    876 
    877 loser:
    878    if (poolp != NULL) {
    879        PORT_FreeArena(poolp, PR_TRUE);
    880        algid = NULL;
    881    }
    882 
    883    if (pbe_param) {
    884        sec_pkcs5_destroy_pbe_param(pbe_param);
    885    }
    886 
    887    return ret_algid;
    888 }
    889 
    890 SECStatus
    891 pbe_PK11AlgidToParam(SECAlgorithmID *algid, SECItem *mech)
    892 {
    893    SEC_PKCS5PBEParameter p5_param;
    894    SECItem *salt = NULL;
    895    SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
    896    PLArenaPool *arena = NULL;
    897    SECStatus rv = SECFailure;
    898    unsigned char *paramData = NULL;
    899    unsigned char *pSalt = NULL;
    900    CK_ULONG iterations;
    901    int paramLen = 0;
    902    int iv_len = -1;
    903 
    904    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    905    if (arena == NULL) {
    906        goto loser;
    907    }
    908 
    909    /*
    910     * decode the algid based on the pbe type
    911     */
    912    PORT_Memset(&p5_param, 0, sizeof(p5_param));
    913    if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
    914        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
    915        rv = SEC_ASN1DecodeItem(arena, &p5_param,
    916                                SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
    917    } else if (algorithm == SEC_OID_PKCS5_PBKDF2) {
    918        iv_len = 0;
    919        rv = SEC_ASN1DecodeItem(arena, &p5_param,
    920                                SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
    921    } else {
    922        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
    923        rv = SEC_ASN1DecodeItem(arena, &p5_param, SEC_PKCS5PBEParameterTemplate,
    924                                &algid->parameters);
    925    }
    926 
    927    if (iv_len < 0) {
    928        goto loser;
    929    }
    930 
    931    if (rv != SECSuccess) {
    932        goto loser;
    933    }
    934 
    935    /* get salt */
    936    salt = &p5_param.salt;
    937    iterations = (CK_ULONG)DER_GetInteger(&p5_param.iteration);
    938 
    939    /* allocate and fill in the PKCS #11 parameters
    940     * based on the algorithm. */
    941    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
    942        SECOidTag prfAlgTag;
    943        CK_PKCS5_PBKD2_PARAMS2 *pbeV2_params =
    944            (CK_PKCS5_PBKD2_PARAMS2 *)PORT_ZAlloc(
    945                PR_MAX(sizeof(CK_PKCS5_PBKD2_PARAMS2), sizeof(CK_PKCS5_PBKD2_PARAMS)) + salt->len);
    946 
    947        if (pbeV2_params == NULL) {
    948            goto loser;
    949        }
    950        paramData = (unsigned char *)pbeV2_params;
    951        paramLen = PR_MAX(sizeof(CK_PKCS5_PBKD2_PARAMS2), sizeof(CK_PKCS5_PBKD2_PARAMS));
    952 
    953        /* set the prf */
    954        prfAlgTag = SEC_OID_HMAC_SHA1;
    955        if (p5_param.pPrfAlgId &&
    956            p5_param.pPrfAlgId->algorithm.data != 0) {
    957            prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId);
    958        }
    959        switch (prfAlgTag) {
    960            case SEC_OID_HMAC_SHA1:
    961                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
    962                break;
    963            case SEC_OID_HMAC_SHA224:
    964                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA224;
    965                break;
    966            case SEC_OID_HMAC_SHA256:
    967                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA256;
    968                break;
    969            case SEC_OID_HMAC_SHA384:
    970                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA384;
    971                break;
    972            case SEC_OID_HMAC_SHA512:
    973                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA512;
    974                break;
    975            default:
    976                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    977                goto loser;
    978        }
    979 
    980        /* probably should fetch these from the prfAlgid */
    981        pbeV2_params->pPrfData = NULL;
    982        pbeV2_params->ulPrfDataLen = 0;
    983        pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
    984        pSalt = ((CK_CHAR_PTR)pbeV2_params) + PR_MAX(sizeof(CK_PKCS5_PBKD2_PARAMS2), sizeof(CK_PKCS5_PBKD2_PARAMS));
    985        if (salt->data) {
    986            PORT_Memcpy(pSalt, salt->data, salt->len);
    987        }
    988        pbeV2_params->pSaltSourceData = pSalt;
    989        pbeV2_params->ulSaltSourceDataLen = salt->len;
    990        pbeV2_params->iterations = iterations;
    991    } else {
    992        CK_PBE_PARAMS *pbe_params = NULL;
    993        pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS) +
    994                                                  salt->len + iv_len);
    995        if (pbe_params == NULL) {
    996            goto loser;
    997        }
    998        paramData = (unsigned char *)pbe_params;
    999        paramLen = sizeof(CK_PBE_PARAMS);
   1000 
   1001        pSalt = ((CK_CHAR_PTR)pbe_params) + sizeof(CK_PBE_PARAMS);
   1002        pbe_params->pSalt = pSalt;
   1003        if (salt->data) {
   1004            PORT_Memcpy(pSalt, salt->data, salt->len);
   1005        }
   1006        pbe_params->ulSaltLen = salt->len;
   1007        if (iv_len) {
   1008            pbe_params->pInitVector =
   1009                ((CK_CHAR_PTR)pbe_params) + sizeof(CK_PBE_PARAMS) + salt->len;
   1010        }
   1011        pbe_params->ulIteration = iterations;
   1012    }
   1013 
   1014    /* copy into the mechanism sec item */
   1015    mech->data = paramData;
   1016    mech->len = paramLen;
   1017    if (arena) {
   1018        PORT_FreeArena(arena, PR_TRUE);
   1019    }
   1020    return SECSuccess;
   1021 
   1022 loser:
   1023    if (paramData) {
   1024        PORT_Free(paramData);
   1025    }
   1026    if (arena) {
   1027        PORT_FreeArena(arena, PR_TRUE);
   1028    }
   1029    return SECFailure;
   1030 }
   1031 
   1032 /*
   1033 * public, deprecated, not valid for pkcs5 v2
   1034 *
   1035 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
   1036 * PBE algorithmID's directly.
   1037 */
   1038 SECStatus
   1039 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena,
   1040                     SECAlgorithmID *algId)
   1041 {
   1042    CK_PBE_PARAMS *pbe_param;
   1043    SECItem pbeSalt;
   1044    SECAlgorithmID *pbeAlgID = NULL;
   1045    SECStatus rv;
   1046 
   1047    if (!param || !algId) {
   1048        return SECFailure;
   1049    }
   1050 
   1051    pbe_param = (CK_PBE_PARAMS *)param->data;
   1052    pbeSalt.data = (unsigned char *)pbe_param->pSalt;
   1053    pbeSalt.len = pbe_param->ulSaltLen;
   1054    pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN,
   1055                                          SEC_OID_UNKNOWN, NULL, 0,
   1056                                          &pbeSalt, (int)pbe_param->ulIteration);
   1057    if (!pbeAlgID) {
   1058        return SECFailure;
   1059    }
   1060 
   1061    rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
   1062    SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
   1063    return rv;
   1064 }
   1065 
   1066 /*
   1067 * public, Deprecated, This function is only for binary compatibility with
   1068 * older applications. Does not support PKCS5v2.
   1069 *
   1070 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
   1071 * iv values rather than generating PBE bits directly.
   1072 */
   1073 PBEBitGenContext *
   1074 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
   1075                  SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
   1076                  unsigned int iterations)
   1077 {
   1078    SECItem *context = NULL;
   1079    SECItem mechItem;
   1080    CK_PBE_PARAMS pbe_params;
   1081    CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
   1082    PK11SlotInfo *slot;
   1083    PK11SymKey *symKey = NULL;
   1084    unsigned char ivData[8];
   1085 
   1086    /* use the purpose to select the low level keygen algorithm */
   1087    switch (bitGenPurpose) {
   1088        case pbeBitGenIntegrityKey:
   1089            switch (hashAlgorithm) {
   1090                case SEC_OID_SHA1:
   1091                    mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
   1092                    break;
   1093                case SEC_OID_MD2:
   1094                    mechanism = CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
   1095                    break;
   1096                case SEC_OID_MD5:
   1097                    mechanism = CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
   1098                    break;
   1099                default:
   1100                    break;
   1101            }
   1102            break;
   1103        case pbeBitGenCipherIV:
   1104            if (bitsNeeded > 64) {
   1105                break;
   1106            }
   1107            if (hashAlgorithm != SEC_OID_SHA1) {
   1108                break;
   1109            }
   1110            mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
   1111            break;
   1112        case pbeBitGenCipherKey:
   1113            if (hashAlgorithm != SEC_OID_SHA1) {
   1114                break;
   1115            }
   1116            switch (bitsNeeded) {
   1117                case 40:
   1118                    mechanism = CKM_PBE_SHA1_RC4_40;
   1119                    break;
   1120                case 128:
   1121                    mechanism = CKM_PBE_SHA1_RC4_128;
   1122                    break;
   1123                default:
   1124                    break;
   1125            }
   1126        case pbeBitGenIDNull:
   1127            break;
   1128    }
   1129 
   1130    if (mechanism == CKM_INVALID_MECHANISM) {
   1131        /* we should set an error, but this is a deprecated function, and
   1132         * we are keeping bug for bug compatibility;)... */
   1133        return NULL;
   1134    }
   1135 
   1136    pbe_params.pInitVector = ivData;
   1137    pbe_params.pPassword = pwitem->data;
   1138    pbe_params.ulPasswordLen = pwitem->len;
   1139    pbe_params.pSalt = salt->data;
   1140    pbe_params.ulSaltLen = salt->len;
   1141    pbe_params.ulIteration = iterations;
   1142    mechItem.data = (unsigned char *)&pbe_params;
   1143    mechItem.len = sizeof(pbe_params);
   1144 
   1145    slot = PK11_GetInternalSlot();
   1146    symKey = PK11_RawPBEKeyGen(slot, mechanism,
   1147                               &mechItem, pwitem, PR_FALSE, NULL);
   1148    PK11_FreeSlot(slot);
   1149    if (symKey != NULL) {
   1150        if (bitGenPurpose == pbeBitGenCipherIV) {
   1151            /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
   1152            SECItem ivItem;
   1153 
   1154            ivItem.data = ivData;
   1155            ivItem.len = bitsNeeded / 8;
   1156            context = SECITEM_DupItem(&ivItem);
   1157        } else {
   1158            SECItem *keyData;
   1159            PK11_ExtractKeyValue(symKey);
   1160            keyData = PK11_GetKeyData(symKey);
   1161 
   1162            /* assert bitsNeeded with length? */
   1163            if (keyData) {
   1164                context = SECITEM_DupItem(keyData);
   1165            }
   1166        }
   1167        PK11_FreeSymKey(symKey);
   1168    }
   1169 
   1170    return (PBEBitGenContext *)context;
   1171 }
   1172 
   1173 /*
   1174 * public, Deprecated, This function is only for binary compatibility with
   1175 * older applications. Does not support PKCS5v2.
   1176 *
   1177 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for
   1178 * iv values rather than generating PBE bits directly.
   1179 */
   1180 SECItem *
   1181 PBE_GenerateBits(PBEBitGenContext *context)
   1182 {
   1183    return (SECItem *)context;
   1184 }
   1185 
   1186 /*
   1187 * public, Deprecated, This function is only for binary compatibility with
   1188 * older applications. Does not support PKCS5v2.
   1189 *
   1190 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
   1191 * iv values rather than generating PBE bits directly.
   1192 */
   1193 void
   1194 PBE_DestroyContext(PBEBitGenContext *context)
   1195 {
   1196    SECITEM_FreeItem((SECItem *)context, PR_TRUE);
   1197 }
   1198 
   1199 /*
   1200 * public, deprecated. Replaced with PK11_GetPBEIV().
   1201 */
   1202 SECItem *
   1203 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
   1204 {
   1205    /* pbe stuff */
   1206    CK_MECHANISM_TYPE type;
   1207    SECItem *param = NULL;
   1208    SECItem *iv = NULL;
   1209    SECItem src;
   1210    int iv_len = 0;
   1211    PK11SymKey *symKey;
   1212    PK11SlotInfo *slot;
   1213    CK_PBE_PARAMS_PTR pPBEparams;
   1214    SECOidTag pbeAlg;
   1215 
   1216    pbeAlg = SECOID_GetAlgorithmTag(algid);
   1217    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
   1218        unsigned char *ivData;
   1219        sec_pkcs5V2Parameter *pbeV2_param = NULL;
   1220 
   1221        /* can only return the IV if the crypto Algorithm exists */
   1222        if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
   1223            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1224            goto loser;
   1225        }
   1226        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   1227        if (pbeV2_param == NULL) {
   1228            goto loser;
   1229        }
   1230        /* extract the IV from the cipher algid portion of our pkcs 5 v2
   1231         * algorithm id */
   1232        type = PK11_AlgtagToMechanism(
   1233            SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
   1234        param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
   1235        sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   1236        if (!param) {
   1237            goto loser;
   1238        }
   1239        /* NOTE: NULL is a permissible return here */
   1240        ivData = PK11_IVFromParam(type, param, &iv_len);
   1241        src.data = ivData;
   1242        src.len = iv_len;
   1243        goto done;
   1244    }
   1245 
   1246    type = PK11_AlgtagToMechanism(pbeAlg);
   1247    param = PK11_ParamFromAlgid(algid);
   1248    if (param == NULL) {
   1249        goto done;
   1250    }
   1251    slot = PK11_GetInternalSlot();
   1252    symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
   1253    PK11_FreeSlot(slot);
   1254    if (symKey == NULL) {
   1255        goto loser;
   1256    }
   1257    PK11_FreeSymKey(symKey);
   1258    pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
   1259    iv_len = PK11_GetIVLength(type);
   1260 
   1261    src.data = (unsigned char *)pPBEparams->pInitVector;
   1262    src.len = iv_len;
   1263 
   1264 done:
   1265    iv = SECITEM_DupItem(&src);
   1266 
   1267 loser:
   1268    if (param) {
   1269        SECITEM_ZfreeItem(param, PR_TRUE);
   1270    }
   1271    return iv;
   1272 }
   1273 
   1274 /*
   1275 * Subs from nss 3.x that are deprecated
   1276 */
   1277 PBEBitGenContext *
   1278 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
   1279                    SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
   1280                    unsigned int iterations)
   1281 {
   1282    PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
   1283    return NULL;
   1284 }
   1285 
   1286 SECItem *
   1287 __PBE_GenerateBits(PBEBitGenContext *context)
   1288 {
   1289    PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
   1290    return NULL;
   1291 }
   1292 
   1293 void
   1294 __PBE_DestroyContext(PBEBitGenContext *context)
   1295 {
   1296    PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
   1297 }
   1298 
   1299 SECStatus
   1300 RSA_FormatBlock(SECItem *result, unsigned modulusLen,
   1301                int blockType, SECItem *data)
   1302 {
   1303    PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
   1304    return SECFailure;
   1305 }
   1306 
   1307 /****************************************************************************
   1308 *
   1309 * Now Do The PBE Functions Here...
   1310 *
   1311 ****************************************************************************/
   1312 
   1313 static void
   1314 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
   1315 {
   1316    if (pbe_params) {
   1317        if (pbe_params->pPassword)
   1318            PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
   1319        if (pbe_params->pSalt)
   1320            PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
   1321        PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
   1322    }
   1323 }
   1324 
   1325 /*
   1326 * public, deprecated.  use PK11_CreatePBEAlgorithmID or
   1327 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters,
   1328 * use PK11_ParamFromAlgid from the algorithm id you created using
   1329 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
   1330 */
   1331 SECItem *
   1332 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
   1333 {
   1334    CK_PBE_PARAMS *pbe_params = NULL;
   1335    SECItem *paramRV = NULL;
   1336 
   1337    paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
   1338    if (!paramRV) {
   1339        goto loser;
   1340    }
   1341    /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
   1342    PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
   1343 
   1344    pbe_params = (CK_PBE_PARAMS *)paramRV->data;
   1345    pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
   1346    if (!pbe_params->pPassword) {
   1347        goto loser;
   1348    }
   1349    if (pwd->data) {
   1350        PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
   1351    }
   1352    pbe_params->ulPasswordLen = pwd->len;
   1353 
   1354    pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
   1355    if (!pbe_params->pSalt) {
   1356        goto loser;
   1357    }
   1358    PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
   1359    pbe_params->ulSaltLen = salt->len;
   1360 
   1361    pbe_params->ulIteration = (CK_ULONG)iterations;
   1362    return paramRV;
   1363 
   1364 loser:
   1365    if (pbe_params)
   1366        pk11_destroy_ck_pbe_params(pbe_params);
   1367    if (paramRV)
   1368        PORT_ZFree(paramRV, sizeof(SECItem));
   1369    return NULL;
   1370 }
   1371 
   1372 /*
   1373 * public, deprecated.
   1374 */
   1375 void
   1376 PK11_DestroyPBEParams(SECItem *pItem)
   1377 {
   1378    if (pItem) {
   1379        CK_PBE_PARAMS *params = (CK_PBE_PARAMS *)(pItem->data);
   1380        if (params)
   1381            pk11_destroy_ck_pbe_params(params);
   1382        PORT_ZFree(pItem, sizeof(SECItem));
   1383    }
   1384 }
   1385 
   1386 /*
   1387 * public, Partially supports PKCS5 V2 (some parameters are not controllable
   1388 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
   1389 * finer control these.
   1390 */
   1391 SECAlgorithmID *
   1392 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
   1393 {
   1394    SECAlgorithmID *algid = NULL;
   1395    algid = sec_pkcs5CreateAlgorithmID(algorithm,
   1396                                       SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL,
   1397                                       0, salt, iteration);
   1398    return algid;
   1399 }
   1400 
   1401 /*
   1402 * public, fully support pkcs5v2.
   1403 */
   1404 SECAlgorithmID *
   1405 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
   1406                            SECOidTag prfAlgTag, int keyLength, int iteration,
   1407                            SECItem *salt)
   1408 {
   1409    SECAlgorithmID *algid = NULL;
   1410    algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
   1411                                       NULL, keyLength, salt, iteration);
   1412    return algid;
   1413 }
   1414 
   1415 /*
   1416 * private.
   1417 */
   1418 PK11SymKey *
   1419 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
   1420                             SECItem *params, CK_KEY_TYPE keyType, int keyLen,
   1421                             SECItem *pwitem, void *wincx)
   1422 {
   1423 #ifndef NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY
   1424    SECItem _params = { 0, NULL, 0 };
   1425    CK_PKCS5_PBKD2_PARAMS pbev2_1_params;
   1426    CK_ULONG pwLen;
   1427 #endif
   1428 #ifdef UNSAFE_FUZZER_MODE
   1429    PK11SymKey *zeroKey = NULL;
   1430    unsigned char zeroBuff[32] = { 0 };
   1431    SECItem zeroItem = { siBuffer, zeroBuff, sizeof zeroBuff };
   1432 
   1433    zeroKey = PK11_ImportSymKeyWithFlags(slot, type, PK11_OriginUnwrap,
   1434                                         CKA_FLAGS_ONLY, &zeroItem,
   1435                                         CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT |
   1436                                             CKF_UNWRAP | CKF_WRAP,
   1437                                         PR_FALSE, wincx);
   1438    return zeroKey;
   1439 #else /* UNSAFE_FUZZER_MODE */
   1440 
   1441    /* do some sanity checks */
   1442    if ((params == NULL) || (params->data == NULL)) {
   1443        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1444        return NULL;
   1445    }
   1446 
   1447    if (type == CKM_INVALID_MECHANISM) {
   1448        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1449        return NULL;
   1450    }
   1451 
   1452    /* set the password pointer in the parameters... */
   1453    if (type == CKM_PKCS5_PBKD2) {
   1454        CK_PKCS5_PBKD2_PARAMS2 *pbev2_params;
   1455 
   1456        if (params->len < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2), sizeof(CK_PKCS5_PBKD2_PARAMS))) {
   1457            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1458            return NULL;
   1459        }
   1460        pbev2_params = (CK_PKCS5_PBKD2_PARAMS2 *)params->data;
   1461        pbev2_params->pPassword = pwitem->data;
   1462        pbev2_params->ulPasswordLen = pwitem->len;
   1463        params->len = sizeof(CK_PKCS5_PBKD2_PARAMS2);
   1464 
   1465 #ifndef NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY
   1466        if (PK11_CheckPKCS11Version(slot, 2, 40, PR_FALSE) < 0) {
   1467            /* CK_PKCS5_PBKD2_PARAMS */
   1468            _params.type = params->type;
   1469            _params.data = (CK_CHAR_PTR)&pbev2_1_params;
   1470            _params.len = sizeof(CK_PKCS5_PBKD2_PARAMS);
   1471            memcpy(&pbev2_1_params, pbev2_params,
   1472                   PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2),
   1473                          sizeof(CK_PKCS5_PBKD2_PARAMS)));
   1474 
   1475            pwLen = pwitem->len;
   1476            pbev2_1_params.ulPasswordLen = &pwLen;
   1477            params = &_params;
   1478        }
   1479 #endif
   1480 
   1481    } else {
   1482        CK_PBE_PARAMS *pbe_params;
   1483        if (params->len < sizeof(CK_PBE_PARAMS)) {
   1484            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1485            return NULL;
   1486        }
   1487        pbe_params = (CK_PBE_PARAMS *)params->data;
   1488        pbe_params->pPassword = pwitem->data;
   1489        pbe_params->ulPasswordLen = pwitem->len;
   1490    }
   1491 
   1492    /* generate the key (and sometimes the IV as a side effect...) */
   1493    return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, keyLen, NULL,
   1494                                               CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT | CKF_UNWRAP | CKF_WRAP,
   1495                                               0, wincx);
   1496 #endif /* UNSAFE_FUZZER_MODE */
   1497 }
   1498 
   1499 /*
   1500 * public, deprecated. use PK11_PBEKeyGen instead.
   1501 */
   1502 PK11SymKey *
   1503 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
   1504                  SECItem *pwitem, PRBool faulty3DES, void *wincx)
   1505 {
   1506    if (faulty3DES && (type == CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC)) {
   1507        type = CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC;
   1508    }
   1509    return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
   1510 }
   1511 
   1512 /*
   1513 * pubic, supports pkcs5 v2.
   1514 *
   1515 * Create symkey from a PBE key. The algid can be created with
   1516 *  PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
   1517 *  extraction of der data.
   1518 */
   1519 PK11SymKey *
   1520 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
   1521               PRBool faulty3DES, void *wincx)
   1522 {
   1523    CK_MECHANISM_TYPE type;
   1524    SECItem *param = NULL;
   1525    PK11SymKey *symKey = NULL;
   1526    SECOidTag pbeAlg;
   1527    CK_KEY_TYPE keyType = -1;
   1528    int keyLen = 0;
   1529 
   1530    pbeAlg = SECOID_GetAlgorithmTag(algid);
   1531    /* if we're using PKCS5v2, extract the additional information we need
   1532     * (key length, key type, and pbeAlg). */
   1533    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
   1534        CK_MECHANISM_TYPE cipherMech;
   1535        sec_pkcs5V2Parameter *pbeV2_param;
   1536 
   1537        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   1538        if (pbeV2_param == NULL) {
   1539            return NULL;
   1540        }
   1541        cipherMech = PK11_AlgtagToMechanism(
   1542            SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
   1543        pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
   1544        param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
   1545        sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   1546        keyLen = SEC_PKCS5GetKeyLength(algid);
   1547        if (keyLen == -1) {
   1548            keyLen = 0;
   1549        }
   1550        keyType = PK11_GetKeyType(cipherMech, keyLen);
   1551    } else {
   1552        param = PK11_ParamFromAlgid(algid);
   1553    }
   1554 
   1555    if (param == NULL) {
   1556        goto loser;
   1557    }
   1558 
   1559    type = PK11_AlgtagToMechanism(pbeAlg);
   1560    if (type == CKM_INVALID_MECHANISM) {
   1561        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1562        goto loser;
   1563    }
   1564    if (faulty3DES && (type == CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC)) {
   1565        type = CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC;
   1566    }
   1567    symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen,
   1568                                          pwitem, wincx);
   1569 
   1570 loser:
   1571    if (param) {
   1572        SECITEM_ZfreeItem(param, PR_TRUE);
   1573    }
   1574    return symKey;
   1575 }
   1576 
   1577 /*
   1578 * public, supports pkcs5v2
   1579 */
   1580 SECItem *
   1581 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
   1582 {
   1583    return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
   1584 }
   1585 
   1586 CK_MECHANISM_TYPE
   1587 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
   1588                           SECItem *pbe_pwd, PRBool faulty3DES)
   1589 {
   1590    int keyLen = 0;
   1591    SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
   1592    CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
   1593    CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
   1594    SECItem *iv = NULL;
   1595 
   1596    if (mech == CKM_INVALID_MECHANISM) {
   1597        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1598        goto loser;
   1599    }
   1600    if (PK11_GetIVLength(mech)) {
   1601        iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
   1602        if (iv == NULL) {
   1603            goto loser;
   1604        }
   1605    }
   1606 
   1607    keyLen = SEC_PKCS5GetKeyLength(algid);
   1608 
   1609    *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
   1610    if (*param == NULL) {
   1611        goto loser;
   1612    }
   1613    returnedMechanism = mech;
   1614 
   1615 loser:
   1616    if (iv) {
   1617        SECITEM_FreeItem(iv, PR_TRUE);
   1618    }
   1619    return returnedMechanism;
   1620 }
   1621 
   1622 /*
   1623 * Public, supports pkcs5 v2
   1624 *
   1625 * Get the crypto mechanism directly from the pbe algorithmid.
   1626 *
   1627 * It's important to go directly from the algorithm id so that we can
   1628 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
   1629 *
   1630 * This function returns both the mechanism and the parameter for the mechanism.
   1631 * The caller is responsible for freeing the parameter.
   1632 */
   1633 CK_MECHANISM_TYPE
   1634 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
   1635                           SECItem *pbe_pwd)
   1636 {
   1637    return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);
   1638 }