Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/pkcs12/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 47 kB image not shown  

Quelle  p12local.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "nssrenam.h"
#include "pkcs12.h"
#include "secpkcs7.h"
#include "secasn1.h"
#include "seccomon.h"
#include "secoid.h"
#include "sechash.h"
#include "secitem.h"
#include "secerr.h"
#include "pk11func.h"
#include "p12local.h"
#include "p12.h"
#include "nsshash.h"
#include "secpkcs5.h"
#include "p12plcy.h"

#define SALT_LENGTH 16

SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate)
SEC_ASN1_MKSUB(sgn_DigestInfoTemplate)

CK_MECHANISM_TYPE
sec_pkcs12_algtag_to_mech(SECOidTag algtag)
{
    SECOidTag hmacAlg = HASH_GetHMACOidTagByHashOidTag(algtag);
    return PK11_AlgtagToMechanism(hmacAlg);
}

CK_MECHANISM_TYPE
sec_pkcs12_algtag_to_keygen_mech(SECOidTag algtag)
{
    switch (algtag) {
        case SEC_OID_SHA1:
            return CKM_NSS_PBE_SHA1_HMAC_KEY_GEN;
            break;
        case SEC_OID_MD5:
            return CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
            break;
        case SEC_OID_MD2:
            return CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
            break;
        case SEC_OID_SHA224:
            return CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN;
            break;
        case SEC_OID_SHA256:
            return CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN;
            break;
        case SEC_OID_SHA384:
            return CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN;
            break;
        case SEC_OID_SHA512:
            return CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN;
            break;
        default:
            break;
    }
    return CKM_INVALID_MECHANISM;
}

PK11SymKey *
sec_pkcs12_integrity_key(PK11SlotInfo *slot, sec_PKCS12MacData *macData,
                         SECItem *pwitem, CK_MECHANISM_TYPE *hmacMech,
                         PRBool isDecrypt, void *pwarg)
{
    int iteration;
    CK_MECHANISM_TYPE integrityMech;
    PK11SymKey *symKey = NULL;
    SECItem *params = NULL;
    SECAlgorithmID *prfAlgid = &macData->safeMac.digestAlgorithm;
    SECOidTag algtag = SECOID_GetAlgorithmTag(prfAlgid);

    /* handle PBE v2 case */
    if (algtag == SEC_OID_PKCS5_PBMAC1) {
        SECOidTag hmacAlg;
        SECItem utf8Pw;
        int keyLen;

        hmacAlg = SEC_PKCS5GetCryptoAlgorithm(prfAlgid);
        /* make sure we are using an hmac */
        if (HASH_GetHashOidTagByHMACOidTag(hmacAlg) == SEC_OID_UNKNOWN) {
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
        }
        if (!SEC_PKCS12IntegrityHashAllowed(hmacAlg, isDecrypt)) {
            PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
            return NULL;
        }
        /* make sure the length is valid, as well as decoding the length
         * from prfAlgid, SEC_PKCS5GetLength does some
         * fallbacks, which evenutally gets the max length of the key if
         * the decode fails. All HMAC keys have a max length of 128 bytes
         * in softoken, so if we get a keyLen of 128 we know we hit an error. */

        keyLen = SEC_PKCS5GetKeyLength(prfAlgid);
        if ((keyLen == 0) || (keyLen == 128)) {
            PORT_SetError(SEC_ERROR_BAD_DER);
            return NULL;
        }
        *hmacMech = PK11_AlgtagToMechanism(hmacAlg);
        /* pkcs12v2 hmac uses UTF8 rather than unicode */
        if (!sec_pkcs12_convert_item_to_unicode(NULL, &utf8Pw, pwitem,
                                                PR_FALSE, PR_FALSE, PR_FALSE)) {
            return NULL;
        }
        symKey = PK11_PBEKeyGen(slot, prfAlgid, &utf8Pw, PR_FALSE, pwarg);
        SECITEM_ZfreeItem(&utf8Pw, PR_FALSE);
        return symKey;
    }

    /* handle Legacy case */
    if (!SEC_PKCS12IntegrityHashAllowed(algtag, isDecrypt)) {
        PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
        return NULL;
    }
    integrityMech = sec_pkcs12_algtag_to_keygen_mech(algtag);
    *hmacMech = sec_pkcs12_algtag_to_mech(algtag);
    if (integrityMech == CKM_INVALID_MECHANISM) {
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
        goto loser;
    }
    if (macData->iter.data) {
        iteration = (int)DER_GetInteger(&macData->iter);
    } else {
        iteration = 1;
    }

    params = PK11_CreatePBEParams(&macData->macSalt, pwitem, iteration);
    if (params == NULL) {
        goto loser;
    }

    symKey = PK11_KeyGen(slot, integrityMech, params, 0, pwarg);
    PK11_DestroyPBEParams(params);
    params = NULL;
    if (!symKey)
        goto loser;
    return symKey;

loser:
    if (params) {
        PK11_DestroyPBEParams(params);
    }
    return NULL;
}

