sl@0: /* evp_pkey.c */ sl@0: /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL sl@0: * project 1999. sl@0: */ sl@0: /* ==================================================================== sl@0: * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in sl@0: * the documentation and/or other materials provided with the sl@0: * distribution. sl@0: * sl@0: * 3. All advertising materials mentioning features or use of this sl@0: * software must display the following acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" sl@0: * sl@0: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to sl@0: * endorse or promote products derived from this software without sl@0: * prior written permission. For written permission, please contact sl@0: * licensing@OpenSSL.org. sl@0: * sl@0: * 5. Products derived from this software may not be called "OpenSSL" sl@0: * nor may "OpenSSL" appear in their names without prior written sl@0: * permission of the OpenSSL Project. sl@0: * sl@0: * 6. Redistributions of any form whatsoever must retain the following sl@0: * acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY sl@0: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR sl@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR sl@0: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, sl@0: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT sl@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; sl@0: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) sl@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED sl@0: * OF THE POSSIBILITY OF SUCH DAMAGE. sl@0: * ==================================================================== sl@0: * sl@0: * This product includes cryptographic software written by Eric Young sl@0: * (eay@cryptsoft.com). This product includes software written by Tim sl@0: * Hudson (tjh@cryptsoft.com). sl@0: * sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include "cryptlib.h" sl@0: #include sl@0: #include sl@0: #ifndef OPENSSL_NO_RSA sl@0: #include sl@0: #endif sl@0: #ifndef OPENSSL_NO_DSA sl@0: #include sl@0: #endif sl@0: #include sl@0: sl@0: #ifndef OPENSSL_NO_DSA sl@0: static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey); sl@0: #endif sl@0: #ifndef OPENSSL_NO_EC sl@0: static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey); sl@0: #endif sl@0: sl@0: /* Extract a private key from a PKCS8 structure */ sl@0: sl@0: EXPORT_C EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) sl@0: { sl@0: EVP_PKEY *pkey = NULL; sl@0: #ifndef OPENSSL_NO_RSA sl@0: RSA *rsa = NULL; sl@0: #endif sl@0: #ifndef OPENSSL_NO_DSA sl@0: DSA *dsa = NULL; sl@0: ASN1_TYPE *t1, *t2; sl@0: ASN1_INTEGER *privkey; sl@0: STACK_OF(ASN1_TYPE) *ndsa = NULL; sl@0: #endif sl@0: #ifndef OPENSSL_NO_EC sl@0: EC_KEY *eckey = NULL; sl@0: const unsigned char *p_tmp; sl@0: #endif sl@0: #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) sl@0: ASN1_TYPE *param = NULL; sl@0: BN_CTX *ctx = NULL; sl@0: int plen; sl@0: #endif sl@0: X509_ALGOR *a; sl@0: const unsigned char *p; sl@0: const unsigned char *cp; sl@0: int pkeylen; sl@0: int nid; sl@0: char obj_tmp[80]; sl@0: sl@0: if(p8->pkey->type == V_ASN1_OCTET_STRING) { sl@0: p8->broken = PKCS8_OK; sl@0: p = p8->pkey->value.octet_string->data; sl@0: pkeylen = p8->pkey->value.octet_string->length; sl@0: } else { sl@0: p8->broken = PKCS8_NO_OCTET; sl@0: p = p8->pkey->value.sequence->data; sl@0: pkeylen = p8->pkey->value.sequence->length; sl@0: } sl@0: if (!(pkey = EVP_PKEY_new())) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); sl@0: return NULL; sl@0: } sl@0: a = p8->pkeyalg; sl@0: nid = OBJ_obj2nid(a->algorithm); sl@0: switch(nid) sl@0: { sl@0: #ifndef OPENSSL_NO_RSA sl@0: case NID_rsaEncryption: sl@0: cp = p; sl@0: if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: return NULL; sl@0: } sl@0: EVP_PKEY_assign_RSA (pkey, rsa); sl@0: break; sl@0: #endif sl@0: #ifndef OPENSSL_NO_DSA sl@0: case NID_dsa: sl@0: /* PKCS#8 DSA is weird: you just get a private key integer sl@0: * and parameters in the AlgorithmIdentifier the pubkey must sl@0: * be recalculated. sl@0: */ sl@0: sl@0: /* Check for broken DSA PKCS#8, UGH! */ sl@0: if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { sl@0: if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, sl@0: d2i_ASN1_TYPE, sl@0: ASN1_TYPE_free))) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: if(sk_ASN1_TYPE_num(ndsa) != 2 ) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: /* Handle Two broken types: sl@0: * SEQUENCE {parameters, priv_key} sl@0: * SEQUENCE {pub_key, priv_key} sl@0: */ sl@0: sl@0: t1 = sk_ASN1_TYPE_value(ndsa, 0); sl@0: t2 = sk_ASN1_TYPE_value(ndsa, 1); sl@0: if(t1->type == V_ASN1_SEQUENCE) { sl@0: p8->broken = PKCS8_EMBEDDED_PARAM; sl@0: param = t1; sl@0: } else if(a->parameter->type == V_ASN1_SEQUENCE) { sl@0: p8->broken = PKCS8_NS_DB; sl@0: param = a->parameter; sl@0: } else { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: sl@0: if(t2->type != V_ASN1_INTEGER) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: privkey = t2->value.integer; sl@0: } else { sl@0: if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: param = p8->pkeyalg->parameter; sl@0: } sl@0: if (!param || (param->type != V_ASN1_SEQUENCE)) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: cp = p = param->value.sequence->data; sl@0: plen = param->value.sequence->length; sl@0: if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: /* We have parameters now set private key */ sl@0: if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: /* Calculate public key (ouch!) */ sl@0: if (!(dsa->pub_key = BN_new())) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); sl@0: goto dsaerr; sl@0: } sl@0: if (!(ctx = BN_CTX_new())) { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); sl@0: goto dsaerr; sl@0: } sl@0: sl@0: if (!BN_mod_exp(dsa->pub_key, dsa->g, sl@0: dsa->priv_key, dsa->p, ctx)) { sl@0: sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); sl@0: goto dsaerr; sl@0: } sl@0: sl@0: EVP_PKEY_assign_DSA(pkey, dsa); sl@0: BN_CTX_free (ctx); sl@0: if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); sl@0: else ASN1_INTEGER_free(privkey); sl@0: break; sl@0: dsaerr: sl@0: BN_CTX_free (ctx); sl@0: sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); sl@0: DSA_free(dsa); sl@0: EVP_PKEY_free(pkey); sl@0: return NULL; sl@0: break; sl@0: #endif sl@0: #ifndef OPENSSL_NO_EC sl@0: case NID_X9_62_id_ecPublicKey: sl@0: p_tmp = p; sl@0: /* extract the ec parameters */ sl@0: param = p8->pkeyalg->parameter; sl@0: sl@0: if (!param || ((param->type != V_ASN1_SEQUENCE) && sl@0: (param->type != V_ASN1_OBJECT))) sl@0: { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto ecerr; sl@0: } sl@0: sl@0: if (param->type == V_ASN1_SEQUENCE) sl@0: { sl@0: cp = p = param->value.sequence->data; sl@0: plen = param->value.sequence->length; sl@0: sl@0: if (!(eckey = d2i_ECParameters(NULL, &cp, plen))) sl@0: { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, sl@0: EVP_R_DECODE_ERROR); sl@0: goto ecerr; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: EC_GROUP *group; sl@0: cp = p = param->value.object->data; sl@0: plen = param->value.object->length; sl@0: sl@0: /* type == V_ASN1_OBJECT => the parameters are given sl@0: * by an asn1 OID sl@0: */ sl@0: if ((eckey = EC_KEY_new()) == NULL) sl@0: { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, sl@0: ERR_R_MALLOC_FAILURE); sl@0: goto ecerr; sl@0: } sl@0: group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); sl@0: if (group == NULL) sl@0: goto ecerr; sl@0: EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); sl@0: if (EC_KEY_set_group(eckey, group) == 0) sl@0: goto ecerr; sl@0: EC_GROUP_free(group); sl@0: } sl@0: sl@0: /* We have parameters now set private key */ sl@0: if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen)) sl@0: { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); sl@0: goto ecerr; sl@0: } sl@0: sl@0: /* calculate public key (if necessary) */ sl@0: if (EC_KEY_get0_public_key(eckey) == NULL) sl@0: { sl@0: const BIGNUM *priv_key; sl@0: const EC_GROUP *group; sl@0: EC_POINT *pub_key; sl@0: /* the public key was not included in the SEC1 private sl@0: * key => calculate the public key */ sl@0: group = EC_KEY_get0_group(eckey); sl@0: pub_key = EC_POINT_new(group); sl@0: if (pub_key == NULL) sl@0: { sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); sl@0: goto ecerr; sl@0: } sl@0: if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) sl@0: { sl@0: EC_POINT_free(pub_key); sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); sl@0: goto ecerr; sl@0: } sl@0: priv_key = EC_KEY_get0_private_key(eckey); sl@0: if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) sl@0: { sl@0: EC_POINT_free(pub_key); sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); sl@0: goto ecerr; sl@0: } sl@0: if (EC_KEY_set_public_key(eckey, pub_key) == 0) sl@0: { sl@0: EC_POINT_free(pub_key); sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); sl@0: goto ecerr; sl@0: } sl@0: EC_POINT_free(pub_key); sl@0: } sl@0: sl@0: EVP_PKEY_assign_EC_KEY(pkey, eckey); sl@0: if (ctx) sl@0: BN_CTX_free(ctx); sl@0: break; sl@0: ecerr: sl@0: if (ctx) sl@0: BN_CTX_free(ctx); sl@0: if (eckey) sl@0: EC_KEY_free(eckey); sl@0: if (pkey) sl@0: EVP_PKEY_free(pkey); sl@0: return NULL; sl@0: #endif sl@0: default: sl@0: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); sl@0: if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp); sl@0: else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); sl@0: ERR_add_error_data(2, "TYPE=", obj_tmp); sl@0: EVP_PKEY_free (pkey); sl@0: return NULL; sl@0: } sl@0: return pkey; sl@0: } sl@0: sl@0: EXPORT_C PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) sl@0: { sl@0: return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK); sl@0: } sl@0: sl@0: /* Turn a private key into a PKCS8 structure */ sl@0: sl@0: EXPORT_C PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken) sl@0: { sl@0: PKCS8_PRIV_KEY_INFO *p8; sl@0: sl@0: if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) { sl@0: EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE); sl@0: return NULL; sl@0: } sl@0: p8->broken = broken; sl@0: if (!ASN1_INTEGER_set(p8->version, 0)) { sl@0: EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE); sl@0: PKCS8_PRIV_KEY_INFO_free (p8); sl@0: return NULL; sl@0: } sl@0: if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) { sl@0: EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE); sl@0: PKCS8_PRIV_KEY_INFO_free (p8); sl@0: return NULL; sl@0: } sl@0: p8->pkey->type = V_ASN1_OCTET_STRING; sl@0: switch (EVP_PKEY_type(pkey->type)) { sl@0: #ifndef OPENSSL_NO_RSA sl@0: case EVP_PKEY_RSA: sl@0: sl@0: if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE; sl@0: sl@0: p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption); sl@0: p8->pkeyalg->parameter->type = V_ASN1_NULL; sl@0: if (!ASN1_pack_string_of (EVP_PKEY,pkey, i2d_PrivateKey, sl@0: &p8->pkey->value.octet_string)) { sl@0: EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE); sl@0: PKCS8_PRIV_KEY_INFO_free (p8); sl@0: return NULL; sl@0: } sl@0: break; sl@0: #endif sl@0: #ifndef OPENSSL_NO_DSA sl@0: case EVP_PKEY_DSA: sl@0: if(!dsa_pkey2pkcs8(p8, pkey)) { sl@0: PKCS8_PRIV_KEY_INFO_free (p8); sl@0: return NULL; sl@0: } sl@0: sl@0: break; sl@0: #endif sl@0: #ifndef OPENSSL_NO_EC sl@0: case EVP_PKEY_EC: sl@0: if (!eckey_pkey2pkcs8(p8, pkey)) sl@0: { sl@0: PKCS8_PRIV_KEY_INFO_free(p8); sl@0: return(NULL); sl@0: } sl@0: break; sl@0: #endif sl@0: default: sl@0: EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); sl@0: PKCS8_PRIV_KEY_INFO_free (p8); sl@0: return NULL; sl@0: } sl@0: RAND_add(p8->pkey->value.octet_string->data, sl@0: p8->pkey->value.octet_string->length, 0.0); sl@0: return p8; sl@0: } sl@0: sl@0: EXPORT_C PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) sl@0: { sl@0: switch (broken) { sl@0: sl@0: case PKCS8_OK: sl@0: p8->broken = PKCS8_OK; sl@0: return p8; sl@0: break; sl@0: sl@0: case PKCS8_NO_OCTET: sl@0: p8->broken = PKCS8_NO_OCTET; sl@0: p8->pkey->type = V_ASN1_SEQUENCE; sl@0: return p8; sl@0: break; sl@0: sl@0: default: sl@0: EVPerr(EVP_F_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); sl@0: return NULL; sl@0: } sl@0: } sl@0: sl@0: #ifndef OPENSSL_NO_DSA sl@0: static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey) sl@0: { sl@0: ASN1_STRING *params = NULL; sl@0: ASN1_INTEGER *prkey = NULL; sl@0: ASN1_TYPE *ttmp = NULL; sl@0: STACK_OF(ASN1_TYPE) *ndsa = NULL; sl@0: unsigned char *p = NULL, *q; sl@0: int len; sl@0: sl@0: p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); sl@0: len = i2d_DSAparams (pkey->pkey.dsa, NULL); sl@0: if (!(p = OPENSSL_malloc(len))) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: q = p; sl@0: i2d_DSAparams (pkey->pkey.dsa, &q); sl@0: if (!(params = ASN1_STRING_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: if (!ASN1_STRING_set(params, p, len)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: OPENSSL_free(p); sl@0: p = NULL; sl@0: /* Get private key into integer */ sl@0: if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR); sl@0: goto err; sl@0: } sl@0: sl@0: switch(p8->broken) { sl@0: sl@0: case PKCS8_OK: sl@0: case PKCS8_NO_OCTET: sl@0: sl@0: if (!ASN1_pack_string_of(ASN1_INTEGER,prkey, i2d_ASN1_INTEGER, sl@0: &p8->pkey->value.octet_string)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: M_ASN1_INTEGER_free (prkey); sl@0: prkey = NULL; sl@0: p8->pkeyalg->parameter->value.sequence = params; sl@0: params = NULL; sl@0: p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; sl@0: sl@0: break; sl@0: sl@0: case PKCS8_NS_DB: sl@0: sl@0: p8->pkeyalg->parameter->value.sequence = params; sl@0: params = NULL; sl@0: p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; sl@0: if (!(ndsa = sk_ASN1_TYPE_new_null())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: if (!(ttmp = ASN1_TYPE_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: if (!(ttmp->value.integer = sl@0: BN_to_ASN1_INTEGER(pkey->pkey.dsa->pub_key, NULL))) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR); sl@0: goto err; sl@0: } sl@0: ttmp->type = V_ASN1_INTEGER; sl@0: if (!sk_ASN1_TYPE_push(ndsa, ttmp)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: if (!(ttmp = ASN1_TYPE_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: ttmp->value.integer = prkey; sl@0: prkey = NULL; sl@0: ttmp->type = V_ASN1_INTEGER; sl@0: if (!sk_ASN1_TYPE_push(ndsa, ttmp)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: ttmp = NULL; sl@0: sl@0: if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, sl@0: &p8->pkey->value.octet_string->data, sl@0: &p8->pkey->value.octet_string->length)) { sl@0: sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); sl@0: break; sl@0: sl@0: case PKCS8_EMBEDDED_PARAM: sl@0: sl@0: p8->pkeyalg->parameter->type = V_ASN1_NULL; sl@0: if (!(ndsa = sk_ASN1_TYPE_new_null())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: if (!(ttmp = ASN1_TYPE_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: ttmp->value.sequence = params; sl@0: params = NULL; sl@0: ttmp->type = V_ASN1_SEQUENCE; sl@0: if (!sk_ASN1_TYPE_push(ndsa, ttmp)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: if (!(ttmp = ASN1_TYPE_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: ttmp->value.integer = prkey; sl@0: prkey = NULL; sl@0: ttmp->type = V_ASN1_INTEGER; sl@0: if (!sk_ASN1_TYPE_push(ndsa, ttmp)) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: ttmp = NULL; sl@0: sl@0: if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) { sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, sl@0: &p8->pkey->value.octet_string->data, sl@0: &p8->pkey->value.octet_string->length)) { sl@0: sl@0: EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); sl@0: break; sl@0: } sl@0: return 1; sl@0: err: sl@0: if (p != NULL) OPENSSL_free(p); sl@0: if (params != NULL) ASN1_STRING_free(params); sl@0: if (prkey != NULL) M_ASN1_INTEGER_free(prkey); sl@0: if (ttmp != NULL) ASN1_TYPE_free(ttmp); sl@0: if (ndsa != NULL) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); sl@0: return 0; sl@0: } sl@0: #endif sl@0: sl@0: #ifndef OPENSSL_NO_EC sl@0: static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey) sl@0: { sl@0: EC_KEY *ec_key; sl@0: const EC_GROUP *group; sl@0: unsigned char *p, *pp; sl@0: int nid, i, ret = 0; sl@0: unsigned int tmp_flags, old_flags; sl@0: sl@0: ec_key = pkey->pkey.ec; sl@0: if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, EVP_R_MISSING_PARAMETERS); sl@0: return 0; sl@0: } sl@0: sl@0: /* set the ec parameters OID */ sl@0: if (p8->pkeyalg->algorithm) sl@0: ASN1_OBJECT_free(p8->pkeyalg->algorithm); sl@0: sl@0: p8->pkeyalg->algorithm = OBJ_nid2obj(NID_X9_62_id_ecPublicKey); sl@0: sl@0: /* set the ec parameters */ sl@0: sl@0: if (p8->pkeyalg->parameter) sl@0: { sl@0: ASN1_TYPE_free(p8->pkeyalg->parameter); sl@0: p8->pkeyalg->parameter = NULL; sl@0: } sl@0: sl@0: if ((p8->pkeyalg->parameter = ASN1_TYPE_new()) == NULL) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); sl@0: return 0; sl@0: } sl@0: sl@0: if (EC_GROUP_get_asn1_flag(group) sl@0: && (nid = EC_GROUP_get_curve_name(group))) sl@0: { sl@0: /* we have a 'named curve' => just set the OID */ sl@0: p8->pkeyalg->parameter->type = V_ASN1_OBJECT; sl@0: p8->pkeyalg->parameter->value.object = OBJ_nid2obj(nid); sl@0: } sl@0: else /* explicit parameters */ sl@0: { sl@0: if ((i = i2d_ECParameters(ec_key, NULL)) == 0) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); sl@0: return 0; sl@0: } sl@0: if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); sl@0: return 0; sl@0: } sl@0: pp = p; sl@0: if (!i2d_ECParameters(ec_key, &pp)) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); sl@0: OPENSSL_free(p); sl@0: return 0; sl@0: } sl@0: p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; sl@0: if ((p8->pkeyalg->parameter->value.sequence sl@0: = ASN1_STRING_new()) == NULL) sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_ASN1_LIB); sl@0: OPENSSL_free(p); sl@0: return 0; sl@0: } sl@0: ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, i); sl@0: OPENSSL_free(p); sl@0: } sl@0: sl@0: /* set the private key */ sl@0: sl@0: /* do not include the parameters in the SEC1 private key sl@0: * see PKCS#11 12.11 */ sl@0: old_flags = EC_KEY_get_enc_flags(pkey->pkey.ec); sl@0: tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; sl@0: EC_KEY_set_enc_flags(pkey->pkey.ec, tmp_flags); sl@0: i = i2d_ECPrivateKey(pkey->pkey.ec, NULL); sl@0: if (!i) sl@0: { sl@0: EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); sl@0: return 0; sl@0: } sl@0: p = (unsigned char *) OPENSSL_malloc(i); sl@0: if (!p) sl@0: { sl@0: EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); sl@0: return 0; sl@0: } sl@0: pp = p; sl@0: if (!i2d_ECPrivateKey(pkey->pkey.ec, &pp)) sl@0: { sl@0: EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB); sl@0: OPENSSL_free(p); sl@0: return 0; sl@0: } sl@0: /* restore old encoding flags */ sl@0: EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags); sl@0: sl@0: switch(p8->broken) { sl@0: sl@0: case PKCS8_OK: sl@0: p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); sl@0: if (!p8->pkey->value.octet_string || sl@0: !M_ASN1_OCTET_STRING_set(p8->pkey->value.octet_string, sl@0: (const void *)p, i)) sl@0: sl@0: { sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); sl@0: } sl@0: else sl@0: ret = 1; sl@0: break; sl@0: case PKCS8_NO_OCTET: /* RSA specific */ sl@0: case PKCS8_NS_DB: /* DSA specific */ sl@0: case PKCS8_EMBEDDED_PARAM: /* DSA specific */ sl@0: default: sl@0: EVPerr(EVP_F_ECKEY_PKEY2PKCS8,EVP_R_ENCODE_ERROR); sl@0: } sl@0: OPENSSL_cleanse(p, (size_t)i); sl@0: OPENSSL_free(p); sl@0: return ret; sl@0: } sl@0: #endif sl@0: sl@0: /* EVP_PKEY attribute functions */ sl@0: sl@0: EXPORT_C int EVP_PKEY_get_attr_count(const EVP_PKEY *key) sl@0: { sl@0: return X509at_get_attr_count(key->attributes); sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, sl@0: int lastpos) sl@0: { sl@0: return X509at_get_attr_by_NID(key->attributes, nid, lastpos); sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj, sl@0: int lastpos) sl@0: { sl@0: return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos); sl@0: } sl@0: sl@0: EXPORT_C X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc) sl@0: { sl@0: return X509at_get_attr(key->attributes, loc); sl@0: } sl@0: sl@0: EXPORT_C X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc) sl@0: { sl@0: return X509at_delete_attr(key->attributes, loc); sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr) sl@0: { sl@0: if(X509at_add1_attr(&key->attributes, attr)) return 1; sl@0: return 0; sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, sl@0: const ASN1_OBJECT *obj, int type, sl@0: const unsigned char *bytes, int len) sl@0: { sl@0: if(X509at_add1_attr_by_OBJ(&key->attributes, obj, sl@0: type, bytes, len)) return 1; sl@0: return 0; sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, sl@0: int nid, int type, sl@0: const unsigned char *bytes, int len) sl@0: { sl@0: if(X509at_add1_attr_by_NID(&key->attributes, nid, sl@0: type, bytes, len)) return 1; sl@0: return 0; sl@0: } sl@0: sl@0: EXPORT_C int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, sl@0: const char *attrname, int type, sl@0: const unsigned char *bytes, int len) sl@0: { sl@0: if(X509at_add1_attr_by_txt(&key->attributes, attrname, sl@0: type, bytes, len)) return 1; sl@0: return 0; sl@0: }