1diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c 2index 0fabf98..69511d1 100644 3--- a/tpm/tpm_cmd_handler.c 4+++ b/tpm/tpm_cmd_handler.c 5@@ -3343,6 +3343,39 @@ static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp) 6 return res; 7 } 8 9+static TPM_RESULT execute_TPM_DeepQuote(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 myPCR; 18+ TPM_PCR_SELECTION ptPCR; 19+ 20+ tpm_compute_in_param_digest(req); 21+ 22+ ptr = req->param; 23+ len = req->paramSize; 24+ if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce) 25+ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &myPCR) 26+ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &ptPCR) 27+ || len != 0) return TPM_BAD_PARAMETER; 28+ 29+ res = TPM_DeepQuote(&nonce, &myPCR, &ptPCR, &req->auth1, &sigSize, &sig); 30+ if (res != TPM_SUCCESS) return res; 31+ rsp->paramSize = len = sigSize; 32+ rsp->param = ptr = tpm_malloc(len); 33+ if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) { 34+ tpm_free(rsp->param); 35+ res = TPM_FAIL; 36+ } 37+ tpm_free(sig); 38+ 39+ return res; 40+} 41+ 42 static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp) 43 { 44 tpm_hmac_ctx_t hmac; 45@@ -4098,6 +4131,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp) 46 res = execute_TPM_ParentSignEK(req, rsp); 47 break; 48 49+ case TPM_ORD_DeepQuote: 50+ debug("[TPM_ORD_DeepQuote]"); 51+ res = execute_TPM_DeepQuote(req, rsp); 52+ break; 53+ 54 default: 55 #ifdef MTM_EMULATOR 56 res = mtm_execute_command(req, rsp); 57diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h 58index 7fef934..328d1be 100644 59--- a/tpm/tpm_commands.h 60+++ b/tpm/tpm_commands.h 61@@ -3071,6 +3071,25 @@ TPM_RESULT TPM_ParentSignEK( 62 BYTE **sig 63 ); 64 65+/** 66+ * TPM_DeepQuote - gets a hardware TPM quote of a vTPM's PCRs 67+ * @externalData: [in] AntiReplay nonce to prevent replay of messages 68+ * @myPCR: [in] PCR selection for the virtual TPM 69+ * @ptPCR: [in] PCR selection for the hardware TPM 70+ * @auth1: [in, out] Authorization protocol parameters 71+ * @sigSize: [out] The length of the returned digital signature 72+ * @sig: [out] The resulting digital signature and PCR values 73+ * Returns: TPM_SUCCESS on success, a TPM error code otherwise. 74+ */ 75+TPM_RESULT TPM_DeepQuote( 76+ TPM_NONCE *externalData, 77+ TPM_PCR_SELECTION *myPCR, 78+ TPM_PCR_SELECTION *ptPCR, 79+ TPM_AUTH *auth1, 80+ UINT32 *sigSize, 81+ BYTE **sig 82+); 83+ 84 /* 85 * Error handling 86 * [tpm_error.c] 87diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c 88index 01f29e6..c0d62e7 100644 89--- a/tpm/tpm_credentials.c 90+++ b/tpm/tpm_credentials.c 91@@ -211,3 +211,49 @@ TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel, 92 free_TPM_PUBKEY(pubKey); 93 return res; 94 } 95+ 96+static const BYTE dquot_hdr[] = { 97+ 0, 0, 0, 0, 'D', 'Q', 'U', 'T' 98+}; 99+ 100+TPM_RESULT TPM_DeepQuote(TPM_NONCE *externalData, TPM_PCR_SELECTION *myPCR, 101+ TPM_PCR_SELECTION *ptPCR, TPM_AUTH *auth1, 102+ UINT32 *sigSize, BYTE **sig) 103+{ 104+ TPM_RESULT res; 105+ TPM_DIGEST hres; 106+ TPM_PCR_INFO_SHORT pcrData; 107+ tpm_sha1_ctx_t ctx; 108+ BYTE *buf, *ptr; 109+ UINT32 size, len; 110+ 111+ info("TPM_DeepQuote()"); 112+ 113+ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); 114+ if (res != TPM_SUCCESS) return res; 115+ 116+ res = tpm_compute_pcr_digest(myPCR, &pcrData.digestAtRelease, NULL); 117+ if (res != TPM_SUCCESS) return res; 118+ 119+ pcrData.pcrSelection.sizeOfSelect = myPCR->sizeOfSelect; 120+ memcpy(pcrData.pcrSelection.pcrSelect, myPCR->pcrSelect, myPCR->sizeOfSelect); 121+ pcrData.localityAtRelease = 1 << tpmData.stany.flags.localityModifier; 122+ 123+ size = len = sizeof_TPM_PCR_INFO_SHORT(pcrData); 124+ buf = ptr = tpm_malloc(size); 125+ if (buf == NULL) return TPM_NOSPACE; 126+ if (tpm_marshal_TPM_PCR_INFO_SHORT(&ptr, &len, &pcrData)) 127+ return TPM_FAIL; 128+ 129+ tpm_sha1_init(&ctx); 130+ tpm_sha1_update(&ctx, dquot_hdr, 8); 131+ tpm_sha1_update(&ctx, externalData->nonce, 20); 132+ tpm_sha1_update(&ctx, buf, size); 133+ tpm_sha1_final(&ctx, hres.digest); 134+ 135+ tpm_free(buf); 136+ 137+ res = VTPM_GetParentQuote(&hres, ptPCR, sigSize, sig); 138+ 139+ return res; 140+} 141diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h 142index b0f4625..dfb1894 100644 143--- a/tpm/tpm_structures.h 144+++ b/tpm/tpm_structures.h 145@@ -660,6 +660,42 @@ typedef struct tdTPM_CMK_MA_APPROVAL { 146 147 /* VTPM-only commands: */ 148 /* 149+ * Deep Quote - Create quote of PCRs 150+ * Input: 151+ * TPM_TAG tag TPM_TAG_RQU_AUTH1_COMMAND 152+ * UINT32 paramSize Total size of request 153+ * TPM_COMMAND_CODE ordinal TPM_ORD_DeepQuote 154+ * TPM_NONCE externData 20 bytes of external data 155+ * TPM_PCR_SELECTION vtSel PCR selection for virtual TPM 156+ * TPM_PCR_SELECTION ptSel PCR selection for physical TPM 157+ * --- 158+ * UINT32 authHandle Owner authorization session (OIAP) 159+ * TPM_NONCE nonceOdd Nonce for authHandle 160+ * BOOL continueAuth Continue flag for authHandle 161+ * TPM_AUTHDATA privAuth Authorization digest for command 162+ * 163+ * Output: 164+ * TPM_TAG tag TPM_TAG_RSP_AUTH1_COMMAND 165+ * UINT32 paramSize Total size of response 166+ * TPM_RESULT returnCode Return code of the operation 167+ * BYTE[] sig Signature provided by physical TPM 168+ * TPM_PCRVALUE[] pcrValue Values of hardware PCRs used in the quote 169+ * --- 170+ * TPM_NONCE nonceEven Nonce for authHandle 171+ * BOOL continueAuth Continue flag for authHandle 172+ * TPM_AUTHDATA resAuth Authorization digest for response 173+ * 174+ * The values of the virutal TPM's PCRs are not included in the response. 175+ * The signature is a standard TPM_Quote response from the physical TPM; its 176+ * externalData is the SHA1 hash of the following structure: 177+ * TPM_STRUCT_VER version MUST be 0.0.0.0 178+ * BYTE[4] fixed MUST be the string "DQUT" 179+ * TPM_NONCE externData From input to the deep quote 180+ * TPM_PCR_INFO_SHORT pcrData Virtual TPM's PCRs 181+ */ 182+#define TPM_ORD_DeepQuote (TPM_VENDOR_COMMAND | TPM_ORD_Quote) 183+ 184+/* 185 * ParentSignEK - Proof of fresh provisioning and EK value 186 * 187 * Input: 188