/* helper functions */
/* returns proper bag type template based upon object type tag */
const SEC_ASN1Template *
sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding)
{
    const SEC_ASN1Template *theTemplate;
    SEC_PKCS12SafeBag *safebag;
    SECOidData *oiddata;

    if (src_or_dest == NULL) {
        return NULL;
    }

    safebag = (SEC_PKCS12SafeBag *)src_or_dest;

    oiddata = safebag->safeBagTypeTag;
    if (oiddata == NULL) {
        oiddata = SECOID_FindOID(&safebag->safeBagType);
        safebag->safeBagTypeTag = oiddata;
    }

    switch (oiddata->offset) {
        default:
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
            break;
        case SEC_OID_PKCS12_KEY_BAG_ID:
            theTemplate = SEC_PointerToPKCS12KeyBagTemplate;
            break;
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
            theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD;
            break;
        case SEC_OID_PKCS12_SECRET_BAG_ID:
            theTemplate = SEC_PointerToPKCS12SecretBagTemplate;
            break;
    }
    return theTemplate;
}

const SEC_ASN1Template *
sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding)
{
    const SEC_ASN1Template *theTemplate;
    SEC_PKCS12SafeBag *safebag;
    SECOidData *oiddata;

    if (src_or_dest == NULL) {
        return NULL;
    }

    safebag = (SEC_PKCS12SafeBag *)src_or_dest;

    oiddata = safebag->safeBagTypeTag;
    if (oiddata == NULL) {
        oiddata = SECOID_FindOID(&safebag->safeBagType);
        safebag->safeBagTypeTag = oiddata;
    }

    switch (oiddata->offset) {
        default:
            theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
            break;
        case SEC_OID_PKCS12_KEY_BAG_ID:
            theTemplate = SEC_PKCS12PrivateKeyBagTemplate;
            break;
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
            theTemplate = SEC_PKCS12CertAndCRLBagTemplate;
            break;
        case SEC_OID_PKCS12_SECRET_BAG_ID:
            theTemplate = SEC_PKCS12SecretBagTemplate;
            break;
    }
    return theTemplate;
}

/* returns proper cert crl template based upon type tag */
const SEC_ASN1Template *
sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding)
{
    const SEC_ASN1Template *theTemplate;
    SEC_PKCS12CertAndCRL *certbag;
    SECOidData *oiddata;

    if (src_or_dest == NULL) {
        return NULL;
    }

    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
    oiddata = certbag->BagTypeTag;
    if (oiddata == NULL) {
        oiddata = SECOID_FindOID(&certbag->BagID);
        certbag->BagTypeTag = oiddata;
    }

    switch (oiddata->offset) {
        default:
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
            break;
        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD;
            break;
        case SEC_OID_PKCS12_SDSI_CERT_BAG:
            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
            break;
    }
    return theTemplate;
}

const SEC_ASN1Template *
sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding)
{
    const SEC_ASN1Template *theTemplate;
    SEC_PKCS12CertAndCRL *certbag;
    SECOidData *oiddata;

    if (src_or_dest == NULL) {
        return NULL;
    }

    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
    oiddata = certbag->BagTypeTag;
    if (oiddata == NULL) {
        oiddata = SECOID_FindOID(&certbag->BagID);
        certbag->BagTypeTag = oiddata;
    }

    switch (oiddata->offset) {
        default:
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
            break;
        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate;
            break;
        case SEC_OID_PKCS12_SDSI_CERT_BAG:
            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
            break;
    }
    return theTemplate;
}

