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

Quelle  pk11pk12.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/. */

/*
 * This file PKCS #12 fuctions that should really be moved to the
 * PKCS #12 directory, however we can't do that in a point release
 * because that will break binary compatibility, so we keep them here for now.
 */


#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "secmodt.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "secitem.h"
#include "keyhi.h"
#include "secoid.h"
#include "secasn1.h"
#include "secerr.h"
#include "prerror.h"

/* These data structures should move to a common .h file shared between the
 * wrappers and the pkcs 12 code. */


/*
** RSA Raw Private Key structures
*/


/* member names from PKCS#1, section 7.2 */
struct SECKEYRSAPrivateKeyStr {
    PLArenaPool *arena;
    SECItem version;
    SECItem modulus;
    SECItem publicExponent;
    SECItem privateExponent;
    SECItem prime1;
    SECItem prime2;
    SECItem exponent1;
    SECItem exponent2;
    SECItem coefficient;
};
typedef struct SECKEYRSAPrivateKeyStr SECKEYRSAPrivateKey;

/*
** DSA Raw Private Key structures
*/


struct SECKEYDSAPrivateKeyStr {
    SECKEYPQGParams params;
    SECItem privateValue;
};
typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey;

/*
** Diffie-Hellman Raw Private Key structures
** Structure member names suggested by PKCS#3.
*/

struct SECKEYDHPrivateKeyStr {
    PLArenaPool *arena;
    SECItem prime;
    SECItem base;
    SECItem privateValue;
};
typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey;

/*
** Elliptic Curve Private Key structures
** <https://tools.ietf.org/html/rfc5915#section-3>
*/

struct SECKEYECPrivateKeyStr {
    PLArenaPool *arena;
    SECItem version;
    SECItem curveOID;    /* optional/ignored */
    SECItem publicValue; /* required (for now) */
    SECItem privateValue;
};
typedef struct SECKEYECPrivateKeyStr SECKEYECPrivateKey;

/*
** raw private key object
*/

struct SECKEYRawPrivateKeyStr {
    PLArenaPool *arena;
    KeyType keyType;
    union {
        SECKEYRSAPrivateKey rsa;
        SECKEYDSAPrivateKey dsa;
        SECKEYDHPrivateKey dh;
        SECKEYECPrivateKey ec;
    } u;
};
typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey;

SEC_ASN1_MKSUB(SEC_AnyTemplate)
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)

/* ASN1 Templates for new decoder/encoder */
/*
 * Attribute value for PKCS8 entries (static?)
 */

const SEC_ASN1Template SECKEY_AttributeTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(SECKEYAttribute) },
    { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) },
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(SECKEYAttribute, attrValue),
      SEC_ASN1_SUB(SEC_AnyTemplate) },
    { 0 }
};

const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
    { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
};

const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo, version) },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
      offsetof(SECKEYPrivateKeyInfo, algorithm),
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo, privateKey) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(SECKEYPrivateKeyInfo, attributes),
      SECKEY_SetOfAttributeTemplate },
    { 0 }
};

const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
    { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
};

const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.version) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.modulus) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.publicExponent) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.privateExponent) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime1) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime2) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent1) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent2) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.coefficient) },
    { 0 }
};

const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = {
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dsa.privateValue) },
};

const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = {
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.privateValue) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.base) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.prime) },
};

SEC_ASN1_MKSUB(SEC_BitStringTemplate)
SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)

const SEC_ASN1Template SECKEY_ECPrivateKeyExportTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
    { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.ec.version) },
    { SEC_ASN1_OCTET_STRING,
      offsetof(SECKEYRawPrivateKey, u.ec.privateValue) },
    /* This value will always be ignored. u.ec.curveOID will always be
     * overriden with the outer AlgorithmID.parameters. */

    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
          SEC_ASN1_XTRN | 0,
      offsetof(SECKEYRawPrivateKey, u.ec.curveOID),
      SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
    /* The public value is optional per RFC, but required in NSS. We
     * can't do scalar mult on ECs to get a raw point with PK11 APIs. */

    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
          SEC_ASN1_XTRN | 1,
      offsetof(SECKEYRawPrivateKey, u.ec.publicValue),
      SEC_ASN1_SUB(SEC_BitStringTemplate) },
    { 0 }
};

