]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
SecurityPkg Tpm2DeviceLibDTpm: Update enum type name to match the one in lib
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2NVStorage.c
1 /** @file
2 Implement TPM2 NVStorage related command.
3
4 Copyright (c) 2013 - 2018, 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 if (NvPublicSize > sizeof(TPMS_NV_PUBLIC)) {
238 DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvPublic.size error %x\n", NvPublicSize));
239 return EFI_DEVICE_ERROR;
240 }
241
242 NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize)));
243 if (NvNameSize > sizeof(TPMU_NAME)){
244 DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvNameSize error %x\n", NvNameSize));
245 return EFI_DEVICE_ERROR;
246 }
247
248 if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) {
249 DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize));
250 return EFI_NOT_FOUND;
251 }
252
253 //
254 // Return the response
255 //
256 CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize);
257 NvPublic->size = NvPublicSize;
258 NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex);
259 NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg);
260 WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));
261 NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size);
262 Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy;
263 Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size;
264 NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
265
266 CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize);
267 NvName->size = NvNameSize;
268
269 return EFI_SUCCESS;
270 }
271
272 /**
273 This command defines the attributes of an NV Index and causes the TPM to
274 reserve space to hold the data associated with the index.
275 If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED.
276
277 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
278 @param[in] AuthSession Auth Session context
279 @param[in] Auth The authorization data.
280 @param[in] NvPublic The public area of the index.
281
282 @retval EFI_SUCCESS Operation completed successfully.
283 @retval EFI_DEVICE_ERROR The command was unsuccessful.
284 @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined.
285 **/
286 EFI_STATUS
287 EFIAPI
288 Tpm2NvDefineSpace (
289 IN TPMI_RH_PROVISION AuthHandle,
290 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
291 IN TPM2B_AUTH *Auth,
292 IN TPM2B_NV_PUBLIC *NvPublic
293 )
294 {
295 EFI_STATUS Status;
296 TPM2_NV_DEFINESPACE_COMMAND SendBuffer;
297 TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer;
298 UINT32 SendBufferSize;
299 UINT32 RecvBufferSize;
300 UINT16 NvPublicSize;
301 UINT8 *Buffer;
302 UINT32 SessionInfoSize;
303 TPM_RC ResponseCode;
304
305 //
306 // Construct command
307 //
308 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
309 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace);
310 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
311
312 //
313 // Add in Auth session
314 //
315 Buffer = (UINT8 *)&SendBuffer.AuthSession;
316
317 // sessionInfoSize
318 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
319 Buffer += SessionInfoSize;
320 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
321
322 //
323 // IndexAuth
324 //
325 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size));
326 Buffer += sizeof(UINT16);
327 CopyMem(Buffer, Auth->buffer, Auth->size);
328 Buffer += Auth->size;
329
330 //
331 // NvPublic
332 //
333 NvPublicSize = NvPublic->size;
334
335 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize));
336 Buffer += sizeof(UINT16);
337 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex));
338 Buffer += sizeof(UINT32);
339 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg));
340 Buffer += sizeof(UINT16);
341 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes)));
342 Buffer += sizeof(UINT32);
343 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size));
344 Buffer += sizeof(UINT16);
345 CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size);
346 Buffer += NvPublic->nvPublic.authPolicy.size;
347 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize));
348 Buffer += sizeof(UINT16);
349
350 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
351 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
352
353 //
354 // send Tpm command
355 //
356 RecvBufferSize = sizeof (RecvBuffer);
357 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
358 if (EFI_ERROR (Status)) {
359 goto Done;
360 }
361
362 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
363 DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));
364 Status = EFI_DEVICE_ERROR;
365 goto Done;
366 }
367
368 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
369 if (ResponseCode != TPM_RC_SUCCESS) {
370 DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
371 }
372 switch (ResponseCode) {
373 case TPM_RC_SUCCESS:
374 // return data
375 break;
376 case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo:
377 case TPM_RC_SIZE + RC_NV_DefineSpace_auth:
378 Status = EFI_BAD_BUFFER_SIZE;
379 break;
380 case TPM_RC_ATTRIBUTES:
381 case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo:
382 Status = EFI_UNSUPPORTED;
383 break;
384 case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle:
385 Status = EFI_INVALID_PARAMETER;
386 break;
387 case TPM_RC_NV_DEFINED:
388 Status = EFI_ALREADY_STARTED;
389 break;
390 case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo:
391 case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle:
392 Status = EFI_INVALID_PARAMETER;
393 break;
394 case TPM_RC_NV_SPACE:
395 Status = EFI_OUT_OF_RESOURCES;
396 break;
397 default:
398 Status = EFI_DEVICE_ERROR;
399 break;
400 }
401
402 Done:
403 //
404 // Clear AuthSession Content
405 //
406 ZeroMem (&SendBuffer, sizeof(SendBuffer));
407 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
408 return Status;
409 }
410
411 /**
412 This command removes an index from the TPM.
413
414 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
415 @param[in] NvIndex The NV Index.
416 @param[in] AuthSession Auth Session context
417
418 @retval EFI_SUCCESS Operation completed successfully.
419 @retval EFI_DEVICE_ERROR The command was unsuccessful.
420 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
421 **/
422 EFI_STATUS
423 EFIAPI
424 Tpm2NvUndefineSpace (
425 IN TPMI_RH_PROVISION AuthHandle,
426 IN TPMI_RH_NV_INDEX NvIndex,
427 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
428 )
429 {
430 EFI_STATUS Status;
431 TPM2_NV_UNDEFINESPACE_COMMAND SendBuffer;
432 TPM2_NV_UNDEFINESPACE_RESPONSE RecvBuffer;
433 UINT32 SendBufferSize;
434 UINT32 RecvBufferSize;
435 UINT8 *Buffer;
436 UINT32 SessionInfoSize;
437 TPM_RC ResponseCode;
438
439 //
440 // Construct command
441 //
442 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
443 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_UndefineSpace);
444
445 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
446 SendBuffer.NvIndex = SwapBytes32 (NvIndex);
447
448 //
449 // Add in Auth session
450 //
451 Buffer = (UINT8 *)&SendBuffer.AuthSession;
452
453 // sessionInfoSize
454 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
455 Buffer += SessionInfoSize;
456 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
457
458 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
459 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
460
461 //
462 // send Tpm command
463 //
464 RecvBufferSize = sizeof (RecvBuffer);
465 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
466 if (EFI_ERROR (Status)) {
467 goto Done;
468 }
469
470 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
471 DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize));
472 Status = EFI_DEVICE_ERROR;
473 goto Done;
474 }
475
476 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
477 if (ResponseCode != TPM_RC_SUCCESS) {
478 DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
479 }
480 switch (ResponseCode) {
481 case TPM_RC_SUCCESS:
482 // return data
483 break;
484 case TPM_RC_ATTRIBUTES:
485 case TPM_RC_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex:
486 Status = EFI_UNSUPPORTED;
487 break;
488 case TPM_RC_NV_AUTHORIZATION:
489 Status = EFI_SECURITY_VIOLATION;
490 break;
491 case TPM_RC_HANDLE + RC_NV_UndefineSpace_nvIndex: // TPM_RC_NV_DEFINED:
492 Status = EFI_NOT_FOUND;
493 break;
494 case TPM_RC_HANDLE + RC_NV_UndefineSpace_authHandle: // TPM_RC_NV_DEFINED:
495 Status = EFI_INVALID_PARAMETER;
496 break;
497 case TPM_RC_VALUE + RC_NV_UndefineSpace_authHandle:
498 case TPM_RC_VALUE + RC_NV_UndefineSpace_nvIndex:
499 Status = EFI_INVALID_PARAMETER;
500 break;
501 default:
502 Status = EFI_DEVICE_ERROR;
503 break;
504 }
505
506 Done:
507 //
508 // Clear AuthSession Content
509 //
510 ZeroMem (&SendBuffer, sizeof(SendBuffer));
511 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
512 return Status;
513 }
514
515 /**
516 This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace().
517
518 @param[in] AuthHandle the handle indicating the source of the authorization value.
519 @param[in] NvIndex The index to be read.
520 @param[in] AuthSession Auth Session context
521 @param[in] Size Number of bytes to read.
522 @param[in] Offset Byte offset into the area.
523 @param[in,out] OutData The data read.
524
525 @retval EFI_SUCCESS Operation completed successfully.
526 @retval EFI_DEVICE_ERROR The command was unsuccessful.
527 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
528 **/
529 EFI_STATUS
530 EFIAPI
531 Tpm2NvRead (
532 IN TPMI_RH_NV_AUTH AuthHandle,
533 IN TPMI_RH_NV_INDEX NvIndex,
534 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
535 IN UINT16 Size,
536 IN UINT16 Offset,
537 IN OUT TPM2B_MAX_BUFFER *OutData
538 )
539 {
540 EFI_STATUS Status;
541 TPM2_NV_READ_COMMAND SendBuffer;
542 TPM2_NV_READ_RESPONSE RecvBuffer;
543 UINT32 SendBufferSize;
544 UINT32 RecvBufferSize;
545 UINT8 *Buffer;
546 UINT32 SessionInfoSize;
547 TPM_RC ResponseCode;
548
549 //
550 // Construct command
551 //
552 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
553 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Read);
554
555 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
556 SendBuffer.NvIndex = SwapBytes32 (NvIndex);
557
558 //
559 // Add in Auth session
560 //
561 Buffer = (UINT8 *)&SendBuffer.AuthSession;
562
563 // sessionInfoSize
564 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
565 Buffer += SessionInfoSize;
566 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
567
568 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Size));
569 Buffer += sizeof(UINT16);
570 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));
571 Buffer += sizeof(UINT16);
572
573 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
574 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
575
576 //
577 // send Tpm command
578 //
579 RecvBufferSize = sizeof (RecvBuffer);
580 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
581 if (EFI_ERROR (Status)) {
582 goto Done;
583 }
584
585 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
586 DEBUG ((EFI_D_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize));
587 Status = EFI_DEVICE_ERROR;
588 goto Done;
589 }
590 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
591 if (ResponseCode != TPM_RC_SUCCESS) {
592 DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode));
593 }
594 switch (ResponseCode) {
595 case TPM_RC_SUCCESS:
596 // return data
597 break;
598 case TPM_RC_NV_AUTHORIZATION:
599 Status = EFI_SECURITY_VIOLATION;
600 break;
601 case TPM_RC_NV_LOCKED:
602 Status = EFI_ACCESS_DENIED;
603 break;
604 case TPM_RC_NV_RANGE:
605 Status = EFI_BAD_BUFFER_SIZE;
606 break;
607 case TPM_RC_NV_UNINITIALIZED:
608 Status = EFI_NOT_READY;
609 break;
610 case TPM_RC_HANDLE + RC_NV_Read_nvIndex: // TPM_RC_NV_DEFINED:
611 Status = EFI_NOT_FOUND;
612 break;
613 case TPM_RC_HANDLE + RC_NV_Read_authHandle: // TPM_RC_NV_DEFINED:
614 Status = EFI_INVALID_PARAMETER;
615 break;
616 case TPM_RC_VALUE + RC_NV_Read_nvIndex:
617 case TPM_RC_VALUE + RC_NV_Read_authHandle:
618 Status = EFI_INVALID_PARAMETER;
619 break;
620 case TPM_RC_BAD_AUTH + RC_NV_Read_authHandle + TPM_RC_S:
621 Status = EFI_INVALID_PARAMETER;
622 break;
623 case TPM_RC_AUTH_UNAVAILABLE:
624 Status = EFI_INVALID_PARAMETER;
625 break;
626 case TPM_RC_AUTH_FAIL + RC_NV_Read_authHandle + TPM_RC_S:
627 Status = EFI_INVALID_PARAMETER;
628 break;
629 case TPM_RC_ATTRIBUTES + RC_NV_Read_authHandle + TPM_RC_S:
630 Status = EFI_UNSUPPORTED;
631 break;
632 default:
633 Status = EFI_DEVICE_ERROR;
634 break;
635 }
636 if (Status != EFI_SUCCESS) {
637 goto Done;
638 }
639
640 //
641 // Return the response
642 //
643 OutData->size = SwapBytes16 (RecvBuffer.Data.size);
644 if (OutData->size > MAX_DIGEST_BUFFER) {
645 DEBUG ((DEBUG_ERROR, "Tpm2NvRead - OutData->size error %x\n", OutData->size));
646 Status = EFI_DEVICE_ERROR;
647 goto Done;
648 }
649
650 CopyMem (OutData->buffer, &RecvBuffer.Data.buffer, OutData->size);
651
652 Done:
653 //
654 // Clear AuthSession Content
655 //
656 ZeroMem (&SendBuffer, sizeof(SendBuffer));
657 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
658 return Status;
659 }
660
661 /**
662 This command writes a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().
663
664 @param[in] AuthHandle the handle indicating the source of the authorization value.
665 @param[in] NvIndex The NV Index of the area to write.
666 @param[in] AuthSession Auth Session context
667 @param[in] InData The data to write.
668 @param[in] Offset The offset into the NV Area.
669
670 @retval EFI_SUCCESS Operation completed successfully.
671 @retval EFI_DEVICE_ERROR The command was unsuccessful.
672 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
673 **/
674 EFI_STATUS
675 EFIAPI
676 Tpm2NvWrite (
677 IN TPMI_RH_NV_AUTH AuthHandle,
678 IN TPMI_RH_NV_INDEX NvIndex,
679 IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
680 IN TPM2B_MAX_BUFFER *InData,
681 IN UINT16 Offset
682 )
683 {
684 EFI_STATUS Status;
685 TPM2_NV_WRITE_COMMAND SendBuffer;
686 TPM2_NV_WRITE_RESPONSE RecvBuffer;
687 UINT32 SendBufferSize;
688 UINT32 RecvBufferSize;
689 UINT8 *Buffer;
690 UINT32 SessionInfoSize;
691 TPM_RC ResponseCode;
692
693 //
694 // Construct command
695 //
696 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
697 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_Write);
698
699 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
700 SendBuffer.NvIndex = SwapBytes32 (NvIndex);
701
702 //
703 // Add in Auth session
704 //
705 Buffer = (UINT8 *)&SendBuffer.AuthSession;
706
707 // sessionInfoSize
708 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
709 Buffer += SessionInfoSize;
710 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
711
712 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size));
713 Buffer += sizeof(UINT16);
714 CopyMem (Buffer, InData->buffer, InData->size);
715 Buffer += InData->size;
716 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Offset));
717 Buffer += sizeof(UINT16);
718
719 SendBufferSize = (UINT32) (Buffer - (UINT8 *)&SendBuffer);
720 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
721
722 //
723 // send Tpm command
724 //
725 RecvBufferSize = sizeof (RecvBuffer);
726 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
727 if (EFI_ERROR (Status)) {
728 goto Done;
729 }
730
731 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
732 DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize));
733 Status = EFI_DEVICE_ERROR;
734 goto Done;
735 }
736 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
737 if (ResponseCode != TPM_RC_SUCCESS) {
738 DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode));
739 }
740 switch (ResponseCode) {
741 case TPM_RC_SUCCESS:
742 // return data
743 break;
744 case TPM_RC_ATTRIBUTES:
745 Status = EFI_UNSUPPORTED;
746 break;
747 case TPM_RC_NV_AUTHORIZATION:
748 Status = EFI_SECURITY_VIOLATION;
749 break;
750 case TPM_RC_NV_LOCKED:
751 Status = EFI_ACCESS_DENIED;
752 break;
753 case TPM_RC_NV_RANGE:
754 Status = EFI_BAD_BUFFER_SIZE;
755 break;
756 case TPM_RC_HANDLE + RC_NV_Write_nvIndex: // TPM_RC_NV_DEFINED:
757 Status = EFI_NOT_FOUND;
758 break;
759 case TPM_RC_HANDLE + RC_NV_Write_authHandle: // TPM_RC_NV_DEFINED:
760 Status = EFI_INVALID_PARAMETER;
761 break;
762 case TPM_RC_VALUE + RC_NV_Write_nvIndex:
763 case TPM_RC_VALUE + RC_NV_Write_authHandle:
764 Status = EFI_INVALID_PARAMETER;
765 break;
766 case TPM_RC_BAD_AUTH + RC_NV_Write_authHandle + TPM_RC_S:
767 Status = EFI_INVALID_PARAMETER;
768 break;
769 case TPM_RC_AUTH_UNAVAILABLE:
770 Status = EFI_INVALID_PARAMETER;
771 break;
772 case TPM_RC_AUTH_FAIL + RC_NV_Write_authHandle + TPM_RC_S:
773 Status = EFI_INVALID_PARAMETER;
774 break;
775 case TPM_RC_ATTRIBUTES + RC_NV_Write_authHandle + TPM_RC_S:
776 Status = EFI_UNSUPPORTED;
777 break;
778 default:
779 Status = EFI_DEVICE_ERROR;
780 break;
781 }
782
783 Done:
784 //
785 // Clear AuthSession Content
786 //
787 ZeroMem (&SendBuffer, sizeof(SendBuffer));
788 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
789 return Status;
790 }
791
792 /**
793 This command may be used to prevent further reads of the Index until the next TPM2_Startup (TPM_SU_CLEAR).
794
795 @param[in] AuthHandle the handle indicating the source of the authorization value.
796 @param[in] NvIndex The NV Index of the area to lock.
797 @param[in] AuthSession Auth Session context
798
799 @retval EFI_SUCCESS Operation completed successfully.
800 @retval EFI_DEVICE_ERROR The command was unsuccessful.
801 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
802 **/
803 EFI_STATUS
804 EFIAPI
805 Tpm2NvReadLock (
806 IN TPMI_RH_NV_AUTH AuthHandle,
807 IN TPMI_RH_NV_INDEX NvIndex,
808 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
809 )
810 {
811 EFI_STATUS Status;
812 TPM2_NV_READLOCK_COMMAND SendBuffer;
813 TPM2_NV_READLOCK_RESPONSE RecvBuffer;
814 UINT32 SendBufferSize;
815 UINT32 RecvBufferSize;
816 UINT8 *Buffer;
817 UINT32 SessionInfoSize;
818 TPM_RC ResponseCode;
819
820 //
821 // Construct command
822 //
823 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
824 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadLock);
825
826 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
827 SendBuffer.NvIndex = SwapBytes32 (NvIndex);
828
829 //
830 // Add in Auth session
831 //
832 Buffer = (UINT8 *)&SendBuffer.AuthSession;
833
834 // sessionInfoSize
835 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
836 Buffer += SessionInfoSize;
837 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
838
839 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
840 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
841
842 //
843 // send Tpm command
844 //
845 RecvBufferSize = sizeof (RecvBuffer);
846 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
847 if (EFI_ERROR (Status)) {
848 goto Done;
849 }
850
851 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
852 DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize));
853 Status = EFI_DEVICE_ERROR;
854 goto Done;
855 }
856
857 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
858 if (ResponseCode != TPM_RC_SUCCESS) {
859 DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
860 }
861 switch (ResponseCode) {
862 case TPM_RC_SUCCESS:
863 // return data
864 break;
865 default:
866 Status = EFI_DEVICE_ERROR;
867 break;
868 }
869
870 Done:
871 //
872 // Clear AuthSession Content
873 //
874 ZeroMem (&SendBuffer, sizeof(SendBuffer));
875 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
876 return Status;
877 }
878
879 /**
880 This command may be used to inhibit further writes of the Index.
881
882 @param[in] AuthHandle the handle indicating the source of the authorization value.
883 @param[in] NvIndex The NV Index of the area to lock.
884 @param[in] AuthSession Auth Session context
885
886 @retval EFI_SUCCESS Operation completed successfully.
887 @retval EFI_DEVICE_ERROR The command was unsuccessful.
888 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
889 **/
890 EFI_STATUS
891 EFIAPI
892 Tpm2NvWriteLock (
893 IN TPMI_RH_NV_AUTH AuthHandle,
894 IN TPMI_RH_NV_INDEX NvIndex,
895 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
896 )
897 {
898 EFI_STATUS Status;
899 TPM2_NV_WRITELOCK_COMMAND SendBuffer;
900 TPM2_NV_WRITELOCK_RESPONSE RecvBuffer;
901 UINT32 SendBufferSize;
902 UINT32 RecvBufferSize;
903 UINT8 *Buffer;
904 UINT32 SessionInfoSize;
905 TPM_RC ResponseCode;
906
907 //
908 // Construct command
909 //
910 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
911 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_WriteLock);
912
913 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
914 SendBuffer.NvIndex = SwapBytes32 (NvIndex);
915
916 //
917 // Add in Auth session
918 //
919 Buffer = (UINT8 *)&SendBuffer.AuthSession;
920
921 // sessionInfoSize
922 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
923 Buffer += SessionInfoSize;
924 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
925
926 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
927 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
928
929 //
930 // send Tpm command
931 //
932 RecvBufferSize = sizeof (RecvBuffer);
933 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
934 if (EFI_ERROR (Status)) {
935 goto Done;
936 }
937
938 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
939 DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));
940 Status = EFI_DEVICE_ERROR;
941 goto Done;
942 }
943
944 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
945 if (ResponseCode != TPM_RC_SUCCESS) {
946 DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
947 }
948 switch (ResponseCode) {
949 case TPM_RC_SUCCESS:
950 // return data
951 break;
952 default:
953 Status = EFI_DEVICE_ERROR;
954 break;
955 }
956
957 Done:
958 //
959 // Clear AuthSession Content
960 //
961 ZeroMem (&SendBuffer, sizeof(SendBuffer));
962 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
963 return Status;
964 }
965
966 /**
967 The command will SET TPMA_NV_WRITELOCKED for all indexes that have their TPMA_NV_GLOBALLOCK attribute SET.
968
969 @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}.
970 @param[in] AuthSession Auth Session context
971
972 @retval EFI_SUCCESS Operation completed successfully.
973 @retval EFI_DEVICE_ERROR The command was unsuccessful.
974 @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
975 **/
976 EFI_STATUS
977 EFIAPI
978 Tpm2NvGlobalWriteLock (
979 IN TPMI_RH_PROVISION AuthHandle,
980 IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL
981 )
982 {
983 EFI_STATUS Status;
984 TPM2_NV_GLOBALWRITELOCK_COMMAND SendBuffer;
985 TPM2_NV_GLOBALWRITELOCK_RESPONSE RecvBuffer;
986 UINT32 SendBufferSize;
987 UINT32 RecvBufferSize;
988 UINT8 *Buffer;
989 UINT32 SessionInfoSize;
990 TPM_RC ResponseCode;
991
992 //
993 // Construct command
994 //
995 SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
996 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_GlobalWriteLock);
997
998 SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
999
1000 //
1001 // Add in Auth session
1002 //
1003 Buffer = (UINT8 *)&SendBuffer.AuthSession;
1004
1005 // sessionInfoSize
1006 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
1007 Buffer += SessionInfoSize;
1008 SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
1009
1010 SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
1011 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
1012
1013 //
1014 // send Tpm command
1015 //
1016 RecvBufferSize = sizeof (RecvBuffer);
1017 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
1018 if (EFI_ERROR (Status)) {
1019 goto Done;
1020 }
1021
1022 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
1023 DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize));
1024 Status = EFI_DEVICE_ERROR;
1025 goto Done;
1026 }
1027
1028 ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode);
1029 if (ResponseCode != TPM_RC_SUCCESS) {
1030 DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
1031 }
1032 switch (ResponseCode) {
1033 case TPM_RC_SUCCESS:
1034 // return data
1035 break;
1036 default:
1037 Status = EFI_DEVICE_ERROR;
1038 break;
1039 }
1040
1041 Done:
1042 //
1043 // Clear AuthSession Content
1044 //
1045 ZeroMem (&SendBuffer, sizeof(SendBuffer));
1046 ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
1047 return Status;
1048 }