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