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

Complete EVP_PKEY_ASN1_METHOD ENGINE support.

parent 8fecd4b4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -4,7 +4,9 @@

 Changes between 0.9.8b and 0.9.9  [xx XXX xxxx]

  *) Initial engine support for EVP_PKEY_ASN1_METHOD.
  *) Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process
     an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code.
     [Steve Henson]

  *) Initial engine support for EVP_PKEY_METHOD. New functions to permit
     an engine to register a method. Add ENGINE lookups for methods and
+28 −8
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif

static int init_keygen_file(BIO *err, EVP_PKEY_CTX **pctx,
				const char *file, ENGINE *e);
@@ -85,7 +88,7 @@ int MAIN(int argc, char **argv)
	EVP_PKEY_CTX *ctx = NULL;
	char *pass = NULL;
	int badarg = 0;
	int ret = 1;
	int ret = 1, rv;

	int do_param = 0;

@@ -204,7 +207,7 @@ int MAIN(int argc, char **argv)
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
#endif
		return 1;
		goto end;
		}

	if (!app_passwd(bio_err, passarg, NULL, &pass, NULL))
@@ -256,25 +259,36 @@ int MAIN(int argc, char **argv)
		}

	if (do_param)
		PEM_write_bio_Parameters(out, pkey);
		rv = PEM_write_bio_Parameters(out, pkey);
	else if (outformat == FORMAT_PEM) 
		PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0,
		rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0,
								NULL, pass);
	else if (outformat == FORMAT_ASN1)
		i2d_PrivateKey_bio(out, pkey);
		rv = i2d_PrivateKey_bio(out, pkey);
	else
		{
		BIO_printf(bio_err, "Bad format specified for key\n");
		goto end;
		}

	if (rv <= 0)
		{
		BIO_puts(bio_err, "Error writing key\n");
		ERR_print_errors(bio_err);
		}

	if (text)
		{
		if (do_param)
			EVP_PKEY_print_params(out, pkey, 0, NULL);
			rv = EVP_PKEY_print_params(out, pkey, 0, NULL);
		else
			EVP_PKEY_print_private(out, pkey, 0, NULL);
			rv = EVP_PKEY_print_private(out, pkey, 0, NULL);

		if (rv <= 0)
			{
			BIO_puts(bio_err, "Error printing key\n");
			ERR_print_errors(bio_err);
			}
		}

	ret = 0;
@@ -346,14 +360,16 @@ static int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx,
	{
	EVP_PKEY_CTX *ctx = NULL;
	const EVP_PKEY_ASN1_METHOD *ameth;
	ENGINE *tmpeng = NULL;
	int pkey_id;

	if (*pctx)
		{
		BIO_puts(err, "Algorithm already set!\n");
		return 0;
		}
	ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);

	ameth = EVP_PKEY_asn1_find_str(algname, -1);
	if (!ameth)
		{
		BIO_printf(bio_err, "Algorithm %s not found\n", algname);
@@ -361,6 +377,10 @@ static int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx,
		}

	EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
#ifndef OPENSSL_NO_ENGINE
	if (tmpeng)
		ENGINE_finish(tmpeng);
#endif
	ctx = EVP_PKEY_CTX_new_id(pkey_id, e);

	if (!ctx)
+46 −27
Original line number Diff line number Diff line
@@ -145,8 +145,8 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx);
static int req_check_len(int len,int n_min,int n_max);
static int check_end(const char *str, const char *end);
static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
					long *pkeylen, const char **palgnam,
					ENGINE *e);
					long *pkeylen, char **palgnam,
					ENGINE *keygen_engine);
#ifndef MONOLITH
static char *default_config_file=NULL;
#endif
@@ -157,19 +157,14 @@ int MAIN(int, char **);

int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
#ifndef OPENSSL_NO_DSA
	DSA *dsa_params=NULL;
#endif
#ifndef OPENSSL_NO_ECDSA
	EC_KEY *ec_params = NULL;
