audk/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c

1049 lines
34 KiB
C

/** @file
Implement TPM2 NVStorage related command.
Copyright (c) 2013 - 2018, 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);
if (NvPublicSize > sizeof(TPMS_NV_PUBLIC)) {
DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvPublic.size error %x\n", NvPublicSize));
return EFI_DEVICE_ERROR;
}
NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize)));
if (NvNameSize > sizeof(TPMU_NAME)){
DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvNameSize error %x\n", NvNameSize));
return EFI_DEVICE_ERROR;
}
if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) {
DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize));
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);
if (OutData->size > MAX_DIGEST_BUFFER) {
DEBUG ((DEBUG_ERROR, "Tpm2NvRead - OutData->size error %x\n", OutData->size));
Status = EFI_DEVICE_ERROR;
goto Done;
}
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;
}