1 /** @file 2 Implement TPM1.2 NV storage related command. 3 4 Copyright (c) 2015, Intel Corporation. All rights reserved. <BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <Uefi.h> 16 #include <IndustryStandard/Tpm12.h> 17 #include <Library/BaseMemoryLib.h> 18 #include <Library/BaseLib.h> 19 #include <Library/Tpm12DeviceLib.h> 20 #include <Library/Tpm12CommandLib.h> 21 #include <Library/DebugLib.h> 22 23 // 24 // Max TPM command/reponse length 25 // 26 #define TPMCMDBUFLENGTH 1024 27 28 #pragma pack(1) 29 30 typedef struct { 31 TPM_RQU_COMMAND_HDR Hdr; 32 TPM12_NV_DATA_PUBLIC PubInfo; 33 TPM_ENCAUTH EncAuth; 34 } TPM_CMD_NV_DEFINE_SPACE; 35 36 typedef struct { 37 TPM_RSP_COMMAND_HDR Hdr; 38 } TPM_RSP_NV_DEFINE_SPACE; 39 40 typedef struct { 41 TPM_RQU_COMMAND_HDR Hdr; 42 TPM_NV_INDEX NvIndex; 43 UINT32 Offset; 44 UINT32 DataSize; 45 } TPM_CMD_NV_READ_VALUE; 46 47 typedef struct { 48 TPM_RSP_COMMAND_HDR Hdr; 49 UINT32 DataSize; 50 UINT8 Data[TPMCMDBUFLENGTH]; 51 } TPM_RSP_NV_READ_VALUE; 52 53 typedef struct { 54 TPM_RQU_COMMAND_HDR Hdr; 55 TPM_NV_INDEX NvIndex; 56 UINT32 Offset; 57 UINT32 DataSize; 58 UINT8 Data[TPMCMDBUFLENGTH]; 59 } TPM_CMD_NV_WRITE_VALUE; 60 61 typedef struct { 62 TPM_RSP_COMMAND_HDR Hdr; 63 } TPM_RSP_NV_WRITE_VALUE; 64 65 #pragma pack() 66 67 /** 68 Send NV DefineSpace command to TPM1.2. 69 70 @param PubInfo The public parameters of the NV area. 71 @param EncAuth The encrypted AuthData, only valid if the attributes require subsequent authorization. 72 73 @retval EFI_SUCCESS Operation completed successfully. 74 @retval EFI_DEVICE_ERROR Unexpected device behavior. 75 **/ 76 EFI_STATUS 77 EFIAPI 78 Tpm12NvDefineSpace ( 79 IN TPM12_NV_DATA_PUBLIC *PubInfo, 80 IN TPM_ENCAUTH *EncAuth 81 ) 82 { 83 EFI_STATUS Status; 84 UINT32 TpmRecvSize; 85 UINT32 TpmSendSize; 86 TPM_CMD_NV_DEFINE_SPACE SendBuffer; 87 TPM_RSP_NV_DEFINE_SPACE RecvBuffer; 88 UINT32 ReturnCode; 89 90 // 91 // send Tpm command TPM_ORD_NV_DefineSpace 92 // 93 TpmRecvSize = sizeof (TPM_RSP_NV_DEFINE_SPACE); 94 TpmSendSize = sizeof (TPM_CMD_NV_DEFINE_SPACE); 95 SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); 96 SendBuffer.Hdr.paramSize = SwapBytes32 (sizeof(TPM_CMD_NV_DEFINE_SPACE)); 97 SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_DefineSpace); 98 SendBuffer.PubInfo.tag = SwapBytes16 (PubInfo->tag); 99 SendBuffer.PubInfo.nvIndex = SwapBytes32 (PubInfo->nvIndex); 100 SendBuffer.PubInfo.pcrInfoRead.pcrSelection.sizeOfSelect = SwapBytes16 (PubInfo->pcrInfoRead.pcrSelection.sizeOfSelect); 101 SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[0] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[0]; 102 SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[1] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[1]; 103 SendBuffer.PubInfo.pcrInfoRead.pcrSelection.pcrSelect[2] = PubInfo->pcrInfoRead.pcrSelection.pcrSelect[2]; 104 SendBuffer.PubInfo.pcrInfoRead.localityAtRelease = PubInfo->pcrInfoRead.localityAtRelease; 105 CopyMem (&SendBuffer.PubInfo.pcrInfoRead.digestAtRelease, &PubInfo->pcrInfoRead.digestAtRelease, sizeof(PubInfo->pcrInfoRead.digestAtRelease)); 106 SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.sizeOfSelect = SwapBytes16 (PubInfo->pcrInfoWrite.pcrSelection.sizeOfSelect); 107 SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[0] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[0]; 108 SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[1] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[1]; 109 SendBuffer.PubInfo.pcrInfoWrite.pcrSelection.pcrSelect[2] = PubInfo->pcrInfoWrite.pcrSelection.pcrSelect[2]; 110 SendBuffer.PubInfo.pcrInfoWrite.localityAtRelease = PubInfo->pcrInfoWrite.localityAtRelease; 111 CopyMem (&SendBuffer.PubInfo.pcrInfoWrite.digestAtRelease, &PubInfo->pcrInfoWrite.digestAtRelease, sizeof(PubInfo->pcrInfoWrite.digestAtRelease)); 112 SendBuffer.PubInfo.permission.tag = SwapBytes16 (PubInfo->permission.tag); 113 SendBuffer.PubInfo.permission.attributes = SwapBytes32 (PubInfo->permission.attributes); 114 SendBuffer.PubInfo.bReadSTClear = PubInfo->bReadSTClear; 115 SendBuffer.PubInfo.bWriteSTClear = PubInfo->bWriteSTClear; 116 SendBuffer.PubInfo.bWriteDefine = PubInfo->bWriteDefine; 117 SendBuffer.PubInfo.dataSize = SwapBytes32 (PubInfo->dataSize); 118 CopyMem (&SendBuffer.EncAuth, EncAuth, sizeof(*EncAuth)); 119 120 Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer); 121 if (EFI_ERROR (Status)) { 122 return Status; 123 } 124 ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode); 125 DEBUG ((DEBUG_INFO, "Tpm12NvDefineSpace - ReturnCode = %x\n", ReturnCode)); 126 switch (ReturnCode) { 127 case TPM_SUCCESS: 128 break; 129 default: 130 return EFI_DEVICE_ERROR; 131 } 132 133 return EFI_SUCCESS; 134 } 135 136 /** 137 Send NV ReadValue command to TPM1.2. 138 139 @param NvIndex The index of the area to set. 140 @param Offset The offset into the area. 141 @param DataSize The size of the data area. 142 @param Data The data to set the area to. 143 144 @retval EFI_SUCCESS Operation completed successfully. 145 @retval EFI_DEVICE_ERROR Unexpected device behavior. 146 **/ 147 EFI_STATUS 148 EFIAPI 149 Tpm12NvReadValue ( 150 IN TPM_NV_INDEX NvIndex, 151 IN UINT32 Offset, 152 IN OUT UINT32 *DataSize, 153 OUT UINT8 *Data 154 ) 155 { 156 EFI_STATUS Status; 157 UINT32 TpmRecvSize; 158 UINT32 TpmSendSize; 159 TPM_CMD_NV_READ_VALUE SendBuffer; 160 TPM_RSP_NV_READ_VALUE RecvBuffer; 161 UINT32 ReturnCode; 162 163 // 164 // send Tpm command TPM_ORD_NV_ReadValue 165 // 166 TpmRecvSize = sizeof (TPM_RSP_NV_READ_VALUE); 167 TpmSendSize = sizeof (TPM_CMD_NV_READ_VALUE); 168 SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); 169 SendBuffer.Hdr.paramSize = SwapBytes32 (sizeof(TPM_CMD_NV_READ_VALUE)); 170 SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_ReadValue); 171 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 172 SendBuffer.Offset = SwapBytes32 (Offset); 173 SendBuffer.DataSize = SwapBytes32 (*DataSize); 174 175 Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer); 176 if (EFI_ERROR (Status)) { 177 return Status; 178 } 179 ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode); 180 DEBUG ((DEBUG_INFO, "Tpm12NvReadValue - ReturnCode = %x\n", ReturnCode)); 181 switch (ReturnCode) { 182 case TPM_SUCCESS: 183 break; 184 default: 185 return EFI_DEVICE_ERROR; 186 } 187 188 // 189 // Return the response 190 // 191 *DataSize = SwapBytes32(RecvBuffer.DataSize); 192 CopyMem (Data, &RecvBuffer.Data, *DataSize); 193 194 return EFI_SUCCESS; 195 } 196 197 /** 198 Send NV WriteValue command to TPM1.2. 199 200 @param NvIndex The index of the area to set. 201 @param Offset The offset into the NV Area. 202 @param DataSize The size of the data parameter. 203 @param Data The data to set the area to. 204 205 @retval EFI_SUCCESS Operation completed successfully. 206 @retval EFI_DEVICE_ERROR Unexpected device behavior. 207 **/ 208 EFI_STATUS 209 EFIAPI 210 Tpm12NvWriteValue ( 211 IN TPM_NV_INDEX NvIndex, 212 IN UINT32 Offset, 213 IN UINT32 DataSize, 214 IN UINT8 *Data 215 ) 216 { 217 EFI_STATUS Status; 218 UINT32 TpmRecvSize; 219 UINT32 TpmSendSize; 220 TPM_CMD_NV_WRITE_VALUE SendBuffer; 221 TPM_RSP_NV_WRITE_VALUE RecvBuffer; 222 UINT32 ReturnCode; 223 224 if (DataSize > sizeof(SendBuffer.Data)) { 225 return EFI_UNSUPPORTED; 226 } 227 228 // 229 // send Tpm command TPM_ORD_NV_WriteValue 230 // 231 TpmRecvSize = sizeof (TPM_RSP_NV_WRITE_VALUE); 232 TpmSendSize = sizeof (TPM_CMD_NV_WRITE_VALUE) - sizeof(SendBuffer.Data) + DataSize; 233 SendBuffer.Hdr.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); 234 SendBuffer.Hdr.paramSize = SwapBytes32 (sizeof(TPM_CMD_NV_WRITE_VALUE) - sizeof(SendBuffer.Data) + DataSize); 235 SendBuffer.Hdr.ordinal = SwapBytes32 (TPM_ORD_NV_WriteValue); 236 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 237 SendBuffer.Offset = SwapBytes32 (Offset); 238 SendBuffer.DataSize = SwapBytes32 (DataSize); 239 CopyMem (SendBuffer.Data, Data, DataSize); 240 241 Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, (UINT8 *)&RecvBuffer); 242 if (EFI_ERROR (Status)) { 243 return Status; 244 } 245 ReturnCode = SwapBytes32(RecvBuffer.Hdr.returnCode); 246 DEBUG ((DEBUG_INFO, "Tpm12NvWritedValue - ReturnCode = %x\n", ReturnCode)); 247 switch (ReturnCode) { 248 case TPM_SUCCESS: 249 break; 250 default: 251 return EFI_DEVICE_ERROR; 252 } 253 254 return EFI_SUCCESS; 255 } 256