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;
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)
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 */;
#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)
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; */
#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);
}
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[] =
EVP_PKEY_DSA,
0,
- "dsa",
+ "DSA",
"OpenSSL DSA method",
dsa_pub_decode,
dsa_param_print,
int_dsa_free,
- 0
+ 0,
+ old_dsa_priv_decode,
+ old_dsa_priv_encode
}
};
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,
eckey_param_print,
int_ec_free,
- 0
+ 0,
+ old_ec_priv_decode,
+ old_ec_priv_encode
};
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);
#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
#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)
-
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"},
{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"},
{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}
};
#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
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)
{
/* 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) &&
* 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;
#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)
{
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);
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)
{
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
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;
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);
EVP_PKEY_RSA,
0,
- "rsa",
+ "RSA",
"OpenSSL RSA method",
rsa_pub_decode,
0,0,0,0,0,0,
int_rsa_free,
- 0
+ 0,
+ old_rsa_priv_decode,
+ old_rsa_priv_encode
},
{