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
Tpm2NvReadPublic(IN TPMI_RH_NV_INDEX NvIndex,OUT TPM2B_NV_PUBLIC * NvPublic,OUT TPM2B_NAME * NvName)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 *)&NvPublic->nvPublic.authPolicy;
254   Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size;
255   NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
256 
257   CopyMem (NvName, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize, 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
Tpm2NvDefineSpace(IN TPMI_RH_PROVISION AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession,OPTIONAL IN TPM2B_AUTH * Auth,IN TPM2B_NV_PUBLIC * NvPublic)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
Tpm2NvUndefineSpace(IN TPMI_RH_PROVISION AuthHandle,IN TPMI_RH_NV_INDEX NvIndex,IN TPMS_AUTH_COMMAND * AuthSession OPTIONAL)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
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)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
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)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
Tpm2NvReadLock(IN TPMI_RH_NV_AUTH AuthHandle,IN TPMI_RH_NV_INDEX NvIndex,IN TPMS_AUTH_COMMAND * AuthSession OPTIONAL)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
Tpm2NvWriteLock(IN TPMI_RH_NV_AUTH AuthHandle,IN TPMI_RH_NV_INDEX NvIndex,IN TPMS_AUTH_COMMAND * AuthSession OPTIONAL)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
Tpm2NvGlobalWriteLock(IN TPMI_RH_PROVISION AuthHandle,IN TPMS_AUTH_COMMAND * AuthSession OPTIONAL)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