#endif
	ENGINE *e = NULL, *gen_eng = NULL;
	unsigned long nmflag = 0, reqflag = 0;
	int ex=1,x509=0,days=30;
	X509 *x509ss=NULL;
	X509_REQ *req=NULL;
	EVP_PKEY_CTX *genctx = NULL;
	const char *keyalg = NULL, *keyalgstr;
	const char *keyalg = NULL;
	char *keyalgstr = NULL;
	STACK *pkeyopts = NULL;
	EVP_PKEY *pkey=NULL;
	int i=0,badops=0,newreq=0,verbose=0,pkey_type=EVP_PKEY_RSA;
@@ -235,6 +230,16 @@ int MAIN(int argc, char **argv)
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
		else if (strcmp(*argv,"-keygen_engine") == 0)
			{
			if (--argc < 1) goto bad;
			gen_eng = ENGINE_by_id(*(++argv));
			if (gen_eng == NULL)
				{
				BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
				goto end;
				}
			}
#endif
		else if (strcmp(*argv,"-key") == 0)
			{
@@ -634,7 +639,7 @@ bad:
		if (keyalg)
			{
			genctx = set_keygen_ctx(bio_err, keyalg, &newkey,
							&keyalgstr, e);
							&keyalgstr, gen_eng);
			if (!genctx)
				goto end;
			}
@@ -655,7 +660,7 @@ bad:
		if (!genctx)
			{
			genctx = set_keygen_ctx(bio_err, NULL, &newkey,
							&keyalgstr, e);
							&keyalgstr, gen_eng);
			if (!genctx)
				goto end;
			}
@@ -1080,18 +1085,18 @@ end:
		EVP_PKEY_CTX_free(genctx);
	if (pkeyopts)
		sk_free(pkeyopts);
#ifndef OPENSSL_NO_ENGINE
	if (gen_eng)
		ENGINE_free(gen_eng);
#endif
	if (keyalgstr)
		OPENSSL_free(keyalgstr);
	X509_REQ_free(req);
	X509_free(x509ss);
	ASN1_INTEGER_free(serial);
	if(passargin && passin) OPENSSL_free(passin);
	if(passargout && passout) OPENSSL_free(passout);
	OBJ_cleanup();
#ifndef OPENSSL_NO_DSA
	if (dsa_params != NULL) DSA_free(dsa_params);
#endif
#ifndef OPENSSL_NO_ECDSA
	if (ec_params != NULL) EC_KEY_free(ec_params);
#endif
	apps_shutdown();
	OPENSSL_EXIT(ex);
	}
@@ -1566,8 +1571,8 @@ static int check_end(const char *str, const char *end)
}

