Check selftest status in all crypto operations and abort with
[oweals/openssl.git] / crypto / evp / evp_pkey.c
index 41107686ec97e319f5528da44c2436ead9c799c6..0147f3e02a683979b43f10aaf60fbaefc06a59b8 100644 (file)
 #include "cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/rand.h>
+#ifndef OPENSSL_NO_RSA
 #include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
 #include <openssl/dsa.h>
+#endif
 #include <openssl/bn.h>
 
 #ifndef OPENSSL_NO_DSA
@@ -74,7 +78,7 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey);
 
 /* Extract a private key from a PKCS8 structure */
 
-EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8)
 {
        EVP_PKEY *pkey = NULL;
 #ifndef OPENSSL_NO_RSA
@@ -250,6 +254,7 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
                }
                else
                {
+                       EC_GROUP *group;
                        cp = p = param->value.object->data;
                        plen = param->value.object->length;
 
@@ -262,11 +267,13 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
                                        ERR_R_MALLOC_FAILURE);
                                goto ecerr;
                        }
-                       if ((eckey->group = EC_GROUP_new_by_nid(
-                             OBJ_obj2nid(a->parameter->value.object))) == NULL)
+                       group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object));
+                       if (group == NULL)
+                               goto ecerr;
+                       EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+                       if (EC_KEY_set_group(eckey, group) == 0)
                                goto ecerr;
-                       EC_GROUP_set_asn1_flag(eckey->group, 
-                                               OPENSSL_EC_NAMED_CURVE);
+                       EC_GROUP_free(group);
                }
 
                /* We have parameters now set private key */
@@ -277,28 +284,40 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
                }
 
                /* calculate public key (if necessary) */
-               if (!eckey->pub_key)
+               if (EC_KEY_get0_public_key(eckey) == NULL)
                {
+                       const BIGNUM *priv_key;
+                       const EC_GROUP *group;
+                       EC_POINT *pub_key;
                        /* the public key was not included in the SEC1 private
                         * key => calculate the public key */
-                       eckey->pub_key = EC_POINT_new(eckey->group);
-                       if (!eckey->pub_key)
+                       group   = EC_KEY_get0_group(eckey);
+                       pub_key = EC_POINT_new(group);
+                       if (pub_key == NULL)
                        {
                                EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
                                goto ecerr;
                        }
-                       if (!EC_POINT_copy(eckey->pub_key, 
-                               EC_GROUP_get0_generator(eckey->group)))
+                       if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
                        {
+                               EC_POINT_free(pub_key);
                                EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
                                goto ecerr;
                        }
-                       if (!EC_POINT_mul(eckey->group, eckey->pub_key, 
-                               eckey->priv_key, NULL, NULL, ctx))
+                       priv_key = EC_KEY_get0_private_key(eckey);
+                       if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
                        {
+                               EC_POINT_free(pub_key);
                                EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
                                goto ecerr;
                        }
+                       if (EC_KEY_set_public_key(eckey, pub_key) == 0)
+                       {
+                               EC_POINT_free(pub_key);
+                               EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
+                               goto ecerr;
+                       }
+                       EC_POINT_free(pub_key);
                }
 
                EVP_PKEY_assign_EC_KEY(pkey, eckey);
@@ -337,17 +356,17 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
        PKCS8_PRIV_KEY_INFO *p8;
 
        if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {        
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
                return NULL;
        }
        p8->broken = broken;
        if (!ASN1_INTEGER_set(p8->version, 0)) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
                PKCS8_PRIV_KEY_INFO_free (p8);
                return NULL;
        }
        if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
                PKCS8_PRIV_KEY_INFO_free (p8);
                return NULL;
        }
@@ -362,7 +381,7 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
                p8->pkeyalg->parameter->type = V_ASN1_NULL;
                if (!ASN1_pack_string_of (EVP_PKEY,pkey, i2d_PrivateKey,
                                         &p8->pkey->value.octet_string)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
                        PKCS8_PRIV_KEY_INFO_free (p8);
                        return NULL;
                }
@@ -387,7 +406,7 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
                break;
 #endif
                default:
-               EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
                PKCS8_PRIV_KEY_INFO_free (p8);
                return NULL;
        }
@@ -412,7 +431,7 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken)
                break;
 
                default:
-               EVPerr(EVP_F_EVP_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE);
+               EVPerr(EVP_F_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE);
                return NULL;
        }
 }
@@ -430,24 +449,24 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
        p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa);
        len = i2d_DSAparams (pkey->pkey.dsa, NULL);
        if (!(p = OPENSSL_malloc(len))) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                goto err;
        }
        q = p;
        i2d_DSAparams (pkey->pkey.dsa, &q);
        if (!(params = ASN1_STRING_new())) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                goto err;
        }
        if (!ASN1_STRING_set(params, p, len)) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                goto err;
        }
        OPENSSL_free(p);
        p = NULL;
        /* Get private key into integer */
        if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
+               EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
                goto err;
        }
 
@@ -458,7 +477,7 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 
                if (!ASN1_pack_string_of(ASN1_INTEGER,prkey, i2d_ASN1_INTEGER,
                                         &p8->pkey->value.octet_string)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
 
@@ -476,39 +495,39 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                params = NULL;
                p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
                if (!(ndsa = sk_ASN1_TYPE_new_null())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                if (!(ttmp->value.integer =
                        BN_to_ASN1_INTEGER(pkey->pkey.dsa->pub_key, NULL))) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
                        goto err;
                }
                ttmp->type = V_ASN1_INTEGER;
                if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
 
                if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                ttmp->value.integer = prkey;
                prkey = NULL;
                ttmp->type = V_ASN1_INTEGER;
                if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                ttmp = NULL;
 
                if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
 
@@ -516,7 +535,7 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                                         &p8->pkey->value.octet_string->data,
                                         &p8->pkey->value.octet_string->length)) {
 
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
@@ -526,36 +545,36 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 
                p8->pkeyalg->parameter->type = V_ASN1_NULL;
                if (!(ndsa = sk_ASN1_TYPE_new_null())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                ttmp->value.sequence = params;
                params = NULL;
                ttmp->type = V_ASN1_SEQUENCE;
                if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
 
                if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                ttmp->value.integer = prkey;
                prkey = NULL;
                ttmp->type = V_ASN1_INTEGER;
                if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                ttmp = NULL;
 
                if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
 
@@ -563,7 +582,7 @@ static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                                         &p8->pkey->value.octet_string->data,
                                         &p8->pkey->value.octet_string->length)) {
 
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
                        goto err;
                }
                sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
@@ -583,17 +602,18 @@ err:
 #ifndef OPENSSL_NO_EC
 static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 {
-       EC_KEY          *eckey;
+       EC_KEY          *ec_key;
+       const EC_GROUP  *group;
        unsigned char   *p, *pp;
        int             nid, i, ret = 0;
-       unsigned int    tmp_flags;
+       unsigned int    tmp_flags, old_flags;
 
-       if (pkey->pkey.eckey == NULL || pkey->pkey.eckey->group == NULL)
+       ec_key = pkey->pkey.ec;
+       if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) 
        {
-               EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, EVP_R_MISSING_PARAMETERS);
+               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, EVP_R_MISSING_PARAMETERS);
                return 0;
        }
-       eckey = pkey->pkey.eckey;
 
        /* set the ec parameters OID */
        if (p8->pkeyalg->algorithm)
@@ -611,12 +631,12 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 
        if ((p8->pkeyalg->parameter = ASN1_TYPE_new()) == NULL)
        {
-               EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
                return 0;
        }
        
-       if (EC_GROUP_get_asn1_flag(eckey->group)
-                     && (nid = EC_GROUP_get_curve_name(eckey->group)))
+       if (EC_GROUP_get_asn1_flag(group)
+                     && (nid = EC_GROUP_get_curve_name(group)))
        {
                /* we have a 'named curve' => just set the OID */
                p8->pkeyalg->parameter->type = V_ASN1_OBJECT;
@@ -624,20 +644,20 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
        }
        else    /* explicit parameters */
        {
-               if ((i = i2d_ECParameters(eckey, NULL)) == 0)
+               if ((i = i2d_ECParameters(ec_key, NULL)) == 0)
                {
-                       EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_EC_LIB);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
                        return 0;
                }
                if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
                {
-                       EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
                        return 0;
                }       
                pp = p;