/* The template operates a private key consisting only of private key. */
const SEC_ASN1Template SECKEY_ECRawPrivateKeyTemplate[] = {
    { SEC_ASN1_OCTET_STRING,
      offsetof(SECKEYRawPrivateKey, u.ec.privateValue) },
    { 0 }
};

const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
      offsetof(SECKEYEncryptedPrivateKeyInfo, algorithm),
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    { SEC_ASN1_OCTET_STRING,
      offsetof(SECKEYEncryptedPrivateKeyInfo, encryptedData) },
    { 0 }
};

const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
    { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
};

SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)

/*
 * See bugzilla bug 125359
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
 * all of the templates above that en/decode into integers must be converted
 * from ASN.1's signed integer type.  This is done by marking either the
 * source or destination (encoding or decoding, respectively) type as
 * siUnsignedInteger.
 */


static void
prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
    key->u.rsa.modulus.type = siUnsignedInteger;
    key->u.rsa.publicExponent.type = siUnsignedInteger;
    key->u.rsa.privateExponent.type = siUnsignedInteger;
    key->u.rsa.prime1.type = siUnsignedInteger;
    key->u.rsa.prime2.type = siUnsignedInteger;
    key->u.rsa.exponent1.type = siUnsignedInteger;
    key->u.rsa.exponent2.type = siUnsignedInteger;
    key->u.rsa.coefficient.type = siUnsignedInteger;
}

static void
prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
    key->u.dsa.privateValue.type = siUnsignedInteger;
    key->u.dsa.params.prime.type = siUnsignedInteger;
    key->u.dsa.params.subPrime.type = siUnsignedInteger;
    key->u.dsa.params.base.type = siUnsignedInteger;
}

static void
prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
    key->u.dh.privateValue.type = siUnsignedInteger;
    key->u.dh.prime.type = siUnsignedInteger;
    key->u.dh.base.type = siUnsignedInteger;
}

static void
prepare_ec_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
    key->u.ec.version.type = siUnsignedInteger;
    key->u.ec.curveOID.type = siUnsignedInteger;
    key->u.ec.privateValue.type = siUnsignedInteger;
    key->u.ec.publicValue.type = siUnsignedInteger;
}

SECStatus
PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI,
                             SECItem *nickname, SECItem *publicValue, PRBool isPerm,
                             PRBool isPrivate, unsigned int keyUsage, void *wincx)
{
    return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI,
                                                    nickname, publicValue,
                                                    isPerm, isPrivate, keyUsage,
                                                    NULL, wincx);
}

SECStatus
PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI,
                                         SECItem *nickname, SECItem *publicValue,
                                         PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
                                         SECKEYPrivateKey **privk, void *wincx)
{
    SECKEYPrivateKeyInfo *pki = NULL;
    PLArenaPool *temparena = NULL;
    SECStatus rv = SECFailure;

    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!temparena) {
        return rv;
    }

    pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
    if (!pki) {
        PORT_FreeArena(temparena, PR_FALSE);
        return rv;
    }
    pki->arena = temparena;

    rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
                            derPKI);
    if (rv != SECSuccess) {
        /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the
         * validity of the data in pki. The best we can do is free the arena
         * and return. */

        PORT_FreeArena(temparena, PR_TRUE);
        return rv;
    }
    if (pki->privateKey.data == NULL) {
        /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey
         * is a zero-length octet string, free the arena and return a failure
         * to avoid trying to zero the corresponding SECItem in
         * SECKEY_DestroyPrivateKeyInfo(). */

        PORT_FreeArena(temparena, PR_TRUE);
        PORT_SetError(SEC_ERROR_BAD_KEY);
        return SECFailure;
    }

    rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
                                               publicValue, isPerm, isPrivate,
                                               keyUsage, privk, wincx);

    /* this zeroes the key and frees the arena */
    SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
    return rv;
}

