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