-               if (!i2d_ECParameters(eckey, &pp))
+               if (!i2d_ECParameters(ec_key, &pp))
                {
-                       EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_EC_LIB);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
                        OPENSSL_free(p);
                        return 0;
                }
@@ -645,7 +665,7 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                if ((p8->pkeyalg->parameter->value.sequence 
                        = ASN1_STRING_new()) == NULL)
                {
-                       EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_ASN1_LIB);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_ASN1_LIB);
                        OPENSSL_free(p);
                        return 0;
                }
@@ -657,32 +677,33 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 
        /* do not include the parameters in the SEC1 private key
         * see PKCS#11 12.11 */
-       tmp_flags  = pkey->pkey.eckey->enc_flag;
-       pkey->pkey.eckey->enc_flag |= EC_PKEY_NO_PARAMETERS;
-       i = i2d_ECPrivateKey(pkey->pkey.eckey, NULL);
+       old_flags = EC_KEY_get_enc_flags(pkey->pkey.ec);
+       tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
+       EC_KEY_set_enc_flags(pkey->pkey.ec, tmp_flags);
+       i = i2d_ECPrivateKey(pkey->pkey.ec, NULL);
        if (!i)
        {
-               pkey->pkey.eckey->enc_flag = tmp_flags;
-               EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_EC_LIB);
+               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
+               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
                return 0;
        }
        p = (unsigned char *) OPENSSL_malloc(i);
        if (!p)
        {
-               pkey->pkey.eckey->enc_flag = tmp_flags;
-               EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
+               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
                return 0;
        }
        pp = p;
-       if (!i2d_ECPrivateKey(pkey->pkey.eckey, &pp))
+       if (!i2d_ECPrivateKey(pkey->pkey.ec, &pp))
        {
-               pkey->pkey.eckey->enc_flag = tmp_flags;
-               EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_EC_LIB);
+               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
+               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
                OPENSSL_free(p);
                return 0;
        }
        /* restore old encoding flags */
-       pkey->pkey.eckey->enc_flag = tmp_flags;
+       EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
 
        switch(p8->broken) {
 
@@ -693,7 +714,7 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                    (const void *)p, i))
 
                {
-                       EVPerr(EVP_F_EC_KEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
                }
                else
                        ret = 1;
@@ -702,10 +723,72 @@ static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
                case PKCS8_NS_DB:               /* DSA specific */
                case PKCS8_EMBEDDED_PARAM:      /* DSA specific */
                default:
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
+                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
        }
        OPENSSL_cleanse(p, (size_t)i);
        OPENSSL_free(p);
        return ret;
 }
 #endif
+
+/* EVP_PKEY attribute functions */
+
+int EVP_PKEY_get_attr_count(const EVP_PKEY *key)
+{
+       return X509at_get_attr_count(key->attributes);
+}
+
+int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
+                         int lastpos)
+{
+       return X509at_get_attr_by_NID(key->attributes, nid, lastpos);
+}
+
+int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
+                         int lastpos)
+{
+       return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos);
+}
+
+X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc)
+{
+       return X509at_get_attr(key->attributes, loc);
+}
+
+X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc)
+{
+       return X509at_delete_attr(key->attributes, loc);
+}
+
+int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr)
+{
+       if(X509at_add1_attr(&key->attributes, attr)) return 1;
+       return 0;
+}
+
+int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+                       const ASN1_OBJECT *obj, int type,
+                       const unsigned char *bytes, int len)
+{
+       if(X509at_add1_attr_by_OBJ(&key->attributes, obj,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+                       int nid, int type,
+                       const unsigned char *bytes, int len)
+{
+       if(X509at_add1_attr_by_NID(&key->attributes, nid,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+                       const char *attrname, int type,
+                       const unsigned char *bytes, int len)
+{
+       if(X509at_add1_attr_by_txt(&key->attributes, attrname,
+                               type, bytes, len)) return 1;
+       return 0;
+}