SECStatus
PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
                               SECItem *nickname, SECItem *publicValue, PRBool isPerm,
                               PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
                               void *wincx)
{
    CK_BBOOL cktrue = CK_TRUE;
    CK_BBOOL ckfalse = CK_FALSE;
    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
    CK_KEY_TYPE keyType = CKK_RSA;
    CK_OBJECT_HANDLE objectID;
    CK_ATTRIBUTE theTemplate[20];
    int templateCount = 0;
    SECStatus rv = SECFailure;
    CK_ATTRIBUTE *attrs;
    CK_ATTRIBUTE *signedattr = NULL;
    int signedcount = 0;
    CK_ATTRIBUTE *ap;
    SECItem *ck_id = NULL;

    attrs = theTemplate;

    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
    attrs++;
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
    attrs++;
    PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse,
                  sizeof(CK_BBOOL));
    attrs++;
    PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse,
                  sizeof(CK_BBOOL));
    attrs++;
    PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
                  sizeof(CK_BBOOL));
    attrs++;

    switch (lpk->keyType) {
        case rsaKey:
            keyType = CKK_RSA;
            PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
                          (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
                                                            : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
            if (ck_id == NULL) {
                goto loser;
            }
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
            attrs++;
            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }
            signedattr = attrs;
            PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
                          lpk->u.rsa.modulus.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
                          lpk->u.rsa.publicExponent.data,
                          lpk->u.rsa.publicExponent.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT,
                          lpk->u.rsa.privateExponent.data,
                          lpk->u.rsa.privateExponent.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_PRIME_1,
                          lpk->u.rsa.prime1.data,
                          lpk->u.rsa.prime1.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_PRIME_2,
                          lpk->u.rsa.prime2.data,
                          lpk->u.rsa.prime2.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_EXPONENT_1,
                          lpk->u.rsa.exponent1.data,
                          lpk->u.rsa.exponent1.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_EXPONENT_2,
                          lpk->u.rsa.exponent2.data,
                          lpk->u.rsa.exponent2.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_COEFFICIENT,
                          lpk->u.rsa.coefficient.data,
                          lpk->u.rsa.coefficient.len);
            attrs++;
            break;
        case dsaKey:
            keyType = CKK_DSA;
            /* To make our intenal PKCS #11 module work correctly with
             * our database, we need to pass in the public key value for
             * this dsa key. We have a netscape only CKA_ value to do this.
             * Only send it to internal slots */

            if (publicValue == NULL) {
                goto loser;
            }
            if (PK11_IsInternal(slot)) {
                PK11_SETATTRS(attrs, CKA_NSS_DB,
                              publicValue->data, publicValue->len);
                attrs++;
            }
            PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL));
            attrs++;
            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }
            ck_id = PK11_MakeIDFromPubKey(publicValue);
            if (ck_id == NULL) {
                goto loser;
            }
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
            attrs++;
            signedattr = attrs;
            PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data,
                          lpk->u.dsa.params.prime.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_SUBPRIME, lpk->u.dsa.params.subPrime.data,
                          lpk->u.dsa.params.subPrime.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data,
                          lpk->u.dsa.params.base.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data,
                          lpk->u.dsa.privateValue.len);
            attrs++;
            break;
        case dhKey:
            keyType = CKK_DH;
            /* To make our intenal PKCS #11 module work correctly with
             * our database, we need to pass in the public key value for
             * this dh key. We have a netscape only CKA_ value to do this.
             * Only send it to internal slots */

            if (PK11_IsInternal(slot)) {
                PK11_SETATTRS(attrs, CKA_NSS_DB,
                              publicValue->data, publicValue->len);
                attrs++;
            }
            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
            attrs++;
            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }
            ck_id = PK11_MakeIDFromPubKey(publicValue);
            if (ck_id == NULL) {
                goto loser;
            }
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
            attrs++;
            signedattr = attrs;
            PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data,
                          lpk->u.dh.prime.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data,
                          lpk->u.dh.base.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data,
                          lpk->u.dh.privateValue.len);
            attrs++;
            break;
        case ecKey:
            keyType = CKK_EC;
            if (lpk->u.ec.publicValue.len != 0) {
                if (PK11_IsInternal(slot)) {
                    PK11_SETATTRS(attrs, CKA_NSS_DB,
                                  lpk->u.ec.publicValue.data,
                                  lpk->u.ec.publicValue.len);
                    attrs++;
                }
            }

            PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
                          (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
                                                            : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue : &ckfalse,
                          sizeof(CK_BBOOL));
            attrs++;
            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }
            ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue);
            if (ck_id == NULL) {
                goto loser;
            }
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
            attrs++;
            /* No signed attrs for EC */
            /* curveOID always is a copy of AlgorithmID.parameters. */
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
                          lpk->u.ec.curveOID.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
                          lpk->u.ec.privateValue.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_EC_POINT, lpk->u.ec.publicValue.data,
                          lpk->u.ec.publicValue.len);
            attrs++;
            break;
        case edKey:
            keyType = CKK_EC_EDWARDS;
            PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
            attrs++;
            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }

            /* No signed attrs for EC */
            /* curveOID always is a copy of AlgorithmID.parameters. */
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
                          lpk->u.ec.curveOID.len);
            attrs++;
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
                          lpk->u.ec.privateValue.len);
            attrs++;
            break;
        case ecMontKey:
            keyType = CKK_EC_MONTGOMERY;

            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
            attrs++;

            if (nickname) {
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
                attrs++;
            }

            /* No signed attrs for EC */
            /* curveOID always is a copy of AlgorithmID.parameters. */
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
                          lpk->u.ec.curveOID.len);
            attrs++;

            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
                          lpk->u.ec.privateValue.len);
            attrs++;
            break;
        default:
            PORT_SetError(SEC_ERROR_BAD_KEY);
            goto loser;
    }
    templateCount = attrs - theTemplate;
    PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
    if (lpk->keyType != ecKey && lpk->keyType != edKey && lpk->keyType != ecMontKey) {
        PORT_Assert(signedattr);
        signedcount = attrs - signedattr;
        for (ap = signedattr; signedcount; ap++, signedcount--) {
            pk11_SignedToUnsigned(ap);
        }
    }

    rv = PK11_CreateNewObject(slot, CK_INVALID_HANDLE,
                              theTemplate, templateCount, isPerm, &objectID);

    /* create and return a SECKEYPrivateKey */
    if (rv == SECSuccess && privk != NULL) {
        *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
        if (*privk == NULL) {
            rv = SECFailure;
        }
    }
