/** @file | |
Implement TPM2 EnhancedAuthorization related command. | |
Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved. <BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include <IndustryStandard/UefiTcgPlatform.h> | |
#include <Library/Tpm2CommandLib.h> | |
#include <Library/Tpm2DeviceLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#pragma pack(1) | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_DH_ENTITY AuthHandle; | |
TPMI_SH_POLICY PolicySession; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
TPM2B_NONCE NonceTPM; | |
TPM2B_DIGEST CpHashA; | |
TPM2B_NONCE PolicyRef; | |
INT32 Expiration; | |
} TPM2_POLICY_SECRET_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPM2B_TIMEOUT Timeout; | |
TPMT_TK_AUTH PolicyTicket; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_POLICY_SECRET_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_SH_POLICY PolicySession; | |
TPML_DIGEST HashList; | |
} TPM2_POLICY_OR_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
} TPM2_POLICY_OR_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_SH_POLICY PolicySession; | |
TPM_CC Code; | |
} TPM2_POLICY_COMMAND_CODE_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
} TPM2_POLICY_COMMAND_CODE_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_SH_POLICY PolicySession; | |
} TPM2_POLICY_GET_DIGEST_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
TPM2B_DIGEST PolicyHash; | |
} TPM2_POLICY_GET_DIGEST_RESPONSE; | |
#pragma pack() | |
/** | |
This command includes a secret-based authorization to a policy. | |
The caller proves knowledge of the secret value using an authorization | |
session using the authValue associated with authHandle. | |
@param[in] AuthHandle Handle for an entity providing the authorization | |
@param[in] PolicySession Handle for the policy session being extended. | |
@param[in] AuthSession Auth Session context | |
@param[in] NonceTPM The policy nonce for the session. | |
@param[in] CpHashA Digest of the command parameters to which this authorization is limited. | |
@param[in] PolicyRef A reference to a policy relating to the authorization. | |
@param[in] Expiration Time when authorization will expire, measured in seconds from the time that nonceTPM was generated. | |
@param[out] Timeout Time value used to indicate to the TPM when the ticket expires. | |
@param[out] PolicyTicket A ticket that includes a value indicating when the authorization expires. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2PolicySecret ( | |
IN TPMI_DH_ENTITY AuthHandle, | |
IN TPMI_SH_POLICY PolicySession, | |
IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL | |
IN TPM2B_NONCE *NonceTPM, | |
IN TPM2B_DIGEST *CpHashA, | |
IN TPM2B_NONCE *PolicyRef, | |
IN INT32 Expiration, | |
OUT TPM2B_TIMEOUT *Timeout, | |
OUT TPMT_TK_AUTH *PolicyTicket | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_POLICY_SECRET_COMMAND SendBuffer; | |
TPM2_POLICY_SECRET_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.PolicySession = SwapBytes32 (PolicySession); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
// | |
// Real data | |
// | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size); | |
Buffer += NonceTPM->size; | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, CpHashA->buffer, CpHashA->size); | |
Buffer += CpHashA->size; | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size); | |
Buffer += PolicyRef->size; | |
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration)); | |
Buffer += sizeof(UINT32); | |
SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); | |
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); | |
// | |
// send Tpm command | |
// | |
RecvBufferSize = sizeof (RecvBuffer); | |
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); | |
if (EFI_ERROR (Status)) { | |
goto Done; | |
} | |
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
// | |
// Return the response | |
// | |
Buffer = (UINT8 *)&RecvBuffer.Timeout; | |
Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Timeout->buffer, Buffer, Timeout->size); | |
PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); | |
Buffer += sizeof(UINT16); | |
PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer)); | |
Buffer += sizeof(UINT32); | |
PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); | |
Buffer += sizeof(UINT16); | |
CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size); | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command allows options in authorizations without requiring that the TPM evaluate all of the options. | |
If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that | |
satisfies the policy. This command will indicate that one of the required sets of conditions has been | |
satisfied. | |
@param[in] PolicySession Handle for the policy session being extended. | |
@param[in] HashList the list of hashes to check for a match. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2PolicyOR ( | |
IN TPMI_SH_POLICY PolicySession, | |
IN TPML_DIGEST *HashList | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_POLICY_OR_COMMAND SendBuffer; | |
TPM2_POLICY_OR_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINTN Index; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR); | |
SendBuffer.PolicySession = SwapBytes32 (PolicySession); | |
Buffer = (UINT8 *)&SendBuffer.HashList; | |
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count)); | |
Buffer += sizeof(UINT32); | |
for (Index = 0; Index < HashList->count; Index++) { | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size); | |
Buffer += HashList->digests[Index].size; | |
} | |
SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); | |
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); | |
// | |
// send Tpm command | |
// | |
RecvBufferSize = sizeof (RecvBuffer); | |
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
return EFI_DEVICE_ERROR; | |
} | |
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
return EFI_DEVICE_ERROR; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
This command indicates that the authorization will be limited to a specific command code. | |
@param[in] PolicySession Handle for the policy session being extended. | |
@param[in] Code The allowed commandCode. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2PolicyCommandCode ( | |
IN TPMI_SH_POLICY PolicySession, | |
IN TPM_CC Code | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_POLICY_COMMAND_CODE_COMMAND SendBuffer; | |
TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode); | |
SendBuffer.PolicySession = SwapBytes32 (PolicySession); | |
SendBuffer.Code = SwapBytes32 (Code); | |
SendBufferSize = (UINT32) sizeof (SendBuffer); | |
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); | |
// | |
// send Tpm command | |
// | |
RecvBufferSize = sizeof (RecvBuffer); | |
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
return EFI_DEVICE_ERROR; | |
} | |
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
return EFI_DEVICE_ERROR; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
This command returns the current policyDigest of the session. This command allows the TPM | |
to be used to perform the actions required to precompute the authPolicy for an object. | |
@param[in] PolicySession Handle for the policy session. | |
@param[out] PolicyHash the current value of the policyHash of policySession. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2PolicyGetDigest ( | |
IN TPMI_SH_POLICY PolicySession, | |
OUT TPM2B_DIGEST *PolicyHash | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_POLICY_GET_DIGEST_COMMAND SendBuffer; | |
TPM2_POLICY_GET_DIGEST_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest); | |
SendBuffer.PolicySession = SwapBytes32 (PolicySession); | |
SendBufferSize = (UINT32) sizeof (SendBuffer); | |
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); | |
// | |
// send Tpm command | |
// | |
RecvBufferSize = sizeof (RecvBuffer); | |
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
return EFI_DEVICE_ERROR; | |
} | |
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
return EFI_DEVICE_ERROR; | |
} | |
// | |
// Return the response | |
// | |
PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size); | |
CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size); | |
return EFI_SUCCESS; | |
} |