[openssl-dev] [PATCH] openssl tpm engine: add new openssl bio method for seamless loading of tpm keys

2016-11-30 Thread James Bottomley
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 
---
 configure.in |   2 +
 e_tpm.c  | 139 +++
 2 files changed, 113 insertions(+), 28 deletions(-)

diff --git a/configure.in b/configure.in
index d07617d..4e2eff9 100644
--- a/configure.in
+++ b/configure.in
@@ -51,6 +51,8 @@ AC_PROG_LIBTOOL
 CFLAGS="$CFLAGS -Wall"
 AC_SUBST(CFLAGS)
 
+AC_CHECK_LIB(crypto, ENGINE_find_engine_load_key, 
[AC_DEFINE(HAVE_ENGINE_FIND_ENGINE_LOAD_KEY)])
+
 AC_OUTPUT(Makefile test/Makefile)
 
 echo "CFLAGS=$CFLAGS"
diff --git a/e_tpm.c b/e_tpm.c
index 3e20f8e..40ed4da 100644
--- a/e_tpm.c
+++ b/e_tpm.c
@@ -43,13 +43,20 @@
 #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 *);
+/* note unused unless HAVE_ENGINE_FIND_ENGINE_LOAD_KEY is defined */
+static int tpm_engine_load_key_bio(ENGINE *, EVP_PKEY **, BIO *, 
pem_password_cb *, void *) __attribute__((unused));
+static char *tpm_engine_get_auth(struct tpm_ui *, char *, int, char *, void *);
 
 #ifndef OPENSSL_NO_RSA
 /* rsa functions */
@@ -212,6 +219,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 HAVE_ENGINE_FIND_ENGINE_LOAD_KEY
+!ENGINE_set_load_privkey_bio_function(e, tpm_engine_load_key_bio) 
||
+#endif
!ENGINE_set_cmd_defns(e, tpm_cmd_defns))
return 0;
 
@@ -244,7 +254,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 +461,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 +490,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 +610,9 @@ 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 int tpm_engine_load_key_core(ENGINE *e, EVP_PKEY **ppkey,
+   const char *key_id, BIO *bio,
+   struct tpm_ui *ui, void *cb_data)
 {
ASN1_OCTET_STRING *blobstr;
TSS_HKEY hKey;
@@ -589,39 +625,57 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const 
char *key_id,
 
DBG("%s", __FUNCTION__);
 
-   if (!key_id) {
+   if (!key_id && !bio) {
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,
-  

[openssl-dev] [PATCH] openssl tpm engine: add new openssl bio method for seamless loading of tpm keys

2016-11-16 Thread James Bottomley
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 =