tor-browser

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

p12local.c (48781B)


      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 "nssrenam.h"
      6 #include "pkcs12.h"
      7 #include "secpkcs7.h"
      8 #include "secasn1.h"
      9 #include "seccomon.h"
     10 #include "secoid.h"
     11 #include "sechash.h"
     12 #include "secitem.h"
     13 #include "secerr.h"
     14 #include "pk11func.h"
     15 #include "p12local.h"
     16 #include "p12.h"
     17 #include "nsshash.h"
     18 #include "secpkcs5.h"
     19 #include "p12plcy.h"
     20 
     21 #define SALT_LENGTH 16
     22 
     23 SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate)
     24 SEC_ASN1_MKSUB(sgn_DigestInfoTemplate)
     25 
     26 CK_MECHANISM_TYPE
     27 sec_pkcs12_algtag_to_mech(SECOidTag algtag)
     28 {
     29    SECOidTag hmacAlg = HASH_GetHMACOidTagByHashOidTag(algtag);
     30    return PK11_AlgtagToMechanism(hmacAlg);
     31 }
     32 
     33 CK_MECHANISM_TYPE
     34 sec_pkcs12_algtag_to_keygen_mech(SECOidTag algtag)
     35 {
     36    switch (algtag) {
     37        case SEC_OID_SHA1:
     38            return CKM_NSS_PBE_SHA1_HMAC_KEY_GEN;
     39            break;
     40        case SEC_OID_MD5:
     41            return CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
     42            break;
     43        case SEC_OID_MD2:
     44            return CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
     45            break;
     46        case SEC_OID_SHA224:
     47            return CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN;
     48            break;
     49        case SEC_OID_SHA256:
     50            return CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN;
     51            break;
     52        case SEC_OID_SHA384:
     53            return CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN;
     54            break;
     55        case SEC_OID_SHA512:
     56            return CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN;
     57            break;
     58        default:
     59            break;
     60    }
     61    return CKM_INVALID_MECHANISM;
     62 }
     63 
     64 PK11SymKey *
     65 sec_pkcs12_integrity_key(PK11SlotInfo *slot, sec_PKCS12MacData *macData,
     66                         SECItem *pwitem, CK_MECHANISM_TYPE *hmacMech,
     67                         PRBool isDecrypt, void *pwarg)
     68 {
     69    int iteration;
     70    CK_MECHANISM_TYPE integrityMech;
     71    PK11SymKey *symKey = NULL;
     72    SECItem *params = NULL;
     73    SECAlgorithmID *prfAlgid = &macData->safeMac.digestAlgorithm;
     74    SECOidTag algtag = SECOID_GetAlgorithmTag(prfAlgid);
     75 
     76    /* handle PBE v2 case */
     77    if (algtag == SEC_OID_PKCS5_PBMAC1) {
     78        SECOidTag hmacAlg;
     79        SECItem utf8Pw;
     80        int keyLen;
     81 
     82        hmacAlg = SEC_PKCS5GetCryptoAlgorithm(prfAlgid);
     83        /* make sure we are using an hmac */
     84        if (HASH_GetHashOidTagByHMACOidTag(hmacAlg) == SEC_OID_UNKNOWN) {
     85            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
     86            return NULL;
     87        }
     88        if (!SEC_PKCS12IntegrityHashAllowed(hmacAlg, isDecrypt)) {
     89            PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
     90            return NULL;
     91        }
     92        /* make sure the length is valid, as well as decoding the length
     93         * from prfAlgid, SEC_PKCS5GetLength does some
     94         * fallbacks, which evenutally gets the max length of the key if
     95         * the decode fails. All HMAC keys have a max length of 128 bytes
     96         * in softoken, so if we get a keyLen of 128 we know we hit an error. */
     97        keyLen = SEC_PKCS5GetKeyLength(prfAlgid);
     98        if ((keyLen == 0) || (keyLen == 128)) {
     99            PORT_SetError(SEC_ERROR_BAD_DER);
    100            return NULL;
    101        }
    102        *hmacMech = PK11_AlgtagToMechanism(hmacAlg);
    103        /* pkcs12v2 hmac uses UTF8 rather than unicode */
    104        if (!sec_pkcs12_convert_item_to_unicode(NULL, &utf8Pw, pwitem,
    105                                                PR_FALSE, PR_FALSE, PR_FALSE)) {
    106            return NULL;
    107        }
    108        symKey = PK11_PBEKeyGen(slot, prfAlgid, &utf8Pw, PR_FALSE, pwarg);
    109        SECITEM_ZfreeItem(&utf8Pw, PR_FALSE);
    110        return symKey;
    111    }
    112 
    113    /* handle Legacy case */
    114    if (!SEC_PKCS12IntegrityHashAllowed(algtag, isDecrypt)) {
    115        PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
    116        return NULL;
    117    }
    118    integrityMech = sec_pkcs12_algtag_to_keygen_mech(algtag);
    119    *hmacMech = sec_pkcs12_algtag_to_mech(algtag);
    120    if (integrityMech == CKM_INVALID_MECHANISM) {
    121        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    122        goto loser;
    123    }
    124    if (macData->iter.data) {
    125        iteration = (int)DER_GetInteger(&macData->iter);
    126    } else {
    127        iteration = 1;
    128    }
    129 
    130    params = PK11_CreatePBEParams(&macData->macSalt, pwitem, iteration);
    131    if (params == NULL) {
    132        goto loser;
    133    }
    134 
    135    symKey = PK11_KeyGen(slot, integrityMech, params, 0, pwarg);
    136    PK11_DestroyPBEParams(params);
    137    params = NULL;
    138    if (!symKey)
    139        goto loser;
    140    return symKey;
    141 
    142 loser:
    143    if (params) {
    144        PK11_DestroyPBEParams(params);
    145    }
    146    return NULL;
    147 }
    148 
    149 /* helper functions */
    150 /* returns proper bag type template based upon object type tag */
    151 const SEC_ASN1Template *
    152 sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding)
    153 {
    154    const SEC_ASN1Template *theTemplate;
    155    SEC_PKCS12SafeBag *safebag;
    156    SECOidData *oiddata;
    157 
    158    if (src_or_dest == NULL) {
    159        return NULL;
    160    }
    161 
    162    safebag = (SEC_PKCS12SafeBag *)src_or_dest;
    163 
    164    oiddata = safebag->safeBagTypeTag;
    165    if (oiddata == NULL) {
    166        oiddata = SECOID_FindOID(&safebag->safeBagType);
    167        safebag->safeBagTypeTag = oiddata;
    168    }
    169 
    170    switch (oiddata->offset) {
    171        default:
    172            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
    173            break;
    174        case SEC_OID_PKCS12_KEY_BAG_ID:
    175            theTemplate = SEC_PointerToPKCS12KeyBagTemplate;
    176            break;
    177        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
    178            theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD;
    179            break;
    180        case SEC_OID_PKCS12_SECRET_BAG_ID:
    181            theTemplate = SEC_PointerToPKCS12SecretBagTemplate;
    182            break;
    183    }
    184    return theTemplate;
    185 }
    186 
    187 const SEC_ASN1Template *
    188 sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding)
    189 {
    190    const SEC_ASN1Template *theTemplate;
    191    SEC_PKCS12SafeBag *safebag;
    192    SECOidData *oiddata;
    193 
    194    if (src_or_dest == NULL) {
    195        return NULL;
    196    }
    197 
    198    safebag = (SEC_PKCS12SafeBag *)src_or_dest;
    199 
    200    oiddata = safebag->safeBagTypeTag;
    201    if (oiddata == NULL) {
    202        oiddata = SECOID_FindOID(&safebag->safeBagType);
    203        safebag->safeBagTypeTag = oiddata;
    204    }
    205 
    206    switch (oiddata->offset) {
    207        default:
    208            theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
    209            break;
    210        case SEC_OID_PKCS12_KEY_BAG_ID:
    211            theTemplate = SEC_PKCS12PrivateKeyBagTemplate;
    212            break;
    213        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
    214            theTemplate = SEC_PKCS12CertAndCRLBagTemplate;
    215            break;
    216        case SEC_OID_PKCS12_SECRET_BAG_ID:
    217            theTemplate = SEC_PKCS12SecretBagTemplate;
    218            break;
    219    }
    220    return theTemplate;
    221 }
    222 
    223 /* returns proper cert crl template based upon type tag */
    224 const SEC_ASN1Template *
    225 sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding)
    226 {
    227    const SEC_ASN1Template *theTemplate;
    228    SEC_PKCS12CertAndCRL *certbag;
    229    SECOidData *oiddata;
    230 
    231    if (src_or_dest == NULL) {
    232        return NULL;
    233    }
    234 
    235    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
    236    oiddata = certbag->BagTypeTag;
    237    if (oiddata == NULL) {
    238        oiddata = SECOID_FindOID(&certbag->BagID);
    239        certbag->BagTypeTag = oiddata;
    240    }
    241 
    242    switch (oiddata->offset) {
    243        default:
    244            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
    245            break;
    246        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
    247            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD;
    248            break;
    249        case SEC_OID_PKCS12_SDSI_CERT_BAG:
    250            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
    251            break;
    252    }
    253    return theTemplate;
    254 }
    255 
    256 const SEC_ASN1Template *
    257 sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding)
    258 {
    259    const SEC_ASN1Template *theTemplate;
    260    SEC_PKCS12CertAndCRL *certbag;
    261    SECOidData *oiddata;
    262 
    263    if (src_or_dest == NULL) {
    264        return NULL;
    265    }
    266 
    267    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
    268    oiddata = certbag->BagTypeTag;
    269    if (oiddata == NULL) {
    270        oiddata = SECOID_FindOID(&certbag->BagID);
    271        certbag->BagTypeTag = oiddata;
    272    }
    273 
    274    switch (oiddata->offset) {
    275        default:
    276            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
    277            break;
    278        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
    279            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate;
    280            break;
    281        case SEC_OID_PKCS12_SDSI_CERT_BAG:
    282            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
    283            break;
    284    }
    285    return theTemplate;
    286 }
    287 
    288 /* returns appropriate shroud template based on object type tag */
    289 const SEC_ASN1Template *
    290 sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding)
    291 {
    292    const SEC_ASN1Template *theTemplate;
    293    SEC_PKCS12ESPVKItem *espvk;
    294    SECOidData *oiddata;
    295 
    296    if (src_or_dest == NULL) {
    297        return NULL;
    298    }
    299 
    300    espvk = (SEC_PKCS12ESPVKItem *)src_or_dest;
    301    oiddata = espvk->espvkTag;
    302    if (oiddata == NULL) {
    303        oiddata = SECOID_FindOID(&espvk->espvkOID);
    304        espvk->espvkTag = oiddata;
    305    }
    306 
    307    switch (oiddata->offset) {
    308        default:
    309            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
    310            break;
    311        case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING:
    312            theTemplate =
    313                SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate);
    314            break;
    315    }
    316    return theTemplate;
    317 }
    318 
    319 /* generate SALT  placing it into the character array passed in.
    320 * it is assumed that salt_dest is an array of appropriate size
    321 * XXX We might want to generate our own random context
    322 */
    323 SECItem *
    324 sec_pkcs12_generate_salt(void)
    325 {
    326    SECItem *salt;
    327 
    328    salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    329    if (salt == NULL) {
    330        PORT_SetError(SEC_ERROR_NO_MEMORY);
    331        return NULL;
    332    }
    333    salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
    334                                              SALT_LENGTH);
    335    salt->len = SALT_LENGTH;
    336    if (salt->data == NULL) {
    337        PORT_SetError(SEC_ERROR_NO_MEMORY);
    338        SECITEM_ZfreeItem(salt, PR_TRUE);
    339        return NULL;
    340    }
    341 
    342    PK11_GenerateRandom(salt->data, salt->len);
    343 
    344    return salt;
    345 }
    346 
    347 /* generate KEYS -- as per PKCS12 section 7.
    348 * only used for MAC
    349 */
    350 SECItem *
    351 sec_pkcs12_generate_key_from_password(SECOidTag algorithm,
    352                                      SECItem *salt,
    353                                      SECItem *password)
    354 {
    355    unsigned char *pre_hash = NULL;
    356    unsigned char *hash_dest = NULL;
    357    SECStatus res;
    358    PLArenaPool *poolp;
    359    SECItem *key = NULL;
    360    int key_len = 0;
    361 
    362    if ((salt == NULL) || (password == NULL)) {
    363        return NULL;
    364    }
    365 
    366    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    367    if (poolp == NULL) {
    368        PORT_SetError(SEC_ERROR_NO_MEMORY);
    369        return NULL;
    370    }
    371 
    372    pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * (salt->len + password->len));
    373    if (pre_hash == NULL) {
    374        PORT_SetError(SEC_ERROR_NO_MEMORY);
    375        goto loser;
    376    }
    377 
    378    hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp,
    379                                                  sizeof(unsigned char) * SHA1_LENGTH);
    380    if (hash_dest == NULL) {
    381        PORT_SetError(SEC_ERROR_NO_MEMORY);
    382        goto loser;
    383    }
    384 
    385    PORT_Memcpy(pre_hash, salt->data, salt->len);
    386    /* handle password of 0 length case */
    387    if (password->len > 0) {
    388        PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
    389    }
    390 
    391    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash,
    392                       (salt->len + password->len));
    393    if (res == SECFailure) {
    394        PORT_SetError(SEC_ERROR_NO_MEMORY);
    395        goto loser;
    396    }
    397 
    398    switch (algorithm) {
    399        case SEC_OID_SHA1:
    400            if (key_len == 0)
    401                key_len = 16;
    402            key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    403            if (key == NULL) {
    404                PORT_SetError(SEC_ERROR_NO_MEMORY);
    405                goto loser;
    406            }
    407            key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * key_len);
    408            if (key->data == NULL) {
    409                PORT_SetError(SEC_ERROR_NO_MEMORY);
    410                goto loser;
    411            }
    412            key->len = key_len;
    413            PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH - key->len], key->len);
    414            break;
    415        default:
    416            goto loser;
    417            break;
    418    }
    419 
    420    PORT_FreeArena(poolp, PR_TRUE);
    421    return key;
    422 
    423 loser:
    424    PORT_FreeArena(poolp, PR_TRUE);
    425    if (key != NULL) {
    426        SECITEM_ZfreeItem(key, PR_TRUE);
    427    }
    428    return NULL;
    429 }
    430 
    431 /* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
    432 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
    433 * because it is not known how long the message actually is.  String
    434 * manipulation routines will not necessarily work because msg may have
    435 * imbedded NULLs
    436 */
    437 static SECItem *
    438 sec_pkcs12_generate_old_mac(SECItem *key,
    439                            SECItem *msg)
    440 {
    441    SECStatus res;
    442    PLArenaPool *temparena = NULL;
    443    unsigned char *hash_dest = NULL, *hash_src1 = NULL, *hash_src2 = NULL;
    444    int i;
    445    SECItem *mac = NULL;
    446 
    447    if ((key == NULL) || (msg == NULL))
    448        goto loser;
    449 
    450    /* allocate return item */
    451    mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    452    if (mac == NULL)
    453        return NULL;
    454    mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * SHA1_LENGTH);
    455    mac->len = SHA1_LENGTH;
    456    if (mac->data == NULL)
    457        goto loser;
    458 
    459    /* allocate temporary items */
    460    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    461    if (temparena == NULL)
    462        goto loser;
    463 
    464    hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
    465                                                  sizeof(unsigned char) * (16 + msg->len));
    466    if (hash_src1 == NULL)
    467        goto loser;
    468 
    469    hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
    470                                                  sizeof(unsigned char) * (SHA1_LENGTH + 16));
    471    if (hash_src2 == NULL)
    472        goto loser;
    473 
    474    hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena,
    475                                                  sizeof(unsigned char) * SHA1_LENGTH);
    476    if (hash_dest == NULL)
    477        goto loser;
    478 
    479    /* perform mac'ing as per PKCS 12 */
    480 
    481    /* first round of hashing */
    482    for (i = 0; i < 16; i++)
    483        hash_src1[i] = key->data[i] ^ 0x36;
    484    PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
    485    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16 + msg->len));
    486    if (res == SECFailure)
    487        goto loser;
    488 
    489    /* second round of hashing */
    490    for (i = 0; i < 16; i++)
    491        hash_src2[i] = key->data[i] ^ 0x5c;
    492    PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
    493    res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH + 16);
    494    if (res == SECFailure)
    495        goto loser;
    496 
    497    PORT_FreeArena(temparena, PR_TRUE);
    498    return mac;
    499 
    500 loser:
    501    if (temparena != NULL)
    502        PORT_FreeArena(temparena, PR_TRUE);
    503    if (mac != NULL)
    504        SECITEM_ZfreeItem(mac, PR_TRUE);
    505    return NULL;
    506 }
    507 
    508 /* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
    509 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
    510 * because it is not known how long the message actually is.  String
    511 * manipulation routines will not necessarily work because msg may have
    512 * imbedded NULLs
    513 */
    514 SECItem *
    515 sec_pkcs12_generate_mac(SECItem *key,
    516                        SECItem *msg,
    517                        PRBool old_method)
    518 {
    519    SECStatus res = SECFailure;
    520    SECItem *mac = NULL;
    521    PK11Context *pk11cx = NULL;
    522    SECItem ignore = { 0 };
    523 
    524    if ((key == NULL) || (msg == NULL)) {
    525        return NULL;
    526    }
    527 
    528    if (old_method == PR_TRUE) {
    529        return sec_pkcs12_generate_old_mac(key, msg);
    530    }
    531 
    532    /* allocate return item */
    533    mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH);
    534    if (mac == NULL) {
    535        return NULL;
    536    }
    537 
    538    pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive,
    539                                        CKA_SIGN, key, &ignore, NULL);
    540    if (pk11cx == NULL) {
    541        goto loser;
    542    }
    543 
    544    res = PK11_DigestBegin(pk11cx);
    545    if (res == SECFailure) {
    546        goto loser;
    547    }
    548 
    549    res = PK11_DigestOp(pk11cx, msg->data, msg->len);
    550    if (res == SECFailure) {
    551        goto loser;
    552    }
    553 
    554    res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH);
    555    if (res == SECFailure) {
    556        goto loser;
    557    }
    558 
    559    PK11_DestroyContext(pk11cx, PR_TRUE);
    560    pk11cx = NULL;
    561 
    562 loser:
    563 
    564    if (res != SECSuccess) {
    565        SECITEM_ZfreeItem(mac, PR_TRUE);
    566        mac = NULL;
    567        if (pk11cx) {
    568            PK11_DestroyContext(pk11cx, PR_TRUE);
    569        }
    570    }
    571 
    572    return mac;
    573 }
    574 
    575 /* compute the thumbprint of the DER cert and create a digest info
    576 * to store it in and return the digest info.
    577 * a return of NULL indicates an error.
    578 */
    579 SGNDigestInfo *
    580 sec_pkcs12_compute_thumbprint(SECItem *der_cert)
    581 {
    582    SGNDigestInfo *thumb = NULL;
    583    SECItem digest;
    584    PLArenaPool *temparena = NULL;
    585    SECStatus rv = SECFailure;
    586 
    587    if (der_cert == NULL)
    588        return NULL;
    589 
    590    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    591    if (temparena == NULL) {
    592        return NULL;
    593    }
    594 
    595    digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
    596                                                    sizeof(unsigned char) *
    597                                                        SHA1_LENGTH);
    598    /* digest data and create digest info */
    599    if (digest.data != NULL) {
    600        digest.len = SHA1_LENGTH;
    601        rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data,
    602                          der_cert->len);
    603        if (rv == SECSuccess) {
    604            thumb = SGN_CreateDigestInfo(SEC_OID_SHA1,
    605                                         digest.data,
    606                                         digest.len);
    607        } else {
    608            PORT_SetError(SEC_ERROR_NO_MEMORY);
    609        }
    610    } else {
    611        PORT_SetError(SEC_ERROR_NO_MEMORY);
    612    }
    613 
    614    PORT_FreeArena(temparena, PR_TRUE);
    615 
    616    return thumb;
    617 }
    618 
    619 /* create a virtual password per PKCS 12, the password is converted
    620 * to unicode, the salt is prepended to it, and then the whole thing
    621 * is returned */
    622 SECItem *
    623 sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt,
    624                                   PRBool swap)
    625 {
    626    SECItem uniPwd = { siBuffer, NULL, 0 }, *retPwd = NULL;
    627 
    628    if ((password == NULL) || (salt == NULL)) {
    629        return NULL;
    630    }
    631 
    632    if (password->len == 0) {
    633        uniPwd.data = (unsigned char *)PORT_ZAlloc(2);
    634        uniPwd.len = 2;
    635        if (!uniPwd.data) {
    636            return NULL;
    637        }
    638    } else {
    639        uniPwd.data = (unsigned char *)PORT_ZAlloc(password->len * 3);
    640        uniPwd.len = password->len * 3;
    641        if (!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
    642                                       uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
    643            SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
    644            return NULL;
    645        }
    646    }
    647 
    648    retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    649    if (retPwd == NULL) {
    650        goto loser;
    651    }
    652 
    653    /* allocate space and copy proper data */
    654    retPwd->len = uniPwd.len + salt->len;
    655    retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len);
    656    if (retPwd->data == NULL) {
    657        PORT_Free(retPwd);
    658        goto loser;
    659    }
    660 
    661    PORT_Memcpy(retPwd->data, salt->data, salt->len);
    662    PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len);
    663 
    664    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
    665 
    666    return retPwd;
    667 
    668 loser:
    669    PORT_SetError(SEC_ERROR_NO_MEMORY);
    670    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
    671    return NULL;
    672 }
    673 
    674 /* appends a shrouded key to a key bag.  this is used for exporting
    675 * to store externally wrapped keys.  it is used when importing to convert
    676 * old items to new
    677 */
    678 SECStatus
    679 sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag,
    680                               SEC_PKCS12ESPVKItem *espvk)
    681 {
    682    int size;
    683    void *mark = NULL, *dummy = NULL;
    684 
    685    if ((bag == NULL) || (espvk == NULL))
    686        return SECFailure;
    687 
    688    mark = PORT_ArenaMark(bag->poolp);
    689 
    690    /* grow the list */
    691    size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *);
    692    dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp,
    693                                                   bag->espvks, size,
    694                                                   size + sizeof(SEC_PKCS12ESPVKItem *));
    695    bag->espvks = (SEC_PKCS12ESPVKItem **)dummy;
    696    if (dummy == NULL) {
    697        PORT_SetError(SEC_ERROR_NO_MEMORY);
    698        goto loser;
    699    }
    700 
    701    bag->espvks[bag->nEspvks] = espvk;
    702    bag->nEspvks++;
    703    bag->espvks[bag->nEspvks] = NULL;
    704 
    705    PORT_ArenaUnmark(bag->poolp, mark);
    706    return SECSuccess;
    707 
    708 loser:
    709    PORT_ArenaRelease(bag->poolp, mark);
    710    return SECFailure;
    711 }
    712 
    713 /* search a certificate list for a nickname, a thumbprint, or both
    714 * within a certificate bag.  if the certificate could not be
    715 * found or an error occurs, NULL is returned;
    716 */
    717 static SEC_PKCS12CertAndCRL *
    718 sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
    719                                SECItem *nickname, SGNDigestInfo *thumbprint)
    720 {
    721    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
    722    int i, j;
    723 
    724    if ((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
    725        return NULL;
    726    }
    727 
    728    if (thumbprint && nickname) {
    729        search_both = PR_TRUE;
    730    }
    731 
    732    if (nickname) {
    733        search_nickname = PR_TRUE;
    734    }
    735 
    736 search_again:
    737    i = 0;
    738    while (certbag->certAndCRLs[i] != NULL) {
    739        SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];
    740 
    741        if (SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {
    742 
    743            /* check nicknames */
    744            if (search_nickname) {
    745                if (SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
    746                    return cert;
    747                }
    748            } else {
    749                /* check thumbprints */
    750                SECItem **derCertList;
    751 
    752                /* get pointer to certificate list, does not need to
    753                 * be freed since it is within the arena which will
    754                 * be freed later.
    755                 */
    756                derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
    757                j = 0;
    758                if (derCertList != NULL) {
    759                    while (derCertList[j] != NULL) {
    760                        SECComparison eq;
    761                        SGNDigestInfo *di;
    762                        di = sec_pkcs12_compute_thumbprint(derCertList[j]);
    763                        if (di) {
    764                            eq = SGN_CompareDigestInfo(thumbprint, di);
    765                            SGN_DestroyDigestInfo(di);
    766                            if (eq == SECEqual) {
    767                                /* copy the derCert for later reference */
    768                                cert->value.x509->derLeafCert = derCertList[j];
    769                                return cert;
    770                            }
    771                        } else {
    772                            /* an error occurred */
    773                            return NULL;
    774                        }
    775                        j++;
    776                    }
    777                }
    778            }
    779        }
    780 
    781        i++;
    782    }
    783 
    784    if (search_both) {
    785        search_both = PR_FALSE;
    786        search_nickname = PR_FALSE;
    787        goto search_again;
    788    }
    789 
    790    return NULL;
    791 }
    792 
    793 /* search a key list for a nickname, a thumbprint, or both
    794 * within a key bag.  if the key could not be
    795 * found or an error occurs, NULL is returned;
    796 */
    797 static SEC_PKCS12PrivateKey *
    798 sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag,
    799                              SECItem *nickname, SGNDigestInfo *thumbprint)
    800 {
    801    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
    802    int i, j;
    803 
    804    if ((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
    805        return NULL;
    806    }
    807 
    808    if (keybag->privateKeys == NULL) {
    809        return NULL;
    810    }
    811 
    812    if (thumbprint && nickname) {
    813        search_both = PR_TRUE;
    814    }
    815 
    816    if (nickname) {
    817        search_nickname = PR_TRUE;
    818    }
    819 
    820 search_again:
    821    i = 0;
    822    while (keybag->privateKeys[i] != NULL) {
    823        SEC_PKCS12PrivateKey *key = keybag->privateKeys[i];
    824 
    825        /* check nicknames */
    826        if (search_nickname) {
    827            if (SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) {
    828                return key;
    829            }
    830        } else {
    831            /* check digests */
    832            SGNDigestInfo **assocCerts = key->pvkData.assocCerts;
    833            if ((assocCerts == NULL) || (assocCerts[0] == NULL)) {
    834                return NULL;
    835            }
    836 
    837            j = 0;
    838            while (assocCerts[j] != NULL) {
    839                SECComparison eq;
    840                eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]);
    841                if (eq == SECEqual) {
    842                    return key;
    843                }
    844                j++;
    845            }
    846        }
    847        i++;
    848    }
    849 
    850    if (search_both) {
    851        search_both = PR_FALSE;
    852        search_nickname = PR_FALSE;
    853        goto search_again;
    854    }
    855 
    856    return NULL;
    857 }
    858 
    859 /* seach the safe first then try the baggage bag
    860 *  safe and bag contain certs and keys to search
    861 *  objType is the object type to look for
    862 *  bagType is the type of bag that was found by sec_pkcs12_find_object
    863 *  index is the entity in safe->safeContents or bag->unencSecrets which
    864 *    is being searched
    865 *  nickname and thumbprint are the search criteria
    866 *
    867 * a return of null indicates no match
    868 */
    869 static void *
    870 sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe,
    871                    SEC_PKCS12BaggageItem *bag,
    872                    SECOidTag objType, SECOidTag bagType, int index,
    873                    SECItem *nickname, SGNDigestInfo *thumbprint)
    874 {
    875    PRBool searchSafe;
    876    int i = index;
    877 
    878    if ((safe == NULL) && (bag == NULL)) {
    879        return NULL;
    880    }
    881 
    882    searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE);
    883    switch (objType) {
    884        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
    885            if (objType == bagType) {
    886                SEC_PKCS12CertAndCRLBag *certBag;
    887 
    888                if (searchSafe) {
    889                    certBag = safe->contents[i]->safeContent.certAndCRLBag;
    890                } else {
    891                    certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag;
    892                }
    893                return sec_pkcs12_find_cert_in_certbag(certBag, nickname,
    894                                                       thumbprint);
    895            }
    896            break;
    897        case SEC_OID_PKCS12_KEY_BAG_ID:
    898            if (objType == bagType) {
    899                SEC_PKCS12PrivateKeyBag *keyBag;
    900 
    901                if (searchSafe) {
    902                    keyBag = safe->contents[i]->safeContent.keyBag;
    903                } else {
    904                    keyBag = bag->unencSecrets[i]->safeContent.keyBag;
    905                }
    906                return sec_pkcs12_find_key_in_keybag(keyBag, nickname,
    907                                                     thumbprint);
    908            }
    909            break;
    910        default:
    911            break;
    912    }
    913 
    914    return NULL;
    915 }
    916 
    917 /* searches both the baggage and the safe areas looking for
    918 * object of specified type matching either the nickname or the
    919 * thumbprint specified.
    920 *
    921 * safe and baggage store certs and keys
    922 * objType is the OID for the bag type to be searched:
    923 *   SEC_OID_PKCS12_KEY_BAG_ID, or
    924 *   SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID
    925 * nickname and thumbprint are the search criteria
    926 *
    927 * if no match found, NULL returned and error set
    928 */
    929 void *
    930 sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe,
    931                       SEC_PKCS12Baggage *baggage,
    932                       SECOidTag objType,
    933                       SECItem *nickname,
    934                       SGNDigestInfo *thumbprint)
    935 {
    936    int i, j;
    937    void *retItem;
    938 
    939    if (((safe == NULL) && (thumbprint == NULL)) ||
    940        ((nickname == NULL) && (thumbprint == NULL))) {
    941        return NULL;
    942    }
    943 
    944    i = 0;
    945    if ((safe != NULL) && (safe->contents != NULL)) {
    946        while (safe->contents[i] != NULL) {
    947            SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType);
    948            retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i,
    949                                          nickname, thumbprint);
    950            if (retItem != NULL) {
    951                return retItem;
    952            }
    953            i++;
    954        }
    955    }
    956 
    957    if ((baggage != NULL) && (baggage->bags != NULL)) {
    958        i = 0;
    959        while (baggage->bags[i] != NULL) {
    960            SEC_PKCS12BaggageItem *xbag = baggage->bags[i];
    961            j = 0;
    962            if (xbag->unencSecrets != NULL) {
    963                while (xbag->unencSecrets[j] != NULL) {
    964                    SECOidTag bagType;
    965                    bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType);
    966                    retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType,
    967                                                  j, nickname, thumbprint);
    968                    if (retItem != NULL) {
    969                        return retItem;
    970                    }
    971                    j++;
    972                }
    973            }
    974            i++;
    975        }
    976    }
    977 
    978    PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);
    979    return NULL;
    980 }
    981 
    982 /* this function converts a password to UCS2 and ensures that the
    983 * required double 0 byte be placed at the end of the string (if zeroTerm
    984 * is set), or the 0 bytes at the end are dropped (if zeroTerm is not set).
    985 * If toUnicode is false, we convert from UCS2 to UTF8/ASCII (latter is a
    986 * proper subset of the former) depending on the state of the asciiCovert
    987 * flag)
    988 */
    989 PRBool
    990 sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest,
    991                                   SECItem *src, PRBool zeroTerm,
    992                                   PRBool asciiConvert, PRBool toUnicode)
    993 {
    994    PRBool success = PR_FALSE;
    995    int bufferSize;
    996 
    997    if (!src || !dest) {
    998        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    999        return PR_FALSE;
   1000    }
   1001 
   1002    bufferSize = src->len * 3 + 2;
   1003    dest->len = bufferSize;
   1004    if (arena) {
   1005        dest->data = (unsigned char *)PORT_ArenaZAlloc(arena, dest->len);
   1006    } else {
   1007        dest->data = (unsigned char *)PORT_ZAlloc(dest->len);
   1008    }
   1009 
   1010    if (!dest->data) {
   1011        dest->len = 0;
   1012        return PR_FALSE;
   1013    }
   1014 
   1015    if (!asciiConvert) {
   1016        success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data,
   1017                                           dest->len, &dest->len);
   1018    } else {
   1019 #ifndef IS_LITTLE_ENDIAN
   1020        PRBool swapUnicode = PR_FALSE;
   1021 #else
   1022        PRBool swapUnicode = PR_TRUE;
   1023 #endif
   1024        success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data,
   1025                                            dest->len, &dest->len, swapUnicode);
   1026    }
   1027 
   1028    if (!success) {
   1029        if (!arena) {
   1030            PORT_Free(dest->data);
   1031            dest->data = NULL;
   1032            dest->len = 0;
   1033        }
   1034        return PR_FALSE;
   1035    }
   1036 
   1037    /* in some cases we need to add NULL terminations and in others
   1038     * we need to drop null terminations */
   1039    if (zeroTerm) {
   1040        /* unicode adds two nulls at the end */
   1041        if (toUnicode) {
   1042            if ((dest->len < 2) || dest->data[dest->len - 1] || dest->data[dest->len - 2]) {
   1043                /* we've already allocated space for these new NULLs */
   1044                PORT_Assert(dest->len + 2 <= bufferSize);
   1045                dest->len += 2;
   1046                dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0;
   1047            }
   1048            /* ascii/utf-8 adds just 1 */
   1049        } else if (!dest->len || dest->data[dest->len - 1]) {
   1050            PORT_Assert(dest->len + 1 <= bufferSize);
   1051            dest->len++;
   1052            dest->data[dest->len - 1] = 0;
   1053        }
   1054    } else {
   1055        /* handle the drop case, no need to do any allocations here. */
   1056        if (toUnicode) {
   1057            while ((dest->len >= 2) && !dest->data[dest->len - 1] &&
   1058                   !dest->data[dest->len - 2]) {
   1059                dest->len -= 2;
   1060            }
   1061        } else {
   1062            while (dest->len && !dest->data[dest->len - 1]) {
   1063                dest->len--;
   1064            }
   1065        }
   1066    }
   1067 
   1068    return PR_TRUE;
   1069 }
   1070 
   1071 PRBool
   1072 sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
   1073 {
   1074    switch (algorithm) {
   1075        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   1076        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   1077        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
   1078        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1079        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1080        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1081        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1082        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1083        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1084        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1085        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1086        /* those are actually PKCS #5 v1.5 PBEs, but we
   1087         * historically treat them in the same way as PKCS #12
   1088         * PBEs */
   1089        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
   1090        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
   1091        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
   1092            return PR_TRUE;
   1093        default:
   1094            return PR_FALSE;
   1095    }
   1096 }
   1097 
   1098 /* this function decodes a password from Unicode if necessary,
   1099 * according to the PBE algorithm.
   1100 *
   1101 * we assume that the pwitem is already encoded in Unicode by the
   1102 * caller.  if the encryption scheme is not the one defined in PKCS
   1103 * #12, decode the pwitem back into UTF-8. NOTE: UTF-8 strings are
   1104 * used in the PRF without the trailing NULL */
   1105 PRBool
   1106 sec_pkcs12_decode_password(PLArenaPool *arena,
   1107                           SECItem *result,
   1108                           SECOidTag algorithm,
   1109                           const SECItem *pwitem)
   1110 {
   1111    if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
   1112        return sec_pkcs12_convert_item_to_unicode(arena, result,
   1113                                                  (SECItem *)pwitem,
   1114                                                  PR_FALSE, PR_FALSE, PR_FALSE);
   1115 
   1116    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
   1117 }
   1118 
   1119 /* this function encodes a password into Unicode if necessary,
   1120 * according to the PBE algorithm.
   1121 *
   1122 * we assume that the pwitem holds a raw password.  if the encryption
   1123 * scheme is the one defined in PKCS #12, encode the password into
   1124 * BMPString. */
   1125 PRBool
   1126 sec_pkcs12_encode_password(PLArenaPool *arena,
   1127                           SECItem *result,
   1128                           SECOidTag algorithm,
   1129                           const SECItem *pwitem)
   1130 {
   1131    if (sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
   1132        return sec_pkcs12_convert_item_to_unicode(arena, result,
   1133                                                  (SECItem *)pwitem,
   1134                                                  PR_TRUE, PR_TRUE, PR_TRUE);
   1135 
   1136    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
   1137 }
   1138 
   1139 /* pkcs 12 templates */
   1140 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
   1141    sec_pkcs12_choose_shroud_type;
   1142 
   1143 const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] = {
   1144    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
   1145    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
   1146    { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) },
   1147    { 0 }
   1148 };
   1149 
   1150 const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] = {
   1151    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
   1152    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
   1153    { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) },
   1154    { 0 }
   1155 };
   1156 
   1157 const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] = {
   1158    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
   1159      SEC_PKCS12CodedCertBagTemplate },
   1160 };
   1161 
   1162 const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] = {
   1163    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
   1164    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
   1165    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
   1166      SEC_PKCS12PVKSupportingDataTemplate_OLD },
   1167    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
   1168          SEC_ASN1_DYNAMIC | 0,
   1169      offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
   1170      &sec_pkcs12_shroud_chooser },
   1171    { 0 }
   1172 };
   1173 
   1174 const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] = {
   1175    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
   1176    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
   1177    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
   1178      SEC_PKCS12PVKSupportingDataTemplate },
   1179    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
   1180          SEC_ASN1_DYNAMIC | 0,
   1181      offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
   1182      &sec_pkcs12_shroud_chooser },
   1183    { 0 }
   1184 };
   1185 
   1186 const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] = {
   1187    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) },
   1188    { SEC_ASN1_OBJECT_ID,
   1189      offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) },
   1190    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1191      offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) },
   1192    { 0 }
   1193 };
   1194 
   1195 const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] = {
   1196    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
   1197    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
   1198      offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
   1199      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
   1200    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
   1201      offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
   1202    { SEC_ASN1_PRINTABLE_STRING,
   1203      offsetof(SEC_PKCS12PVKSupportingData, nickname) },
   1204    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
   1205      offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
   1206    { 0 }
   1207 };
   1208 
   1209 const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] = {
   1210    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
   1211    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
   1212      offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
   1213      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
   1214    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
   1215      offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
   1216    { SEC_ASN1_BMP_STRING,
   1217      offsetof(SEC_PKCS12PVKSupportingData, uniNickName) },
   1218    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
   1219      offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
   1220    { 0 }
   1221 };
   1222 
   1223 const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] = {
   1224    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) },
   1225    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks),
   1226      SEC_PKCS12ESPVKItemTemplate },
   1227    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
   1228      SEC_PKCS12SafeBagTemplate },
   1229    /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
   1230        SEC_PKCS12CodedSafeBagTemplate }, */
   1231    { 0 }
   1232 };
   1233 
   1234 const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] = {
   1235    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags),
   1236      SEC_PKCS12BaggageItemTemplate },
   1237 };
   1238 
   1239 const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] = {
   1240    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks),
   1241      SEC_PKCS12ESPVKItemTemplate_OLD },
   1242 };
   1243 
   1244 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser =
   1245    sec_pkcs12_choose_bag_type;
   1246 
   1247 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old =
   1248    sec_pkcs12_choose_bag_type_old;
   1249 
   1250 const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] = {
   1251    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
   1252    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
   1253    { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
   1254          SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1255      offsetof(SEC_PKCS12SafeBag, safeContent),
   1256      &sec_pkcs12_bag_chooser_old },
   1257    { 0 }
   1258 };
   1259 
   1260 const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] = {
   1261    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
   1262    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
   1263    { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER,
   1264      offsetof(SEC_PKCS12SafeBag, safeContent),
   1265      &sec_pkcs12_bag_chooser },
   1266    { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING,
   1267      offsetof(SEC_PKCS12SafeBag, uniSafeBagName) },
   1268    { 0 }
   1269 };
   1270 
   1271 const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] = {
   1272    { SEC_ASN1_SET_OF,
   1273      offsetof(SEC_PKCS12SafeContents, contents),
   1274      SEC_PKCS12SafeBagTemplate_OLD }
   1275 };
   1276 
   1277 const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] = {
   1278    { SEC_ASN1_SET_OF,
   1279      offsetof(SEC_PKCS12SafeContents, contents),
   1280      SEC_PKCS12SafeBagTemplate } /* here */
   1281 };
   1282 
   1283 const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] = {
   1284    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) },
   1285    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData),
   1286      SEC_PKCS12PVKSupportingDataTemplate },
   1287    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1288      offsetof(SEC_PKCS12PrivateKey, pkcs8data),
   1289      SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) },
   1290    { 0 }
   1291 };
   1292 
   1293 const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] = {
   1294    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) },
   1295    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys),
   1296      SEC_PKCS12PrivateKeyTemplate },
   1297    { 0 }
   1298 };
   1299 
   1300 const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] = {
   1301    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
   1302    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
   1303      sec_PKCS7ContentInfoTemplate },
   1304    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1305      offsetof(SEC_PKCS12X509CertCRL, thumbprint),
   1306      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
   1307    { 0 }
   1308 };
   1309 
   1310 const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] = {
   1311    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
   1312    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
   1313      sec_PKCS7ContentInfoTemplate },
   1314    { 0 }
   1315 };
   1316 
   1317 const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] = {
   1318    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
   1319    { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) },
   1320    { 0 }
   1321 };
   1322 
   1323 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old =
   1324    sec_pkcs12_choose_cert_crl_type_old;
   1325 
   1326 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser =
   1327    sec_pkcs12_choose_cert_crl_type;
   1328 
   1329 const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] = {
   1330    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
   1331    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
   1332    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT |
   1333          SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0,
   1334      offsetof(SEC_PKCS12CertAndCRL, value),
   1335      &sec_pkcs12_cert_crl_chooser_old },
   1336    { 0 }
   1337 };
   1338 
   1339 const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] = {
   1340    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
   1341    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
   1342    { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
   1343          SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1344      offsetof(SEC_PKCS12CertAndCRL, value),
   1345      &sec_pkcs12_cert_crl_chooser },
   1346    { 0 }
   1347 };
   1348 
   1349 const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] = {
   1350    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
   1351      SEC_PKCS12CertAndCRLTemplate },
   1352 };
   1353 
   1354 const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] = {
   1355    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) },
   1356    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
   1357      SEC_PKCS12CertAndCRLTemplate_OLD },
   1358    { 0 }
   1359 };
   1360 
   1361 const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] = {
   1362    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) },
   1363    { SEC_ASN1_OBJECT_ID,
   1364      offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) },
   1365    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT,
   1366      offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) },
   1367    { 0 }
   1368 };
   1369 
   1370 const SEC_ASN1Template SEC_PKCS12SecretTemplate[] = {
   1371    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
   1372    { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) },
   1373    { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) },
   1374    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
   1375      offsetof(SEC_PKCS12Secret, secretAdditional),
   1376      SEC_PKCS12SecretAdditionalTemplate },
   1377    { 0 }
   1378 };
   1379 
   1380 const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] = {
   1381    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
   1382    { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1383      offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate },
   1384    { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1385      offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate },
   1386    { 0 }
   1387 };
   1388 
   1389 const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] = {
   1390    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets),
   1391      SEC_PKCS12SecretItemTemplate },
   1392 };
   1393 
   1394 const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] = {
   1395    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
   1396    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SEC_PKCS12MacData, safeMac),
   1397      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
   1398    { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) },
   1399    { 0 }
   1400 };
   1401 
   1402 const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] = {
   1403    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
   1404    { SEC_ASN1_OPTIONAL |
   1405          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1406      offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate },
   1407    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1408      offsetof(SEC_PKCS12PFXItem, authSafe),
   1409      sec_PKCS7ContentInfoTemplate },
   1410    { 0 }
   1411 };
   1412 
   1413 const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] = {
   1414    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
   1415    { SEC_ASN1_OPTIONAL |
   1416          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1417      offsetof(SEC_PKCS12PFXItem, old_safeMac),
   1418      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
   1419    { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING,
   1420      offsetof(SEC_PKCS12PFXItem, old_macSalt) },
   1421    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1422      offsetof(SEC_PKCS12PFXItem, authSafe),
   1423      sec_PKCS7ContentInfoTemplate },
   1424    { 0 }
   1425 };
   1426 
   1427 const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] = {
   1428    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
   1429    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
   1430      offsetof(SEC_PKCS12AuthenticatedSafe, version) },
   1431    { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID,
   1432      offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
   1433    { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
   1434      offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
   1435    { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF,
   1436      offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags),
   1437      SEC_PKCS12BaggageItemTemplate },
   1438    { SEC_ASN1_POINTER,
   1439      offsetof(SEC_PKCS12AuthenticatedSafe, safe),
   1440      sec_PKCS7ContentInfoTemplate },
   1441    { 0 }
   1442 };
   1443 
   1444 const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] = {
   1445    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
   1446    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
   1447      offsetof(SEC_PKCS12AuthenticatedSafe, version) },
   1448    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
   1449      offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
   1450    { SEC_ASN1_BIT_STRING,
   1451      offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
   1452    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
   1453          SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1454      offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage),
   1455      SEC_PKCS12BaggageTemplate_OLD },
   1456    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1457      offsetof(SEC_PKCS12AuthenticatedSafe, old_safe),
   1458      sec_PKCS7ContentInfoTemplate },
   1459    { 0 }
   1460 };
   1461 
   1462 const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] = {
   1463    { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate }
   1464 };
   1465 
   1466 const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] = {
   1467    { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD }
   1468 };
   1469 
   1470 const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] = {
   1471    { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate }
   1472 };
   1473 
   1474 const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] = {
   1475    { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate }
   1476 };
   1477 
   1478 const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] = {
   1479    { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD }
   1480 };
   1481 
   1482 const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] = {
   1483    { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate }
   1484 };
   1485 
   1486 const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] = {
   1487    { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate }
   1488 };