1 /** @file 2 Implement TPM2 NVStorage related command. 3 4 Copyright (c) 2013 - 2016, 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 <IndustryStandard/UefiTcgPlatform.h> 16 #include <Library/Tpm2CommandLib.h> 17 #include <Library/Tpm2DeviceLib.h> 18 #include <Library/BaseMemoryLib.h> 19 #include <Library/BaseLib.h> 20 #include <Library/DebugLib.h> 21 22 #pragma pack(1) 23 24 #define RC_NV_ReadPublic_nvIndex (TPM_RC_H + TPM_RC_1) 25 26 #define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1) 27 #define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1) 28 #define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2) 29 30 #define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1) 31 #define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2) 32 33 #define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1) 34 #define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2) 35 #define RC_NV_Read_size (TPM_RC_P + TPM_RC_1) 36 #define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2) 37 38 #define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1) 39 #define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2) 40 #define RC_NV_Write_data (TPM_RC_P + TPM_RC_1) 41 #define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2) 42 43 typedef struct { 44 TPM2_COMMAND_HEADER Header; 45 TPMI_RH_NV_INDEX NvIndex; 46 } TPM2_NV_READPUBLIC_COMMAND; 47 48 typedef struct { 49 TPM2_RESPONSE_HEADER Header; 50 TPM2B_NV_PUBLIC NvPublic; 51 TPM2B_NAME NvName; 52 } TPM2_NV_READPUBLIC_RESPONSE; 53 54 typedef struct { 55 TPM2_COMMAND_HEADER Header; 56 TPMI_RH_PROVISION AuthHandle; 57 UINT32 AuthSessionSize; 58 TPMS_AUTH_COMMAND AuthSession; 59 TPM2B_AUTH Auth; 60 TPM2B_NV_PUBLIC NvPublic; 61 } TPM2_NV_DEFINESPACE_COMMAND; 62 63 typedef struct { 64 TPM2_RESPONSE_HEADER Header; 65 UINT32 AuthSessionSize; 66 TPMS_AUTH_RESPONSE AuthSession; 67 } TPM2_NV_DEFINESPACE_RESPONSE; 68 69 typedef struct { 70 TPM2_COMMAND_HEADER Header; 71 TPMI_RH_PROVISION AuthHandle; 72 TPMI_RH_NV_INDEX NvIndex; 73 UINT32 AuthSessionSize; 74 TPMS_AUTH_COMMAND AuthSession; 75 } TPM2_NV_UNDEFINESPACE_COMMAND; 76 77 typedef struct { 78 TPM2_RESPONSE_HEADER Header; 79 UINT32 AuthSessionSize; 80 TPMS_AUTH_RESPONSE AuthSession; 81 } TPM2_NV_UNDEFINESPACE_RESPONSE; 82 83 typedef struct { 84 TPM2_COMMAND_HEADER Header; 85 TPMI_RH_NV_AUTH AuthHandle; 86 TPMI_RH_NV_INDEX NvIndex; 87 UINT32 AuthSessionSize; 88 TPMS_AUTH_COMMAND AuthSession; 89 UINT16 Size; 90 UINT16 Offset; 91 } TPM2_NV_READ_COMMAND; 92 93 typedef struct { 94 TPM2_RESPONSE_HEADER Header; 95 UINT32 AuthSessionSize; 96 TPM2B_MAX_BUFFER Data; 97 TPMS_AUTH_RESPONSE AuthSession; 98 } TPM2_NV_READ_RESPONSE; 99 100 typedef struct { 101 TPM2_COMMAND_HEADER Header; 102 TPMI_RH_NV_AUTH AuthHandle; 103 TPMI_RH_NV_INDEX NvIndex; 104 UINT32 AuthSessionSize; 105 TPMS_AUTH_COMMAND AuthSession; 106 TPM2B_MAX_BUFFER Data; 107 UINT16 Offset; 108 } TPM2_NV_WRITE_COMMAND; 109 110 typedef struct { 111 TPM2_RESPONSE_HEADER Header; 112 UINT32 AuthSessionSize; 113 TPMS_AUTH_RESPONSE AuthSession; 114 } TPM2_NV_WRITE_RESPONSE; 115 116 typedef struct { 117 TPM2_COMMAND_HEADER Header; 118 TPMI_RH_NV_AUTH AuthHandle; 119 TPMI_RH_NV_INDEX NvIndex; 120 UINT32 AuthSessionSize; 121 TPMS_AUTH_COMMAND AuthSession; 122 } TPM2_NV_READLOCK_COMMAND; 123 124 typedef struct { 125 TPM2_RESPONSE_HEADER Header; 126 UINT32 AuthSessionSize; 127 TPMS_AUTH_RESPONSE AuthSession; 128 } TPM2_NV_READLOCK_RESPONSE; 129 130 typedef struct { 131 TPM2_COMMAND_HEADER Header; 132 TPMI_RH_NV_AUTH AuthHandle; 133 TPMI_RH_NV_INDEX NvIndex; 134 UINT32 AuthSessionSize; 135 TPMS_AUTH_COMMAND AuthSession; 136 } TPM2_NV_WRITELOCK_COMMAND; 137 138 typedef struct { 139 TPM2_RESPONSE_HEADER Header; 140 UINT32 AuthSessionSize; 141 TPMS_AUTH_RESPONSE AuthSession; 142 } TPM2_NV_WRITELOCK_RESPONSE; 143 144 typedef struct { 145 TPM2_COMMAND_HEADER Header; 146 TPMI_RH_PROVISION AuthHandle; 147 UINT32 AuthSessionSize; 148 TPMS_AUTH_COMMAND AuthSession; 149 } TPM2_NV_GLOBALWRITELOCK_COMMAND; 150 151 typedef struct { 152 TPM2_RESPONSE_HEADER Header; 153 UINT32 AuthSessionSize; 154 TPMS_AUTH_RESPONSE AuthSession; 155 } TPM2_NV_GLOBALWRITELOCK_RESPONSE; 156 157 #pragma pack() 158 159 /** 160 This command is used to read the public area and Name of an NV Index. 161 162 @param[in] NvIndex The NV Index. 163 @param[out] NvPublic The public area of the index. 164 @param[out] NvName The Name of the nvIndex. 165 166 @retval EFI_SUCCESS Operation completed successfully. 167 @retval EFI_DEVICE_ERROR The command was unsuccessful. 168 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 169 **/ 170 EFI_STATUS 171 EFIAPI 172 Tpm2NvReadPublic ( 173 IN TPMI_RH_NV_INDEX NvIndex, 174 OUT TPM2B_NV_PUBLIC *NvPublic, 175 OUT TPM2B_NAME *NvName 176 ) 177 { 178 EFI_STATUS Status; 179 TPM2_NV_READPUBLIC_COMMAND SendBuffer; 180 TPM2_NV_READPUBLIC_RESPONSE RecvBuffer; 181 UINT32 SendBufferSize; 182 UINT32 RecvBufferSize; 183 UINT16 NvPublicSize; 184 UINT16 NvNameSize; 185 UINT8 *Buffer; 186 TPM_RC ResponseCode; 187 188 // 189 // Construct command 190 // 191 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); 192 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic); 193 194 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 195 196 SendBufferSize = (UINT32) sizeof (SendBuffer); 197 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 198 199 // 200 // send Tpm command 201 // 202 RecvBufferSize = sizeof (RecvBuffer); 203 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 204 if (EFI_ERROR (Status)) { 205 return Status; 206 } 207 208 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 209 DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); 210 return EFI_DEVICE_ERROR; 211 } 212 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 213 if (ResponseCode != TPM_RC_SUCCESS) { 214 DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 215 } 216 switch (ResponseCode) { 217 case TPM_RC_SUCCESS: 218 // return data 219 break; 220 case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED: 221 return EFI_NOT_FOUND; 222 case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex: 223 return EFI_INVALID_PARAMETER; 224 default: 225 return EFI_DEVICE_ERROR; 226 } 227 228 if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { 229 DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); 230 return EFI_NOT_FOUND; 231 } 232 233 // 234 // Basic check 235 // 236 NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size); 237 NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize))); 238 239 if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { 240 DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x, NvNameSize %x\n", RecvBufferSize, NvNameSize)); 241 return EFI_NOT_FOUND; 242 } 243 244 // 245 // Return the response 246 // 247 CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize); 248 NvPublic->size = NvPublicSize; 249 NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex); 250 NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg); 251 WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); 252 NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size); 253 Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy; 254 Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size; 255 NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); 256 257 CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize); 258 NvName->size = NvNameSize; 259 260 return EFI_SUCCESS; 261 } 262 263 /** 264 This command defines the attributes of an NV Index and causes the TPM to 265 reserve space to hold the data associated with the index. 266 If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED. 267 268 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. 269 @param[in] AuthSession Auth Session context 270 @param[in] Auth The authorization data. 271 @param[in] NvPublic The public area of the index. 272 273 @retval EFI_SUCCESS Operation completed successfully. 274 @retval EFI_DEVICE_ERROR The command was unsuccessful. 275 @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined. 276 **/ 277 EFI_STATUS 278 EFIAPI 279 Tpm2NvDefineSpace ( 280 IN TPMI_RH_PROVISION AuthHandle, 281 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL 282 IN TPM2B_AUTH *Auth, 283 IN TPM2B_NV_PUBLIC *NvPublic 284 ) 285 { 286 EFI_STATUS Status; 287 TPM2_NV_DEFINESPACE_COMMAND SendBuffer; 288 TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer; 289 UINT32 SendBufferSize; 290 UINT32 RecvBufferSize; 291 UINT16 NvPublicSize; 292 UINT8 *Buffer; 293 UINT32 SessionInfoSize; 294 TPM_RC ResponseCode; 295 296 // 297 // Construct command 298 // 299 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 300 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace); 301 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 302 303 // 304 // Add in Auth session 305 // 306 Buffer = (UINT8 *)&SendBuffer.AuthSession; 307 308 // sessionInfoSize 309 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 310 Buffer += SessionInfoSize; 311 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 312 313 // 314 // IndexAuth 315 // 316 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size)); 317 Buffer += sizeof(UINT16); 318 CopyMem(Buffer, Auth->buffer, Auth->size); 319 Buffer += Auth->size; 320 321 // 322 // NvPublic 323 // 324 NvPublicSize = NvPublic->size; 325 326 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize)); 327 Buffer += sizeof(UINT16); 328 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex)); 329 Buffer += sizeof(UINT32); 330 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg)); 331 Buffer += sizeof(UINT16); 332 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); 333 Buffer += sizeof(UINT32); 334 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size)); 335 Buffer += sizeof(UINT16); 336 CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size); 337 Buffer += NvPublic->nvPublic.authPolicy.size; 338 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize)); 339 Buffer += sizeof(UINT16); 340 341 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 342 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 343 344 // 345 // send Tpm command 346 // 347 RecvBufferSize = sizeof (RecvBuffer); 348 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 349 if (EFI_ERROR (Status)) { 350 goto Done; 351 } 352 353 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 354 DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); 355 Status = EFI_DEVICE_ERROR; 356 goto Done; 357 } 358 359 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 360 if (ResponseCode != TPM_RC_SUCCESS) { 361 DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 362 } 363 switch (ResponseCode) { 364 case TPM_RC_SUCCESS: 365 // return data 366 break; 367 case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo: 368 case TPM_RC_SIZE + RC_NV_DefineSpace_auth: 369 Status = EFI_BAD_BUFFER_SIZE; 370 break; 371 case TPM_RC_ATTRIBUTES: 372 case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo: 373 Status = EFI_UNSUPPORTED; 374 break; 375 case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle: 376 Status = EFI_INVALID_PARAMETER; 377 break; 378 case TPM_RC_NV_DEFINED: 379 Status = EFI_ALREADY_STARTED; 380 break; 381 case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo: 382 case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle: 383 Status = EFI_INVALID_PARAMETER; 384 break; 385 case TPM_RC_NV_SPACE: 386 Status = EFI_OUT_OF_RESOURCES; 387 break; 388 default: 389 Status = EFI_DEVICE_ERROR; 390 break; 391 } 392 393 Done: 394 // 395 // Clear AuthSession Content 396 // 397 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 398 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 399 return Status; 400 } 401 402 /** 403 This command removes an index from the TPM. 404 405 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. 406 @param[in] NvIndex The NV Index. 407 @param[in] AuthSession Auth Session context 408 409 @retval EFI_SUCCESS Operation completed successfully. 410 @retval EFI_DEVICE_ERROR The command was unsuccessful. 411 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 412 **/ 413 EFI_STATUS 414 EFIAPI 415 Tpm2NvUndefineSpace ( 416 IN TPMI_RH_PROVISION AuthHandle, 417 IN TPMI_RH_NV_INDEX NvIndex, 418 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL 419 ) 420 { 421 EFI_STATUS Status; 422 TPM2_NV_UNDEFINESPACE_COMMAND SendBuffer; 423 TPM2_NV_UNDEFINESPACE_RESPONSE RecvBuffer; 424 UINT32 SendBufferSize; 425 UINT32 RecvBufferSize; 426 UINT8 *Buffer; 427 UINT32 SessionInfoSize; 428 TPM_RC ResponseCode; 429 430 // 431 // Construct command 432 // 433 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 434 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_UndefineSpace); 435 436 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 437 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 438 439 // 440 // Add in Auth session 441 // 442 Buffer = (UINT8 *)&SendBuffer.AuthSession; 443 444 // sessionInfoSize 445 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 446 Buffer += SessionInfoSize; 447 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 448 449 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 450 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 451 452 // 453 // send Tpm command 454 // 455 RecvBufferSize = sizeof (RecvBuffer); 456 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 457 if (EFI_ERROR (Status)) { 458 goto Done; 459 } 460 461 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 462 DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); 463 Status = EFI_DEVICE_ERROR; 464 goto Done; 465 } 466 467 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 468 if (ResponseCode != TPM_RC_SUCCESS) { 469 DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 470 } 471 switch (ResponseCode) { 472 case TPM_RC_SUCCESS: 473 // return data 474 break; 475 case TPM_RC_ATTRIBUTES: 476 case TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex: 477 Status = EFI_UNSUPPORTED; 478 break; 479 case TPM_RC_NV_AUTHORIZATION: 480 Status = EFI_SECURITY_VIOLATION; 481 break; 482 case TPM_RC_HANDLE + RC_NV_UndefineSpace_nvIndex: // TPM_RC_NV_DEFINED: 483 Status = EFI_NOT_FOUND; 484 break; 485 case TPM_RC_HANDLE + RC_NV_UndefineSpace_authHandle: // TPM_RC_NV_DEFINED: 486 Status = EFI_INVALID_PARAMETER; 487 break; 488 case TPM_RC_VALUE + RC_NV_UndefineSpace_authHandle: 489 case TPM_RC_VALUE + RC_NV_UndefineSpace_nvIndex: 490 Status = EFI_INVALID_PARAMETER; 491 break; 492 default: 493 Status = EFI_DEVICE_ERROR; 494 break; 495 } 496 497 Done: 498 // 499 // Clear AuthSession Content 500 // 501 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 502 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 503 return Status; 504 } 505 506 /** 507 This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). 508 509 @param[in] AuthHandle the handle indicating the source of the authorization value. 510 @param[in] NvIndex The index to be read. 511 @param[in] AuthSession Auth Session context 512 @param[in] Size Number of bytes to read. 513 @param[in] Offset Byte offset into the area. 514 @param[in,out] OutData The data read. 515 516 @retval EFI_SUCCESS Operation completed successfully. 517 @retval EFI_DEVICE_ERROR The command was unsuccessful. 518 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 519 **/ 520 EFI_STATUS 521 EFIAPI 522 Tpm2NvRead ( 523 IN TPMI_RH_NV_AUTH AuthHandle, 524 IN TPMI_RH_NV_INDEX NvIndex, 525 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL 526 IN UINT16 Size, 527 IN UINT16 Offset, 528 IN OUT TPM2B_MAX_BUFFER *OutData 529 ) 530 { 531 EFI_STATUS Status; 532 TPM2_NV_READ_COMMAND SendBuffer; 533 TPM2_NV_READ_RESPONSE RecvBuffer; 534 UINT32 SendBufferSize; 535 UINT32 RecvBufferSize; 536 UINT8 *Buffer; 537 UINT32 SessionInfoSize; 538 TPM_RC ResponseCode; 539 540 // 541 // Construct command 542 // 543 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 544 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Read); 545 546 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 547 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 548 549 // 550 // Add in Auth session 551 // 552 Buffer = (UINT8 *)&SendBuffer.AuthSession; 553 554 // sessionInfoSize 555 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 556 Buffer += SessionInfoSize; 557 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 558 559 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Size)); 560 Buffer += sizeof(UINT16); 561 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset)); 562 Buffer += sizeof(UINT16); 563 564 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 565 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 566 567 // 568 // send Tpm command 569 // 570 RecvBufferSize = sizeof (RecvBuffer); 571 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 572 if (EFI_ERROR (Status)) { 573 goto Done; 574 } 575 576 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 577 DEBUG ((EFI_D_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize)); 578 Status = EFI_DEVICE_ERROR; 579 goto Done; 580 } 581 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 582 if (ResponseCode != TPM_RC_SUCCESS) { 583 DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode)); 584 } 585 switch (ResponseCode) { 586 case TPM_RC_SUCCESS: 587 // return data 588 break; 589 case TPM_RC_NV_AUTHORIZATION: 590 Status = EFI_SECURITY_VIOLATION; 591 break; 592 case TPM_RC_NV_LOCKED: 593 Status = EFI_ACCESS_DENIED; 594 break; 595 case TPM_RC_NV_RANGE: 596 Status = EFI_BAD_BUFFER_SIZE; 597 break; 598 case TPM_RC_NV_UNINITIALIZED: 599 Status = EFI_NOT_READY; 600 break; 601 case TPM_RC_HANDLE + RC_NV_Read_nvIndex: // TPM_RC_NV_DEFINED: 602 Status = EFI_NOT_FOUND; 603 break; 604 case TPM_RC_HANDLE + RC_NV_Read_authHandle: // TPM_RC_NV_DEFINED: 605 Status = EFI_INVALID_PARAMETER; 606 break; 607 case TPM_RC_VALUE + RC_NV_Read_nvIndex: 608 case TPM_RC_VALUE + RC_NV_Read_authHandle: 609 Status = EFI_INVALID_PARAMETER; 610 break; 611 case TPM_RC_BAD_AUTH + RC_NV_Read_authHandle + TPM_RC_S: 612 Status = EFI_INVALID_PARAMETER; 613 break; 614 case TPM_RC_AUTH_UNAVAILABLE: 615 Status = EFI_INVALID_PARAMETER; 616 break; 617 case TPM_RC_AUTH_FAIL + RC_NV_Read_authHandle + TPM_RC_S: 618 Status = EFI_INVALID_PARAMETER; 619 break; 620 case TPM_RC_ATTRIBUTES + RC_NV_Read_authHandle + TPM_RC_S: 621 Status = EFI_UNSUPPORTED; 622 break; 623 default: 624 Status = EFI_DEVICE_ERROR; 625 break; 626 } 627 if (Status != EFI_SUCCESS) { 628 goto Done; 629 } 630 631 // 632 // Return the response 633 // 634 OutData->size = SwapBytes16 (RecvBuffer.Data.size); 635 CopyMem (OutData->buffer, &RecvBuffer.Data.buffer, OutData->size); 636 637 Done: 638 // 639 // Clear AuthSession Content 640 // 641 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 642 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 643 return Status; 644 } 645 646 /** 647 This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace(). 648 649 @param[in] AuthHandle the handle indicating the source of the authorization value. 650 @param[in] NvIndex The NV Index of the area to write. 651 @param[in] AuthSession Auth Session context 652 @param[in] InData The data to write. 653 @param[in] Offset The offset into the NV Area. 654 655 @retval EFI_SUCCESS Operation completed successfully. 656 @retval EFI_DEVICE_ERROR The command was unsuccessful. 657 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 658 **/ 659 EFI_STATUS 660 EFIAPI 661 Tpm2NvWrite ( 662 IN TPMI_RH_NV_AUTH AuthHandle, 663 IN TPMI_RH_NV_INDEX NvIndex, 664 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL 665 IN TPM2B_MAX_BUFFER *InData, 666 IN UINT16 Offset 667 ) 668 { 669 EFI_STATUS Status; 670 TPM2_NV_WRITE_COMMAND SendBuffer; 671 TPM2_NV_WRITE_RESPONSE RecvBuffer; 672 UINT32 SendBufferSize; 673 UINT32 RecvBufferSize; 674 UINT8 *Buffer; 675 UINT32 SessionInfoSize; 676 TPM_RC ResponseCode; 677 678 // 679 // Construct command 680 // 681 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 682 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Write); 683 684 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 685 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 686 687 // 688 // Add in Auth session 689 // 690 Buffer = (UINT8 *)&SendBuffer.AuthSession; 691 692 // sessionInfoSize 693 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 694 Buffer += SessionInfoSize; 695 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 696 697 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size)); 698 Buffer += sizeof(UINT16); 699 CopyMem (Buffer, InData->buffer, InData->size); 700 Buffer += InData->size; 701 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset)); 702 Buffer += sizeof(UINT16); 703 704 SendBufferSize = (UINT32) (Buffer - (UINT8 *)&SendBuffer); 705 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 706 707 // 708 // send Tpm command 709 // 710 RecvBufferSize = sizeof (RecvBuffer); 711 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 712 if (EFI_ERROR (Status)) { 713 goto Done; 714 } 715 716 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 717 DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize)); 718 Status = EFI_DEVICE_ERROR; 719 goto Done; 720 } 721 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 722 if (ResponseCode != TPM_RC_SUCCESS) { 723 DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode)); 724 } 725 switch (ResponseCode) { 726 case TPM_RC_SUCCESS: 727 // return data 728 break; 729 case TPM_RC_ATTRIBUTES: 730 Status = EFI_UNSUPPORTED; 731 break; 732 case TPM_RC_NV_AUTHORIZATION: 733 Status = EFI_SECURITY_VIOLATION; 734 break; 735 case TPM_RC_NV_LOCKED: 736 Status = EFI_ACCESS_DENIED; 737 break; 738 case TPM_RC_NV_RANGE: 739 Status = EFI_BAD_BUFFER_SIZE; 740 break; 741 case TPM_RC_HANDLE + RC_NV_Write_nvIndex: // TPM_RC_NV_DEFINED: 742 Status = EFI_NOT_FOUND; 743 break; 744 case TPM_RC_HANDLE + RC_NV_Write_authHandle: // TPM_RC_NV_DEFINED: 745 Status = EFI_INVALID_PARAMETER; 746 break; 747 case TPM_RC_VALUE + RC_NV_Write_nvIndex: 748 case TPM_RC_VALUE + RC_NV_Write_authHandle: 749 Status = EFI_INVALID_PARAMETER; 750 break; 751 case TPM_RC_BAD_AUTH + RC_NV_Write_authHandle + TPM_RC_S: 752 Status = EFI_INVALID_PARAMETER; 753 break; 754 case TPM_RC_AUTH_UNAVAILABLE: 755 Status = EFI_INVALID_PARAMETER; 756 break; 757 case TPM_RC_AUTH_FAIL + RC_NV_Write_authHandle + TPM_RC_S: 758 Status = EFI_INVALID_PARAMETER; 759 break; 760 case TPM_RC_ATTRIBUTES + RC_NV_Write_authHandle + TPM_RC_S: 761 Status = EFI_UNSUPPORTED; 762 break; 763 default: 764 Status = EFI_DEVICE_ERROR; 765 break; 766 } 767 768 Done: 769 // 770 // Clear AuthSession Content 771 // 772 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 773 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 774 return Status; 775 } 776 777 /** 778 This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR). 779 780 @param[in] AuthHandle the handle indicating the source of the authorization value. 781 @param[in] NvIndex The NV Index of the area to lock. 782 @param[in] AuthSession Auth Session context 783 784 @retval EFI_SUCCESS Operation completed successfully. 785 @retval EFI_DEVICE_ERROR The command was unsuccessful. 786 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 787 **/ 788 EFI_STATUS 789 EFIAPI 790 Tpm2NvReadLock ( 791 IN TPMI_RH_NV_AUTH AuthHandle, 792 IN TPMI_RH_NV_INDEX NvIndex, 793 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL 794 ) 795 { 796 EFI_STATUS Status; 797 TPM2_NV_READLOCK_COMMAND SendBuffer; 798 TPM2_NV_READLOCK_RESPONSE RecvBuffer; 799 UINT32 SendBufferSize; 800 UINT32 RecvBufferSize; 801 UINT8 *Buffer; 802 UINT32 SessionInfoSize; 803 TPM_RC ResponseCode; 804 805 // 806 // Construct command 807 // 808 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 809 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadLock); 810 811 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 812 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 813 814 // 815 // Add in Auth session 816 // 817 Buffer = (UINT8 *)&SendBuffer.AuthSession; 818 819 // sessionInfoSize 820 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 821 Buffer += SessionInfoSize; 822 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 823 824 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 825 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 826 827 // 828 // send Tpm command 829 // 830 RecvBufferSize = sizeof (RecvBuffer); 831 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 832 if (EFI_ERROR (Status)) { 833 goto Done; 834 } 835 836 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 837 DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize)); 838 Status = EFI_DEVICE_ERROR; 839 goto Done; 840 } 841 842 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 843 if (ResponseCode != TPM_RC_SUCCESS) { 844 DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 845 } 846 switch (ResponseCode) { 847 case TPM_RC_SUCCESS: 848 // return data 849 break; 850 default: 851 Status = EFI_DEVICE_ERROR; 852 break; 853 } 854 855 Done: 856 // 857 // Clear AuthSession Content 858 // 859 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 860 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 861 return Status; 862 } 863 864 /** 865 This command may be used to inhibit further writes of the Index. 866 867 @param[in] AuthHandle the handle indicating the source of the authorization value. 868 @param[in] NvIndex The NV Index of the area to lock. 869 @param[in] AuthSession Auth Session context 870 871 @retval EFI_SUCCESS Operation completed successfully. 872 @retval EFI_DEVICE_ERROR The command was unsuccessful. 873 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 874 **/ 875 EFI_STATUS 876 EFIAPI 877 Tpm2NvWriteLock ( 878 IN TPMI_RH_NV_AUTH AuthHandle, 879 IN TPMI_RH_NV_INDEX NvIndex, 880 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL 881 ) 882 { 883 EFI_STATUS Status; 884 TPM2_NV_WRITELOCK_COMMAND SendBuffer; 885 TPM2_NV_WRITELOCK_RESPONSE RecvBuffer; 886 UINT32 SendBufferSize; 887 UINT32 RecvBufferSize; 888 UINT8 *Buffer; 889 UINT32 SessionInfoSize; 890 TPM_RC ResponseCode; 891 892 // 893 // Construct command 894 // 895 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 896 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_WriteLock); 897 898 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 899 SendBuffer.NvIndex = SwapBytes32 (NvIndex); 900 901 // 902 // Add in Auth session 903 // 904 Buffer = (UINT8 *)&SendBuffer.AuthSession; 905 906 // sessionInfoSize 907 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 908 Buffer += SessionInfoSize; 909 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 910 911 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 912 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 913 914 // 915 // send Tpm command 916 // 917 RecvBufferSize = sizeof (RecvBuffer); 918 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 919 if (EFI_ERROR (Status)) { 920 goto Done; 921 } 922 923 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 924 DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); 925 Status = EFI_DEVICE_ERROR; 926 goto Done; 927 } 928 929 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 930 if (ResponseCode != TPM_RC_SUCCESS) { 931 DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 932 } 933 switch (ResponseCode) { 934 case TPM_RC_SUCCESS: 935 // return data 936 break; 937 default: 938 Status = EFI_DEVICE_ERROR; 939 break; 940 } 941 942 Done: 943 // 944 // Clear AuthSession Content 945 // 946 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 947 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 948 return Status; 949 } 950 951 /** 952 The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET. 953 954 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. 955 @param[in] AuthSession Auth Session context 956 957 @retval EFI_SUCCESS Operation completed successfully. 958 @retval EFI_DEVICE_ERROR The command was unsuccessful. 959 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. 960 **/ 961 EFI_STATUS 962 EFIAPI 963 Tpm2NvGlobalWriteLock ( 964 IN TPMI_RH_PROVISION AuthHandle, 965 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL 966 ) 967 { 968 EFI_STATUS Status; 969 TPM2_NV_GLOBALWRITELOCK_COMMAND SendBuffer; 970 TPM2_NV_GLOBALWRITELOCK_RESPONSE RecvBuffer; 971 UINT32 SendBufferSize; 972 UINT32 RecvBufferSize; 973 UINT8 *Buffer; 974 UINT32 SessionInfoSize; 975 TPM_RC ResponseCode; 976 977 // 978 // Construct command 979 // 980 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); 981 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_GlobalWriteLock); 982 983 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); 984 985 // 986 // Add in Auth session 987 // 988 Buffer = (UINT8 *)&SendBuffer.AuthSession; 989 990 // sessionInfoSize 991 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); 992 Buffer += SessionInfoSize; 993 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); 994 995 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); 996 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); 997 998 // 999 // send Tpm command 1000 // 1001 RecvBufferSize = sizeof (RecvBuffer); 1002 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); 1003 if (EFI_ERROR (Status)) { 1004 goto Done; 1005 } 1006 1007 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { 1008 DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); 1009 Status = EFI_DEVICE_ERROR; 1010 goto Done; 1011 } 1012 1013 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); 1014 if (ResponseCode != TPM_RC_SUCCESS) { 1015 DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); 1016 } 1017 switch (ResponseCode) { 1018 case TPM_RC_SUCCESS: 1019 // return data 1020 break; 1021 default: 1022 Status = EFI_DEVICE_ERROR; 1023 break; 1024 } 1025 1026 Done: 1027 // 1028 // Clear AuthSession Content 1029 // 1030 ZeroMem (&SendBuffer, sizeof(SendBuffer)); 1031 ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); 1032 return Status; 1033 } 1034