Add support for legacy PEM format private keys in EVP_PKEY_ASN1_METHOD.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 23 Mar 2006 18:02:23 +0000 (18:02 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 23 Mar 2006 18:02:23 +0000 (18:02 +0000)
13 files changed:
crypto/asn1/ameth_lib.c
crypto/asn1/asn1_locl.h
crypto/asn1/d2i_pr.c
crypto/asn1/i2d_pr.c
crypto/dsa/dsa_ameth.c
crypto/ec/ec_ameth.c
crypto/evp/evp.h
crypto/pem/pem.h
crypto/pem/pem_all.c
crypto/pem/pem_err.c
crypto/pem/pem_lib.c
crypto/pem/pem_pkey.c
crypto/rsa/rsa_ameth.c

index d753720..c95ccf0 100644 (file)
@@ -105,6 +105,25 @@ static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
         return ((*a)->pkey_id - (*b)->pkey_id);
        }
 
+int EVP_PKEY_asn1_get_count(void)
+       {
+       int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
+       if (app_methods)
+               num += sk_num(app_methods);
+       return num;
+       }
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
+       {
+       int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
+       if (idx < 0)
+               return NULL; 
+       if (idx < num)
+               return standard_methods[idx];
+       idx -= num;
+       return (const EVP_PKEY_ASN1_METHOD *)sk_value(app_methods, idx);
+       }
+
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
        {
        EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
@@ -129,6 +148,22 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
        return *ret;
        }
 
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(const char *str, int len)
+       {
+       int i;
+       const EVP_PKEY_ASN1_METHOD *ameth;
+       for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
+               {
+               ameth = EVP_PKEY_asn1_get0(i);
+               if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+                       continue;
+               if ((strlen(ameth->pem_str) == len) && 
+                       !strncasecmp(ameth->pem_str, str, len))
+                       return ameth;
+               }
+       return NULL;
+       }
+
 int EVP_PKEY_asn1_add(const EVP_PKEY_ASN1_METHOD *ameth)
        {
        if (app_methods == NULL)
index aafb5af..3acb439 100644 (file)
@@ -107,4 +107,11 @@ struct evp_pkey_asn1_method_st
 
        void (*pkey_free)(EVP_PKEY *pkey);
        void (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
+
+       /* Legacy functions for old PEM */
+
+       int (*old_priv_decode)(EVP_PKEY *pkey,
+                               const unsigned char **pder, int derlen);
+       int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
+
        } /* EVP_PKEY_ASN1_METHOD */;
index bb6582b..b4e47d4 100644 (file)
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include <openssl/asn1.h>
-#ifndef OPENSSL_NO_RSA
-#include <openssl/rsa.h>
-#endif
-#ifndef OPENSSL_NO_DSA
-#include <openssl/dsa.h>
-#endif
-#ifndef OPENSSL_NO_EC
-#include <openssl/ec.h>
-#endif
+#include "asn1_locl.h"
 
 EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
             long length)
@@ -90,39 +82,17 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
        ret->save_type=type;
        ret->type=EVP_PKEY_type(type);
        ret->ameth = EVP_PKEY_asn1_find(type);