/* returns appropriate shroud template based on object type tag */
const SEC_ASN1Template *
sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding)
{
    const SEC_ASN1Template *theTemplate;
    SEC_PKCS12ESPVKItem *espvk;
    SECOidData *oiddata;

    if (src_or_dest == NULL) {
        return NULL;
    }

    espvk = (SEC_PKCS12ESPVKItem *)src_or_dest;
    oiddata = espvk->espvkTag;
    if (oiddata == NULL) {
        oiddata = SECOID_FindOID(&espvk->espvkOID);
        espvk->espvkTag = oiddata;
    }

    switch (oiddata->offset) {
        default:
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
            break;
        case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING:
            theTemplate =
                SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate);
            break;
    }
    return theTemplate;
}

/* generate SALT  placing it into the character array passed in.
 * it is assumed that salt_dest is an array of appropriate size
 * XXX We might want to generate our own random context
 */

SECItem *
sec_pkcs12_generate_salt(void)
{
    SECItem *salt;

    salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    if (salt == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return NULL;
    }
    salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
                                              SALT_LENGTH);
    salt->len = SALT_LENGTH;
    if (salt->data == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        SECITEM_ZfreeItem(salt, PR_TRUE);
        return NULL;
    }

    PK11_GenerateRandom(salt->data, salt->len);

    return salt;
}

/* generate KEYS -- as per PKCS12 section 7.
 * only used for MAC
 */

SECItem *
sec_pkcs12_generate_key_from_password(SECOidTag algorithm,
                                      SECItem *salt,
                                      SECItem *password)
{
    unsigned char *pre_hash = NULL;
    unsigned char *hash_dest = NULL;
    SECStatus res;
    PLArenaPool *poolp;
    SECItem *key = NULL;
    int key_len = 0;

    if ((salt == NULL) || (password == NULL)) {
        return NULL;
    }

    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (poolp == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return NULL;
    }

    pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * (salt->len + password->len));
    if (pre_hash == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }

    hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp,
                                                  sizeof(unsigned char) * SHA1_LENGTH);
    if (hash_dest == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }

    PORT_Memcpy(pre_hash, salt->data, salt->len);
    /* handle password of 0 length case */
    if (password->len > 0) {
        PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
    }

    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash,
                       (salt->len + password->len));
    if (res == SECFailure) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }

    switch (algorithm) {
        case SEC_OID_SHA1:
            if (key_len == 0)
                key_len = 16;
            key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
            if (key == NULL) {
                PORT_SetError(SEC_ERROR_NO_MEMORY);
                goto loser;
            }
            key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * key_len);
            if (key->data == NULL) {
                PORT_SetError(SEC_ERROR_NO_MEMORY);
                goto loser;
            }
            key->len = key_len;
            PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH - key->len], key->len);
            break;
        default:
            goto loser;
            break;
    }

    PORT_FreeArena(poolp, PR_TRUE);
    return key;

loser:
    PORT_FreeArena(poolp, PR_TRUE);
    if (key != NULL) {
        SECITEM_ZfreeItem(key, PR_TRUE);
    }
    return NULL;
}

/* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
 * because it is not known how long the message actually is.  String
 * manipulation routines will not necessarily work because msg may have
 * imbedded NULLs
 */

static SECItem *
sec_pkcs12_generate_old_mac(SECItem *key,
                            SECItem *msg)
{
    SECStatus res;
    PLArenaPool *temparena = NULL;
    unsigned char *hash_dest = NULL, *hash_src1 = NULL, *hash_src2 = NULL;
    int i;
    SECItem *mac = NULL;

    if ((key == NULL) || (msg == NULL))
        goto loser;

    /* allocate return item */
    mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    if (mac == NULL)
        return NULL;
    mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * SHA1_LENGTH);
    mac->len = SHA1_LENGTH;
    if (mac->data == NULL)
        goto loser;

    /* allocate temporary items */
    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (temparena == NULL)
        goto loser;

    hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
                                                  sizeof(unsigned char) * (16 + msg->len));
    if (hash_src1 == NULL)
        goto loser;

    hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
                                                  sizeof(unsigned char) * (SHA1_LENGTH + 16));
    if (hash_src2 == NULL)
        goto loser;

    hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena,
                                                  sizeof(unsigned char) * SHA1_LENGTH);
    if (hash_dest == NULL)
        goto loser;

    /* perform mac'ing as per PKCS 12 */

    /* first round of hashing */
    for (i = 0; i < 16; i++)
        hash_src1[i] = key->data[i] ^ 0x36;
    PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16 + msg->len));
    if (res == SECFailure)
        goto loser;

    /* second round of hashing */
    for (i = 0; i < 16; i++)
        hash_src2[i] = key->data[i] ^ 0x5c;
    PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
    res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH + 16);
    if (res == SECFailure)
        goto loser;

    PORT_FreeArena(temparena, PR_TRUE);
    return mac;

