Hello,

I have been actively working with the OpenSSL Engine provided by
Trousers in the last two months and I fixed some bugs and added some
features we needed. Our project manager agreed on me providing you all
the changes I made so you can incorporate them into Trousers if you
like. Here is what I changed in detail:

-  tpm_rsa_priv_enc(): When using SigScheme TSS_SS_RSASSAPKCS1V15_SHA1,
the data to sign passed by OpenSSL is already PKCS 1.5 padded. The
padding must be removed at that point again, otherwise signing with the
TPM will fail always. This might also be the case for the other
SigScheme, I have not tested. According to some other post on this
mailing list, this behavior was not always the same, so if someone knows
the exact version, please let us know so we can add the appropriate
version define there.

-  tpm_load_srk(): If ui is NULL, use TSS_WELL_KNOWN_SECRET for
authentication as described in the TSS specification.

-  tpm_engine_load_key(): Allow passing an "nvram_request" structure as
the cb_data. This will cause the load_key function to retrieve the
keyblob from the TPM NVRAM instead of using a file.

-  Added a new command "TPM_CMD_QUOTE", which takes a "quote_request"
structure and performs a TPM_Quote(). Such a command is necessary if you
want to use the OpenSSL Engine with Remote Attestation. It is arguable
if a control command like I did it, is the best way, but it works for us.


The patch is attached (and you may remove any comments about my
authorship that I made for some additions).


If you have any comments what could be improved, questions or if I made
any mistakes, feel free to let me know.


Best regards,



Christian Holler

-- 
Sirrix AG security technologies -- http://www.sirrix.com
B.Sc. Christian Holler  eMail: [email protected]
Mobile: +49 (176) 21 98 50 42

Vorstand: Ammar Alkassar (Vors.), Christian Stueble
Vorsitzender des Aufsichtsrates: Prof. Dr. Kai Rannenberg
Sitz der Gesellschaft: Homburg/Saar, HRB 3857 Amtsgericht Saarbruecken

This message may contain confidential and/or privileged information.
If you are not the addressee, you must not use, copy, disclose or
take any action based on this message or any information herein.
If you have received this message in error, please advise the sender
immediately by reply e-mail and delete this message.

diff -aur openssl_tpm_engine-0.4.1/e_tpm.c openssl_tpm_engine-0.4.1.patched/e_tpm.c
--- openssl_tpm_engine-0.4.1/e_tpm.c	2007-02-05 21:32:10.000000000 +0100
+++ openssl_tpm_engine-0.4.1.patched/e_tpm.c	2010-06-07 17:22:54.402266831 +0200
@@ -45,6 +45,7 @@
 #include <tss/tspi.h>
 
 #include <trousers/trousers.h>  // XXX DEBUG
+#include <trousers/tss.h>  // XXX DEBUG
 
 #include "e_tpm.h"
 
@@ -77,6 +78,11 @@
 static const char *TPM_F_Policy_SetSecret = "Tspi_Policy_SetSecret";
 static const char *TPM_F_Policy_AssignToObject = "Tspi_Policy_AssignToObject";
 
+/* Added by [email protected] */
+static const char *TPM_F_PcrComposite_SelectPcrIndex = "Tspi_PcrComposite_SelectPcrIndex";
+static const char *TPM_F_TPM_Quote = "Tspi_TPM_Quote";
+static const char *TPM_F_NV_ReadValue = "Tspi_NV_ReadValue";
+
 /* engine specific functions */
 static int tpm_engine_destroy(ENGINE *);
 static int tpm_engine_init(ENGINE *);
@@ -106,6 +112,8 @@
 #define TPM_CMD_SO_PATH		ENGINE_CMD_BASE
 #define TPM_CMD_PIN		ENGINE_CMD_BASE+1
 #define TPM_CMD_SECRET_MODE	ENGINE_CMD_BASE+2