loser:
    if (ck_id) {
        SECITEM_ZfreeItem(ck_id, PR_TRUE);
    }
    return rv;
}

SECStatus
PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
                                      SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
                                      PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
                                      SECKEYPrivateKey **privk, void *wincx)
{
    SECStatus rv = SECFailure;
    SECKEYRawPrivateKey *lpk = NULL;
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
    void *paramDest = NULL;
    PLArenaPool *arena = NULL;

    arena = PORT_NewArena(2048);
    if (!arena) {
        return SECFailure;
    }

    /* need to change this to use RSA/DSA keys */
    lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
                                                  sizeof(SECKEYRawPrivateKey));
    if (lpk == NULL) {
        goto loser;
    }
    lpk->arena = arena;

    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
            prepare_rsa_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = rsaKey;
            break;
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
            prepare_dsa_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
            paramTemplate = SECKEY_PQGParamsTemplate;
            paramDest = &(lpk->u.dsa.params);
            lpk->keyType = dsaKey;
            break;
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
            if (!publicValue) {
                goto loser;
            }
            prepare_dh_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = dhKey;
            break;
        case SEC_OID_ED25519_PUBLIC_KEY:
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = edKey;
            break;
        case SEC_OID_X25519:
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = ecMontKey;
            break;
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
            prepare_ec_priv_key_export_for_asn1(lpk);
            keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
            paramTemplate = NULL;
            paramDest = NULL;
            lpk->keyType = ecKey;
            break;

        default:
            keyTemplate = NULL;
            paramTemplate = NULL;
            paramDest = NULL;
            break;
    }

    if (!keyTemplate) {
        goto loser;
    }

    /* decode the private key and any algorithm parameters */
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
    if (rv != SECSuccess) {
        goto loser;
    }

    if (lpk->keyType == ecKey) {
        /* Convert length in bits to length in bytes. */
        lpk->u.ec.publicValue.len >>= 3;

        /* Always override curveOID, we're ignoring any given value. */
        rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID,
                              &pki->algorithm.parameters);
        if (rv != SECSuccess) {
            goto loser;
        }
    }

    if (lpk->keyType == edKey || lpk->keyType == ecMontKey) {
        /* SECKEY_ECRawPrivateKeyTemplate (used for both key types) does not reference
           publicKey, curveOID, ec verion. */

        if (pki->algorithm.parameters.len != 0) {
            /* Currently supporting only (Pure)Ed25519/X25519 .*/
            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
            goto loser;
        }

        SECOidData *oid25519 = SECOID_FindOIDByTag(SECOID_GetAlgorithmTag(&pki->algorithm));
        if (!oid25519) {
            goto loser;
        }

        if (!SECITEM_AllocItem(arena, &lpk->u.ec.curveOID, oid25519->oid.len + 2)) {
            goto loser;
        }
        lpk->u.ec.curveOID.data[0] = SEC_ASN1_OBJECT_ID;
        lpk->u.ec.curveOID.data[1] = oid25519->oid.len;
        PORT_Memcpy(lpk->u.ec.curveOID.data + 2, oid25519->oid.data, oid25519->oid.len);
    }

    if (paramDest && paramTemplate) {
        rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
                                &(pki->algorithm.parameters));
        if (rv != SECSuccess) {
            goto loser;
        }
    }

    rv = PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue, isPerm,
                                        isPrivate, keyUsage, privk, wincx);