loser:
    if (temparena != NULL)
        PORT_FreeArena(temparena, PR_TRUE);
    if (mac != NULL)
        SECITEM_ZfreeItem(mac, PR_TRUE);
    return NULL;
}

/* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
 * because it is not known how long the message actually is.  String
 * manipulation routines will not necessarily work because msg may have
 * imbedded NULLs
 */

SECItem *
sec_pkcs12_generate_mac(SECItem *key,
                        SECItem *msg,
                        PRBool old_method)
{
    SECStatus res = SECFailure;
    SECItem *mac = NULL;
    PK11Context *pk11cx = NULL;
    SECItem ignore = { 0 };

    if ((key == NULL) || (msg == NULL)) {
        return NULL;
    }

    if (old_method == PR_TRUE) {
        return sec_pkcs12_generate_old_mac(key, msg);
    }

    /* allocate return item */
    mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH);
    if (mac == NULL) {
        return NULL;
    }

    pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive,
                                        CKA_SIGN, key, &ignore, NULL);
    if (pk11cx == NULL) {
        goto loser;
    }

    res = PK11_DigestBegin(pk11cx);
    if (res == SECFailure) {
        goto loser;
    }

    res = PK11_DigestOp(pk11cx, msg->data, msg->len);
    if (res == SECFailure) {
        goto loser;
    }

    res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH);
    if (res == SECFailure) {
        goto loser;
    }

    PK11_DestroyContext(pk11cx, PR_TRUE);
    pk11cx = NULL;

loser:

    if (res != SECSuccess) {
        SECITEM_ZfreeItem(mac, PR_TRUE);
        mac = NULL;
        if (pk11cx) {
            PK11_DestroyContext(pk11cx, PR_TRUE);
        }
    }

    return mac;
}

/* compute the thumbprint of the DER cert and create a digest info
 * to store it in and return the digest info.
 * a return of NULL indicates an error.
 */

SGNDigestInfo *
sec_pkcs12_compute_thumbprint(SECItem *der_cert)
{
    SGNDigestInfo *thumb = NULL;
    SECItem digest;
    PLArenaPool *temparena = NULL;
    SECStatus rv = SECFailure;

    if (der_cert == NULL)
        return NULL;

    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if (temparena == NULL) {
        return NULL;
    }

    digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
                                                    sizeof(unsigned char) *
                                                        SHA1_LENGTH);
    /* digest data and create digest info */
    if (digest.data != NULL) {
        digest.len = SHA1_LENGTH;
        rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data,
                          der_cert->len);
        if (rv == SECSuccess) {
            thumb = SGN_CreateDigestInfo(SEC_OID_SHA1,
                                         digest.data,
                                         digest.len);
        } else {
            PORT_SetError(SEC_ERROR_NO_MEMORY);
        }
    } else {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
    }

    PORT_FreeArena(temparena, PR_TRUE);

    return thumb;
}

/* create a virtual password per PKCS 12, the password is converted
 * to unicode, the salt is prepended to it, and then the whole thing
 * is returned */

SECItem *
sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt,
                                   PRBool swap)
{
    SECItem uniPwd = { siBuffer, NULL, 0 }, *retPwd = NULL;

    if ((password == NULL) || (salt == NULL)) {
        return NULL;
    }

    if (password->len == 0) {
        uniPwd.data = (unsigned char *)PORT_ZAlloc(2);
        uniPwd.len = 2;
        if (!uniPwd.data) {
            return NULL;
        }
    } else {
        uniPwd.data = (unsigned char *)PORT_ZAlloc(password->len * 3);
        uniPwd.len = password->len * 3;
        if (!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
                                       uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
            SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
            return NULL;
        }
    }

    retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    if (retPwd == NULL) {
        goto loser;
    }

    /* allocate space and copy proper data */
    retPwd->len = uniPwd.len + salt->len;
    retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len);
    if (retPwd->data == NULL) {
        PORT_Free(retPwd);
        goto loser;
    }

    PORT_Memcpy(retPwd->data, salt->data, salt->len);
    PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len);

    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);

    return retPwd;

