[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 16 15:48:33 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>

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_OCTET_STRING,
 				    "TSS KEY BLOB", bf, NULL, NULL, NULL);
+
+
+	if (!tpm_flag_is_bio(flags))
+		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 +694,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 +704,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 +713,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 +751,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 +759,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,13 +771,44 @@ 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_flags(ENGINE *e, EVP_PKEY **ppkey,
+				     const char *key_id,
+				     pem_password_cb *pem_cb, void *cb,
+				     unsigned int flags)
+{
+	struct tpm_ui tui = {
+		.ui_method = NULL,
+		.pem_cb = pem_cb,
+	};
+
+	return tpm_engine_load_key_core(e, ppkey, key_id, &tui, cb, flags);
+}
+
+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, &tui, cb, 0);
+	if (ret == 1)
+		return pkey;
+	return NULL;
+}
+
 
 static int tpm_create_srk_policy(void *secret)
 {


More information about the openssl-dev mailing list