Commit e4263314 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add support for legacy PEM format private keys in EVP_PKEY_ASN1_METHOD.

parent bd50e313
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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)
+7 −0
Original line number Diff line number Diff line
@@ -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 */;
+7 −37
Original line number Diff line number Diff line
@@ -62,15 +62,7 @@
#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)
	else
		{
			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);
		goto err;
		/* break; */
+3 −29
Original line number Diff line number Diff line
@@ -58,41 +58,15 @@

#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);
	}
+22 −2
Original line number Diff line number Diff line
@@ -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
		}
	};
Loading