loser:
    PORT_SetError(SEC_ERROR_NO_MEMORY);
    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
    return NULL;
}

/* appends a shrouded key to a key bag.  this is used for exporting
 * to store externally wrapped keys.  it is used when importing to convert
 * old items to new
 */

SECStatus
sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag,
                               SEC_PKCS12ESPVKItem *espvk)
{
    int size;
    void *mark = NULL, *dummy = NULL;

    if ((bag == NULL) || (espvk == NULL))
        return SECFailure;

    mark = PORT_ArenaMark(bag->poolp);

    /* grow the list */
    size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *);
    dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp,
                                                   bag->espvks, size,
                                                   size + sizeof(SEC_PKCS12ESPVKItem *));
    bag->espvks = (SEC_PKCS12ESPVKItem **)dummy;
    if (dummy == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }

    bag->espvks[bag->nEspvks] = espvk;
    bag->nEspvks++;
    bag->espvks[bag->nEspvks] = NULL;

    PORT_ArenaUnmark(bag->poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(bag->poolp, mark);
    return SECFailure;
}

/* search a certificate list for a nickname, a thumbprint, or both
 * within a certificate bag.  if the certificate could not be
 * found or an error occurs, NULL is returned;
 */

static SEC_PKCS12CertAndCRL *
sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
                                SECItem *nickname, SGNDigestInfo *thumbprint)
{
    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
    int i, j;

    if ((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
        return NULL;
    }

    if (thumbprint && nickname) {
        search_both = PR_TRUE;
    }

    if (nickname) {
        search_nickname = PR_TRUE;
    }

search_again:
    i = 0;
    while (certbag->certAndCRLs[i] != NULL) {
        SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];

        if (SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {

            /* check nicknames */
            if (search_nickname) {
                if (SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
                    return cert;
                }
            } else {
                /* check thumbprints */
                SECItem **derCertList;

                /* get pointer to certificate list, does not need to
                 * be freed since it is within the arena which will
                 * be freed later.
                 */

                derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
                j = 0;
                if (derCertList != NULL) {
                    while (derCertList[j] != NULL) {
                        SECComparison eq;
                        SGNDigestInfo *di;
                        di = sec_pkcs12_compute_thumbprint(derCertList[j]);
                        if (di) {
                            eq = SGN_CompareDigestInfo(thumbprint, di);
                            SGN_DestroyDigestInfo(di);
                            if (eq == SECEqual) {
                                /* copy the derCert for later reference */
                                cert->value.x509->derLeafCert = derCertList[j];
                                return cert;
                            }
                        } else {
                            /* an error occurred */
                            return NULL;
                        }
                        j++;
                    }
                }
            }
        }

        i++;
    }

    if (search_both) {
        search_both = PR_FALSE;
        search_nickname = PR_FALSE;
        goto search_again;
    }

    return NULL;
}

/* search a key list for a nickname, a thumbprint, or both
 * within a key bag.  if the key could not be
 * found or an error occurs, NULL is returned;
 */

static SEC_PKCS12PrivateKey *
sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag,
                              SECItem *nickname, SGNDigestInfo *thumbprint)
{
    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
    int i, j;

    if ((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
        return NULL;
    }

    if (keybag->privateKeys == NULL) {
        return NULL;
    }

    if (thumbprint && nickname) {
        search_both = PR_TRUE;
    }

    if (nickname) {
        search_nickname = PR_TRUE;
    }

search_again:
    i = 0;
    while (keybag->privateKeys[i] != NULL) {
        SEC_PKCS12PrivateKey *key = keybag->privateKeys[i];

        /* check nicknames */
        if (search_nickname) {
            if (SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) {
                return key;
            }
        } else {
            /* check digests */
            SGNDigestInfo **assocCerts = key->pvkData.assocCerts;
            if ((assocCerts == NULL) || (assocCerts[0] == NULL)) {
                return NULL;
            }

            j = 0;
            while (assocCerts[j] != NULL) {
                SECComparison eq;
                eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]);
                if (eq == SECEqual) {
                    return key;
                }
                j++;
            }
        }
        i++;
    }

    if (search_both) {
        search_both = PR_FALSE;
        search_nickname = PR_FALSE;
        goto search_again;
    }

    return NULL;
}

