--- src/e_tpm.c.orig	2017-12-18 15:45:34 UTC
+++ src/e_tpm.c
@@ -34,6 +34,7 @@
 #include <tss/tspi.h>
 
 #include <trousers/trousers.h>  // XXX DEBUG
+#include <trousers/tss.h>
 
 #include "e_tpm.h"
 #include "ssl_compat.h"
@@ -55,10 +56,10 @@ static char *tpm_engine_get_auth(UI_METHOD *, char *, 
 /* rsa functions */
 static int tpm_rsa_init(RSA *rsa);
 static int tpm_rsa_finish(RSA *rsa);
-static int tpm_rsa_pub_dec(int, const unsigned char *, unsigned char *, RSA *, int);
-static int tpm_rsa_pub_enc(int, const unsigned char *, unsigned char *, RSA *, int);
-static int tpm_rsa_priv_dec(int, const unsigned char *, unsigned char *, RSA *, int);
-static int tpm_rsa_priv_enc(int, const unsigned char *, unsigned char *, RSA *, int);
+static int tpm_rsa_pub_dec(int, unsigned char *, unsigned char *, RSA *, int);
+static int tpm_rsa_pub_enc(int, unsigned char *, unsigned char *, RSA *, int);
+static int tpm_rsa_priv_dec(int, unsigned char *, unsigned char *, RSA *, int);
+static int tpm_rsa_priv_enc(int, unsigned char *, unsigned char *, RSA *, int);
 //static int tpm_rsa_sign(int, const unsigned char *, unsigned int, unsigned char *, unsigned int *, const RSA *);
 static int tpm_rsa_keygen(RSA *, int, BIGNUM *, BN_GENCB *);
 #endif
@@ -72,6 +73,7 @@ static RAND_SEED_RET_TYPE tpm_rand_seed(const void *, 
 #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",
@@ -85,6 +87,10 @@ static const ENGINE_CMD_DEFN tpm_cmd_defns[] = {
 	 "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}
 };
 
@@ -151,6 +157,9 @@ static unsigned int (*p_tspi_Hash_SetHashValue)();
 static unsigned int (*p_tspi_GetPolicyObject)();
 static unsigned int (*p_tspi_Policy_SetSecret)();
 static unsigned int (*p_tspi_Policy_AssignToObject)();
+static unsigned int (*p_tspi_PcrComposite_SelectPcrIndex)();
+static unsigned int (*p_tspi_TPM_Quote)();
+static unsigned int (*p_tspi_NV_ReadValue)();
 
 /* Override the real function calls to use our indirect pointers */
 #define Tspi_Context_Create p_tspi_Context_Create
@@ -177,6 +186,9 @@ static unsigned int (*p_tspi_Policy_AssignToObject)();
 #define Tspi_Hash_SetHashValue p_tspi_Hash_SetHashValue
 #define Tspi_Policy_SetSecret p_tspi_Policy_SetSecret
 #define Tspi_Policy_AssignToObject p_tspi_Policy_AssignToObject
+#define	Tspi_PcrComposite_SelectPcrIndex p_tspi_PcrComposite_SelectPcrIndex
+#define	Tspi_TPM_Quote p_tspi_TPM_Quote
+#define	Tspi_NV_ReadValue p_tspi_NV_ReadValue
 #endif /* DLOPEN_TSPI */
 
 static int setup_rsa_method()
@@ -262,6 +274,7 @@ int tpm_load_srk(UI_METHOD *ui, void *cb_data)
 	TSS_RESULT result;
 	UINT32 authusage;
 	BYTE *auth;
+	BYTE well_known[TPM_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
 
 	if (hSRK != NULL_HKEY) {
 		DBGFN("SRK is already loaded.");
@@ -308,6 +321,7 @@ int tpm_load_srk(UI_METHOD *ui, void *cb_data)
 		return 0;
 	}
 
+	if (ui) {
 	if ((auth = calloc(1, 128)) == NULL) {
 		TSSerr(TPM_F_TPM_LOAD_SRK, ERR_R_MALLOC_FAILURE);
 		return 0;
@@ -333,6 +347,15 @@ int tpm_load_srk(UI_METHOD *ui, void *cb_data)
 
 	free(auth);
 
+	} else {
+		if ((result = Tspi_Policy_SetSecret(hSRKPolicy, TSS_SECRET_MODE_SHA1, 20, well_known))) {
+			Tspi_Context_CloseObject(hContext, hSRK);
+			free(auth);
+			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED);
+			return 0;
+		}
+	}
+
 	return 1;
 }
 
@@ -390,7 +413,10 @@ static int tpm_engine_init(ENGINE * e)
 	    !bind_tspi_func(tpm_dso, Context_GetTpmObject) ||
 	    !bind_tspi_func(tpm_dso, GetAttribUint32) ||
 	    !bind_tspi_func(tpm_dso, SetAttribData) ||
-	    !bind_tspi_func(tpm_dso, Policy_AssignToObject)
+	    !bind_tspi_func(tpm_dso, Policy_AssignToObject) ||
+	    !bind_tspi_func(tpm_dso, PcrComposite_SelectPcrIndex) ||
+	    !bind_tspi_func(tpm_dso, TPM_Quote) ||
+	    !bind_tspi_func(tpm_dso, NV_ReadValue)
 	    ) {
 		TSSerr(TPM_F_TPM_ENGINE_INIT, TPM_R_DSO_FAILURE);
 		goto err;
@@ -452,6 +478,9 @@ err:
 	p_tspi_Policy_AssignToObject = NULL;
 	p_tspi_TPM_StirRandom = NULL;
 	p_tspi_TPM_GetRandom = NULL;
+	p_tspi_PcrComposite_SelectPcrIndex = NULL;
+	p_tspi_TPM_Quote = NULL;
+	p_tspi_NV_ReadValue = NULL;
 #endif
 	return 0;
 }
@@ -590,6 +619,55 @@ err:
 	return 0;
 }
 