+#define TPM_CMD_QUOTE		ENGINE_CMD_BASE+3
+
 static const ENGINE_CMD_DEFN tpm_cmd_defns[] = {
 	{TPM_CMD_SO_PATH,
 	 "SO_PATH",
@@ -119,6 +127,10 @@
 	 "SECRET_MODE",
 	 "The TSS secret mode for all secrets",
 	 ENGINE_CMD_FLAG_NUMERIC},
+	{TPM_CMD_QUOTE,
+	 "QUOTE",
+	 "Perform a TPM_Quote() with the given structure",
+	 ENGINE_CMD_FLAG_NUMERIC},
 	{0, NULL, NULL, 0}
 };
 
@@ -201,6 +213,11 @@
 static unsigned int (*p_tspi_Policy_SetSecret)();
 static unsigned int (*p_tspi_Policy_AssignToObject)();
 
+/* Added by [email protected] */
+static unsigned int (*p_tspi_PcrComposite_SelectPcrIndex)();
+static unsigned int (*p_tspi_TPM_Quote)();
+static unsigned int (*p_tspi_NV_ReadValue)();
+
 /* This internal function is used by ENGINE_tpm() and possibly by the
  * "dynamic" ENGINE support too */
 static int bind_helper(ENGINE * e)
@@ -255,6 +272,9 @@
 	UINT32 authusage;
 	BYTE *auth;
 