static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
					long *pkeylen, const char **palgnam,
					ENGINE *e)
					long *pkeylen, char **palgnam,
					ENGINE *keygen_engine)
	{
	EVP_PKEY_CTX *gctx = NULL;
	EVP_PKEY *param = NULL;
@@ -1593,14 +1598,18 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
		{
		const char *p = strchr(gstr, ':');
		int len;
		ENGINE *tmpeng;
		const EVP_PKEY_ASN1_METHOD *ameth;

		if (p)
			len = p - gstr;
		else
			len = strlen(gstr);
		/* The lookup of a the string will cover all engines so
		 * keep a note of the implementation.
		 */

		ameth = EVP_PKEY_asn1_find_str(gstr, len);
		ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);

		if (!ameth)
			{
@@ -1610,6 +1619,10 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,

		EVP_PKEY_asn1_get0_info(NULL, &pkey_type, NULL, NULL, NULL,
									ameth);
#ifndef OPENSSL_NO_ENGINE
		if (tmpeng)
			ENGINE_finish(tmpeng);
#endif
		if (pkey_type == EVP_PKEY_RSA)
			{
			if (p)
@@ -1666,24 +1679,30 @@ static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr,
	if (palgnam)
		{
		const EVP_PKEY_ASN1_METHOD *ameth;
		ameth = EVP_PKEY_asn1_find(pkey_type);
		ENGINE *tmpeng;
		const char *anam;
		ameth = EVP_PKEY_asn1_find(&tmpeng, pkey_type);
		if (!ameth)
			{
			BIO_puts(err, "Internal error: can't find key algorithm\n");
			return NULL;
			}
		EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, palgnam,
						ameth);
		EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
		*palgnam = BUF_strdup(anam);
#ifndef OPENSSL_NO_ENGINE
		if (tmpeng)
			ENGINE_finish(tmpeng);
#endif
		}

	if (param)
		{
		gctx = EVP_PKEY_CTX_new(param, e);
		gctx = EVP_PKEY_CTX_new(param, keygen_engine);
		*pkeylen = EVP_PKEY_bits(param);
		EVP_PKEY_free(param);
		}
	else
		gctx = EVP_PKEY_CTX_new_id(pkey_type, e);
		gctx = EVP_PKEY_CTX_new_id(pkey_type, keygen_engine);

	if (!gctx)
		{
+62 −5
Original line number Diff line number Diff line
@@ -59,7 +59,9 @@
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/ec.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#include "asn1_locl.h"

extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
@@ -132,7 +134,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
	return (const EVP_PKEY_ASN1_METHOD *)sk_value(app_methods, idx);
	}

const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
	{
	EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
	tmp.pkey_id = type;
@@ -151,17 +153,72 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type)
			(int (*)(const void *, const void *))ameth_cmp);
	if (!ret || !*ret)
		return NULL;
	if ((*ret)->pkey_flags & ASN1_PKEY_ALIAS)
		return EVP_PKEY_asn1_find((*ret)->pkey_base_id);
	return *ret;
	}

const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(const char *str, int len)
/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
 * also search through engines and set *pe to a functional reference
 * to the engine implementing 'type' or NULL if no engine implements 
 * it.
 */

const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
	{
	const EVP_PKEY_ASN1_METHOD *t;
	ENGINE *e;

	for (;;)
		{
		t = pkey_asn1_find(type);
		if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
			break;
		type = t->pkey_base_id;
		}
	if (pe)
		{
#ifndef OPENSSL_NO_ENGINE
		/* type will contain the final unaliased type */
		e = ENGINE_get_pkey_asn1_meth_engine(type);
		if (e)
			{
			*pe = e;
			return ENGINE_get_pkey_asn1_meth(e, type);
			}
#endif
		*pe = NULL;
		}
	return t;
	}

const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
					const char *str, int len)
	{
	int i;
	const EVP_PKEY_ASN1_METHOD *ameth;
	if (len == -1)
		len = strlen(str);
	if (pe)
		{
#ifndef OPENSSL_NO_ENGINE
		ENGINE *e;
		for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
			{
			ameth = ENGINE_get_pkey_asn1_meth_str(e, str, len);
			if (ameth)
				{
				/* Convert structural into
				 * functional reference
				 */
				if (!ENGINE_init(e))
					ameth = NULL;
				ENGINE_free(e);
				*pe = e;
				return ameth;
				}
			}
#endif
		*pe = NULL;
		}
	for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
		{
		ameth = EVP_PKEY_asn1_get0(i);
+15 −12
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
#include <openssl/asn1.h>
#include "asn1_locl.h"

@@ -77,25 +78,27 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
			return(NULL);
			}
		}
	else	ret= *a;

	ret->save_type=type;
	ret->type=EVP_PKEY_type(type);
	ret->ameth = EVP_PKEY_asn1_find(type);
	if (ret->ameth)
	else
		{
		if (!ret->ameth->old_priv_decode ||
			!ret->ameth->old_priv_decode(ret, pp, length))
		ret= *a;
		if (ret->engine)
			{
			ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB);
			goto err;
			ENGINE_finish(ret->engine);
			ret->engine = NULL;
			}
		}
	else

	if (!EVP_PKEY_set_type(ret, type))
		{
		ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
		goto err;
		/* break; */
		}

	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;
		}
	if (a != NULL) (*a)=ret;
	return(ret);
Loading