-       switch (ret->type)
+       if (ret->ameth)
                {
-#ifndef OPENSSL_NO_RSA
-       case EVP_PKEY_RSA:
-               if ((ret->pkey.rsa=d2i_RSAPrivateKey(NULL,
-                       (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */
+               if (!ret->ameth->old_priv_decode ||
+                       !ret->ameth->old_priv_decode(ret, pp, length))
                        {
                        ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB);
                        goto err;
                        }
-               break;
-#endif
-#ifndef OPENSSL_NO_DSA
-       case EVP_PKEY_DSA:
-               if ((ret->pkey.dsa=d2i_DSAPrivateKey(NULL,
-                       (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */
-                       {
-                       ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB);
-                       goto err;
-                       }
-               break;
-#endif
-#ifndef OPENSSL_NO_EC
-       case EVP_PKEY_EC:
-               if ((ret->pkey.ec = d2i_ECPrivateKey(NULL, 
-                       (const unsigned char **)pp, length)) == NULL)
-                       {
-                       ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
-                       goto err;
-                       }
-               break;
-#endif
-       default:
+               }
+       else
+               {
                ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
                goto err;
                /* break; */
index 0be52c5..0ca7b70 100644 (file)
 
 #include <stdio.h>
 #include "cryptlib.h"
-#include <openssl/bn.h>
 #include <openssl/evp.h>
-#include <openssl/objects.h>
-#ifndef OPENSSL_NO_RSA
-#include <openssl/rsa.h>
-#endif
-#ifndef OPENSSL_NO_DSA
-#include <openssl/dsa.h>
-#endif
-#ifndef OPENSSL_NO_EC
-#include <openssl/ec.h>
-#endif
+#include "asn1_locl.h"
 
 int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
        {
-#ifndef OPENSSL_NO_RSA
-       if (a->type == EVP_PKEY_RSA)
+       if (a->ameth && a->ameth->old_priv_encode)
                {
-               return(i2d_RSAPrivateKey(a->pkey.rsa,pp));
+               return a->ameth->old_priv_encode(a, pp);
                }
-       else
-#endif
-#ifndef OPENSSL_NO_DSA
-       if (a->type == EVP_PKEY_DSA)
-               {
-               return(i2d_DSAPrivateKey(a->pkey.dsa,pp));
-               }
-#endif
-#ifndef OPENSSL_NO_EC
-       if (a->type == EVP_PKEY_EC)
-               {
-               return(i2d_ECPrivateKey(a->pkey.ec, pp));
-               }
-#endif
-
        ASN1err(ASN1_F_I2D_PRIVATEKEY,ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
        return(-1);
        }
index ed0ab2b..3198224 100644 (file)
@@ -493,6 +493,24 @@ static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
        return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
        }
 
+static int old_dsa_priv_decode(EVP_PKEY *pkey,
+                                       const unsigned char **pder, int derlen)
+       {
+       DSA *dsa;
+       if (!(dsa = d2i_DSAPrivateKey (NULL, pder, derlen)))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_DSA_LIB);
+               return 0;
+               }
+       EVP_PKEY_assign_DSA(pkey, dsa);
+       return 1;
+       }
+
+static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+       {
+       return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
+       }
+
 /* NB these are sorted in pkey_id order, lowest first */
 
 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 
@@ -527,7 +545,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
                EVP_PKEY_DSA,
                0,
 
-               "dsa",
+               "DSA",
                "OpenSSL DSA method",
 
                dsa_pub_decode,
@@ -549,7 +567,9 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
                dsa_param_print,
 
                int_dsa_free,
-               0
+               0,
+               old_dsa_priv_decode,
+               old_dsa_priv_encode
                }
        };
 
index aead4db..2fee623 100644 (file)
@@ -534,12 +534,30 @@ static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
        return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
        }
 
+static int old_ec_priv_decode(EVP_PKEY *pkey,
+                                       const unsigned char **pder, int derlen)
+       {
+       EC_KEY *ec;
+       if (!(ec = d2i_ECPrivateKey (NULL, pder, derlen)))
+               {
+               ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
+               return 0;
+               }
+       EVP_PKEY_assign_EC_KEY(pkey, ec);
+       return 1;
+       }
+
+static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+       {
+       return i2d_ECPrivateKey(pkey->pkey.ec, pder);
+       }
+
 EVP_PKEY_ASN1_METHOD eckey_asn1_meth = 
        {
        EVP_PKEY_EC,
        EVP_PKEY_EC,
        0,
-       "ec",
+       "EC",
        "OpenSSL EC algorithm",
 
        eckey_pub_decode,
@@ -561,5 +579,7 @@ EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
        eckey_param_print,
 
        int_ec_free,
-       0
+       0,
+       old_ec_priv_decode,
+       old_ec_priv_encode
        };
index 62f3320..76ed876 100644 (file)
@@ -855,7 +855,10 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
                    EVP_PBE_KEYGEN *keygen);
 void EVP_PBE_cleanup(void);
 
+int EVP_PKEY_asn1_get_count(void);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(const char *str, int len);
 int EVP_PKEY_asn1_add(const EVP_PKEY_ASN1_METHOD *ameth);
 EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
                                        const char *pem_str, const char *info);
index 6ccb14e..f2c5f32 100644 (file)
@@ -731,6 +731,7 @@ void ERR_load_PEM_strings(void);
 #define PEM_F_PEM_SIGNFINAL                             112
 #define PEM_F_PEM_WRITE                                         113
 #define PEM_F_PEM_WRITE_BIO                             114
+#define PEM_F_PEM_WRITE_PRIVATEKEY                      139
 #define PEM_F_PEM_X509_INFO_READ                        115
 #define PEM_F_PEM_X509_INFO_READ_BIO                    116
 #define PEM_F_PEM_X509_INFO_WRITE_BIO                   117
index d696f15..713cd17 100644 (file)
@@ -294,15 +294,4 @@ IMPLEMENT_PEM_rw_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
 
 #endif
 
-
-/* The PrivateKey case is not that straightforward.
- *   IMPLEMENT_PEM_rw_cb(PrivateKey, EVP_PKEY, PEM_STRING_EVP_PKEY, PrivateKey)
- * does not work, RSA and DSA keys have specific strings.
- * (When reading, parameter PEM_STRING_EVP_PKEY is a wildcard for anything
- * appropriate.)
- */
-IMPLEMENT_PEM_write_cb(PrivateKey, EVP_PKEY, ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:\
-                       (x->type == EVP_PKEY_RSA)?PEM_STRING_RSA:PEM_STRING_ECPRIVATEKEY), PrivateKey)
-
 IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
-
index c63195c..c435855 100644 (file)
@@ -71,7 +71,7 @@
 static ERR_STRING_DATA PEM_str_functs[]=
        {
 {ERR_FUNC(PEM_F_B2I_DSS),      "B2I_DSS"},
-{ERR_FUNC(PEM_F_B2I_PVK_BIO),  "B2I_PVK_BIO"},
+{ERR_FUNC(PEM_F_B2I_PVK_BIO),  "b2i_PVK_bio"},
 {ERR_FUNC(PEM_F_B2I_RSA),      "B2I_RSA"},
 {ERR_FUNC(PEM_F_CHECK_BITLEN_DSA),     "CHECK_BITLEN_DSA"},
 {ERR_FUNC(PEM_F_CHECK_BITLEN_RSA),     "CHECK_BITLEN_RSA"},
@@ -85,7 +85,7 @@ static ERR_STRING_DATA PEM_str_functs[]=
 {ERR_FUNC(PEM_F_DO_PVK_BODY),  "DO_PVK_BODY"},
 {ERR_FUNC(PEM_F_DO_PVK_HEADER),        "DO_PVK_HEADER"},
 {ERR_FUNC(PEM_F_I2B_PVK),      "I2B_PVK"},
-{ERR_FUNC(PEM_F_I2B_PVK_BIO),  "I2B_PVK_BIO"},
+{ERR_FUNC(PEM_F_I2B_PVK_BIO),  "i2b_PVK_bio"},
 {ERR_FUNC(PEM_F_LOAD_IV),      "LOAD_IV"},
 {ERR_FUNC(PEM_F_PEM_ASN1_READ),        "PEM_ASN1_read"},
 {ERR_FUNC(PEM_F_PEM_ASN1_READ_BIO),    "PEM_ASN1_read_bio"},
@@ -105,8 +105,9 @@ static ERR_STRING_DATA PEM_str_functs[]=
 {ERR_FUNC(PEM_F_PEM_SIGNFINAL),        "PEM_SignFinal"},
 {ERR_FUNC(PEM_F_PEM_WRITE),    "PEM_write"},
 {ERR_FUNC(PEM_F_PEM_WRITE_BIO),        "PEM_write_bio"},
-{ERR_FUNC(PEM_F_PEM_X509_INFO_READ),   "PEM_X509_INFO_read"},
-{ERR_FUNC(PEM_F_PEM_X509_INFO_READ_BIO),       "PEM_X509_INFO_read_bio"},
+{ERR_FUNC(PEM_F_PEM_WRITE_PRIVATEKEY), "PEM_WRITE_PRIVATEKEY"},
+{ERR_FUNC(PEM_F_PEM_X509_INFO_READ),   "PEM_X509_INFO_READ"},
+{ERR_FUNC(PEM_F_PEM_X509_INFO_READ_BIO),       "PEM_X509_INFO_READ_BIO"},
 {ERR_FUNC(PEM_F_PEM_X509_INFO_WRITE_BIO),      "PEM_X509_INFO_write_bio"},
 {0,NULL}
        };