+	/* Added by [email protected] */
+	BYTE well_known[TPM_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
+
 	if (hSRK != NULL_HKEY) {
 		DBGFN("SRK is already loaded.");
 		return 1;
@@ -300,25 +320,34 @@
 		return 0;
 	}
 
-	if ((auth = calloc(1, 128)) == NULL) {
-		TSSerr(TPM_F_TPM_LOAD_SRK, ERR_R_MALLOC_FAILURE);
-		return 0;
-	}
+	/* [email protected]: If the UI method is NULL, use TSS_WELL_KNOWN_SECRET */
+	if (ui) {
+		if ((auth = calloc(1, 128)) == NULL) {
+			TSSerr(TPM_F_TPM_LOAD_SRK, ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
 
-	if (!tpm_engine_get_auth(ui, (char *)auth, 128, "SRK authorization: ")) {
-		p_tspi_Context_CloseObject(hContext, hSRK);
-		free(auth);
-		TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
-	}
+		if (!tpm_engine_get_auth(ui, (char *)auth, 128, "SRK authorization: ")) {
+			p_tspi_Context_CloseObject(hContext, hSRK);
+			free(auth);
+			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
+		}
 
-	/* secret_mode is a global that may be set by engine ctrl
-	 * commands.  By default, its set to TSS_SECRET_MODE_PLAIN */
-	if ((result = p_tspi_Policy_SetSecret(hSRKPolicy, secret_mode,
-					      strlen((char *)auth), auth))) {
-		p_tspi_Context_CloseObject(hContext, hSRK);
-		free(auth);
-		TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
-		return 0;
+		/* secret_mode is a global that may be set by engine ctrl
+		 * commands.  By default, its set to TSS_SECRET_MODE_PLAIN */
+		if ((result = p_tspi_Policy_SetSecret(hSRKPolicy, secret_mode,
+						      strlen((char *)auth), auth))) {
+			p_tspi_Context_CloseObject(hContext, hSRK);
+			free(auth);
+			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
+			return 0;
+		}
+	} else {
+		if (result = p_tspi_Policy_SetSecret(hSRKPolicy, TSS_SECRET_MODE_SHA1, 20, well_known)) {
+			p_tspi_Context_CloseObject(hContext, hSRK);
+			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
+			return 0;
+		}
 	}
 
 	free(auth);
@@ -363,6 +392,12 @@
 	void (*p22) ();
 	void (*p23) ();
 	void (*p24) ();
+
+	/* Added by [email protected] */
+	void (*p25) ();
+	void (*p26) ();
+	void (*p27) ();
+	
 	TSS_RESULT result;
 
 	DBG("%s", __FUNCTION__);
@@ -400,6 +435,12 @@
 	    !(p21 = DSO_bind_func(tpm_dso, TPM_F_Context_GetTpmObject)) ||
 	    !(p22 = DSO_bind_func(tpm_dso, TPM_F_GetAttribUint32)) ||
 	    !(p23 = DSO_bind_func(tpm_dso, TPM_F_SetAttribData)) ||
+
+	    /* Added by [email protected] */
+	    !(p25 = DSO_bind_func(tpm_dso, TPM_F_TPM_Quote)) ||
+	    !(p26 = DSO_bind_func(tpm_dso, TPM_F_PcrComposite_SelectPcrIndex)) ||
+	    !(p27 = DSO_bind_func(tpm_dso, TPM_F_NV_ReadValue)) ||
+
 	    !(p24 = DSO_bind_func(tpm_dso, TPM_F_Policy_AssignToObject))
 	    ) {
 		TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_DSO_FAILURE);
@@ -431,6 +472,11 @@
 	p_tspi_GetAttribUint32 = (unsigned int (*) ()) p22;
 	p_tspi_SetAttribData = (unsigned int (*) ()) p23;
 	p_tspi_Policy_AssignToObject = (unsigned int (*) ()) p24;
+	
+	/* Added by [email protected] */
+	p_tspi_TPM_Quote = (unsigned int (*) ()) p25;
+	p_tspi_PcrComposite_SelectPcrIndex = (unsigned int (*) ()) p26;
+	p_tspi_NV_ReadValue = (unsigned int (*) ()) p27;
 
 	if ((result = p_tspi_Context_Create(&hContext))) {
 		TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_UNIT_FAILURE);
@@ -487,6 +533,11 @@
 	p_tspi_TPM_StirRandom = NULL;
 	p_tspi_TPM_GetRandom = NULL;
 
+	/* Added by [email protected] */
+	p_tspi_TPM_Quote = NULL;
+	p_tspi_PcrComposite_SelectPcrIndex = NULL;
+	p_tspi_NV_ReadValue = NULL;
+
 	return 0;
 }
 
@@ -612,6 +663,55 @@
 	return 1;
 }
 
+/*
+ *	Read a keyblob from NVRAM into an OpenSSL memory BIO
+ *		by Christian Holler ([email protected]), Sirrix AG
+ */
+int BIO_from_nvram(unsigned int index, unsigned int length, BIO** bio)
+{
+	TSS_RESULT result;
+	TSS_HNVSTORE hNVStore;
+	BYTE *dataRead = NULL;
+
+	//unsigned int blobLength = 559;
+
+	BIO *mem = BIO_new(BIO_s_mem());
+
+	/* Create TPM NV object */
+	result = p_tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_NV, 0,
+				  &hNVStore);
+	
+	if (result != TSS_SUCCESS) {
+		TSSerr(TPM_F_TPM_BIO_FROM_NVRAM,
+		       TPM_R_REQUEST_FAILED);
+		return 0;
+	}
+	
+	/* Set the index to be read */
+	result = p_tspi_SetAttribUint32(hNVStore, TSS_TSPATTRIB_NV_INDEX, 0,
+			     (UINT32) index);
+
+	if (result != TSS_SUCCESS) {
+		TSSerr(TPM_F_TPM_BIO_FROM_NVRAM,
+		       TPM_R_REQUEST_FAILED);
+		return 0;
+	}
+
+	result = p_tspi_NV_ReadValue(hNVStore, 0, &length, &dataRead);
+	BIO_write(mem, dataRead, length);
+	p_tspi_Context_FreeMemory(hContext, dataRead);
+
+	if (result != TSS_SUCCESS ) {
+		TSSerr(TPM_F_TPM_BIO_FROM_NVRAM,
+		       TPM_R_REQUEST_FAILED);
+		return 0;
+	}
+
+	*bio = mem;
+
+	return 1;
+}
+
 static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id,
 				     UI_METHOD *ui, void *cb_data)
 {
@@ -627,7 +727,7 @@
 
 	DBG("%s", __FUNCTION__);
 
-	if (!key_id) {
+	if (!key_id && !cb_data) {
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 	}
@@ -637,10 +737,21 @@
 		return NULL;
 	}
 
-	if ((bf = BIO_new_file(key_id, "r")) == NULL) {
-		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
-		       TPM_R_FILE_NOT_FOUND);
-		return NULL;
+	if (cb_data) {
+		struct nvram_request *nvreq = cb_data;
+
+		if (!BIO_from_nvram(nvreq->index, nvreq->length, &bf)) {
+			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
+				TPM_R_NVRAM_FAILED);
+			return NULL;
+		}
+	} else {
+
+		if ((bf = BIO_new_file(key_id, "r")) == NULL) {
+			TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
+			       TPM_R_FILE_NOT_FOUND);
+			return NULL;
+		}
 	}
 retry:
 	if ((rc = BIO_read(bf, &blob_buf[0], 4096)) < 0) {
@@ -782,6 +893,70 @@
 	return 1;
 }
 