/* seach the safe first then try the baggage bag
 *  safe and bag contain certs and keys to search
 *  objType is the object type to look for
 *  bagType is the type of bag that was found by sec_pkcs12_find_object
 *  index is the entity in safe->safeContents or bag->unencSecrets which
 *    is being searched
 *  nickname and thumbprint are the search criteria
 *
 * a return of null indicates no match
 */

static void *
sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe,
                    SEC_PKCS12BaggageItem *bag,
                    SECOidTag objType, SECOidTag bagType, int index,
                    SECItem *nickname, SGNDigestInfo *thumbprint)
{
    PRBool searchSafe;
    int i = index;

    if ((safe == NULL) && (bag == NULL)) {
        return NULL;
    }

    searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE);
    switch (objType) {
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
            if (objType == bagType) {
                SEC_PKCS12CertAndCRLBag *certBag;

                if (searchSafe) {
                    certBag = safe->contents[i]->safeContent.certAndCRLBag;
                } else {
                    certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag;
                }
                return sec_pkcs12_find_cert_in_certbag(certBag, nickname,
                                                       thumbprint);
            }
            break;
        case SEC_OID_PKCS12_KEY_BAG_ID:
            if (objType == bagType) {
                SEC_PKCS12PrivateKeyBag *keyBag;

                if (searchSafe) {
                    keyBag = safe->contents[i]->safeContent.keyBag;
                } else {
                    keyBag = bag->unencSecrets[i]->safeContent.keyBag;
                }
                return sec_pkcs12_find_key_in_keybag(keyBag, nickname,
                                                     thumbprint);
            }
            break;
        default:
            break;
    }

    return NULL;
}

/* searches both the baggage and the safe areas looking for
 * object of specified type matching either the nickname or the
 * thumbprint specified.
 *
 * safe and baggage store certs and keys
 * objType is the OID for the bag type to be searched:
 *   SEC_OID_PKCS12_KEY_BAG_ID, or
 *   SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID
 * nickname and thumbprint are the search criteria
 *
 * if no match found, NULL returned and error set
 */

void *
sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe,
                       SEC_PKCS12Baggage *baggage,
                       SECOidTag objType,
                       SECItem *nickname,
                       SGNDigestInfo *thumbprint)
{
    int i, j;
    void *retItem;

    if (((safe == NULL) && (thumbprint == NULL)) ||
        ((nickname == NULL) && (thumbprint == NULL))) {
        return NULL;
    }

    i = 0;
    if ((safe != NULL) && (safe->contents != NULL)) {
        while (safe->contents[i] != NULL) {
            SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType);
            retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i,
                                          nickname, thumbprint);
            if (retItem != NULL) {
                return retItem;
            }
            i++;
        }
    }

    if ((baggage != NULL) && (baggage->bags != NULL)) {
        i = 0;
        while (baggage->bags[i] != NULL) {
            SEC_PKCS12BaggageItem *xbag = baggage->bags[i];
            j = 0;
            if (xbag->unencSecrets != NULL) {
                while (xbag->unencSecrets[j] != NULL) {
                    SECOidTag bagType;
                    bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType);
                    retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType,
                                                  j, nickname, thumbprint);
                    if (retItem != NULL) {
                        return retItem;
                    }
                    j++;
                }
            }
            i++;
        }
    }

    PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);
    return NULL;
}

/* this function converts a password to UCS2 and ensures that the
 * required double 0 byte be placed at the end of the string (if zeroTerm
 * is set), or the 0 bytes at the end are dropped (if zeroTerm is not set).
 * If toUnicode is false, we convert from UCS2 to UTF8/ASCII (latter is a
 * proper subset of the former) depending on the state of the asciiCovert
 * flag)
 */

