/** @file Implement TPM1.2 NV storage related command. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include // // Max TPM NV value length // #define TPMNVVALUELENGTH 1024 #pragma pack(1) typedef struct { TPM_RQU_COMMAND_HDR Hdr; TPM12_NV_DATA_PUBLIC PubInfo; TPM_ENCAUTH EncAuth; } TPM_CMD_NV_DEFINE_SPACE; typedef struct { TPM_RQU_COMMAND_HDR Hdr; TPM_NV_INDEX NvIndex; UINT32 Offset; UINT32 DataSize; } TPM_CMD_NV_READ_VALUE; typedef struct { TPM_RSP_COMMAND_HDR Hdr; UINT32 DataSize; UINT8 Data[TPMNVVALUELENGTH]; } TPM_RSP_NV_READ_VALUE; typedef struct { TPM_RQU_COMMAND_HDR Hdr; TPM_NV_INDEX NvIndex; UINT32 Offset; UINT32 DataSize; UINT8 Data[TPMNVVALUELENGTH]; } TPM_CMD_NV_WRITE_VALUE; #pragma pack() /** Send NV DefineSpace command to TPM1.2. @param PubInfo The public parameters of the NV area. @param EncAuth The encrypted AuthData, only valid if the attributes require subsequent authorization. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm12NvDefineSpace ( IN TPM12_NV_DATA_PUBLIC *PubInfo, IN TPM_ENCAUTH *EncAuth ) { EFI_STATUS Status; TPM_CMD_NV_DEFINE_SPACE Command; TPM_RSP_COMMAND_HDR Response; UINT32 Length; // // send Tpm command TPM_ORD_NV_DefineSpace // Command.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); Command.Hdr.paramSize = SwapBytes32 (sizeof (Command)); Command.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_DefineSpace); Command.PubInfo.tag = SwapBytes16 (PubInfo->tag); Command.PubInfo.nvIndex = SwapBytes32 (PubInfo->nvIndex); Command.PubInfo.pcrInfoRead.pcrSelection.sizeOfSelect = SwapBytes16 (PubInfo->pcrInfoRead.pcrSelection.sizeOfSelect); Command.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[0] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[0]; Command.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[1] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[1]; Command.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[2] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[2]; Command.PubInfo.pcrInfoRead.localityAtRelease = PubInfo->pcrInfoRead.localityAtRelease; CopyMem (&Command.PubInfo.pcrInfoRead.digestAtRelease, &PubInfo->pcrInfoRead.digestAtRelease, sizeof (PubInfo->pcrInfoRead.digestAtRelease)); Command.PubInfo.pcrInfoWrite.pcrSelection.sizeOfSelect = SwapBytes16 (PubInfo->pcrInfoWrite.pcrSelection.sizeOfSelect); Command.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[0] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[0]; Command.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[1] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[1]; Command.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[2] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[2]; Command.PubInfo.pcrInfoWrite.localityAtRelease = PubInfo->pcrInfoWrite.localityAtRelease; CopyMem (&Command.PubInfo.pcrInfoWrite.digestAtRelease, &PubInfo->pcrInfoWrite.digestAtRelease, sizeof (PubInfo->pcrInfoWrite.digestAtRelease)); Command.PubInfo.permission.tag = SwapBytes16 (PubInfo->permission.tag); Command.PubInfo.permission.attributes = SwapBytes32 (PubInfo->permission.attributes); Command.PubInfo.bReadSTClear = PubInfo->bReadSTClear; Command.PubInfo.bWriteSTClear = PubInfo->bWriteSTClear; Command.PubInfo.bWriteDefine = PubInfo->bWriteDefine; Command.PubInfo.dataSize = SwapBytes32 (PubInfo->dataSize); CopyMem (&Command.EncAuth, EncAuth, sizeof (*EncAuth)); Length = sizeof (Response); Status = Tpm12SubmitCommand (sizeof (Command), (UINT8 *)&Command, &Length, (UINT8 *)&Response); if (EFI_ERROR (Status)) { return Status; } DEBUG ((DEBUG_INFO, "Tpm12NvDefineSpace - ReturnCode = %x\n", SwapBytes32 (Response.returnCode))); switch (SwapBytes32 (Response.returnCode)) { case TPM_SUCCESS: return EFI_SUCCESS; default: return EFI_DEVICE_ERROR; } } /** Send NV ReadValue command to TPM1.2. @param NvIndex The index of the area to set. @param Offset The offset into the area. @param DataSize The size of the data area. @param Data The data to set the area to. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm12NvReadValue ( IN TPM_NV_INDEX NvIndex, IN UINT32 Offset, IN OUT UINT32 *DataSize, OUT UINT8 *Data ) { EFI_STATUS Status; TPM_CMD_NV_READ_VALUE Command; TPM_RSP_NV_READ_VALUE Response; UINT32 Length; // // send Tpm command TPM_ORD_NV_ReadValue // Command.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); Command.Hdr.paramSize = SwapBytes32 (sizeof (Command)); Command.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_ReadValue); Command.NvIndex = SwapBytes32 (NvIndex); Command.Offset = SwapBytes32 (Offset); Command.DataSize = SwapBytes32 (*DataSize); Length = sizeof (Response); Status = Tpm12SubmitCommand (sizeof (Command), (UINT8 *)&Command, &Length, (UINT8 *)&Response); if (EFI_ERROR (Status)) { return Status; } DEBUG ((DEBUG_INFO, "Tpm12NvReadValue - ReturnCode = %x\n", SwapBytes32 (Response.Hdr.returnCode))); switch (SwapBytes32 (Response.Hdr.returnCode)) { case TPM_SUCCESS: break; default: return EFI_DEVICE_ERROR; } // // Return the response // if (SwapBytes32 (Response.DataSize) > *DataSize) { return EFI_BUFFER_TOO_SMALL; } *DataSize = SwapBytes32 (Response.DataSize); ZeroMem (Data, *DataSize); CopyMem (Data, &Response.Data, *DataSize); return EFI_SUCCESS; } /** Send NV WriteValue command to TPM1.2. @param NvIndex The index of the area to set. @param Offset The offset into the NV Area. @param DataSize The size of the data parameter. @param Data The data to set the area to. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm12NvWriteValue ( IN TPM_NV_INDEX NvIndex, IN UINT32 Offset, IN UINT32 DataSize, IN UINT8 *Data ) { EFI_STATUS Status; TPM_CMD_NV_WRITE_VALUE Command; UINT32 CommandLength; TPM_RSP_COMMAND_HDR Response; UINT32 ResponseLength; if (DataSize > sizeof (Command.Data)) { return EFI_UNSUPPORTED; } // // send Tpm command TPM_ORD_NV_WriteValue // Command.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); CommandLength = sizeof (Command) - sizeof (Command.Data) + DataSize; Command.Hdr.paramSize = SwapBytes32 (CommandLength); Command.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_WriteValue); Command.NvIndex = SwapBytes32 (NvIndex); Command.Offset = SwapBytes32 (Offset); Command.DataSize = SwapBytes32 (DataSize); CopyMem (Command.Data, Data, DataSize); ResponseLength = sizeof (Response); Status = Tpm12SubmitCommand (CommandLength, (UINT8 *)&Command, &ResponseLength, (UINT8 *)&Response); if (EFI_ERROR (Status)) { return Status; } DEBUG ((DEBUG_INFO, "Tpm12NvWriteValue - ReturnCode = %x\n", SwapBytes32 (Response.returnCode))); switch (SwapBytes32 (Response.returnCode)) { case TPM_SUCCESS: return EFI_SUCCESS; default: return EFI_DEVICE_ERROR; } }