+static int tpm_quote(void* p) {
+	TSS_RESULT result;
+	TSS_HPCRS hPcrComposite;
+	TSS_VALIDATION tssVal;
+	
+	unsigned int i = 0;
+
+	struct quote_request *request = p;
+
+	struct rsa_app_data *app_data = RSA_get_ex_data(request->rsa, ex_app_data);
+
+	/* No app_data, this is not a TPM Key and we cannot use it for quote */
+	if (!app_data) {
+		return 0;
+	}
+
+	/* Key is invalid */
+	if (app_data->hKey == NULL_HKEY) {
+		TSSerr(TPM_F_TPM_QUOTE, TPM_R_INVALID_KEY);
+		return 0;
+	}
+
+	/* Set up PcrComposite Structure, this is a set 
+	 * of PCRs which will be used for the quote */
+	result =
+		p_tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS,
+				TSS_PCRS_STRUCT_INFO, &hPcrComposite);
+	if (result != TSS_SUCCESS) {
+		TSSerr(TPM_F_TPM_QUOTE, TPM_R_REQUEST_FAILED);
+		return 0;
+	}
+
+	/* Add all PCR values to be used to PcrComposite structure */
+	for (i = 0; i < request->PCRSelLength; i++) {
+		if (request->PCRSel[i]) {
+			result = p_tspi_PcrComposite_SelectPcrIndex(hPcrComposite, i);
+
+			if (result != TSS_SUCCESS) {
+				TSSerr(TPM_F_TPM_QUOTE, TPM_R_REQUEST_FAILED);
+				return 0;
+			}
+		}
+	}
+
+	/* Set the nonce */
+	tssVal.rgbExternalData = request->nonce;
+	tssVal.ulExternalDataLength = SHA_DIGEST_LENGTH;
+
+	result = p_tspi_TPM_Quote(hTPM, app_data->hKey, hPcrComposite, &tssVal);
+
+	if (result != TSS_SUCCESS) {
+		TSSerr(TPM_F_TPM_QUOTE, TPM_R_REQUEST_FAILED);
+		return 0;
+	}
+
+	request->rgbData = tssVal.rgbData;
+	request->ulValidationDataLength = tssVal.ulValidationDataLength;
+	request->rgbValidationData = tssVal.rgbValidationData;
+
+	p_tspi_Context_CloseObject(hContext, hPcrComposite);
+
+	return 1;
+}
+
 static int tpm_engine_ctrl(ENGINE * e, int cmd, long i, void *p, void (*f) ())
 {
 	int initialised = ((tpm_dso == NULL) ? 0 : 1);
@@ -820,6 +995,8 @@
 			return 1;
 		case TPM_CMD_PIN:
 			return tpm_create_srk_policy(p);
+		case TPM_CMD_QUOTE:
+			return tpm_quote(p);
 		default:
 			break;
 	}
