[openssl-dev] [RFC 1/2] engine: add new flag based method for loading engine keys
James Bottomley
James.Bottomley at HansenPartnership.com
Wed Nov 16 15:47:55 UTC 2016
The assumption in all the current engine code is that key_id can be
passed as something like a file name. There are some new users that
actually want to pass a BIO, so add a new load_key method for engines
that takes a flag value. The first defined flag is
ENGINE_LOAD_KEY_FLAG_BIO which means that the key_id is actually a bio
pointer.
Signed-off-by: James Bottomley <jejb at linux.vnet.ibm.com>
---
crypto/engine/eng_int.h | 1 +
crypto/engine/eng_pkey.c | 38 ++++++++++++++++++++++++++++++++++++++
crypto/engine/engine.h | 26 ++++++++++++++++++++++++++
3 files changed, 65 insertions(+)
diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
index 46f163b..b65cc41 100644
--- a/crypto/engine/eng_int.h
+++ b/crypto/engine/eng_int.h
@@ -197,6 +197,7 @@ struct engine_st {
ENGINE_CTRL_FUNC_PTR ctrl;
ENGINE_LOAD_KEY_PTR load_privkey;
ENGINE_LOAD_KEY_PTR load_pubkey;
+ ENGINE_LOAD_KEY_FLAGS_PTR load_key_flags;
ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;
const ENGINE_CMD_DEFN *cmd_defns;
int flags;
diff --git a/crypto/engine/eng_pkey.c b/crypto/engine/eng_pkey.c
index 23580d9..124426f 100644
--- a/crypto/engine/eng_pkey.c
+++ b/crypto/engine/eng_pkey.c
@@ -64,6 +64,13 @@ int ENGINE_set_load_privkey_function(ENGINE *e,
return 1;
}
+int ENGINE_set_load_key_flags_function(ENGINE *e,
+ ENGINE_LOAD_KEY_FLAGS_PTR load_f)
+{
+ e->load_key_flags = load_f;
+ return 1;
+}
+
int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f)
{
e->load_pubkey = loadpub_f;
@@ -88,6 +95,11 @@ ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e)
return e->load_pubkey;
}
+ENGINE_LOAD_KEY_FLAGS_PTR ENGINE_get_load_key_flags_function(const ENGINE *e)
+{
+ return e->load_key_flags;
+}
+
ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
*e)
{
@@ -184,3 +196,29 @@ int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
ui_method, callback_data);
}
+
+int ENGINE_find_engine_load_key(ENGINE **e, EVP_PKEY **pkey, const char *key_id,
+ pem_password_cb *cb, void *cb_data,
+ unsigned int flags)
+{
+ ENGINE *ep;
+ int ret = 0;
+
+ for (ep = ENGINE_get_first(); ep != NULL; ep = ENGINE_get_next(ep)) {
+ if (!ep->load_key_flags)
+ continue;
+ if (ep->load_key_flags(ep, pkey, key_id, cb, cb_data, flags) == 1) {
+ ret = 1;
+ break;
+ }
+ if (flags & ENGINE_LOAD_KEY_FLAG_BIO)
+ (void)BIO_reset((BIO *)key_id);
+ ERR_clear_error();
+ }
+ if (e)
+ *e = ep;
+ else if (ep)
+ ENGINE_free(ep);
+
+ return ret;
+}
diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h
index bd7b591..49f6a55 100644
--- a/crypto/engine/engine.h
+++ b/crypto/engine/engine.h
@@ -97,6 +97,7 @@
# include <openssl/symhacks.h>
# include <openssl/x509.h>
+# include <openssl/pem.h>
#ifdef __cplusplus
extern "C" {
@@ -338,6 +339,19 @@ typedef int (*ENGINE_CTRL_FUNC_PTR) (ENGINE *, int, long, void *,
typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
UI_METHOD *ui_method,
void *callback_data);
+
+/*
+ * This flag signals that the const char *key_id (3rd argument) actually
+ * points to a SSL BIO structure
+ */
+#define ENGINE_LOAD_KEY_FLAG_BIO 0x01
+
+/* Replacement load_key with flags and return code */
+typedef int (*ENGINE_LOAD_KEY_FLAGS_PTR)(ENGINE *, EVP_PKEY **,
+ const char *,
+ pem_password_cb *pwd_callback,
+ void *callback_data,
+ unsigned int flags);
typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl,
STACK_OF(X509_NAME) *ca_dn,
X509 **pcert, EVP_PKEY **pkey,
@@ -565,6 +579,8 @@ int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
int ENGINE_set_load_privkey_function(ENGINE *e,
ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_key_flags_function(ENGINE *e,
+ ENGINE_LOAD_KEY_FLAGS_PTR loadpriv_f);
int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
ENGINE_SSL_CLIENT_CERT_PTR
@@ -611,6 +627,7 @@ ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_FLAGS_PTR ENGINE_get_load_key_flags_function(const ENGINE *e);
ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
*e);
ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
@@ -671,6 +688,15 @@ int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
UI_METHOD *ui_method, void *callback_data);
/*
+ * Given a key_id, this method iterates over all present engines to
+ * see if any can handle it. It's functionality depends on the engine
+ * implementing e->load_key_flags.
+ */
+int ENGINE_find_engine_load_key(ENGINE **e, EVP_PKEY **pkey, const char *key_id,
+ pem_password_cb *cb, void *cb_data,
+ unsigned int flags);
+
+/*
* This returns a pointer for the current ENGINE structure that is (by
* default) performing any RSA operations. The value returned is an
* incremented reference, so it should be free'd (ENGINE_finish) before it is
More information about the openssl-dev
mailing list