[openssl-dev] [RFC v2 1/2] engine: add new bio based method for loading engine keys
James Bottomley
James.Bottomley at HansenPartnership.com
Wed Nov 30 15:26:22 UTC 2016
Some engines have a PEM format for their keys, so add a mechanism
whereby these keys can be read in to EVP_PKEY structures backed by the
engine methods. The expectation is that each engine that wants to use
this will define its own unique guard tags for the PEM file.
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 | 17 +++++++++++++++++
3 files changed, 56 insertions(+)
diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
index 46f163b..1d182c8 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_BIO_PTR load_privkey_bio;
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..0eb7d6e 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_privkey_bio_function(ENGINE *e,
+ ENGINE_LOAD_KEY_BIO_PTR load_f)
+{
+ e->load_privkey_bio = 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_BIO_PTR ENGINE_get_load_privkey_bio_function(const ENGINE *e)
+{
+ return e->load_privkey_bio;
+}
+
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, BIO *bio,
+ pem_password_cb *cb, void *cb_data)
+{
+ ENGINE *ep;
+ int ret = 0;
+
+ for (ep = ENGINE_get_first(); ep != NULL; ep = ENGINE_get_next(ep)) {
+ if (!ep->load_privkey_bio)
+ continue;
+ if (ep->load_privkey_bio(ep, pkey, bio, cb, cb_data) == 1) {
+ ret = 1;
+ break;
+ }
+
+ /* reset the bio and clear any error */
+ (void)BIO_reset(bio);
+ 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..022be41 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,11 @@ 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);
+
+/* Load key from bio if engine recognises the pem guards */
+typedef int (*ENGINE_LOAD_KEY_BIO_PTR)(ENGINE *, EVP_PKEY **, BIO *,
+ pem_password_cb *pwd_callback,
+ void *callback_data);
typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl,
STACK_OF(X509_NAME) *ca_dn,
X509 **pcert, EVP_PKEY **pkey,
@@ -565,6 +571,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_privkey_bio_function(ENGINE *e,
+ ENGINE_LOAD_KEY_BIO_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 +619,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_BIO_PTR ENGINE_get_load_privkey_bio_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 +680,14 @@ int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
UI_METHOD *ui_method, void *callback_data);
/*
+ * Given a bio, this method iterates over all present engines to
+ * see if any can handle it. It's functionality depends on the engine
+ * implementing e->load_privkey_bio.
+ */
+int ENGINE_find_engine_load_key(ENGINE **e, EVP_PKEY **pkey, BIO *bio,
+ pem_password_cb *cb, void *cb_data);
+
+/*
* 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
--
2.6.6
More information about the openssl-dev
mailing list