PRBool
sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest,
                                   SECItem *src, PRBool zeroTerm,
                                   PRBool asciiConvert, PRBool toUnicode)
{
    PRBool success = PR_FALSE;
    int bufferSize;

    if (!src || !dest) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return PR_FALSE;
    }

    bufferSize = src->len * 3 + 2;
    dest->len = bufferSize;
    if (arena) {
        dest->data = (unsigned char *)PORT_ArenaZAlloc(arena, dest->len);
    } else {
        dest->data = (unsigned char *)PORT_ZAlloc(dest->len);
    }

    if (!dest->data) {
        dest->len = 0;
        return PR_FALSE;
    }

    if (!asciiConvert) {
        success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data,
                                           dest->len, &dest->len);
    } else {
#ifndef IS_LITTLE_ENDIAN
        PRBool swapUnicode = PR_FALSE;
#else
        PRBool swapUnicode = PR_TRUE;
#endif
        success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data,
                                            dest->len, &dest->len, swapUnicode);
    }

    if (!success) {
        if (!arena) {
            PORT_Free(dest->data);
            dest->data = NULL;
            dest->len = 0;
        }
        return PR_FALSE;
    }

    /* in some cases we need to add NULL terminations and in others
     * we need to drop null terminations */

    if (zeroTerm) {
        /* unicode adds two nulls at the end */
        if (toUnicode) {
            if ((dest->len < 2) || dest->data[dest->len - 1] || dest->data[dest->len - 2]) {
                /* we've already allocated space for these new NULLs */
                PORT_Assert(dest->len + 2 <= bufferSize);
                dest->len += 2;
                dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0;
            }
            /* ascii/utf-8 adds just 1 */
        } else if (!dest->len || dest->data[dest->len - 1]) {
            PORT_Assert(dest->len + 1 <= bufferSize);
            dest->len++;
            dest->data[dest->len - 1] = 0;
        }
    } else {
        /* handle the drop case, no need to do any allocations here. */
        if (toUnicode) {
            while ((dest->len >= 2) && !dest->data[dest->len - 1] &&
                   !dest->data[dest->len - 2]) {
                dest->len -= 2;
            }
        } else {
            while (dest->len && !dest->data[dest->len - 1]) {
                dest->len--;
            }
        }
    }

    return PR_TRUE;
}

PRBool
sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
{
    switch (algorithm) {
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
        /* those are actually PKCS #5 v1.5 PBEs, but we
         * historically treat them in the same way as PKCS #12
         * PBEs */

        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
            return PR_TRUE;
        default:
            return PR_FALSE;
    }
}

/* this function decodes a password from Unicode if necessary,
 * according to the PBE algorithm.
 *
 * we assume that the pwitem is already encoded in Unicode by the
 * caller.  if the encryption scheme is not the one defined in PKCS
 * #12, decode the pwitem back into UTF-8. NOTE: UTF-8 strings are
 * used in the PRF without the trailing NULL */

PRBool
sec_pkcs12_decode_password(PLArenaPool *arena,
                           SECItem *result,
                           SECOidTag algorithm,
                           const SECItem *pwitem)
{
    if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
        return sec_pkcs12_convert_item_to_unicode(arena, result,
                                                  (SECItem *)pwitem,
                                                  PR_FALSE, PR_FALSE, PR_FALSE);

    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
}

/* this function encodes a password into Unicode if necessary,
 * according to the PBE algorithm.
 *
 * we assume that the pwitem holds a raw password.  if the encryption
 * scheme is the one defined in PKCS #12, encode the password into
 * BMPString. */

PRBool
sec_pkcs12_encode_password(PLArenaPool *arena,
                           SECItem *result,
                           SECOidTag algorithm,
                           const SECItem *pwitem)
{
    if (sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
        return sec_pkcs12_convert_item_to_unicode(arena, result,
                                                  (SECItem *)pwitem,
                                                  PR_TRUE, PR_TRUE, PR_TRUE);

    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
}

/* pkcs 12 templates */
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
    sec_pkcs12_choose_shroud_type;

const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
    { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
    { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] = {
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
      SEC_PKCS12CodedCertBagTemplate },
};

const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
      SEC_PKCS12PVKSupportingDataTemplate_OLD },
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
          SEC_ASN1_DYNAMIC | 0,
      offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
      &sec_pkcs12_shroud_chooser },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
      SEC_PKCS12PVKSupportingDataTemplate },
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
          SEC_ASN1_DYNAMIC | 0,
      offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
      &sec_pkcs12_shroud_chooser },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) },
    { SEC_ASN1_OBJECT_ID,
      offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) },
    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
      offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
      offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
    { SEC_ASN1_PRINTABLE_STRING,
      offsetof(SEC_PKCS12PVKSupportingData, nickname) },
    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
      offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
      offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
      offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
    { SEC_ASN1_BMP_STRING,
      offsetof(SEC_PKCS12PVKSupportingData, uniNickName) },
    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
      offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) },
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks),
      SEC_PKCS12ESPVKItemTemplate },
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
      SEC_PKCS12SafeBagTemplate },
    /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
        SEC_PKCS12CodedSafeBagTemplate }, */

    { 0 }
};

