Re: [openssl-dev] [RFC 1/2] engine: add new flag based method for loading engine keys
On Wed, Nov 16, 2016, James Bottomley wrote: > The assumption in all the current engine code is that key_id can be > passed as something like a file name. Well no it's a null terminated string whose meaning is engine specific. In some cases it is a key ID, in others it is a more complex string indicating multiple parameters. Steve. -- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] [RFC 0/2] Proposal for seamless handling of TPM based RSA keys in openssl
Thank you! I think I understand. (Sounds like an ugly and hardly necessary complication to me – not to mention that there might not be a filesystem to keep those around, but…) — Regards, Uri On 11/16/16, 5:06 PM, "openssl-dev on behalf of Dr. Stephen Henson" wrote: On Wed, Nov 16, 2016, Richard Levitte wrote: > If I understand correctly, the intention is to avoid having to use > ENGINE_load_private_key() directly or having to say '-keyform ENGINE' > to the openssl commands, and to avoid having to remember some cryptic > key identity to give with '-key'. Instead of all that, just give the > name of a .pem file with '-key' and if that file contains some kind of > magic information that the engine can understand, it will dig out a > reference to the hw protected key. > > Many years ago, I was thinking of something along the same lines, but > with a .pem file that would just have a few headers, holding the name > of the intended engine and the key identity, something like this: > > -BEGIN PRIVATE KEY- > X-key-id: flarflarflar > X-key-engine: foo > -END PRIVATE KEY- > > The intent was that the PEM code would be massaged to recognise these > headers and would then use ENGINE_by_id() / ENGINE_load_private_key() > with those data and that would be it. > Yes me too. Though if you're doing that something like "ENGINE PRIVATE KEY" or "OPENSSL ENGINE PRIVATE KEY" as just "PRIVATE KEY" is associated with PKCS#8. Steve. -- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev smime.p7s Description: S/MIME cryptographic signature -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] [RFC 0/2] Proposal for seamless handling of TPM based RSA keys in openssl
On Wed, Nov 16, 2016, Richard Levitte wrote: > If I understand correctly, the intention is to avoid having to use > ENGINE_load_private_key() directly or having to say '-keyform ENGINE' > to the openssl commands, and to avoid having to remember some cryptic > key identity to give with '-key'. Instead of all that, just give the > name of a .pem file with '-key' and if that file contains some kind of > magic information that the engine can understand, it will dig out a > reference to the hw protected key. > > Many years ago, I was thinking of something along the same lines, but > with a .pem file that would just have a few headers, holding the name > of the intended engine and the key identity, something like this: > > -BEGIN PRIVATE KEY- > X-key-id: flarflarflar > X-key-engine: foo > -END PRIVATE KEY- > > The intent was that the PEM code would be massaged to recognise these > headers and would then use ENGINE_by_id() / ENGINE_load_private_key() > with those data and that would be it. > Yes me too. Though if you're doing that something like "ENGINE PRIVATE KEY" or "OPENSSL ENGINE PRIVATE KEY" as just "PRIVATE KEY" is associated with PKCS#8. Steve. -- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] [RFC 1/2] engine: add new flag based method for loading engine keys
It is a heck of a lot easier for everyone if you make pull requests and not just mail big patches. Can you do that? -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] [RFC 0/2] Proposal for seamless handling of TPM based RSA keys in openssl
If I understand correctly, the intention is to avoid having to use ENGINE_load_private_key() directly or having to say '-keyform ENGINE' to the openssl commands, and to avoid having to remember some cryptic key identity to give with '-key'. Instead of all that, just give the name of a .pem file with '-key' and if that file contains some kind of magic information that the engine can understand, it will dig out a reference to the hw protected key. Many years ago, I was thinking of something along the same lines, but with a .pem file that would just have a few headers, holding the name of the intended engine and the key identity, something like this: -BEGIN PRIVATE KEY- X-key-id: flarflarflar X-key-engine: foo -END PRIVATE KEY- The intent was that the PEM code would be massaged to recognise these headers and would then use ENGINE_by_id() / ENGINE_load_private_key() with those data and that would be it. James, did I catch your intention about right? I think that's essentially what e_tpm.c does for loading keys, right? Cheers, Richard ( gotta love to see someone use "flarflarflar" as a key id ;-) ) In message <60f14e07-d0dc-486f-aff7-c74f5929b...@ll.mit.edu> on Wed, 16 Nov 2016 15:56:05 +, "Blumenthal, Uri - 0553 - MITLL" said: uri> My apologies – I don’t fully understand “file based engine keys”. I thought the keys were either on a hardware device (a TPM, a PKCS#11-accessible HSM or smartcard, etc), or in a file. If a key is in a file – it’s not an “engine key”. uri> uri> What am I missing, and what’s your use case(s)? uri> — uri> Regards, uri> Uri uri> uri> uri> On 11/16/16, 10:46 AM, "openssl-dev on behalf of James Bottomley" wrote: uri> uri> [David Woodhouse told me that openssl-dev is a closed list, so the uri> original messages got trashed. This is a resend with apologies to uri> David and Peter] uri> uri> One of the principle problems of using TPM based keys is that there's uri> no easy way of integrating them with standard file based keys. This uri> proposal adds a generic method for handling file based engine keys that uri> can be loaded as PEM files. Integration into the PEM loader requires a uri> BIO based engine API callback which the first patch adds. The second uri> patch checks to see if the key can be loaded by any of the present uri> engines. Note that this requires that any engine which is to be used uri> must be present and initialised via openssl.cnf. uri> uri> I'll also post to this list the patch to openssl_tpm_engine that makes uri> use if this infrastructure so the integration of the whole can be seen. uri> It should also be noted that gnutls has had this functionality since uri> 2012. uri> uri> The patch was done against 1.0.2h for easier testing and you can try it uri> and the openssl_tpm_engine out (if you run openSUSE) here: uri> uri> https://build.opensuse.org/project/show/home:jejb1:Tumbleweed uri> uri> James uri> uri> --- uri> uri> James Bottomley (2): uri> engine: add new flag based method for loading engine keys uri> pem: load engine keys uri> uri> crypto/engine/eng_int.h | 1 + uri> crypto/engine/eng_pkey.c | 38 ++ uri> crypto/engine/engine.h | 26 ++ uri> crypto/pem/pem_pkey.c| 5 + uri> 4 files changed, 70 insertions(+) uri> uri> -- uri> openssl-dev mailing list uri> To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev uri> -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] [RFC 0/2] Proposal for seamless handling of TPM based RSA keys in openssl
My apologies – I don’t fully understand “file based engine keys”. I thought the keys were either on a hardware device (a TPM, a PKCS#11-accessible HSM or smartcard, etc), or in a file. If a key is in a file – it’s not an “engine key”. What am I missing, and what’s your use case(s)? — Regards, Uri On 11/16/16, 10:46 AM, "openssl-dev on behalf of James Bottomley" wrote: [David Woodhouse told me that openssl-dev is a closed list, so the original messages got trashed. This is a resend with apologies to David and Peter] One of the principle problems of using TPM based keys is that there's no easy way of integrating them with standard file based keys. This proposal adds a generic method for handling file based engine keys that can be loaded as PEM files. Integration into the PEM loader requires a BIO based engine API callback which the first patch adds. The second patch checks to see if the key can be loaded by any of the present engines. Note that this requires that any engine which is to be used must be present and initialised via openssl.cnf. I'll also post to this list the patch to openssl_tpm_engine that makes use if this infrastructure so the integration of the whole can be seen. It should also be noted that gnutls has had this functionality since 2012. The patch was done against 1.0.2h for easier testing and you can try it and the openssl_tpm_engine out (if you run openSUSE) here: https://build.opensuse.org/project/show/home:jejb1:Tumbleweed James --- James Bottomley (2): engine: add new flag based method for loading engine keys pem: load engine keys crypto/engine/eng_int.h | 1 + crypto/engine/eng_pkey.c | 38 ++ crypto/engine/engine.h | 26 ++ crypto/pem/pem_pkey.c| 5 + 4 files changed, 70 insertions(+) -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev smime.p7s Description: S/MIME cryptographic signature -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
[openssl-dev] [RFC 2/2] pem: load engine keys
Before trying to process the PEM file, hand it to each of the loaded engines to see if they can load it. This uses the new bio based callback, so the engine must be loaded and implement this callback to be considered. Signed-off-by: James Bottomley --- crypto/pem/pem_pkey.c | 5 + 1 file changed, 5 insertions(+) diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 04d6319..8d44d45 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -85,6 +85,11 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, int slen; EVP_PKEY *ret = NULL; +if (ENGINE_find_engine_load_key(NULL, &ret, (const char *)bp, cb, u, + ENGINE_LOAD_KEY_FLAG_BIO) == 1) { +return ret; +} + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) return NULL; p = data; -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
[openssl-dev] [RFC 0/2] Proposal for seamless handling of TPM based RSA keys in openssl
[David Woodhouse told me that openssl-dev is a closed list, so the original messages got trashed. This is a resend with apologies to David and Peter] One of the principle problems of using TPM based keys is that there's no easy way of integrating them with standard file based keys. This proposal adds a generic method for handling file based engine keys that can be loaded as PEM files. Integration into the PEM loader requires a BIO based engine API callback which the first patch adds. The second patch checks to see if the key can be loaded by any of the present engines. Note that this requires that any engine which is to be used must be present and initialised via openssl.cnf. I'll also post to this list the patch to openssl_tpm_engine that makes use if this infrastructure so the integration of the whole can be seen. It should also be noted that gnutls has had this functionality since 2012. The patch was done against 1.0.2h for easier testing and you can try it and the openssl_tpm_engine out (if you run openSUSE) here: https://build.opensuse.org/project/show/home:jejb1:Tumbleweed James --- James Bottomley (2): engine: add new flag based method for loading engine keys pem: load engine keys crypto/engine/eng_int.h | 1 + crypto/engine/eng_pkey.c | 38 ++ crypto/engine/engine.h | 26 ++ crypto/pem/pem_pkey.c| 5 + 4 files changed, 70 insertions(+) -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
[openssl-dev] [RFC 1/2] engine: add new flag based method for loading engine keys
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 --- 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 # include +# include #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_fu
[openssl-dev] [PATCH] openssl tpm engine: add new openssl bio method for seamless loading of tpm keys
Permits this engine to be used as part of the openssl pem routines for loading TPM based keys. To use this, the tpm engine must be preloaded via the openssl.cnf file Signed-off-by: James Bottomley diff --git a/e_tpm.c b/e_tpm.c index 3e20f8e..9cb1d6c 100644 --- a/e_tpm.c +++ b/e_tpm.c @@ -43,13 +43,19 @@ #ifndef OPENSSL_NO_HW #ifndef OPENSSL_NO_HW_TPM +struct tpm_ui { +UI_METHOD *ui_method; +pem_password_cb *pem_cb; +}; + /* engine specific functions */ static int tpm_engine_destroy(ENGINE *); static int tpm_engine_init(ENGINE *); static int tpm_engine_finish(ENGINE *); static int tpm_engine_ctrl(ENGINE *, int, long, void *, void (*)()); static EVP_PKEY *tpm_engine_load_key(ENGINE *, const char *, UI_METHOD *, void *); -static char *tpm_engine_get_auth(UI_METHOD *, char *, int, char *, void *); +static int tpm_engine_load_key_flags(ENGINE *, EVP_PKEY **, const char *, pem_password_cb *, void *, unsigned int); +static char *tpm_engine_get_auth(struct tpm_ui *, char *, int, char *, void *); #ifndef OPENSSL_NO_RSA /* rsa functions */ @@ -212,6 +218,9 @@ static int bind_helper(ENGINE * e) !ENGINE_set_ctrl_function(e, tpm_engine_ctrl) || !ENGINE_set_load_pubkey_function(e, tpm_engine_load_key) || !ENGINE_set_load_privkey_function(e, tpm_engine_load_key) || +#ifdef ENGINE_LOAD_KEY_FLAG_BIO +!ENGINE_set_load_key_flags_function(e, tpm_engine_load_key_flags) || +#endif !ENGINE_set_cmd_defns(e, tpm_cmd_defns)) return 0; @@ -244,7 +253,7 @@ void ENGINE_load_tpm(void) ERR_clear_error(); } -int tpm_load_srk(UI_METHOD *ui, void *cb_data) +int tpm_load_srk(struct tpm_ui *ui, void *cb_data) { TSS_RESULT result; UINT32 authusage; @@ -451,8 +460,9 @@ err: return 0; } -static char *tpm_engine_get_auth(UI_METHOD *ui_method, char *auth, int maxlen, -char *input_string, void *cb_data) +static char *tpm_engine_get_auth_ui(UI_METHOD *ui_method, char *auth, + int maxlen, char *input_string, + void *cb_data) { UI *ui; @@ -479,6 +489,30 @@ static char *tpm_engine_get_auth(UI_METHOD *ui_method, char *auth, int maxlen, return auth; } +static char *tpm_engine_get_auth_pem(pem_password_cb *pem_cb, char *auth, + int maxlen, char *input_string, + void *cb_data) +{ + EVP_set_pw_prompt(input_string); + if (!pem_cb) + pem_cb = PEM_def_callback; + pem_cb(auth, maxlen, 0, cb_data); + EVP_set_pw_prompt(NULL); + + return auth; +} + +static char *tpm_engine_get_auth(struct tpm_ui *ui, char *auth, + int maxlen, char *input_string, void *cb_data) +{ + if (ui->ui_method) + return tpm_engine_get_auth_ui(ui->ui_method, auth, maxlen, + input_string, cb_data); + else + return tpm_engine_get_auth_pem(ui->pem_cb, auth, maxlen, + input_string, cb_data); +} + static int tpm_engine_finish(ENGINE * e) { DBG("%s", __FUNCTION__); @@ -575,8 +609,19 @@ int fill_out_rsa_object(RSA *rsa, TSS_HKEY hKey) return 1; } -static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, -UI_METHOD *ui, void *cb_data) +static inline int tpm_flag_is_bio(unsigned int flags) +{ +#ifdef ENGINE_LOAD_KEY_FLAG_BIO + return flags & ENGINE_LOAD_KEY_FLAG_BIO; +#else + return 0; +#endif +} + +static int tpm_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey, + const char *key_id, + struct tpm_ui *ui, + void *cb_data, unsigned int flags) { ASN1_OCTET_STRING *blobstr; TSS_HKEY hKey; @@ -591,37 +636,55 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, if (!key_id) { TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_PASSED_NULL_PARAMETER); - return NULL; - } - - if (!tpm_load_srk(ui, cb_data)) { - TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_SRK_LOAD_FAILED); - return NULL; + return 0; } - if ((bf = BIO_new_file(key_id, "r")) == NULL) { - TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, - TPM_R_FILE_NOT_FOUND); - return NULL; + if (tpm_flag_is_bio(flags)) { + bf = (BIO *)key_id; + } else { + if ((bf = BIO_new_file(key_id, "r")) == NULL) { + TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, + TPM_R_FILE_NOT_FOUND); + return 0; + } } blobstr = PEM_ASN1_read_bio((void *)d2i_ASN1_O