index beb40d7..22793fa 100644 (file)
@@ -66,6 +66,7 @@
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/pkcs12.h>
+#include "asn1_locl.h"
 #ifndef OPENSSL_NO_DES
 #include <openssl/des.h>
 #endif
@@ -76,6 +77,7 @@ const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT;
 
 static int load_iv(char **fromp,unsigned char *to, int num);
 static int check_pem(const char *nm, const char *name);
+int pem_check_suffix(const char *pem_str, const char *suffix);
 
 int PEM_def_callback(char *buf, int num, int w, void *key)
        {
@@ -184,20 +186,24 @@ static int check_pem(const char *nm, const char *name)
 
        /* Make PEM_STRING_EVP_PKEY match any private key */
 
-       if(!strcmp(nm,PEM_STRING_PKCS8) &&
-               !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
-
-       if(!strcmp(nm,PEM_STRING_PKCS8INF) &&
-                !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
-
-       if(!strcmp(nm,PEM_STRING_RSA) &&
-               !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
-
-       if(!strcmp(nm,PEM_STRING_DSA) &&
-                !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
+       if(!strcmp(name,PEM_STRING_EVP_PKEY))
+               {
+               int slen;
+               const EVP_PKEY_ASN1_METHOD *ameth;
+               if(!strcmp(nm,PEM_STRING_PKCS8))
+                       return 1;
+               if(!strcmp(nm,PEM_STRING_PKCS8INF))
+                       return 1;
+               slen = pem_check_suffix(nm, "PRIVATE KEY"); 
+               if (slen > 0)
+                       {
+                       ameth = EVP_PKEY_asn1_find_str(nm, slen);
+                       if (ameth && ameth->old_priv_decode)
+                               return 1;
+                       }
+               return 0;
+               }
 
-       if(!strcmp(nm,PEM_STRING_ECPRIVATEKEY) &&
-                !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
        /* Permit older strings */
 
        if(!strcmp(nm,PEM_STRING_X509_OLD) &&
@@ -783,16 +789,17 @@ err:
  * the return value is 3 for the string "RSA".
  */
 
-int pem_check_suffix(char *pem_str, char *suffix)
+int pem_check_suffix(const char *pem_str, const char *suffix)
        {
        int pem_len = strlen(pem_str);
        int suffix_len = strlen(suffix);
-       char *p;
+       const char *p;
        if (suffix_len + 1 >= pem_len)
                return 0;
-       if (strcmp(pem_str - suffix_len, suffix))
+       p = pem_str + pem_len - suffix_len;
+       if (strcmp(p, suffix))
                return 0;
-       p = pem_str - suffix_len - 1;
+       p--;
        if (*p != ' ')
                return 0;
        return p - pem_str;
index 2162a45..aea826e 100644 (file)
@@ -65,7 +65,9 @@
 #include <openssl/x509.h>
 #include <openssl/pkcs12.h>
 #include <openssl/pem.h>
+#include "asn1_locl.h"
 
+int pem_check_suffix(const char *pem_str, const char *suffix);
 
 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
        {
@@ -73,18 +75,21 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, vo
        const unsigned char *p=NULL;
        unsigned char *data=NULL;
        long len;
+       int slen;
        EVP_PKEY *ret=NULL;
 
        if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
                return NULL;
        p = data;
 
-       if (strcmp(nm,PEM_STRING_RSA) == 0)
-               ret=d2i_PrivateKey(EVP_PKEY_RSA,x,&p,len);
-       else if (strcmp(nm,PEM_STRING_DSA) == 0)
-               ret=d2i_PrivateKey(EVP_PKEY_DSA,x,&p,len);
-       else if (strcmp(nm,PEM_STRING_ECPRIVATEKEY) == 0)
-               ret=d2i_PrivateKey(EVP_PKEY_EC,x,&p,len);
+       if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0)
+               {
+               const EVP_PKEY_ASN1_METHOD *ameth;
+               ameth = EVP_PKEY_asn1_find_str(nm, slen);
+               if (!ameth || !ameth->old_priv_decode)
+                       goto p8err;
+               ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);
+               }
        else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
                PKCS8_PRIV_KEY_INFO *p8inf;
                p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
@@ -129,6 +134,22 @@ err:
        return(ret);
        }
 
+int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+       {
+       char pem_str[80];
+       if (!x->ameth || !x->ameth->old_priv_encode)
+               return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
+                                                       (char *)kstr, klen,
+                                                       cb, u);
+
+       BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
+       return PEM_ASN1_write_bio((i2d_of_void *)openssl_fcast(i2d_PrivateKey),
+                               pem_str,bp,(char *)x,enc,kstr,klen,cb,u);
+       }
+
+
 #ifndef OPENSSL_NO_FP_API
 EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
        {
@@ -145,4 +166,22 @@ EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void
         BIO_free(b);
         return(ret);
        }
+
+int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+                                               unsigned char *kstr, int klen,
+                                               pem_password_cb *cb, void *u)
+       {
+        BIO *b;
+        int ret;
+
+        if ((b=BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
+               {
+               PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY,ERR_R_BUF_LIB);
+                return 0;
+               }
+        ret=PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+        BIO_free(b);
+        return ret;
+       }
+
 #endif
index 0b3a9d0..9057193 100644 (file)
@@ -101,22 +101,24 @@ static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
        return 1;
        }
 
-static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+static int old_rsa_priv_decode(EVP_PKEY *pkey,
+                                       const unsigned char **pder, int derlen)
        {
-       const unsigned char *p;
-       int pklen;
-       RSA *rsa = NULL;
-       if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
-               return 0;
-       if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pklen)))
+       RSA *rsa;
+       if (!(rsa = d2i_RSAPrivateKey (NULL, pder, derlen)))
                {
                RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
                return 0;
                }
-       EVP_PKEY_assign_RSA (pkey, rsa);
+       EVP_PKEY_assign_RSA(pkey, rsa);
        return 1;
        }
 
+static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+       {
+       return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
+       }
+
 static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
        {
        unsigned char *rk = NULL;
@@ -139,6 +141,15 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
        return 1;
        }
 
+static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+       {
+       const unsigned char *p;
+       int pklen;
+       if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
+               return 0;
+       return old_rsa_priv_decode(pkey, &p, pklen);
+       }
+
 static int int_rsa_size(const EVP_PKEY *pkey)
        {
        return RSA_size(pkey->pkey.rsa);
@@ -256,7 +267,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
                EVP_PKEY_RSA,
                0,
 
-               "rsa",
+               "RSA",
                "OpenSSL RSA method",
 
                rsa_pub_decode,
@@ -274,7 +285,9 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
                0,0,0,0,0,0,
 
                int_rsa_free,
-               0
+               0,
+               old_rsa_priv_decode,
+               old_rsa_priv_encode
                },
 
                {