const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] = {
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags),
      SEC_PKCS12BaggageItemTemplate },
};

const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] = {
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks),
      SEC_PKCS12ESPVKItemTemplate_OLD },
};

static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser =
    sec_pkcs12_choose_bag_type;

static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old =
    sec_pkcs12_choose_bag_type_old;

const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
    { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12SafeBag, safeContent),
      &sec_pkcs12_bag_chooser_old },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
    { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER,
      offsetof(SEC_PKCS12SafeBag, safeContent),
      &sec_pkcs12_bag_chooser },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING,
      offsetof(SEC_PKCS12SafeBag, uniSafeBagName) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] = {
    { SEC_ASN1_SET_OF,
      offsetof(SEC_PKCS12SafeContents, contents),
      SEC_PKCS12SafeBagTemplate_OLD }
};

const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] = {
    { SEC_ASN1_SET_OF,
      offsetof(SEC_PKCS12SafeContents, contents),
      SEC_PKCS12SafeBagTemplate } /* here */
};

const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) },
    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData),
      SEC_PKCS12PVKSupportingDataTemplate },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
      offsetof(SEC_PKCS12PrivateKey, pkcs8data),
      SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) },
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys),
      SEC_PKCS12PrivateKeyTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
      sec_PKCS7ContentInfoTemplate },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
      offsetof(SEC_PKCS12X509CertCRL, thumbprint),
      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
    { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
      sec_PKCS7ContentInfoTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
    { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) },
    { 0 }
};

static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old =
    sec_pkcs12_choose_cert_crl_type_old;

static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser =
    sec_pkcs12_choose_cert_crl_type;

const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT |
          SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0,
      offsetof(SEC_PKCS12CertAndCRL, value),
      &sec_pkcs12_cert_crl_chooser_old },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
    { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
    { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12CertAndCRL, value),
      &sec_pkcs12_cert_crl_chooser },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] = {
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
      SEC_PKCS12CertAndCRLTemplate },
};

const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) },
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
      SEC_PKCS12CertAndCRLTemplate_OLD },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) },
    { SEC_ASN1_OBJECT_ID,
      offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) },
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT,
      offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SecretTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
    { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) },
    { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) },
    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
      offsetof(SEC_PKCS12Secret, secretAdditional),
      SEC_PKCS12SecretAdditionalTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
    { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate },
    { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] = {
    { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets),
      SEC_PKCS12SecretItemTemplate },
};

const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SEC_PKCS12MacData, safeMac),
      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
    { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
    { SEC_ASN1_OPTIONAL |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate },
    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(SEC_PKCS12PFXItem, authSafe),
      sec_PKCS7ContentInfoTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
    { SEC_ASN1_OPTIONAL |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
      offsetof(SEC_PKCS12PFXItem, old_safeMac),
      SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING,
      offsetof(SEC_PKCS12PFXItem, old_macSalt) },
    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(SEC_PKCS12PFXItem, authSafe),
      sec_PKCS7ContentInfoTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
      offsetof(SEC_PKCS12AuthenticatedSafe, version) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID,
      offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
    { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
      offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF,
      offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags),
      SEC_PKCS12BaggageItemTemplate },
    { SEC_ASN1_POINTER,
      offsetof(SEC_PKCS12AuthenticatedSafe, safe),
      sec_PKCS7ContentInfoTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
      offsetof(SEC_PKCS12AuthenticatedSafe, version) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
      offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
    { SEC_ASN1_BIT_STRING,
      offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
          SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage),
      SEC_PKCS12BaggageTemplate_OLD },
    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(SEC_PKCS12AuthenticatedSafe, old_safe),
      sec_PKCS7ContentInfoTemplate },
    { 0 }
};

const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate }
};

const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD }
};

const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate }
};

const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate }
};

const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD }
};

const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate }
};

const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] = {
    { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate }
};

Messung V0.5
C=97 H=86 G=91

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.