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 <j...@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 -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev