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) *