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