@@ -1104,7 +1281,12 @@
 	}
 
 	if (app_data->sigScheme == TSS_SS_RSASSAPKCS1V15_SHA1) {
-		if (flen != SHA_DIGEST_LENGTH) {
+		/* [email protected]: Ugly hack, OpenSSL passes PKCS1v1.5 wrapped hash, 
+		 * original SHA1 is last 20 bytes */
+		if (flen == SHA_DIGEST_LENGTH+15) {
+			from += 15;
+			flen = SHA_DIGEST_LENGTH;
+		} else if (flen != SHA_DIGEST_LENGTH) {
 			TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_INVALID_MSG_SIZE);
 			return 0;
 		}
diff -aur openssl_tpm_engine-0.4.1/e_tpm_err.c openssl_tpm_engine-0.4.1.patched/e_tpm_err.c
--- openssl_tpm_engine-0.4.1/e_tpm_err.c	2005-10-05 21:02:16.000000000 +0200
+++ openssl_tpm_engine-0.4.1.patched/e_tpm_err.c	2010-06-07 11:16:53.951211256 +0200
@@ -246,6 +246,7 @@
 	{ERR_PACK(0, TPM_F_TPM_BIND_FN, 0), "TPM_BIND_FN"},
 	{ERR_PACK(0, TPM_F_TPM_FILL_RSA_OBJECT, 0), "TPM_FILL_RSA_OBJECT"},
 	{ERR_PACK(0, TPM_F_TPM_ENGINE_GET_AUTH, 0), "TPM_ENGINE_GET_AUTH"},
+	{ERR_PACK(0, TPM_F_TPM_BIO_FROM_NVRAM, 0), "TPM_BIO_FROM_NVRAM"},
 	{0, NULL}
 };
 
@@ -276,6 +277,7 @@
 	{TPM_R_FILE_READ_FAILED, "failed reading the key file"},
 	{TPM_R_ID_INVALID, "engine id doesn't match"},
 	{TPM_R_UI_METHOD_FAILED, "ui function failed"},
+	{TPM_R_NVRAM_FAILED, "nvram failure"},
 	{0, NULL}
 };
 
diff -aur openssl_tpm_engine-0.4.1/e_tpm.h openssl_tpm_engine-0.4.1.patched/e_tpm.h
--- openssl_tpm_engine-0.4.1/e_tpm.h	2006-08-03 21:22:05.000000000 +0200
+++ openssl_tpm_engine-0.4.1.patched/e_tpm.h	2010-06-07 11:58:31.779226692 +0200
@@ -74,6 +74,8 @@
 #define TPM_F_TPM_FILL_RSA_OBJECT		116
 #define TPM_F_TPM_ENGINE_GET_AUTH		117
 #define TPM_F_TPM_CREATE_SRK_POLICY		118
+#define TPM_F_TPM_BIO_FROM_NVRAM		119
+#define TPM_F_TPM_QUOTE				120
 
 /* Reason codes. */
 #define TPM_R_ALREADY_LOADED			100
@@ -104,6 +106,7 @@
 #define TPM_R_ID_INVALID			125
 #define TPM_R_UI_METHOD_FAILED			126
 #define TPM_R_UNKNOWN_SECRET_MODE		127
+#define TPM_R_NVRAM_FAILED			128
 
 /* structure pointed to by the RSA object's app_data pointer */
 struct rsa_app_data
@@ -115,6 +118,25 @@
 	UINT32 sigScheme;
 };
 
+/* Added by [email protected] */
+struct quote_request
+{
+	RSA* rsa;
+	unsigned int PCRSel[256];
+	unsigned int PCRSelLength;
+	const unsigned char* nonce;
+	unsigned int nonceLen;
+	unsigned char* rgbData;
+	unsigned int ulValidationDataLength;
+	unsigned char* rgbValidationData;
+};
+
+struct nvram_request
+{
+	unsigned int index;
+	unsigned int length;
+};
+
 #define TPM_ENGINE_EX_DATA_UNINIT		-1
 #define RSA_PKCS1_OAEP_PADDING_SIZE		(2 * SHA_DIGEST_LENGTH + 2)

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate 
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the 
lucky parental unit.  See the prize list and enter to win: 
http://p.sf.net/sfu/thinkgeek-promo
_______________________________________________
TrouSerS-tech mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/trousers-tech

Reply via email to