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

James Bottomley James.Bottomley at HansenPartnership.com
Wed Nov 30 15:31:25 UTC 2016


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 <jejb at linux.vnet.ibm.com>
---
 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,
-		       TPM_R_FILE_NOT_FOUND);
-		return NULL;
+	if (bio) {
+		bf = bio;
+	} 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_OCTET_STRING,
 				    "TSS KEY BLOB", bf, NULL, NULL, NULL);
+
+
+	if (!bio)
+		BIO_free(bf);
+
+	/* if no actual key, we're just seeing if we can parse the file */
+	if (!ppkey) {
+		if (blobstr) {
+			ASN1_OCTET_STRING_free(blobstr);
+			return 1;
+		}
+		return 0;
+	}
+
+	/* else we're actually trying to load the key and a wrong
+	 * file format is an error */
 	if (!blobstr) {
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
 		       TPM_R_FILE_READ_FAILED);
-		BIO_free(bf);
-		return NULL;
+		return 0;
+	}
+
+	if (!tpm_load_srk(ui, cb_data)) {
+		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_SRK_LOAD_FAILED);
+		return 0;
 	}
 
-	BIO_free(bf);
 	DBG("Loading blob of size: %d", blobstr->length);
 	if ((result = Tspi_Context_LoadKeyByBlob(hContext, hSRK,
 						   blobstr->length,
 						   blobstr->data, &hKey))) {
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
 		       TPM_R_REQUEST_FAILED);
-		return NULL;
+		return 0;
 	}
 	ASN1_OCTET_STRING_free(blobstr);
 
@@ -631,7 +685,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 		Tspi_Context_CloseObject(hContext, hKey);
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
 		       TPM_R_REQUEST_FAILED);
-		return NULL;
+		return 0;
 	}
 
 	if (authusage) {
@@ -641,7 +695,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 		if ((auth = calloc(1, 128)) == NULL) {
 			Tspi_Context_CloseObject(hContext, hKey);
 			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
-			return NULL;
+			return 0;
 		}
 
 		if (!tpm_engine_get_auth(ui, (char *)auth, 128,
@@ -650,7 +704,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 			Tspi_Context_CloseObject(hContext, hKey);
 			free(auth);
 			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
-			return NULL;
+			return 0;
 		}
 
 		if ((result = Tspi_Context_CreateObject(hContext,
@@ -688,7 +742,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 	if ((pkey = EVP_PKEY_new()) == NULL) {
 		Tspi_Context_CloseObject(hContext, hKey);
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
-		return NULL;
+		return 0;
 	}
 	pkey->type = EVP_PKEY_RSA;
 
@@ -696,7 +750,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 		EVP_PKEY_free(pkey);
 		Tspi_Context_CloseObject(hContext, hKey);
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE);
-		return NULL;
+		return 0;
 	}
 	rsa->meth = &tpm_rsa;
 	/* call our local init function here */
@@ -708,14 +762,43 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 		RSA_free(rsa);
 		Tspi_Context_CloseObject(hContext, hKey);
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED);
-		return NULL;
+		return 0;
 	}
 
 	EVP_PKEY_assign_RSA(pkey, rsa);
 
-	return pkey;
+	*ppkey = pkey;
+	return 1;
+}
+ 
+static int tpm_engine_load_key_bio(ENGINE *e, EVP_PKEY **ppkey, BIO *bio,
+				   pem_password_cb *pem_cb, void *cb)
+{
+	struct tpm_ui tui = {
+		.ui_method = NULL,
+		.pem_cb = pem_cb,
+	};
+
+	return tpm_engine_load_key_core(e, ppkey, NULL, bio, &tui, cb);
+}
+
+static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
+				     UI_METHOD *ui, void *cb)
+{
+	struct tpm_ui tui = {
+		.ui_method = ui,
+		.pem_cb = NULL,
+	};
+	EVP_PKEY *pkey;
+	int ret;
+
+	ret = tpm_engine_load_key_core(e, &pkey, key_id, NULL, &tui, cb);
+	if (ret == 1)
+		return pkey;
+	return NULL;
 }
 
+
 static int tpm_create_srk_policy(void *secret)
 {
 	TSS_RESULT result;
-- 
2.6.6



More information about the openssl-dev mailing list