1diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c 2index 9e1cfb4..0fabf98 100644 3--- a/tpm/tpm_cmd_handler.c 4+++ b/tpm/tpm_cmd_handler.c 5@@ -3312,6 +3312,37 @@ static TPM_RESULT execute_TPM_OwnerReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp 6 return res; 7 } 8 9+static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp) 10+{ 11+ TPM_NONCE nonce; 12+ TPM_RESULT res; 13+ UINT32 sigSize; 14+ BYTE *sig; 15+ BYTE *ptr; 16+ UINT32 len; 17+ TPM_PCR_SELECTION targetPCR; 18+ 19+ tpm_compute_in_param_digest(req); 20+ 21+ ptr = req->param; 22+ len = req->paramSize; 23+ if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce) 24+ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR) 25+ || len != 0) return TPM_BAD_PARAMETER; 26+ 27+ res = TPM_ParentSignEK(&nonce, &targetPCR, &req->auth1, &sigSize, &sig); 28+ if (res != TPM_SUCCESS) return res; 29+ rsp->paramSize = len = sigSize; 30+ rsp->param = ptr = tpm_malloc(len); 31+ if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) { 32+ tpm_free(rsp->param); 33+ res = TPM_FAIL; 34+ } 35+ tpm_free(sig); 36+ 37+ return res; 38+} 39+ 40 static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp) 41 { 42 tpm_hmac_ctx_t hmac; 43@@ -4062,6 +4093,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp) 44 res = execute_TPM_OwnerReadPubek(req, rsp); 45 break; 46 47+ case TPM_ORD_ParentSignEK: 48+ debug("[TPM_ORD_ParentSignEK]"); 49+ res = execute_TPM_ParentSignEK(req, rsp); 50+ break; 51+ 52 default: 53 #ifdef MTM_EMULATOR 54 res = mtm_execute_command(req, rsp); 55diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h 56index a7666f6..7fef934 100644 57--- a/tpm/tpm_commands.h 58+++ b/tpm/tpm_commands.h 59@@ -3054,6 +3054,23 @@ TPM_RESULT TPM_OwnerReadPubek( 60 TPM_PUBKEY *pubEndorsementKey 61 ); 62 63+/** 64+ * TPM_ParentSignEK - gets a hardware TPM quote of a vTPM's EK 65+ * @externalData: [in] AntiReplay nonce to prevent replay of messages 66+ * @sel: [in] PCR selection for the hardware TPM's quote 67+ * @auth1: [in, out] Authorization protocol parameters 68+ * @sigSize: [out] The length of the returned digital signature 69+ * @sig: [out] The resulting digital signature and PCR values 70+ * Returns: TPM_SUCCESS on success, a TPM error code otherwise. 71+ */ 72+TPM_RESULT TPM_ParentSignEK( 73+ TPM_NONCE *externalData, 74+ TPM_PCR_SELECTION *sel, 75+ TPM_AUTH *auth1, 76+ UINT32 *sigSize, 77+ BYTE **sig 78+); 79+ 80 /* 81 * Error handling 82 * [tpm_error.c] 83diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c 84index 9cd64af..01f29e6 100644 85--- a/tpm/tpm_credentials.c 86+++ b/tpm/tpm_credentials.c 87@@ -180,3 +180,34 @@ TPM_RESULT TPM_OwnerReadInternalPub(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1, 88 return TPM_BAD_PARAMETER; 89 } 90 } 91+ 92+int endorsementKeyFresh = 0; 93+ 94+TPM_RESULT VTPM_GetParentQuote(TPM_DIGEST* data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig); 95+ 96+TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel, 97+ TPM_AUTH *auth1, UINT32 *sigSize, BYTE **sig) 98+{ 99+ TPM_PUBKEY pubKey; 100+ TPM_RESULT res; 101+ TPM_DIGEST hres; 102+ 103+ info("TPM_ParentSignEK()"); 104+ 105+ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); 106+ if (res != TPM_SUCCESS) return res; 107+ 108+ if (!endorsementKeyFresh) return TPM_DISABLED_CMD; 109+ 110+ res = tpm_get_pubek(&pubKey); 111+ if (res != TPM_SUCCESS) return res; 112+ 113+ if (tpm_compute_pubkey_checksum(externalData, &pubKey, &hres)) 114+ res = TPM_FAIL; 115+ 116+ if (res == TPM_SUCCESS) 117+ res = VTPM_GetParentQuote(&hres, sel, sigSize, sig); 118+ 119+ free_TPM_PUBKEY(pubKey); 120+ return res; 121+} 122diff --git a/tpm/tpm_data.c b/tpm/tpm_data.c 123index 50c9697..6a0c499 100644 124--- a/tpm/tpm_data.c 125+++ b/tpm/tpm_data.c 126@@ -76,6 +76,8 @@ static void init_timeouts(void) 127 tpmData.permanent.data.cmd_durations[2] = 1000; 128 } 129 130+extern int endorsementKeyFresh; 131+ 132 void tpm_init_data(void) 133 { 134 /* endorsement key */ 135@@ -157,6 +159,7 @@ void tpm_init_data(void) 136 if (tpmConf & TPM_CONF_GENERATE_EK) { 137 /* generate a new endorsement key */ 138 tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048); 139+ endorsementKeyFresh = 1; 140 } else { 141 /* setup endorsement key */ 142 tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey, 143diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h 144index f746c05..b0f4625 100644 145--- a/tpm/tpm_structures.h 146+++ b/tpm/tpm_structures.h 147@@ -658,6 +658,49 @@ typedef struct tdTPM_CMK_MA_APPROVAL { 148 #define TPM_ORD_TickStampBlob 242 149 #define TPM_ORD_MAX 256 150 151+/* VTPM-only commands: */ 152+/* 153+ * ParentSignEK - Proof of fresh provisioning and EK value 154+ * 155+ * Input: 156+ * TPM_TAG tag TPM_TAG_RQU_AUTH1_COMMAND 157+ * UINT32 paramSize Total size of request 158+ * TPM_COMMAND_CODE ordinal TPM_ORD_ParentSignEK 159+ * TPM_NONCE externData 20 bytes of external data 160+ * TPM_PCR_SELECTION ptSel PCR selection for physical TPM 161+ * --- 162+ * UINT32 authHandle Owner authorization session (OIAP) 163+ * TPM_NONCE nonceOdd Nonce for authHandle 164+ * BOOL continueAuth Continue flag for authHandle 165+ * TPM_AUTHDATA privAuth Authorization digest for command 166+ * 167+ * Output: 168+ * TPM_TAG tag TPM_TAG_RSP_AUTH1_COMMAND 169+ * UINT32 paramSize Total size of response 170+ * TPM_RESULT returnCode Return code of the operation 171+ * BYTE[] sig Signature provided by physical TPM 172+ * TPM_PCRVALUE[] pcrValue Values of hardware PCRs used in the quote 173+ * --- 174+ * TPM_NONCE nonceEven Nonce for authHandle 175+ * BOOL continueAuth Continue flag for authHandle 176+ * TPM_AUTHDATA resAuth Authorization digest for response 177+ * 178+ * This command is only valid on the first boot of a vTPM; on any subsequent 179+ * boot, the command returns TPM_DISABLED_CMD. It is intended to be used to 180+ * provide evidence of proper platform configuration to the verifier/CA which is 181+ * responsible for the creation of the vTPM's endorsement credential, which will 182+ * be used on subsequent boots to certify AIKs via the usual Privacy CA protocol. 183+ * 184+ * The values of the virtual TPM's PCRs are not included in the response. 185+ * The signature is a standard TPM_Quote response from the physical TPM; its 186+ * externalData is the SHA1 hash of the following structure: 187+ * TPM_PUBKEY pubEK The vTPM's public EK 188+ * TPM_NONCE externData From input to the deep quote 189+ * 190+ * This structure was chosen to match the return of TPM_ReadPubek 191+ */ 192+#define TPM_ORD_ParentSignEK (TPM_VENDOR_COMMAND | TPM_ORD_ReadPubek) 193+ 194 /* 195 * TCS Ordinals ([TPM_Part2], Section 17.1) 196 * 197