1 /** @file
2   Implement TPM2 EnhancedAuthorization related command.
3 
4 Copyright (c) 2014 - 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 typedef struct {
19   TPM2_COMMAND_HEADER       Header;
20   TPMI_DH_ENTITY            AuthHandle;
21   TPMI_SH_POLICY            PolicySession;
22   UINT32                    AuthSessionSize;
23   TPMS_AUTH_COMMAND         AuthSession;
24   TPM2B_NONCE               NonceTPM;
25   TPM2B_DIGEST              CpHashA;
26   TPM2B_NONCE               PolicyRef;
27   INT32                     Expiration;
28 } TPM2_POLICY_SECRET_COMMAND;
29 
30 typedef struct {
31   TPM2_RESPONSE_HEADER      Header;
32   UINT32                    AuthSessionSize;
33   TPM2B_TIMEOUT             Timeout;
34   TPMT_TK_AUTH              PolicyTicket;
35   TPMS_AUTH_RESPONSE        AuthSession;
36 } TPM2_POLICY_SECRET_RESPONSE;
37 
38 typedef struct {
39   TPM2_COMMAND_HEADER       Header;
40   TPMI_SH_POLICY            PolicySession;
41   TPML_DIGEST               HashList;
42 } TPM2_POLICY_OR_COMMAND;
43 
44 typedef struct {
45   TPM2_RESPONSE_HEADER      Header;
46 } TPM2_POLICY_OR_RESPONSE;
47 
48 typedef struct {
49   TPM2_COMMAND_HEADER       Header;
50   TPMI_SH_POLICY            PolicySession;
51   TPM_CC                    Code;
52 } TPM2_POLICY_COMMAND_CODE_COMMAND;
53 
54 typedef struct {
55   TPM2_RESPONSE_HEADER      Header;
56 } TPM2_POLICY_COMMAND_CODE_RESPONSE;
57 
58 typedef struct {
59   TPM2_COMMAND_HEADER       Header;
60   TPMI_SH_POLICY            PolicySession;
61 } TPM2_POLICY_GET_DIGEST_COMMAND;
62 
63 typedef struct {
64   TPM2_RESPONSE_HEADER      Header;
65   TPM2B_DIGEST              PolicyHash;
66 } TPM2_POLICY_GET_DIGEST_RESPONSE;
67 
68 #pragma pack()
69 
70 /**
71   This command includes a secret-based authorization to a policy.
72   The caller proves knowledge of the secret value using an authorization
73   session using the authValue associated with authHandle.
74 
75   @param[in]  AuthHandle         Handle for an entity providing the authorization
76   @param[in]  PolicySession      Handle for the policy session being extended.
77   @param[in]  AuthSession        Auth Session context
78   @param[in]  NonceTPM           The policy nonce for the session.
79   @param[in]  CpHashA            Digest of the command parameters to which this authorization is limited.
80   @param[in]  PolicyRef          A reference to a policy relating to the authorization.
81   @param[in]  Expiration         Time when authorization will expire, measured in seconds from the time that nonceTPM was generated.
82   @param[out] Timeout            Time value used to indicate to the TPM when the ticket expires.
83   @param[out] PolicyTicket       A ticket that includes a value indicating when the authorization expires.
84 
85   @retval EFI_SUCCESS            Operation completed successfully.
86   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
87 **/
88 EFI_STATUS
89 EFIAPI
Tpm2PolicySecret(IN TPMI_DH_ENTITY AuthHandle,IN TPMI_SH_POLICY PolicySession,IN TPMS_AUTH_COMMAND * AuthSession,OPTIONAL IN TPM2B_NONCE * NonceTPM,IN TPM2B_DIGEST * CpHashA,IN TPM2B_NONCE * PolicyRef,IN INT32 Expiration,OUT TPM2B_TIMEOUT * Timeout,OUT TPMT_TK_AUTH * PolicyTicket)90 Tpm2PolicySecret (
91   IN      TPMI_DH_ENTITY            AuthHandle,
92   IN      TPMI_SH_POLICY            PolicySession,
93   IN      TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL
94   IN      TPM2B_NONCE               *NonceTPM,
95   IN      TPM2B_DIGEST              *CpHashA,
96   IN      TPM2B_NONCE               *PolicyRef,
97   IN      INT32                     Expiration,
98   OUT     TPM2B_TIMEOUT             *Timeout,
99   OUT     TPMT_TK_AUTH              *PolicyTicket
100   )
101 {
102   EFI_STATUS                        Status;
103   TPM2_POLICY_SECRET_COMMAND        SendBuffer;
104   TPM2_POLICY_SECRET_RESPONSE       RecvBuffer;
105   UINT32                            SendBufferSize;
106   UINT32                            RecvBufferSize;
107   UINT8                             *Buffer;
108   UINT32                            SessionInfoSize;
109 
110   //
111   // Construct command
112   //
113   SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
114   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret);
115   SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
116   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
117 
118   //
119   // Add in Auth session
120   //
121   Buffer = (UINT8 *)&SendBuffer.AuthSession;
122 
123   // sessionInfoSize
124   SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
125   Buffer += SessionInfoSize;
126   SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
127 
128   //
129   // Real data
130   //
131   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size));
132   Buffer += sizeof(UINT16);
133   CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size);
134   Buffer += NonceTPM->size;
135 
136   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size));
137   Buffer += sizeof(UINT16);
138   CopyMem (Buffer, CpHashA->buffer, CpHashA->size);
139   Buffer += CpHashA->size;
140 
141   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size));
142   Buffer += sizeof(UINT16);
143   CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size);
144   Buffer += PolicyRef->size;
145 
146   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration));
147   Buffer += sizeof(UINT32);
148 
149   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
150   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
151 
152   //
153   // send Tpm command
154   //
155   RecvBufferSize = sizeof (RecvBuffer);
156   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
157   if (EFI_ERROR (Status)) {
158     goto Done;
159   }
160 
161   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
162     DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize));
163     Status = EFI_DEVICE_ERROR;
164     goto Done;
165   }
166   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
167     DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
168     Status = EFI_DEVICE_ERROR;
169     goto Done;
170   }
171 
172   //
173   // Return the response
174   //
175   Buffer = (UINT8 *)&RecvBuffer.Timeout;
176   Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
177   if (Timeout->size > sizeof(UINT64)) {
178     DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - Timeout->size error %x\n", Timeout->size));
179     Status = EFI_DEVICE_ERROR;
180     goto Done;
181   }
182 
183   Buffer += sizeof(UINT16);
184   CopyMem (Timeout->buffer, Buffer, Timeout->size);
185 
186   PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
187   Buffer += sizeof(UINT16);
188   PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer));
189   Buffer += sizeof(UINT32);
190   PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer));
191   Buffer += sizeof(UINT16);
192   if (PolicyTicket->digest.size > sizeof(TPMU_HA)) {
193     DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - digest.size error %x\n", PolicyTicket->digest.size));
194     Status = EFI_DEVICE_ERROR;
195     goto Done;
196   }
197 
198   CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size);
199 
200 Done:
201   //
202   // Clear AuthSession Content
203   //
204   ZeroMem (&SendBuffer, sizeof(SendBuffer));
205   ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
206   return Status;
207 }
208 
209 /**
210   This command allows options in authorizations without requiring that the TPM evaluate all of the options.
211   If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
212   satisfies the policy. This command will indicate that one of the required sets of conditions has been
213   satisfied.
214 
215   @param[in] PolicySession      Handle for the policy session being extended.
216   @param[in] HashList           the list of hashes to check for a match.
217 
218   @retval EFI_SUCCESS            Operation completed successfully.
219   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
220 **/
221 EFI_STATUS
222 EFIAPI
Tpm2PolicyOR(IN TPMI_SH_POLICY PolicySession,IN TPML_DIGEST * HashList)223 Tpm2PolicyOR (
224   IN TPMI_SH_POLICY           PolicySession,
225   IN TPML_DIGEST              *HashList
226   )
227 {
228   EFI_STATUS                        Status;
229   TPM2_POLICY_OR_COMMAND            SendBuffer;
230   TPM2_POLICY_OR_RESPONSE           RecvBuffer;
231   UINT32                            SendBufferSize;
232   UINT32                            RecvBufferSize;
233   UINT8                             *Buffer;
234   UINTN                             Index;
235 
236   //
237   // Construct command
238   //
239   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
240   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR);
241 
242   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
243   Buffer = (UINT8 *)&SendBuffer.HashList;
244   WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count));
245   Buffer += sizeof(UINT32);
246   for (Index = 0; Index < HashList->count; Index++) {
247     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size));
248     Buffer += sizeof(UINT16);
249     CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size);
250     Buffer += HashList->digests[Index].size;
251   }
252 
253   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
254   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
255 
256   //
257   // send Tpm command
258   //
259   RecvBufferSize = sizeof (RecvBuffer);
260   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
261   if (EFI_ERROR (Status)) {
262     return Status;
263   }
264 
265   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
266     DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize));
267     return EFI_DEVICE_ERROR;
268   }
269   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
270     DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
271     return EFI_DEVICE_ERROR;
272   }
273 
274   return EFI_SUCCESS;
275 }
276 
277 /**
278   This command indicates that the authorization will be limited to a specific command code.
279 
280   @param[in]  PolicySession      Handle for the policy session being extended.
281   @param[in]  Code               The allowed commandCode.
282 
283   @retval EFI_SUCCESS            Operation completed successfully.
284   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
285 **/
286 EFI_STATUS
287 EFIAPI
Tpm2PolicyCommandCode(IN TPMI_SH_POLICY PolicySession,IN TPM_CC Code)288 Tpm2PolicyCommandCode (
289   IN      TPMI_SH_POLICY            PolicySession,
290   IN      TPM_CC                    Code
291   )
292 {
293   EFI_STATUS                        Status;
294   TPM2_POLICY_COMMAND_CODE_COMMAND  SendBuffer;
295   TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer;
296   UINT32                            SendBufferSize;
297   UINT32                            RecvBufferSize;
298 
299   //
300   // Construct command
301   //
302   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
303   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode);
304 
305   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
306   SendBuffer.Code = SwapBytes32 (Code);
307 
308   SendBufferSize = (UINT32) sizeof (SendBuffer);
309   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
310 
311   //
312   // send Tpm command
313   //
314   RecvBufferSize = sizeof (RecvBuffer);
315   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
316   if (EFI_ERROR (Status)) {
317     return Status;
318   }
319 
320   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
321     DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize));
322     return EFI_DEVICE_ERROR;
323   }
324   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
325     DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
326     return EFI_DEVICE_ERROR;
327   }
328 
329   return EFI_SUCCESS;
330 }
331 
332 /**
333   This command returns the current policyDigest of the session. This command allows the TPM
334   to be used to perform the actions required to precompute the authPolicy for an object.
335 
336   @param[in]  PolicySession      Handle for the policy session.
337   @param[out] PolicyHash         the current value of the policyHash of policySession.
338 
339   @retval EFI_SUCCESS            Operation completed successfully.
340   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
341 **/
342 EFI_STATUS
343 EFIAPI
Tpm2PolicyGetDigest(IN TPMI_SH_POLICY PolicySession,OUT TPM2B_DIGEST * PolicyHash)344 Tpm2PolicyGetDigest (
345   IN      TPMI_SH_POLICY            PolicySession,
346      OUT  TPM2B_DIGEST              *PolicyHash
347   )
348 {
349   EFI_STATUS                        Status;
350   TPM2_POLICY_GET_DIGEST_COMMAND    SendBuffer;
351   TPM2_POLICY_GET_DIGEST_RESPONSE   RecvBuffer;
352   UINT32                            SendBufferSize;
353   UINT32                            RecvBufferSize;
354 
355   //
356   // Construct command
357   //
358   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
359   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest);
360 
361   SendBuffer.PolicySession = SwapBytes32 (PolicySession);
362 
363   SendBufferSize = (UINT32) sizeof (SendBuffer);
364   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
365 
366   //
367   // send Tpm command
368   //
369   RecvBufferSize = sizeof (RecvBuffer);
370   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
371   if (EFI_ERROR (Status)) {
372     return Status;
373   }
374 
375   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
376     DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize));
377     return EFI_DEVICE_ERROR;
378   }
379   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
380     DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
381     return EFI_DEVICE_ERROR;
382   }
383 
384   //
385   // Return the response
386   //
387   PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size);
388   if (PolicyHash->size > sizeof(TPMU_HA)) {
389     DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - PolicyHash->size error %x\n", PolicyHash->size));
390     return EFI_DEVICE_ERROR;
391   }
392 
393   CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size);
394 
395   return EFI_SUCCESS;
396 }
397