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
#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);
EVP_PKEY_CTX *ctx = NULL;
char *pass = NULL;
int badarg = 0;
- int ret = 1;
+ int ret = 1, rv;
int do_param = 0;
#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))
}
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;
{
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);
}
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)
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
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;
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)
{
if (keyalg)
{
genctx = set_keygen_ctx(bio_err, keyalg, &newkey,
- &keyalgstr, e);
+ &keyalgstr, gen_eng);
if (!genctx)
goto end;
}
if (!genctx)
{
genctx = set_keygen_ctx(bio_err, NULL, &newkey,
- &keyalgstr, e);
+ &keyalgstr, gen_eng);
if (!genctx)
goto 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);
}
}
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;
{
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)
{
}
EVP_PKEY_asn1_get0_info(NULL, &pkey_type, NULL, NULL, NULL,
- ameth);
+ ameth);
+#ifndef OPENSSL_NO_ENGINE
+ if (tmpeng)
+ ENGINE_finish(tmpeng);
+#endif
if (pkey_type == EVP_PKEY_RSA)
{
if (p)
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)
{
#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[];
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;
(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);
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
+#include <openssl/engine.h>
#include <openssl/asn1.h>
#include "asn1_locl.h"
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);
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
X509_PUBKEY *pk=NULL;
- const EVP_PKEY_ASN1_METHOD *meth;
if (x == NULL) return(0);
if ((pk=X509_PUBKEY_new()) == NULL) goto error;
- meth = EVP_PKEY_asn1_find(pkey->type);
-
- if (meth)
+ if (pkey->ameth)
{
- if (meth->pub_encode)
+ if (pkey->ameth->pub_encode)
{
- if (!meth->pub_encode(pk, pkey))
+ if (!pkey->ameth->pub_encode(pk, pkey))
{
X509err(X509_F_X509_PUBKEY_SET,
X509_R_PUBLIC_KEY_ENCODE_ERROR);
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
{
EVP_PKEY *ret=NULL;
- const EVP_PKEY_ASN1_METHOD *meth;
if (key == NULL) goto error;
goto error;
}
- meth = EVP_PKEY_asn1_find(OBJ_obj2nid(key->algor->algorithm));
+ if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
+ {
+ X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
+ goto error;
+ }
- if (meth)
+ if (ret->ameth->pub_decode)
{
- if (meth->pub_decode)
- {
- if (!meth->pub_decode(ret, key))
- {
- X509err(X509_F_X509_PUBKEY_GET,
- X509_R_PUBLIC_KEY_DECODE_ERROR);
- goto error;
- }
- }
- else
+ if (!ret->ameth->pub_decode(ret, key))
{
X509err(X509_F_X509_PUBKEY_GET,
- X509_R_METHOD_NOT_SUPPORTED);
+ X509_R_PUBLIC_KEY_DECODE_ERROR);
goto error;
}
}
else
{
- X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
+ X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
#endif
if((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e))
return 0;
- if((flags & ENGINE_METHOD_PKEY_METHS) && !ENGINE_set_default_pkey_meths(e))
+ if((flags & ENGINE_METHOD_PKEY_METHS)
+ && !ENGINE_set_default_pkey_meths(e))
+ return 0;
+ if((flags & ENGINE_METHOD_PKEY_ASN1_METHS)
+ && !ENGINE_set_default_pkey_asn1_meths(e))
return 0;
return 1;
}
else if (!strncmp(alg, "DIGESTS", len))
*pflags |= ENGINE_METHOD_DIGESTS;
else if (!strncmp(alg, "PKEY", len))
+ *pflags |=
+ ENGINE_METHOD_PKEY_METHS|ENGINE_METHOD_PKEY_ASN1_METHS;
+ else if (!strncmp(alg, "PKEY_CRYPTO", len))
*pflags |= ENGINE_METHOD_PKEY_METHS;
+ else if (!strncmp(alg, "PKEY_ASN1", len))
+ *pflags |= ENGINE_METHOD_PKEY_ASN1_METHS;
else
return 0;
return 1;
/* Free up dynamically allocated public key methods associated with ENGINE */
void engine_pkey_meths_free(ENGINE *e);
+void engine_pkey_asn1_meths_free(ENGINE *e);
/* This is a structure for storing implementations of various crypto
* algorithms and functions. */
#endif
/* Free up any dynamically allocated public key methods */
engine_pkey_meths_free(e);
+ engine_pkey_asn1_meths_free(e);
/* Give the ENGINE a chance to do any structural cleanup corresponding
* to allocation it did in its constructor (eg. unload error strings) */
if(e->destroy)
#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
#define ENGINE_METHOD_STORE (unsigned int)0x0100
#define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200
+#define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400
/* Obvious all-or-nothing cases. */
#define ENGINE_METHOD_ALL (unsigned int)0xFFFF
#define ENGINE_METHOD_NONE (unsigned int)0x0000
const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid);
const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid);
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+ const char *str, int len);
const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
int ENGINE_get_flags(const ENGINE *e);
ENGINE *ENGINE_get_cipher_engine(int nid);
ENGINE *ENGINE_get_digest_engine(int nid);
ENGINE *ENGINE_get_pkey_meth_engine(int nid);
+ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
/* This sets a new default ENGINE structure for performing RSA
* operations. If the result is non-zero (success) then the ENGINE
int ENGINE_set_default_ciphers(ENGINE *e);
int ENGINE_set_default_digests(ENGINE *e);
int ENGINE_set_default_pkey_meths(ENGINE *e);
+int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
/* The combination "set" - the flags are bitwise "OR"d from the
* ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
*/
#include "eng_int.h"
+#include "asn1_locl.h"
-/* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the function
- * that is used by EVP to hook in pkey_asn1_meth code and cache defaults (etc), will
- * display brief debugging summaries to stderr with the 'nid'. */
+/* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
+ * function that is used by EVP to hook in pkey_asn1_meth code and cache
+ * defaults (etc), will display brief debugging summaries to stderr with the
+ * 'nid'. */
/* #define ENGINE_PKEY_ASN1_METH_DEBUG */
static ENGINE_TABLE *pkey_asn1_meth_table = NULL;
}
}
}
+
+/* Find a method based on a string. This does a linear search through
+ * all implemented algorithms. This is OK in practice because only
+ * a small number of algorithms are likely to be implemented in an engine
+ * and it is only used for non speed critical operations.
+ */
+
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+ const char *str, int len)
+ {
+ int i, nidcount;
+ const int *nids;
+ EVP_PKEY_ASN1_METHOD *ameth;
+ if (!e->pkey_asn1_meths)
+ return NULL;
+ if (len == -1)
+ len = strlen(str);
+ nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ for (i = 0; i < nidcount; i++)
+ {
+ e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
+ if (((int)strlen(ameth->pem_str) == len) &&
+ !strncasecmp(ameth->pem_str, str, len))
+ return ameth;
+ }
+ return NULL;
+ }
int save_type;
int references;
const EVP_PKEY_ASN1_METHOD *ameth;
- const EVP_PKEY_METHOD *pmeth;
+ ENGINE *engine;
union {
char *ptr;
#ifndef OPENSSL_NO_RSA
int EVP_PKEY_base_id(const EVP_PKEY *pkey);
int EVP_PKEY_bits(EVP_PKEY *pkey);
int EVP_PKEY_size(EVP_PKEY *pkey);
+int EVP_PKEY_set_type(EVP_PKEY *pkey,int type);
+int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
int EVP_PKEY_assign(EVP_PKEY *pkey,int type,void *key);
void * EVP_PKEY_get0(EVP_PKEY *pkey);
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);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
+ const char *str, int len);
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
int EVP_PKEY_asn1_add_alias(int to, int from);
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, int *ppkey_flags,
#define EVP_F_PKCS5_PBE_KEYIVGEN 117
#define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118
#define EVP_F_PKCS8_SET_BROKEN 112
+#define EVP_F_PKEY_SET_TYPE 158
#define EVP_F_RC2_MAGIC_TO_METH 109
#define EVP_F_RC5_CTRL 125
#define EVP_R_PUBLIC_KEY_NOT_RSA 106
#define EVP_R_UNKNOWN_PBE_ALGORITHM 121
#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135
+#define EVP_R_UNSUPPORTED_ALGORITHM 156
#define EVP_R_UNSUPPORTED_CIPHER 107
#define EVP_R_UNSUPPORTED_KEYLENGTH 123
#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124
{ERR_FUNC(EVP_F_PKCS5_PBE_KEYIVGEN), "PKCS5_PBE_keyivgen"},
{ERR_FUNC(EVP_F_PKCS5_V2_PBE_KEYIVGEN), "PKCS5_v2_PBE_keyivgen"},
{ERR_FUNC(EVP_F_PKCS8_SET_BROKEN), "PKCS8_set_broken"},
+{ERR_FUNC(EVP_F_PKEY_SET_TYPE), "PKEY_SET_TYPE"},
{ERR_FUNC(EVP_F_RC2_MAGIC_TO_METH), "RC2_MAGIC_TO_METH"},
{ERR_FUNC(EVP_F_RC5_CTRL), "RC5_CTRL"},
{0,NULL}
{ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA) ,"public key not rsa"},
{ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM) ,"unknown pbe algorithm"},
{ERR_REASON(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS),"unsuported number of rounds"},
+{ERR_REASON(EVP_R_UNSUPPORTED_ALGORITHM) ,"unsupported algorithm"},
{ERR_REASON(EVP_R_UNSUPPORTED_CIPHER) ,"unsupported cipher"},
{ERR_REASON(EVP_R_UNSUPPORTED_KEYLENGTH) ,"unsupported keylength"},
{ERR_REASON(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION),"unsupported key derivation function"},
{
EVP_PKEY *pkey = NULL;
ASN1_OBJECT *algoid;
- const EVP_PKEY_ASN1_METHOD *meth;
char obj_tmp[80];
if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
return NULL;
}
- meth = EVP_PKEY_asn1_find(OBJ_obj2nid(algoid));
+ if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid)))
+ {
+ EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
+ ERR_add_error_data(2, "TYPE=", obj_tmp);
+ goto error;
+ }
- if (meth)
+ if (pkey->ameth->priv_decode)
{
- if (meth->priv_decode)
- {
- if (!meth->priv_decode(pkey, p8))
- {
- EVPerr(EVP_F_EVP_PKCS82PKEY,
- EVP_R_PRIVATE_KEY_DECODE_ERROR);
- goto error;
- }
- }
- else
+ if (!pkey->ameth->priv_decode(pkey, p8))
{
EVPerr(EVP_F_EVP_PKCS82PKEY,
- EVP_R_METHOD_NOT_SUPPORTED);
+ EVP_R_PRIVATE_KEY_DECODE_ERROR);
goto error;
}
}
else
{
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
- i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
- ERR_add_error_data(2, "TYPE=", obj_tmp);
+ EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED);
goto error;
}
+
return pkey;
error:
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
{
PKCS8_PRIV_KEY_INFO *p8;
- const EVP_PKEY_ASN1_METHOD *meth;
if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {
EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
}
p8->broken = broken;
- meth = EVP_PKEY_asn1_find(pkey->type);
-
- if (meth)
+ if (pkey->ameth)
{
- if (meth->priv_encode)
+ if (pkey->ameth->priv_encode)
{
- if (!meth->priv_encode(p8, pkey))
+ if (!pkey->ameth->priv_encode(p8, pkey))
{
EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
EVP_R_PRIVATE_KEY_ENCODE_ERROR);
#include <openssl/dh.h>
#endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+
#include "asn1_locl.h"
static void EVP_PKEY_free_it(EVP_PKEY *x);
return(NULL);
}
ret->type=EVP_PKEY_NONE;
+ ret->save_type=EVP_PKEY_NONE;
ret->references=1;
ret->ameth=NULL;
+ ret->engine=NULL;
ret->pkey.ptr=NULL;
ret->attributes=NULL;
ret->save_parameters=1;
return(ret);
}
-int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
+/* Setup a public key ASN1 method and ENGINE from a NID or a string.
+ * If pkey is NULL just return 1 or 0 if the algorithm exists.
+ */
+
+static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
{
const EVP_PKEY_ASN1_METHOD *ameth;
- if (pkey == NULL) return(0);
- if (pkey->pkey.ptr != NULL)
- EVP_PKEY_free_it(pkey);
- ameth = EVP_PKEY_asn1_find(type);
- pkey->ameth = ameth;
- pkey->type = ameth->pkey_id;
- pkey->save_type=type;
+ ENGINE *e = NULL;
+ if (pkey)
+ {
+ if (pkey->pkey.ptr)
+ EVP_PKEY_free_it(pkey);
+ /* If key type matches and a method exists then this
+ * lookup has succeeded once so just indicate success.
+ */
+ if ((type == pkey->save_type) && pkey->ameth)
+ return 1;
+#ifndef OPENSSL_NO_ENGINE
+ /* If we have an ENGINE release it */
+ if (pkey->engine)
+ ENGINE_finish(pkey->engine);
+#endif
+ }
+ if (str)
+ ameth = EVP_PKEY_asn1_find_str(&e, str, len);
+ else
+ ameth = EVP_PKEY_asn1_find(&e, type);
+#ifndef OPENSSL_NO_ENGINE
+ if (!pkey && e)
+ ENGINE_finish(e);
+#endif
+ if (!ameth)
+ {
+ EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+ if (pkey)
+ {
+ pkey->ameth = ameth;
+ pkey->engine = e;
+
+ pkey->type = pkey->ameth->pkey_id;
+ pkey->save_type=type;
+ }
+ return 1;
+ }
+
+int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
+ {
+ return pkey_set_type(pkey, type, NULL, -1);
+ }
+
+int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
+ {
+ return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
+ }
+
+int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
+ {
+ if (!EVP_PKEY_set_type(pkey, type))
+ return 0;
pkey->pkey.ptr=key;
- return(key != NULL);
+ return (key != NULL);
}
void *EVP_PKEY_get0(EVP_PKEY *pkey)
int EVP_PKEY_type(int type)
{
+ int ret;
const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_asn1_find(type);
+ ENGINE *e;
+ ameth = EVP_PKEY_asn1_find(&e, type);
if (ameth)
- return ameth->pkey_id;
- return NID_undef;
+ ret = ameth->pkey_id;
+ else
+ ret = NID_undef;
+#ifndef OPENSSL_NO_ENGINE
+ if (e)
+ ENGINE_finish(e);
+#endif
+ return ret;
}
int EVP_PKEY_id(const EVP_PKEY *pkey)
{
if (x->ameth && x->ameth->pkey_free)
x->ameth->pkey_free(x);
+#ifndef OPENSSL_NO_ENGINE
+ if (x->engine)
+ {
+ ENGINE_finish(x->engine);
+ x->engine = NULL;
+ }
+#endif
}
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
BIO_indent(out, indent, 128);
- BIO_printf(out, "%s %s, algorithm, unsupported\n",
- OBJ_nid2ln(pkey->type), kstr);
+ BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
+ kstr, OBJ_nid2ln(pkey->type));
return 1;
}
pmeth = EVP_PKEY_meth_find(id);
if (pmeth == NULL)
+ {
+ EVPerr(EVP_F_INT_CTX_NEW,EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
+ }
ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
if (!ret)
#ifndef OPENSSL_NO_DES
#include <openssl/des.h>
#endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT;
slen = pem_check_suffix(nm, "PRIVATE KEY");
if (slen > 0)
{
- ameth = EVP_PKEY_asn1_find_str(nm, slen);
+ /* NB: ENGINE implementations wont contain
+ * a deprecated old private key decode function
+ * so don't look for them.
+ */
+ ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
if (ameth && ameth->old_priv_decode)
return 1;
}
slen = pem_check_suffix(nm, "PARAMETERS");
if (slen > 0)
{
- ameth = EVP_PKEY_asn1_find_str(nm, slen);
- if (ameth && ameth->param_decode)
- return 1;
+ ENGINE *e;
+ ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
+ if (ameth)
+ {
+ int r;
+ if (ameth->param_decode)
+ r = 1;
+ else
+ r = 0;
+#ifndef OPENSSL_NO_ENGINE
+ if (e)
+ ENGINE_finish(e);
+#endif
+ return r;
+ }
}
return 0;
}
#include <openssl/x509.h>
#include <openssl/pkcs12.h>
#include <openssl/pem.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
#include "asn1_locl.h"
int pem_check_suffix(const char *pem_str, const char *suffix);
} else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0)
{
const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_asn1_find_str(nm, slen);
+ ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
if (!ameth || !ameth->old_priv_decode)
goto p8err;
ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);
if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0)
{
- const EVP_PKEY_ASN1_METHOD *ameth;
- ameth = EVP_PKEY_asn1_find_str(nm, slen);
- if (!ameth || !ameth->param_decode)
- goto err;
ret = EVP_PKEY_new();
if (!ret)
goto err;
- if (!ameth->param_decode(ret, &p, len))
+ if (!EVP_PKEY_set_type_str(ret, nm, slen)
+ || !ret->ameth->param_decode
+ || !ret->ameth->param_decode(ret, &p, len))
{
EVP_PKEY_free(ret);
ret = NULL;