+/*
+ *     Read a keyblob from NVRAM into an OpenSSL memory BIO
+ *             by Christian Holler (c.hol...@sirrix.com), 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)
 {
@@ -604,7 +682,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const 
 
 	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;
 	}
@@ -614,17 +692,27 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const 
 		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);
+			TPM_R_FILE_NOT_FOUND);
 		return NULL;
 	}
+	}
 
 	blobstr = PEM_ASN1_read_bio((void *)d2i_ASN1_OCTET_STRING,
 				    "TSS KEY BLOB", bf, NULL, NULL, NULL);
 	if (!blobstr) {
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
-		       TPM_R_FILE_READ_FAILED);
+			TPM_R_FILE_READ_FAILED);
 		BIO_free(bf);
 		return NULL;
 	}
@@ -635,7 +723,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const 
 						   blobstr->length,
 						   blobstr->data, &hKey))) {
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
-		       TPM_R_REQUEST_FAILED);
+			TPM_R_REQUEST_FAILED);
 		return NULL;
 	}
 	ASN1_OCTET_STRING_free(blobstr);
@@ -645,7 +733,7 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const 
 					     &authusage))) {
 		Tspi_Context_CloseObject(hContext, hKey);
 		TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY,
-		       TPM_R_REQUEST_FAILED);
+			TPM_R_REQUEST_FAILED);
 		return NULL;
 	}
 
@@ -747,7 +835,7 @@ static int tpm_create_srk_policy(void *secret)
 							  TSS_POLICY_USAGE,
 							  &hSRKPolicy))) {
 			TSSerr(TPM_F_TPM_CREATE_SRK_POLICY,
-			       TPM_R_REQUEST_FAILED);
+				TPM_R_REQUEST_FAILED);
 			return 0;
 		}
 	}
@@ -761,6 +849,70 @@ static int tpm_create_srk_policy(void *secret)
 	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 = !!hContext;
@@ -799,6 +951,8 @@ static int tpm_engine_ctrl(ENGINE * e, int cmd, long i
 			return 1;
 		case TPM_CMD_PIN:
 			return tpm_create_srk_policy(p);
+		case TPM_CMD_QUOTE:
+			return tpm_quote(p);
 		default:
 			break;
 	}
@@ -853,7 +1007,7 @@ static int tpm_rsa_finish(RSA *rsa)
 }
 
 static int tpm_rsa_pub_dec(int flen,
-			   const unsigned char *from,
+			   unsigned char *from,
 			   unsigned char *to,
 			   RSA *rsa,
 			   int padding)
@@ -872,7 +1026,7 @@ static int tpm_rsa_pub_dec(int flen,
 }
 
 static int tpm_rsa_priv_dec(int flen,
-			    const unsigned char *from,
+			    unsigned char *from,
 			    unsigned char *to,
 			    RSA *rsa,
 			    int padding)
@@ -949,7 +1103,7 @@ static int tpm_rsa_priv_dec(int flen,
 }
 
 static int tpm_rsa_pub_enc(int flen,
-			   const unsigned char *from,
+			   unsigned char *from,
 			   unsigned char *to,
 			   RSA *rsa,
 			   int padding)
@@ -1056,7 +1210,7 @@ static int tpm_rsa_pub_enc(int flen,
 }
 
 static int tpm_rsa_priv_enc(int flen,
-			    const unsigned char *from,
+			    unsigned char *from,
 			    unsigned char *to,
 			    RSA *rsa,
 			    int padding)
@@ -1101,7 +1255,10 @@ static int tpm_rsa_priv_enc(int flen,
 	}
 
 	if (app_data->sigScheme == TSS_SS_RSASSAPKCS1V15_SHA1) {
-		if (flen != SHA_DIGEST_LENGTH) {
+		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;
 		}
