Add support for legacy PEM format private keys in EVP_PKEY_ASN1_METHOD.
This commit is contained in:
parent
bd50e31325
commit
e42633140e
@ -105,6 +105,25 @@ static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
|
|||||||
return ((*a)->pkey_id - (*b)->pkey_id);
|
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)
|
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
|
||||||
{
|
{
|
||||||
EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
|
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;
|
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)
|
int EVP_PKEY_asn1_add(const EVP_PKEY_ASN1_METHOD *ameth)
|
||||||
{
|
{
|
||||||
if (app_methods == NULL)
|
if (app_methods == NULL)
|
||||||
|
@ -107,4 +107,11 @@ struct evp_pkey_asn1_method_st
|
|||||||
|
|
||||||
void (*pkey_free)(EVP_PKEY *pkey);
|
void (*pkey_free)(EVP_PKEY *pkey);
|
||||||
void (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
|
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 */;
|
} /* EVP_PKEY_ASN1_METHOD */;
|
||||||
|
@ -62,15 +62,7 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/objects.h>
|
#include <openssl/objects.h>
|
||||||
#include <openssl/asn1.h>
|
#include <openssl/asn1.h>
|
||||||
#ifndef OPENSSL_NO_RSA
|
#include "asn1_locl.h"
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_DSA
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#endif
|
|
||||||
#ifndef OPENSSL_NO_EC
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
|
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
|
||||||
long length)
|
long length)
|
||||||
@ -90,39 +82,17 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
|
|||||||
ret->save_type=type;
|
ret->save_type=type;
|
||||||
ret->type=EVP_PKEY_type(type);
|
ret->type=EVP_PKEY_type(type);
|
||||||
ret->ameth = EVP_PKEY_asn1_find(type);
|
ret->ameth = EVP_PKEY_asn1_find(type);
|
||||||
switch (ret->type)
|
if (ret->ameth)
|
||||||
{
|
{
|
||||||
#ifndef OPENSSL_NO_RSA
|
if (!ret->ameth->old_priv_decode ||
|
||||||
case EVP_PKEY_RSA:
|
!ret->ameth->old_priv_decode(ret, pp, length))
|
||||||
if ((ret->pkey.rsa=d2i_RSAPrivateKey(NULL,
|
|
||||||
(const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */
|
|
||||||
{
|
{
|
||||||
ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB);
|
ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB);
|
||||||
goto err;
|
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;
|
else
|
||||||
#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:
|
|
||||||
ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
|
ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
|
||||||
goto err;
|
goto err;
|
||||||
/* break; */
|
/* break; */
|
||||||
|
@ -58,41 +58,15 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "cryptlib.h"
|
#include "cryptlib.h"
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/objects.h>
|
#include "asn1_locl.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
|
|
||||||
|
|
||||||
int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
|
int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
|
||||||
{
|
{
|
||||||
#ifndef OPENSSL_NO_RSA
|
if (a->ameth && a->ameth->old_priv_encode)
|
||||||
if (a->type == EVP_PKEY_RSA)
|
|
||||||
{
|
{
|
||||||
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);
|
ASN1err(ASN1_F_I2D_PRIVATEKEY,ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
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 */
|
/* NB these are sorted in pkey_id order, lowest first */
|
||||||
|
|
||||||
const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
|
const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
|
||||||
@ -527,7 +545,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
|
|||||||
EVP_PKEY_DSA,
|
EVP_PKEY_DSA,
|
||||||
0,
|
0,
|
||||||
|
|
||||||
"dsa",
|
"DSA",
|
||||||
"OpenSSL DSA method",
|
"OpenSSL DSA method",
|
||||||
|
|
||||||
dsa_pub_decode,
|
dsa_pub_decode,
|
||||||
@ -549,7 +567,9 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
|
|||||||
dsa_param_print,
|
dsa_param_print,
|
||||||
|
|
||||||
int_dsa_free,
|
int_dsa_free,
|
||||||
0
|
0,
|
||||||
|
old_dsa_priv_decode,
|
||||||
|
old_dsa_priv_encode
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
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_ASN1_METHOD eckey_asn1_meth =
|
||||||
{
|
{
|
||||||
EVP_PKEY_EC,
|
EVP_PKEY_EC,
|
||||||
EVP_PKEY_EC,
|
EVP_PKEY_EC,
|
||||||
0,
|
0,
|
||||||
"ec",
|
"EC",
|
||||||
"OpenSSL EC algorithm",
|
"OpenSSL EC algorithm",
|
||||||
|
|
||||||
eckey_pub_decode,
|
eckey_pub_decode,
|
||||||
@ -561,5 +579,7 @@ EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
|
|||||||
eckey_param_print,
|
eckey_param_print,
|
||||||
|
|
||||||
int_ec_free,
|
int_ec_free,
|
||||||
0
|
0,
|
||||||
|
old_ec_priv_decode,
|
||||||
|
old_ec_priv_encode
|
||||||
};
|
};
|
||||||
|
@ -855,7 +855,10 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
|
|||||||
EVP_PBE_KEYGEN *keygen);
|
EVP_PBE_KEYGEN *keygen);
|
||||||
void EVP_PBE_cleanup(void);
|
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(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);
|
int EVP_PKEY_asn1_add(const EVP_PKEY_ASN1_METHOD *ameth);
|
||||||
EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
|
EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id,
|
||||||
const char *pem_str, const char *info);
|
const char *pem_str, const char *info);
|
||||||
|
@ -731,6 +731,7 @@ void ERR_load_PEM_strings(void);
|
|||||||
#define PEM_F_PEM_SIGNFINAL 112
|
#define PEM_F_PEM_SIGNFINAL 112
|
||||||
#define PEM_F_PEM_WRITE 113
|
#define PEM_F_PEM_WRITE 113
|
||||||
#define PEM_F_PEM_WRITE_BIO 114
|
#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 115
|
||||||
#define PEM_F_PEM_X509_INFO_READ_BIO 116
|
#define PEM_F_PEM_X509_INFO_READ_BIO 116
|
||||||
#define PEM_F_PEM_X509_INFO_WRITE_BIO 117
|
#define PEM_F_PEM_X509_INFO_WRITE_BIO 117
|
||||||
|
@ -294,15 +294,4 @@ IMPLEMENT_PEM_rw_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
|
|||||||
|
|
||||||
#endif
|
#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)
|
IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
static ERR_STRING_DATA PEM_str_functs[]=
|
static ERR_STRING_DATA PEM_str_functs[]=
|
||||||
{
|
{
|
||||||
{ERR_FUNC(PEM_F_B2I_DSS), "B2I_DSS"},
|
{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_B2I_RSA), "B2I_RSA"},
|
||||||
{ERR_FUNC(PEM_F_CHECK_BITLEN_DSA), "CHECK_BITLEN_DSA"},
|
{ERR_FUNC(PEM_F_CHECK_BITLEN_DSA), "CHECK_BITLEN_DSA"},
|
||||||
{ERR_FUNC(PEM_F_CHECK_BITLEN_RSA), "CHECK_BITLEN_RSA"},
|
{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_BODY), "DO_PVK_BODY"},
|
||||||
{ERR_FUNC(PEM_F_DO_PVK_HEADER), "DO_PVK_HEADER"},
|
{ERR_FUNC(PEM_F_DO_PVK_HEADER), "DO_PVK_HEADER"},
|
||||||
{ERR_FUNC(PEM_F_I2B_PVK), "I2B_PVK"},
|
{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_LOAD_IV), "LOAD_IV"},
|
||||||
{ERR_FUNC(PEM_F_PEM_ASN1_READ), "PEM_ASN1_read"},
|
{ERR_FUNC(PEM_F_PEM_ASN1_READ), "PEM_ASN1_read"},
|
||||||
{ERR_FUNC(PEM_F_PEM_ASN1_READ_BIO), "PEM_ASN1_read_bio"},
|
{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_SIGNFINAL), "PEM_SignFinal"},
|
||||||
{ERR_FUNC(PEM_F_PEM_WRITE), "PEM_write"},
|
{ERR_FUNC(PEM_F_PEM_WRITE), "PEM_write"},
|
||||||
{ERR_FUNC(PEM_F_PEM_WRITE_BIO), "PEM_write_bio"},
|
{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_WRITE_PRIVATEKEY), "PEM_WRITE_PRIVATEKEY"},
|
||||||
{ERR_FUNC(PEM_F_PEM_X509_INFO_READ_BIO), "PEM_X509_INFO_read_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_X509_INFO_WRITE_BIO), "PEM_X509_INFO_write_bio"},
|
{ERR_FUNC(PEM_F_PEM_X509_INFO_WRITE_BIO), "PEM_X509_INFO_write_bio"},
|
||||||
{0,NULL}
|
{0,NULL}
|
||||||
};
|
};
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/pkcs12.h>
|
#include <openssl/pkcs12.h>
|
||||||
|
#include "asn1_locl.h"
|
||||||
#ifndef OPENSSL_NO_DES
|
#ifndef OPENSSL_NO_DES
|
||||||
#include <openssl/des.h>
|
#include <openssl/des.h>
|
||||||
#endif
|
#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 load_iv(char **fromp,unsigned char *to, int num);
|
||||||
static int check_pem(const char *nm, const char *name);
|
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)
|
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 */
|
/* Make PEM_STRING_EVP_PKEY match any private key */
|
||||||
|
|
||||||
if(!strcmp(nm,PEM_STRING_PKCS8) &&
|
if(!strcmp(name,PEM_STRING_EVP_PKEY))
|
||||||
!strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
|
{
|
||||||
|
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_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(nm,PEM_STRING_ECPRIVATEKEY) &&
|
|
||||||
!strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
|
|
||||||
/* Permit older strings */
|
/* Permit older strings */
|
||||||
|
|
||||||
if(!strcmp(nm,PEM_STRING_X509_OLD) &&
|
if(!strcmp(nm,PEM_STRING_X509_OLD) &&
|
||||||
@ -783,16 +789,17 @@ err:
|
|||||||
* the return value is 3 for the string "RSA".
|
* 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 pem_len = strlen(pem_str);
|
||||||
int suffix_len = strlen(suffix);
|
int suffix_len = strlen(suffix);
|
||||||
char *p;
|
const char *p;
|
||||||
if (suffix_len + 1 >= pem_len)
|
if (suffix_len + 1 >= pem_len)
|
||||||
return 0;
|
return 0;
|
||||||
if (strcmp(pem_str - suffix_len, suffix))
|
p = pem_str + pem_len - suffix_len;
|
||||||
|
if (strcmp(p, suffix))
|
||||||
return 0;
|
return 0;
|
||||||
p = pem_str - suffix_len - 1;
|
p--;
|
||||||
if (*p != ' ')
|
if (*p != ' ')
|
||||||
return 0;
|
return 0;
|
||||||
return p - pem_str;
|
return p - pem_str;
|
||||||
|
@ -65,7 +65,9 @@
|
|||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/pkcs12.h>
|
#include <openssl/pkcs12.h>
|
||||||
#include <openssl/pem.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)
|
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;
|
const unsigned char *p=NULL;
|
||||||
unsigned char *data=NULL;
|
unsigned char *data=NULL;
|
||||||
long len;
|
long len;
|
||||||
|
int slen;
|
||||||
EVP_PKEY *ret=NULL;
|
EVP_PKEY *ret=NULL;
|
||||||
|
|
||||||
if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
|
if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
|
||||||
return NULL;
|
return NULL;
|
||||||
p = data;
|
p = data;
|
||||||
|
|
||||||
if (strcmp(nm,PEM_STRING_RSA) == 0)
|
if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0)
|
||||||
ret=d2i_PrivateKey(EVP_PKEY_RSA,x,&p,len);
|
{
|
||||||
else if (strcmp(nm,PEM_STRING_DSA) == 0)
|
const EVP_PKEY_ASN1_METHOD *ameth;
|
||||||
ret=d2i_PrivateKey(EVP_PKEY_DSA,x,&p,len);
|
ameth = EVP_PKEY_asn1_find_str(nm, slen);
|
||||||
else if (strcmp(nm,PEM_STRING_ECPRIVATEKEY) == 0)
|
if (!ameth || !ameth->old_priv_decode)
|
||||||
ret=d2i_PrivateKey(EVP_PKEY_EC,x,&p,len);
|
goto p8err;
|
||||||
|
ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);
|
||||||
|
}
|
||||||
else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
|
else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
|
||||||
PKCS8_PRIV_KEY_INFO *p8inf;
|
PKCS8_PRIV_KEY_INFO *p8inf;
|
||||||
p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
|
p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
|
||||||
@ -129,6 +134,22 @@ err:
|
|||||||
return(ret);
|
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
|
#ifndef OPENSSL_NO_FP_API
|
||||||
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
|
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);
|
BIO_free(b);
|
||||||
return(ret);
|
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
|
#endif
|
||||||
|
@ -101,22 +101,24 @@ static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
|||||||
return 1;
|
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;
|
RSA *rsa;
|
||||||
int pklen;
|
if (!(rsa = d2i_RSAPrivateKey (NULL, pder, derlen)))
|
||||||
RSA *rsa = NULL;
|
|
||||||
if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
|
|
||||||
return 0;
|
|
||||||
if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pklen)))
|
|
||||||
{
|
{
|
||||||
RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
|
RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EVP_PKEY_assign_RSA (pkey, rsa);
|
EVP_PKEY_assign_RSA(pkey, rsa);
|
||||||
return 1;
|
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)
|
static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
||||||
{
|
{
|
||||||
unsigned char *rk = NULL;
|
unsigned char *rk = NULL;
|
||||||
@ -139,6 +141,15 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
|||||||
return 1;
|
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)
|
static int int_rsa_size(const EVP_PKEY *pkey)
|
||||||
{
|
{
|
||||||
return RSA_size(pkey->pkey.rsa);
|
return RSA_size(pkey->pkey.rsa);
|
||||||
@ -256,7 +267,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
|
|||||||
EVP_PKEY_RSA,
|
EVP_PKEY_RSA,
|
||||||
0,
|
0,
|
||||||
|
|
||||||
"rsa",
|
"RSA",
|
||||||
"OpenSSL RSA method",
|
"OpenSSL RSA method",
|
||||||
|
|
||||||
rsa_pub_decode,
|
rsa_pub_decode,
|
||||||
@ -274,7 +285,9 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
|
|||||||
0,0,0,0,0,0,
|
0,0,0,0,0,0,
|
||||||
|
|
||||||
int_rsa_free,
|
int_rsa_free,
|
||||||
0
|
0,
|
||||||
|
old_rsa_priv_decode,
|
||||||
|
old_rsa_priv_encode
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user