/** @file | |
Implement TPM2 NVStorage related command. | |
Copyright (c) 2013 - 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) | |
#define RC_NV_ReadPublic_nvIndex (TPM_RC_H + TPM_RC_1) | |
#define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1) | |
#define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1) | |
#define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2) | |
#define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1) | |
#define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2) | |
#define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1) | |
#define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2) | |
#define RC_NV_Read_size (TPM_RC_P + TPM_RC_1) | |
#define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2) | |
#define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1) | |
#define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2) | |
#define RC_NV_Write_data (TPM_RC_P + TPM_RC_1) | |
#define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2) | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_NV_INDEX NvIndex; | |
} TPM2_NV_READPUBLIC_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
TPM2B_NV_PUBLIC NvPublic; | |
TPM2B_NAME NvName; | |
} TPM2_NV_READPUBLIC_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_PROVISION AuthHandle; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
TPM2B_AUTH Auth; | |
TPM2B_NV_PUBLIC NvPublic; | |
} TPM2_NV_DEFINESPACE_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_DEFINESPACE_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_PROVISION AuthHandle; | |
TPMI_RH_NV_INDEX NvIndex; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
} TPM2_NV_UNDEFINESPACE_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_UNDEFINESPACE_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_NV_AUTH AuthHandle; | |
TPMI_RH_NV_INDEX NvIndex; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
UINT16 Size; | |
UINT16 Offset; | |
} TPM2_NV_READ_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPM2B_MAX_BUFFER Data; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_READ_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_NV_AUTH AuthHandle; | |
TPMI_RH_NV_INDEX NvIndex; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
TPM2B_MAX_BUFFER Data; | |
UINT16 Offset; | |
} TPM2_NV_WRITE_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_WRITE_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_NV_AUTH AuthHandle; | |
TPMI_RH_NV_INDEX NvIndex; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
} TPM2_NV_READLOCK_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_READLOCK_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_NV_AUTH AuthHandle; | |
TPMI_RH_NV_INDEX NvIndex; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
} TPM2_NV_WRITELOCK_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_WRITELOCK_RESPONSE; | |
typedef struct { | |
TPM2_COMMAND_HEADER Header; | |
TPMI_RH_PROVISION AuthHandle; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_COMMAND AuthSession; | |
} TPM2_NV_GLOBALWRITELOCK_COMMAND; | |
typedef struct { | |
TPM2_RESPONSE_HEADER Header; | |
UINT32 AuthSessionSize; | |
TPMS_AUTH_RESPONSE AuthSession; | |
} TPM2_NV_GLOBALWRITELOCK_RESPONSE; | |
#pragma pack() | |
/** | |
This command is used to read the public area and Name of an NV Index. | |
@param[in] NvIndex The NV Index. | |
@param[out] NvPublic The public area of the index. | |
@param[out] NvName The Name of the nvIndex. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvReadPublic ( | |
IN TPMI_RH_NV_INDEX NvIndex, | |
OUT TPM2B_NV_PUBLIC *NvPublic, | |
OUT TPM2B_NAME *NvName | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_READPUBLIC_COMMAND SendBuffer; | |
TPM2_NV_READPUBLIC_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT16 NvPublicSize; | |
UINT16 NvNameSize; | |
UINT8 *Buffer; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
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, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
return EFI_DEVICE_ERROR; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED: | |
return EFI_NOT_FOUND; | |
case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex: | |
return EFI_INVALID_PARAMETER; | |
default: | |
return EFI_DEVICE_ERROR; | |
} | |
if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Basic check | |
// | |
NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size); | |
NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize))); | |
if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x, NvNameSize %x\n", RecvBufferSize, NvNameSize)); | |
return EFI_NOT_FOUND; | |
} | |
// | |
// Return the response | |
// | |
CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize); | |
NvPublic->size = NvPublicSize; | |
NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex); | |
NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg); | |
WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); | |
NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size); | |
Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy; | |
Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size; | |
NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); | |
CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize); | |
NvName->size = NvNameSize; | |
return EFI_SUCCESS; | |
} | |
/** | |
This command defines the attributes of an NV Index and causes the TPM to | |
reserve space to hold the data associated with the index. | |
If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED. | |
@param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. | |
@param[in] AuthSession Auth Session context | |
@param[in] Auth The authorization data. | |
@param[in] NvPublic The public area of the index. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvDefineSpace ( | |
IN TPMI_RH_PROVISION AuthHandle, | |
IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL | |
IN TPM2B_AUTH *Auth, | |
IN TPM2B_NV_PUBLIC *NvPublic | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_DEFINESPACE_COMMAND SendBuffer; | |
TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT16 NvPublicSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
// | |
// IndexAuth | |
// | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size)); | |
Buffer += sizeof(UINT16); | |
CopyMem(Buffer, Auth->buffer, Auth->size); | |
Buffer += Auth->size; | |
// | |
// NvPublic | |
// | |
NvPublicSize = NvPublic->size; | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize)); | |
Buffer += sizeof(UINT16); | |
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex)); | |
Buffer += sizeof(UINT32); | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg)); | |
Buffer += sizeof(UINT16); | |
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); | |
Buffer += sizeof(UINT32); | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size); | |
Buffer += NvPublic->nvPublic.authPolicy.size; | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize)); | |
Buffer += sizeof(UINT16); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo: | |
case TPM_RC_SIZE + RC_NV_DefineSpace_auth: | |
Status = EFI_BAD_BUFFER_SIZE; | |
break; | |
case TPM_RC_ATTRIBUTES: | |
case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo: | |
Status = EFI_UNSUPPORTED; | |
break; | |
case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_NV_DEFINED: | |
Status = EFI_ALREADY_STARTED; | |
break; | |
case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo: | |
case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_NV_SPACE: | |
Status = EFI_OUT_OF_RESOURCES; | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command removes an index from the TPM. | |
@param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. | |
@param[in] NvIndex The NV Index. | |
@param[in] AuthSession Auth Session context | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvUndefineSpace ( | |
IN TPMI_RH_PROVISION AuthHandle, | |
IN TPMI_RH_NV_INDEX NvIndex, | |
IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_UNDEFINESPACE_COMMAND SendBuffer; | |
TPM2_NV_UNDEFINESPACE_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_UndefineSpace); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
case TPM_RC_ATTRIBUTES: | |
case TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex: | |
Status = EFI_UNSUPPORTED; | |
break; | |
case TPM_RC_NV_AUTHORIZATION: | |
Status = EFI_SECURITY_VIOLATION; | |
break; | |
case TPM_RC_HANDLE + RC_NV_UndefineSpace_nvIndex: // TPM_RC_NV_DEFINED: | |
Status = EFI_NOT_FOUND; | |
break; | |
case TPM_RC_HANDLE + RC_NV_UndefineSpace_authHandle: // TPM_RC_NV_DEFINED: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_VALUE + RC_NV_UndefineSpace_authHandle: | |
case TPM_RC_VALUE + RC_NV_UndefineSpace_nvIndex: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). | |
@param[in] AuthHandle the handle indicating the source of the authorization value. | |
@param[in] NvIndex The index to be read. | |
@param[in] AuthSession Auth Session context | |
@param[in] Size Number of bytes to read. | |
@param[in] Offset Byte offset into the area. | |
@param[in,out] OutData The data read. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvRead ( | |
IN TPMI_RH_NV_AUTH AuthHandle, | |
IN TPMI_RH_NV_INDEX NvIndex, | |
IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL | |
IN UINT16 Size, | |
IN UINT16 Offset, | |
IN OUT TPM2B_MAX_BUFFER *OutData | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_READ_COMMAND SendBuffer; | |
TPM2_NV_READ_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Read); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Size)); | |
Buffer += sizeof(UINT16); | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset)); | |
Buffer += sizeof(UINT16); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode)); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
case TPM_RC_NV_AUTHORIZATION: | |
Status = EFI_SECURITY_VIOLATION; | |
break; | |
case TPM_RC_NV_LOCKED: | |
Status = EFI_ACCESS_DENIED; | |
break; | |
case TPM_RC_NV_RANGE: | |
Status = EFI_BAD_BUFFER_SIZE; | |
break; | |
case TPM_RC_NV_UNINITIALIZED: | |
Status = EFI_NOT_READY; | |
break; | |
case TPM_RC_HANDLE + RC_NV_Read_nvIndex: // TPM_RC_NV_DEFINED: | |
Status = EFI_NOT_FOUND; | |
break; | |
case TPM_RC_HANDLE + RC_NV_Read_authHandle: // TPM_RC_NV_DEFINED: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_VALUE + RC_NV_Read_nvIndex: | |
case TPM_RC_VALUE + RC_NV_Read_authHandle: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_BAD_AUTH + RC_NV_Read_authHandle + TPM_RC_S: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_AUTH_UNAVAILABLE: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_AUTH_FAIL + RC_NV_Read_authHandle + TPM_RC_S: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_ATTRIBUTES + RC_NV_Read_authHandle + TPM_RC_S: | |
Status = EFI_UNSUPPORTED; | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
if (Status != EFI_SUCCESS) { | |
goto Done; | |
} | |
// | |
// Return the response | |
// | |
OutData->size = SwapBytes16 (RecvBuffer.Data.size); | |
CopyMem (OutData->buffer, &RecvBuffer.Data.buffer, OutData->size); | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace(). | |
@param[in] AuthHandle the handle indicating the source of the authorization value. | |
@param[in] NvIndex The NV Index of the area to write. | |
@param[in] AuthSession Auth Session context | |
@param[in] InData The data to write. | |
@param[in] Offset The offset into the NV Area. | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvWrite ( | |
IN TPMI_RH_NV_AUTH AuthHandle, | |
IN TPMI_RH_NV_INDEX NvIndex, | |
IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL | |
IN TPM2B_MAX_BUFFER *InData, | |
IN UINT16 Offset | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_WRITE_COMMAND SendBuffer; | |
TPM2_NV_WRITE_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Write); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size)); | |
Buffer += sizeof(UINT16); | |
CopyMem (Buffer, InData->buffer, InData->size); | |
Buffer += InData->size; | |
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset)); | |
Buffer += sizeof(UINT16); | |
SendBufferSize = (UINT32) (Buffer - (UINT8 *)&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, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode)); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
case TPM_RC_ATTRIBUTES: | |
Status = EFI_UNSUPPORTED; | |
break; | |
case TPM_RC_NV_AUTHORIZATION: | |
Status = EFI_SECURITY_VIOLATION; | |
break; | |
case TPM_RC_NV_LOCKED: | |
Status = EFI_ACCESS_DENIED; | |
break; | |
case TPM_RC_NV_RANGE: | |
Status = EFI_BAD_BUFFER_SIZE; | |
break; | |
case TPM_RC_HANDLE + RC_NV_Write_nvIndex: // TPM_RC_NV_DEFINED: | |
Status = EFI_NOT_FOUND; | |
break; | |
case TPM_RC_HANDLE + RC_NV_Write_authHandle: // TPM_RC_NV_DEFINED: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_VALUE + RC_NV_Write_nvIndex: | |
case TPM_RC_VALUE + RC_NV_Write_authHandle: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_BAD_AUTH + RC_NV_Write_authHandle + TPM_RC_S: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_AUTH_UNAVAILABLE: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_AUTH_FAIL + RC_NV_Write_authHandle + TPM_RC_S: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
case TPM_RC_ATTRIBUTES + RC_NV_Write_authHandle + TPM_RC_S: | |
Status = EFI_UNSUPPORTED; | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR). | |
@param[in] AuthHandle the handle indicating the source of the authorization value. | |
@param[in] NvIndex The NV Index of the area to lock. | |
@param[in] AuthSession Auth Session context | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvReadLock ( | |
IN TPMI_RH_NV_AUTH AuthHandle, | |
IN TPMI_RH_NV_INDEX NvIndex, | |
IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_READLOCK_COMMAND SendBuffer; | |
TPM2_NV_READLOCK_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadLock); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
This command may be used to inhibit further writes of the Index. | |
@param[in] AuthHandle the handle indicating the source of the authorization value. | |
@param[in] NvIndex The NV Index of the area to lock. | |
@param[in] AuthSession Auth Session context | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvWriteLock ( | |
IN TPMI_RH_NV_AUTH AuthHandle, | |
IN TPMI_RH_NV_INDEX NvIndex, | |
IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_WRITELOCK_COMMAND SendBuffer; | |
TPM2_NV_WRITELOCK_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_WriteLock); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
SendBuffer.NvIndex = SwapBytes32 (NvIndex); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} | |
/** | |
The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET. | |
@param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. | |
@param[in] AuthSession Auth Session context | |
@retval EFI_SUCCESS Operation completed successfully. | |
@retval EFI_DEVICE_ERROR The command was unsuccessful. | |
@retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Tpm2NvGlobalWriteLock ( | |
IN TPMI_RH_PROVISION AuthHandle, | |
IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL | |
) | |
{ | |
EFI_STATUS Status; | |
TPM2_NV_GLOBALWRITELOCK_COMMAND SendBuffer; | |
TPM2_NV_GLOBALWRITELOCK_RESPONSE RecvBuffer; | |
UINT32 SendBufferSize; | |
UINT32 RecvBufferSize; | |
UINT8 *Buffer; | |
UINT32 SessionInfoSize; | |
TPM_RC ResponseCode; | |
// | |
// Construct command | |
// | |
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); | |
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_GlobalWriteLock); | |
SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); | |
// | |
// Add in Auth session | |
// | |
Buffer = (UINT8 *)&SendBuffer.AuthSession; | |
// sessionInfoSize | |
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); | |
Buffer += SessionInfoSize; | |
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); | |
SendBufferSize = (UINT32)(Buffer - (UINT8 *)&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, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); | |
Status = EFI_DEVICE_ERROR; | |
goto Done; | |
} | |
ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); | |
if (ResponseCode != TPM_RC_SUCCESS) { | |
DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); | |
} | |
switch (ResponseCode) { | |
case TPM_RC_SUCCESS: | |
// return data | |
break; | |
default: | |
Status = EFI_DEVICE_ERROR; | |
break; | |
} | |
Done: | |
// | |
// Clear AuthSession Content | |
// | |
ZeroMem (&SendBuffer, sizeof(SendBuffer)); | |
ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); | |
return Status; | |
} |