[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 6/7] vtpm: add ordinal for obtaining an EK signature
For a vTPM to be useful for remote attestation, proof that the vTPM's EK was generated and held within a secure vTPM implementation is necessary. This patch adds an ordinal to the vTPM which will request a quote providing this evidence from the TPM Manager; it only functions during the first startup of a given vTPM in order to provide proof that the EK was freshly generated (and not a key whose private part is available elsewhere). Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> --- stubdom/Makefile | 1 + stubdom/vtpm-parent-sign-ek.patch | 196 ++++++++++++++++++++++++++++++++++++++ stubdom/vtpm/vtpm_cmd.c | 45 +++++++++ 3 files changed, 242 insertions(+) create mode 100644 stubdom/vtpm-parent-sign-ek.patch diff --git a/stubdom/Makefile b/stubdom/Makefile index b1822b7..3e5f054 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -208,6 +208,7 @@ tpm_emulator-$(XEN_TARGET_ARCH): tpm_emulator-$(TPMEMU_VERSION).tar.gz patch -d $@ -p1 < tpmemu-$(TPMEMU_VERSION).patch; patch -d $@ -p1 < vtpm-bufsize.patch patch -d $@ -p1 < vtpm-locality.patch + patch -d $@ -p1 < vtpm-parent-sign-ek.patch mkdir $@/build cd $@/build; CC=${CC} $(CMAKE) .. -DCMAKE_C_FLAGS:STRING="-std=c99 -DTPM_NO_EXTERN $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Wno-declaration-after-statement" touch $@ diff --git a/stubdom/vtpm-parent-sign-ek.patch b/stubdom/vtpm-parent-sign-ek.patch new file mode 100644 index 0000000..14e66ee --- /dev/null +++ b/stubdom/vtpm-parent-sign-ek.patch @@ -0,0 +1,196 @@ +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c +index 9e1cfb4..0fabf98 100644 +--- a/tpm/tpm_cmd_handler.c ++++ b/tpm/tpm_cmd_handler.c +@@ -3312,6 +3312,37 @@ static TPM_RESULT execute_TPM_OwnerReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp + return res; + } + ++static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp) ++{ ++ TPM_NONCE nonce; ++ TPM_RESULT res; ++ UINT32 sigSize; ++ BYTE *sig; ++ BYTE *ptr; ++ UINT32 len; ++ TPM_PCR_SELECTION targetPCR; ++ ++ tpm_compute_in_param_digest(req); ++ ++ ptr = req->param; ++ len = req->paramSize; ++ if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce) ++ || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR) ++ || len != 0) return TPM_BAD_PARAMETER; ++ ++ res = TPM_ParentSignEK(&nonce, &targetPCR, &req->auth1, &sigSize, &sig); ++ if (res != TPM_SUCCESS) return res; ++ rsp->paramSize = len = sigSize; ++ rsp->param = ptr = tpm_malloc(len); ++ if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) { ++ tpm_free(rsp->param); ++ res = TPM_FAIL; ++ } ++ tpm_free(sig); ++ ++ return res; ++} ++ + static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp) + { + tpm_hmac_ctx_t hmac; +@@ -4062,6 +4093,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp) + res = execute_TPM_OwnerReadPubek(req, rsp); + break; + ++ case TPM_ORD_ParentSignEK: ++ debug("[TPM_ORD_ParentSignEK]"); ++ res = execute_TPM_ParentSignEK(req, rsp); ++ break; ++ + default: + #ifdef MTM_EMULATOR + res = mtm_execute_command(req, rsp); +diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h +index a7666f6..7fef934 100644 +--- a/tpm/tpm_commands.h ++++ b/tpm/tpm_commands.h +@@ -3054,6 +3054,23 @@ TPM_RESULT TPM_OwnerReadPubek( + TPM_PUBKEY *pubEndorsementKey + ); + ++/** ++ * TPM_ParentSignEK - gets a hardware TPM quote of a vTPM's EK ++ * @externalData: [in] AntiReplay nonce to prevent replay of messages ++ * @sel: [in] PCR selection for the hardware TPM's quote ++ * @auth1: [in, out] Authorization protocol parameters ++ * @sigSize: [out] The length of the returned digital signature ++ * @sig: [out] The resulting digital signature and PCR values ++ * Returns: TPM_SUCCESS on success, a TPM error code otherwise. ++ */ ++TPM_RESULT TPM_ParentSignEK( ++ TPM_NONCE *externalData, ++ TPM_PCR_SELECTION *sel, ++ TPM_AUTH *auth1, ++ UINT32 *sigSize, ++ BYTE **sig ++); ++ + /* + * Error handling + * [tpm_error.c] +diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c +index 9cd64af..01f29e6 100644 +--- a/tpm/tpm_credentials.c ++++ b/tpm/tpm_credentials.c +@@ -180,3 +180,34 @@ TPM_RESULT TPM_OwnerReadInternalPub(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1, + return TPM_BAD_PARAMETER; + } + } ++ ++int endorsementKeyFresh = 0; ++ ++TPM_RESULT VTPM_GetParentQuote(TPM_DIGEST* data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig); ++ ++TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel, ++ TPM_AUTH *auth1, UINT32 *sigSize, BYTE **sig) ++{ ++ TPM_PUBKEY pubKey; ++ TPM_RESULT res; ++ TPM_DIGEST hres; ++ ++ info("TPM_ParentSignEK()"); ++ ++ res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER); ++ if (res != TPM_SUCCESS) return res; ++ ++ if (!endorsementKeyFresh) return TPM_DISABLED_CMD; ++ ++ res = tpm_get_pubek(&pubKey); ++ if (res != TPM_SUCCESS) return res; ++ ++ if (tpm_compute_pubkey_checksum(externalData, &pubKey, &hres)) ++ res = TPM_FAIL; ++ ++ if (res == TPM_SUCCESS) ++ res = VTPM_GetParentQuote(&hres, sel, sigSize, sig); ++ ++ free_TPM_PUBKEY(pubKey); ++ return res; ++} +diff --git a/tpm/tpm_data.c b/tpm/tpm_data.c +index 50c9697..6a0c499 100644 +--- a/tpm/tpm_data.c ++++ b/tpm/tpm_data.c +@@ -76,6 +76,8 @@ static void init_timeouts(void) + tpmData.permanent.data.cmd_durations[2] = 1000; + } + ++extern int endorsementKeyFresh; ++ + void tpm_init_data(void) + { + /* endorsement key */ +@@ -157,6 +159,7 @@ void tpm_init_data(void) + if (tpmConf & TPM_CONF_GENERATE_EK) { + /* generate a new endorsement key */ + tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048); ++ endorsementKeyFresh = 1; + } else { + /* setup endorsement key */ + tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey, +diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h +index f746c05..b0f4625 100644 +--- a/tpm/tpm_structures.h ++++ b/tpm/tpm_structures.h +@@ -658,6 +658,49 @@ typedef struct tdTPM_CMK_MA_APPROVAL { + #define TPM_ORD_TickStampBlob 242 + #define TPM_ORD_MAX 256 + ++/* VTPM-only commands: */ ++/* ++ * ParentSignEK - Proof of fresh provisioning and EK value ++ * ++ * Input: ++ * TPM_TAG tag TPM_TAG_RQU_AUTH1_COMMAND ++ * UINT32 paramSize Total size of request ++ * TPM_COMMAND_CODE ordinal TPM_ORD_ParentSignEK ++ * TPM_NONCE externData 20 bytes of external data ++ * TPM_PCR_SELECTION ptSel PCR selection for physical TPM ++ * --- ++ * UINT32 authHandle Owner authorization session (OIAP) ++ * TPM_NONCE nonceOdd Nonce for authHandle ++ * BOOL continueAuth Continue flag for authHandle ++ * TPM_AUTHDATA privAuth Authorization digest for command ++ * ++ * Output: ++ * TPM_TAG tag TPM_TAG_RSP_AUTH1_COMMAND ++ * UINT32 paramSize Total size of response ++ * TPM_RESULT returnCode Return code of the operation ++ * BYTE[] sig Signature provided by physical TPM ++ * TPM_PCRVALUE[] pcrValue Values of hardware PCRs used in the quote ++ * --- ++ * TPM_NONCE nonceEven Nonce for authHandle ++ * BOOL continueAuth Continue flag for authHandle ++ * TPM_AUTHDATA resAuth Authorization digest for response ++ * ++ * This command is only valid on the first boot of a vTPM; on any subsequent ++ * boot, the command returns TPM_DISABLED_CMD. It is intended to be used to ++ * provide evidence of proper platform configuration to the verifier/CA which is ++ * responsible for the creation of the vTPM's endorsement credential, which will ++ * be used on subsequent boots to certify AIKs via the usual Privacy CA protocol. ++ * ++ * The values of the virtual TPM's PCRs are not included in the response. ++ * The signature is a standard TPM_Quote response from the physical TPM; its ++ * externalData is the SHA1 hash of the following structure: ++ * TPM_PUBKEY pubEK The vTPM's public EK ++ * TPM_NONCE externData From input to the deep quote ++ * ++ * This structure was chosen to match the return of TPM_ReadPubek ++ */ ++#define TPM_ORD_ParentSignEK (TPM_VENDOR_COMMAND | TPM_ORD_ReadPubek) ++ + /* + * TCS Ordinals ([TPM_Part2], Section 17.1) + * diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c index 7eae98b..6fda456 100644 --- a/stubdom/vtpm/vtpm_cmd.c +++ b/stubdom/vtpm/vtpm_cmd.c @@ -217,6 +217,51 @@ egress: return status; } +extern struct tpmfront_dev* tpmfront_dev; +TPM_RESULT VTPM_GetParentQuote(TPM_NONCE *data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig) +{ + TPM_RESULT status = TPM_SUCCESS; + uint8_t* bptr, *resp; + uint8_t* cmdbuf = NULL; + size_t resplen = 0; + UINT32 len; + + TPM_TAG tag = VTPM_TAG_REQ; + UINT32 size; + TPM_COMMAND_CODE ord = VTPM_ORD_GET_QUOTE; + + /*Create the command*/ + len = size = VTPM_COMMAND_HEADER_SIZE + 25; + bptr = cmdbuf = malloc(size); + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord)); + TRYFAILGOTO(tpm_marshal_TPM_NONCE(&bptr, &len, data)); + TRYFAILGOTO(tpm_marshal_TPM_PCR_SELECTION(&bptr, &len, sel)); + + /* Send the command to vtpm_manager */ + info("Requesting Quote from backend"); + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT); + + /* Unpack response header */ + bptr = resp; + len = resplen; + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED); + + /* Check return code */ + CHECKSTATUSGOTO(ord, "VTPM_GetParentQuote()"); + + /* Copy out the value */ + *sigSize = len; + *sig = tpm_malloc(*sigSize); + TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, *sig, *sigSize), ERR_MALFORMED); + + goto egress; +abort_egress: + error("VTPM_GetParentQuote failed"); +egress: + free(cmdbuf); + return status; +} + TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest) { TPM_RESULT status = TPM_SUCCESS; -- 1.8.5.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |