michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: #include "lowkeyi.h" michael@0: #include "secoid.h" michael@0: #include "secitem.h" michael@0: #include "secder.h" michael@0: #include "base64.h" michael@0: #include "secasn1.h" michael@0: #include "secerr.h" michael@0: michael@0: #ifndef NSS_DISABLE_ECC michael@0: #include "softoken.h" michael@0: #endif michael@0: michael@0: SEC_ASN1_MKSUB(SEC_AnyTemplate) michael@0: SEC_ASN1_MKSUB(SEC_BitStringTemplate) michael@0: SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) michael@0: SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) michael@0: michael@0: const SEC_ASN1Template nsslowkey_AttributeTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(NSSLOWKEYAttribute) }, michael@0: { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) }, michael@0: { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , michael@0: offsetof(NSSLOWKEYAttribute, attrValue), michael@0: SEC_ASN1_SUB(SEC_AnyTemplate) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = { michael@0: { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate }, michael@0: }; michael@0: /* ASN1 Templates for new decoder/encoder */ michael@0: const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, michael@0: 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, michael@0: { SEC_ASN1_INTEGER, michael@0: offsetof(NSSLOWKEYPrivateKeyInfo,version) }, michael@0: { SEC_ASN1_INLINE | SEC_ASN1_XTRN, michael@0: offsetof(NSSLOWKEYPrivateKeyInfo,algorithm), michael@0: SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, michael@0: { SEC_ASN1_OCTET_STRING, michael@0: offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) }, michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, michael@0: offsetof(NSSLOWKEYPrivateKeyInfo, attributes), michael@0: nsslowkey_SetOfAttributeTemplate }, michael@0: { 0 } michael@0: }; michael@0: michael@0: const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, michael@0: { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) }, michael@0: { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) }, michael@0: { SEC_ASN1_INTEGER, offsetof(PQGParams,base) }, michael@0: { 0, } michael@0: }; michael@0: michael@0: const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) }, michael@0: { 0 } michael@0: }; michael@0: michael@0: michael@0: const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) }, michael@0: { 0, } michael@0: }; michael@0: michael@0: const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = { michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) }, michael@0: }; michael@0: michael@0: const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) }, michael@0: { 0, } michael@0: }; michael@0: michael@0: #ifndef NSS_DISABLE_ECC michael@0: michael@0: /* XXX This is just a placeholder for later when we support michael@0: * generic curves and need full-blown support for parsing EC michael@0: * parameters. For now, we only support named curves in which michael@0: * EC params are simply encoded as an object ID and we don't michael@0: * use nsslowkey_ECParamsTemplate. michael@0: */ michael@0: const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = { michael@0: { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) }, michael@0: { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named }, michael@0: { 0, } michael@0: }; michael@0: michael@0: michael@0: /* NOTE: The SECG specification allows the private key structure michael@0: * to contain curve parameters but recommends that they be stored michael@0: * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo michael@0: * instead. michael@0: */ michael@0: const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, michael@0: { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) }, michael@0: { SEC_ASN1_OCTET_STRING, michael@0: offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) }, michael@0: /* XXX The following template works for now since we only michael@0: * support named curves for which the parameters are michael@0: * encoded as an object ID. When we support generic curves, michael@0: * we'll need to define nsslowkey_ECParamsTemplate michael@0: */ michael@0: #if 1 michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | michael@0: SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | michael@0: SEC_ASN1_XTRN | 0, michael@0: offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID), michael@0: SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, michael@0: #else michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | michael@0: SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, michael@0: offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams), michael@0: nsslowkey_ECParamsTemplate }, michael@0: #endif michael@0: { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | michael@0: SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | michael@0: SEC_ASN1_XTRN | 1, michael@0: offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue), michael@0: SEC_ASN1_SUB(SEC_BitStringTemplate) }, michael@0: { 0, } michael@0: }; michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: /* michael@0: * See bugzilla bug 125359 michael@0: * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, michael@0: * all of the templates above that en/decode into integers must be converted michael@0: * from ASN.1's signed integer type. This is done by marking either the michael@0: * source or destination (encoding or decoding, respectively) type as michael@0: * siUnsignedInteger. michael@0: */ michael@0: michael@0: void michael@0: prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) michael@0: { michael@0: key->u.rsa.modulus.type = siUnsignedInteger; michael@0: key->u.rsa.publicExponent.type = siUnsignedInteger; michael@0: key->u.rsa.privateExponent.type = siUnsignedInteger; michael@0: key->u.rsa.prime1.type = siUnsignedInteger; michael@0: key->u.rsa.prime2.type = siUnsignedInteger; michael@0: key->u.rsa.exponent1.type = siUnsignedInteger; michael@0: key->u.rsa.exponent2.type = siUnsignedInteger; michael@0: key->u.rsa.coefficient.type = siUnsignedInteger; michael@0: } michael@0: michael@0: void michael@0: prepare_low_pqg_params_for_asn1(PQGParams *params) michael@0: { michael@0: params->prime.type = siUnsignedInteger; michael@0: params->subPrime.type = siUnsignedInteger; michael@0: params->base.type = siUnsignedInteger; michael@0: } michael@0: michael@0: void michael@0: prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) michael@0: { michael@0: key->u.dsa.publicValue.type = siUnsignedInteger; michael@0: key->u.dsa.privateValue.type = siUnsignedInteger; michael@0: key->u.dsa.params.prime.type = siUnsignedInteger; michael@0: key->u.dsa.params.subPrime.type = siUnsignedInteger; michael@0: key->u.dsa.params.base.type = siUnsignedInteger; michael@0: } michael@0: michael@0: void michael@0: prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key) michael@0: { michael@0: key->u.dsa.privateValue.type = siUnsignedInteger; michael@0: } michael@0: michael@0: void michael@0: prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) michael@0: { michael@0: key->u.dh.prime.type = siUnsignedInteger; michael@0: key->u.dh.base.type = siUnsignedInteger; michael@0: key->u.dh.publicValue.type = siUnsignedInteger; michael@0: key->u.dh.privateValue.type = siUnsignedInteger; michael@0: } michael@0: michael@0: #ifndef NSS_DISABLE_ECC michael@0: void michael@0: prepare_low_ecparams_for_asn1(ECParams *params) michael@0: { michael@0: params->DEREncoding.type = siUnsignedInteger; michael@0: params->curveOID.type = siUnsignedInteger; michael@0: } michael@0: michael@0: void michael@0: prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) michael@0: { michael@0: key->u.ec.version.type = siUnsignedInteger; michael@0: key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger; michael@0: key->u.ec.ecParams.curveOID.type = siUnsignedInteger; michael@0: key->u.ec.privateValue.type = siUnsignedInteger; michael@0: key->u.ec.publicValue.type = siUnsignedInteger; michael@0: } michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: michael@0: void michael@0: nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) michael@0: { michael@0: if (privk && privk->arena) { michael@0: PORT_FreeArena(privk->arena, PR_TRUE); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk) michael@0: { michael@0: if (pubk && pubk->arena) { michael@0: PORT_FreeArena(pubk->arena, PR_FALSE); michael@0: } michael@0: } michael@0: unsigned michael@0: nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk) michael@0: { michael@0: unsigned char b0; michael@0: michael@0: /* interpret modulus length as key strength... in michael@0: * fortezza that's the public key length */ michael@0: michael@0: switch (pubk->keyType) { michael@0: case NSSLOWKEYRSAKey: michael@0: b0 = pubk->u.rsa.modulus.data[0]; michael@0: return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; michael@0: default: michael@0: break; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: unsigned michael@0: nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk) michael@0: { michael@0: michael@0: unsigned char b0; michael@0: michael@0: switch (privk->keyType) { michael@0: case NSSLOWKEYRSAKey: michael@0: b0 = privk->u.rsa.modulus.data[0]; michael@0: return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1; michael@0: default: michael@0: break; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: NSSLOWKEYPublicKey * michael@0: nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) michael@0: { michael@0: NSSLOWKEYPublicKey *pubk; michael@0: PLArenaPool *arena; michael@0: michael@0: michael@0: arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); michael@0: if (arena == NULL) { michael@0: PORT_SetError (SEC_ERROR_NO_MEMORY); michael@0: return NULL; michael@0: } michael@0: michael@0: switch(privk->keyType) { michael@0: case NSSLOWKEYRSAKey: michael@0: case NSSLOWKEYNullKey: michael@0: pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, michael@0: sizeof (NSSLOWKEYPublicKey)); michael@0: if (pubk != NULL) { michael@0: SECStatus rv; michael@0: michael@0: pubk->arena = arena; michael@0: pubk->keyType = privk->keyType; michael@0: if (privk->keyType == NSSLOWKEYNullKey) return pubk; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus, michael@0: &privk->u.rsa.modulus); michael@0: if (rv == SECSuccess) { michael@0: rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent, michael@0: &privk->u.rsa.publicExponent); michael@0: if (rv == SECSuccess) michael@0: return pubk; michael@0: } michael@0: } else { michael@0: PORT_SetError (SEC_ERROR_NO_MEMORY); michael@0: } michael@0: break; michael@0: case NSSLOWKEYDSAKey: michael@0: pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, michael@0: sizeof(NSSLOWKEYPublicKey)); michael@0: if (pubk != NULL) { michael@0: SECStatus rv; michael@0: michael@0: pubk->arena = arena; michael@0: pubk->keyType = privk->keyType; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue, michael@0: &privk->u.dsa.publicValue); michael@0: if (rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime, michael@0: &privk->u.dsa.params.prime); michael@0: if (rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime, michael@0: &privk->u.dsa.params.subPrime); michael@0: if (rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base, michael@0: &privk->u.dsa.params.base); michael@0: if (rv == SECSuccess) return pubk; michael@0: } michael@0: break; michael@0: case NSSLOWKEYDHKey: michael@0: pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, michael@0: sizeof(NSSLOWKEYPublicKey)); michael@0: if (pubk != NULL) { michael@0: SECStatus rv; michael@0: michael@0: pubk->arena = arena; michael@0: pubk->keyType = privk->keyType; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue, michael@0: &privk->u.dh.publicValue); michael@0: if (rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime, michael@0: &privk->u.dh.prime); michael@0: if (rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.dh.base, michael@0: &privk->u.dh.base); michael@0: if (rv == SECSuccess) return pubk; michael@0: } michael@0: break; michael@0: #ifndef NSS_DISABLE_ECC michael@0: case NSSLOWKEYECKey: michael@0: pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, michael@0: sizeof(NSSLOWKEYPublicKey)); michael@0: if (pubk != NULL) { michael@0: SECStatus rv; michael@0: michael@0: pubk->arena = arena; michael@0: pubk->keyType = privk->keyType; michael@0: rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, michael@0: &privk->u.ec.publicValue); michael@0: if (rv != SECSuccess) break; michael@0: pubk->u.ec.ecParams.arena = arena; michael@0: /* Copy the rest of the params */ michael@0: rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams), michael@0: &(privk->u.ec.ecParams)); michael@0: if (rv == SECSuccess) return pubk; michael@0: } michael@0: break; michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: /* No Fortezza in Low Key implementations (Fortezza keys aren't michael@0: * stored in our data base */ michael@0: default: michael@0: break; michael@0: } michael@0: michael@0: PORT_FreeArena (arena, PR_FALSE); michael@0: return NULL; michael@0: } michael@0: michael@0: NSSLOWKEYPrivateKey * michael@0: nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey) michael@0: { michael@0: NSSLOWKEYPrivateKey *returnKey = NULL; michael@0: SECStatus rv = SECFailure; michael@0: PLArenaPool *poolp; michael@0: michael@0: if(!privKey) { michael@0: return NULL; michael@0: } michael@0: michael@0: poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if(!poolp) { michael@0: return NULL; michael@0: } michael@0: michael@0: returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey)); michael@0: if(!returnKey) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: returnKey->keyType = privKey->keyType; michael@0: returnKey->arena = poolp; michael@0: michael@0: switch(privKey->keyType) { michael@0: case NSSLOWKEYRSAKey: michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus), michael@0: &(privKey->u.rsa.modulus)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version), michael@0: &(privKey->u.rsa.version)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent), michael@0: &(privKey->u.rsa.publicExponent)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent), michael@0: &(privKey->u.rsa.privateExponent)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1), michael@0: &(privKey->u.rsa.prime1)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2), michael@0: &(privKey->u.rsa.prime2)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1), michael@0: &(privKey->u.rsa.exponent1)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2), michael@0: &(privKey->u.rsa.exponent2)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient), michael@0: &(privKey->u.rsa.coefficient)); michael@0: if(rv != SECSuccess) break; michael@0: break; michael@0: case NSSLOWKEYDSAKey: michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue), michael@0: &(privKey->u.dsa.publicValue)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue), michael@0: &(privKey->u.dsa.privateValue)); michael@0: if(rv != SECSuccess) break; michael@0: returnKey->u.dsa.params.arena = poolp; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime), michael@0: &(privKey->u.dsa.params.prime)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime), michael@0: &(privKey->u.dsa.params.subPrime)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base), michael@0: &(privKey->u.dsa.params.base)); michael@0: if(rv != SECSuccess) break; michael@0: break; michael@0: case NSSLOWKEYDHKey: michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue), michael@0: &(privKey->u.dh.publicValue)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue), michael@0: &(privKey->u.dh.privateValue)); michael@0: if(rv != SECSuccess) break; michael@0: returnKey->u.dsa.params.arena = poolp; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime), michael@0: &(privKey->u.dh.prime)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base), michael@0: &(privKey->u.dh.base)); michael@0: if(rv != SECSuccess) break; michael@0: break; michael@0: #ifndef NSS_DISABLE_ECC michael@0: case NSSLOWKEYECKey: michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version), michael@0: &(privKey->u.ec.version)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue), michael@0: &(privKey->u.ec.publicValue)); michael@0: if(rv != SECSuccess) break; michael@0: rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue), michael@0: &(privKey->u.ec.privateValue)); michael@0: if(rv != SECSuccess) break; michael@0: returnKey->u.ec.ecParams.arena = poolp; michael@0: /* Copy the rest of the params */ michael@0: rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams), michael@0: &(privKey->u.ec.ecParams)); michael@0: if (rv != SECSuccess) break; michael@0: break; michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: default: michael@0: rv = SECFailure; michael@0: } michael@0: michael@0: loser: michael@0: michael@0: if(rv != SECSuccess) { michael@0: PORT_FreeArena(poolp, PR_TRUE); michael@0: returnKey = NULL; michael@0: } michael@0: michael@0: return returnKey; michael@0: }