loser:
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_TRUE);
    }

    return rv;
}

SECStatus
PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki,
                          SECItem *nickname, SECItem *publicValue, PRBool isPerm,
                          PRBool isPrivate, unsigned int keyUsage, void *wincx)
{
    return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
                                                 publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
}

SECItem *
PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
{
    SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
    SECItem *derPKI;

    if (!pki) {
        return NULL;
    }
    derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki,
                                SECKEY_PrivateKeyInfoTemplate);
    SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);
    return derPKI;
}

static PRBool
ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
              PLArenaPool *arena, SECItem *output)
{
    SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type,
                                      arena, output);
    return rv == SECSuccess;
}

/*
 * The caller is responsible for freeing the return value by passing it to
 * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE).
 */

SECKEYPrivateKeyInfo *
PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
{
    /* PrivateKeyInfo version (always zero) */
    const unsigned char pkiVersion = 0;
    /* RSAPrivateKey version (always zero) */
    const unsigned char rsaVersion = 0;
    /* ECPrivateKey version (always one) */
    const unsigned char ecVersion = 1;
    PLArenaPool *arena = NULL;
    SECKEYRawPrivateKey rawKey;
    SECKEYPrivateKeyInfo *pki;
    SECItem *encoded;
    const SEC_ASN1Template *keyTemplate;
    SECStatus rv;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) {
        goto loser;
    }
    memset(&rawKey, 0, sizeof(rawKey));
    rawKey.keyType = pk->keyType;
    pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo);
    if (!pki) {
        goto loser;
    }

    switch (pk->keyType) {
        case rsaKey: {
            rawKey.u.rsa.version.type = siUnsignedInteger;
            rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
            if (!rawKey.u.rsa.version.data) {
                goto loser;
            }

            rawKey.u.rsa.version.data[0] = rsaVersion;
            rawKey.u.rsa.version.len = 1;

            /* Read the component attributes of the private key */
            prepare_rsa_priv_key_export_for_asn1(&rawKey);
            if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) ||
                !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena,
                               &rawKey.u.rsa.publicExponent) ||
                !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena,
                               &rawKey.u.rsa.privateExponent) ||
                !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) ||
                !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) ||
                !ReadAttribute(pk, CKA_EXPONENT_1, arena,
                               &rawKey.u.rsa.exponent1) ||
                !ReadAttribute(pk, CKA_EXPONENT_2, arena,
                               &rawKey.u.rsa.exponent2) ||
                !ReadAttribute(pk, CKA_COEFFICIENT, arena,
                               &rawKey.u.rsa.coefficient)) {
                goto loser;
            }

            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;

            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
            if (rv != SECSuccess) {
                goto loser;
            }

        } break;
        case ecKey: {
            rawKey.u.ec.version.type = siUnsignedInteger;
            rawKey.u.ec.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
            if (!rawKey.u.ec.version.data) {
                goto loser;
            }
            rawKey.u.ec.version.data[0] = ecVersion;
            rawKey.u.ec.version.len = 1;

            SECItem curveOID;
            /* Read the component attributes of the private key */
            prepare_ec_priv_key_export_for_asn1(&rawKey);
            if (!ReadAttribute(pk, CKA_VALUE, arena,
                               &rawKey.u.ec.privateValue) ||
                !ReadAttribute(pk, CKA_EC_PARAMS, arena, &curveOID)) {
                goto loser;
            }
            if (!ReadAttribute(pk, CKA_EC_POINT, arena,
                               &rawKey.u.ec.publicValue)) {
                SECKEYPublicKey *pubk = SECKEY_ConvertToPublicKey(pk);
                if (pubk == NULL)
                    goto loser;
                rv = SECITEM_CopyItem(arena, &rawKey.u.ec.publicValue, &pubk->u.ec.publicValue);
                SECKEY_DestroyPublicKey(pubk);
                if (rv != SECSuccess) {
                    goto loser;
                }
            }

            keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
            /* Convert length in bytes to length in bits. */
            rawKey.u.ec.publicValue.len <<= 3;

            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ANSIX962_EC_PUBLIC_KEY, &curveOID);
            if (rv != SECSuccess) {
                goto loser;
            }

        } break;
        case edKey: {
            if (!ReadAttribute(pk, CKA_VALUE, arena,
                               &rawKey.u.ec.privateValue)) {
                goto loser;
            }

            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
            /* Currently, Ed25519 does not support any parameter.  */
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ED25519_PUBLIC_KEY, NULL);
            if (rv != SECSuccess) {
                goto loser;
            }
        } break;
        case ecMontKey: {
            if (!ReadAttribute(pk, CKA_VALUE, arena,
                               &rawKey.u.ec.privateValue)) {
                goto loser;
            }

            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
            /* Currently, X25519 does not support any parameter.  */
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_X25519, NULL);
            if (rv != SECSuccess) {
                goto loser;
            }
        } break;
        default: {
            PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
            goto loser;
        }
    }

    encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey, keyTemplate);
    if (!encoded) {
        goto loser;
    }
    pki->version.type = siUnsignedInteger;
    pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
    if (!pki->version.data) {
        goto loser;
    }
    pki->version.data[0] = pkiVersion;
    pki->version.len = 1;
    pki->arena = arena;

    return pki;

loser:
    if (arena) {
        PORT_FreeArena(arena, PR_TRUE);
    }
    return NULL;
}

Messung V0.5
C=96 H=73 G=85

¤ Dauer der Verarbeitung: 0.5 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.