1 /** @file
2   Implement TPM2 Session 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_OBJECT            TpmKey;
21   TPMI_DH_ENTITY            Bind;
22   TPM2B_NONCE               NonceCaller;
23   TPM2B_ENCRYPTED_SECRET    Salt;
24   TPM_SE                    SessionType;
25   TPMT_SYM_DEF              Symmetric;
26   TPMI_ALG_HASH             AuthHash;
27 } TPM2_START_AUTH_SESSION_COMMAND;
28 
29 typedef struct {
30   TPM2_RESPONSE_HEADER      Header;
31   TPMI_SH_AUTH_SESSION      SessionHandle;
32   TPM2B_NONCE               NonceTPM;
33 } TPM2_START_AUTH_SESSION_RESPONSE;
34 
35 #pragma pack()
36 
37 /**
38   This command is used to start an authorization session using alternative methods of
39   establishing the session key (sessionKey) that is used for authorization and encrypting value.
40 
41   @param[in]  TpmKey             Handle of a loaded decrypt key used to encrypt salt.
42   @param[in]  Bind               Entity providing the authValue.
43   @param[in]  NonceCaller        Initial nonceCaller, sets nonce size for the session.
44   @param[in]  Salt               Value encrypted according to the type of tpmKey.
45   @param[in]  SessionType        Indicates the type of the session.
46   @param[in]  Symmetric          The algorithm and key size for parameter encryption.
47   @param[in]  AuthHash           Hash algorithm to use for the session.
48   @param[out] SessionHandle      Handle for the newly created session.
49   @param[out] NonceTPM           The initial nonce from the TPM, used in the computation of the sessionKey.
50 
51   @retval EFI_SUCCESS            Operation completed successfully.
52   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
53 **/
54 EFI_STATUS
55 EFIAPI
Tpm2StartAuthSession(IN TPMI_DH_OBJECT TpmKey,IN TPMI_DH_ENTITY Bind,IN TPM2B_NONCE * NonceCaller,IN TPM2B_ENCRYPTED_SECRET * Salt,IN TPM_SE SessionType,IN TPMT_SYM_DEF * Symmetric,IN TPMI_ALG_HASH AuthHash,OUT TPMI_SH_AUTH_SESSION * SessionHandle,OUT TPM2B_NONCE * NonceTPM)56 Tpm2StartAuthSession (
57   IN      TPMI_DH_OBJECT            TpmKey,
58   IN      TPMI_DH_ENTITY            Bind,
59   IN      TPM2B_NONCE               *NonceCaller,
60   IN      TPM2B_ENCRYPTED_SECRET    *Salt,
61   IN      TPM_SE                    SessionType,
62   IN      TPMT_SYM_DEF              *Symmetric,
63   IN      TPMI_ALG_HASH             AuthHash,
64      OUT  TPMI_SH_AUTH_SESSION      *SessionHandle,
65      OUT  TPM2B_NONCE               *NonceTPM
66   )
67 {
68   EFI_STATUS                        Status;
69   TPM2_START_AUTH_SESSION_COMMAND   SendBuffer;
70   TPM2_START_AUTH_SESSION_RESPONSE  RecvBuffer;
71   UINT32                            SendBufferSize;
72   UINT32                            RecvBufferSize;
73   UINT8                             *Buffer;
74 
75   //
76   // Construct command
77   //
78   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
79   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_StartAuthSession);
80 
81   SendBuffer.TpmKey = SwapBytes32 (TpmKey);
82   SendBuffer.Bind = SwapBytes32 (Bind);
83   Buffer = (UINT8 *)&SendBuffer.NonceCaller;
84 
85   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NonceCaller->size));
86   Buffer += sizeof(UINT16);
87   CopyMem (Buffer, NonceCaller->buffer, NonceCaller->size);
88   Buffer += NonceCaller->size;
89 
90   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Salt->size));
91   Buffer += sizeof(UINT16);
92   CopyMem (Buffer, Salt->secret, Salt->size);
93   Buffer += Salt->size;
94 
95   *(TPM_SE *)Buffer = SessionType;
96   Buffer++;
97 
98   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->algorithm));
99   Buffer += sizeof(UINT16);
100   switch (Symmetric->algorithm) {
101   case TPM_ALG_NULL:
102     break;
103   case TPM_ALG_AES:
104     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.aes));
105     Buffer += sizeof(UINT16);
106     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.aes));
107     Buffer += sizeof(UINT16);
108     break;
109   case TPM_ALG_SM4:
110     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.SM4));
111     Buffer += sizeof(UINT16);
112     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.SM4));
113     Buffer += sizeof(UINT16);
114     break;
115   case TPM_ALG_SYMCIPHER:
116     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.sym));
117     Buffer += sizeof(UINT16);
118     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.sym));
119     Buffer += sizeof(UINT16);
120     break;
121   case TPM_ALG_XOR:
122     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.xor));
123     Buffer += sizeof(UINT16);
124     break;
125   default:
126     ASSERT (FALSE);
127     DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm));
128     return EFI_UNSUPPORTED;
129   }
130 
131   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthHash));
132   Buffer += sizeof(UINT16);
133 
134   SendBufferSize = (UINT32) ((UINTN)Buffer - (UINTN)&SendBuffer);
135   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
136 
137   //
138   // send Tpm command
139   //
140   RecvBufferSize = sizeof (RecvBuffer);
141   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
142   if (EFI_ERROR (Status)) {
143     return Status;
144   }
145 
146   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
147     DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize));
148     return EFI_DEVICE_ERROR;
149   }
150   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
151     DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
152     return EFI_DEVICE_ERROR;
153   }
154 
155   //
156   // Return the response
157   //
158   *SessionHandle = SwapBytes32 (RecvBuffer.SessionHandle);
159   NonceTPM->size = SwapBytes16 (RecvBuffer.NonceTPM.size);
160   if (NonceTPM->size > sizeof(TPMU_HA)) {
161     DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - NonceTPM->size error %x\n", NonceTPM->size));
162     return EFI_DEVICE_ERROR;
163   }
164 
165   CopyMem (NonceTPM->buffer, &RecvBuffer.NonceTPM.buffer, NonceTPM->size);
166 
167   return EFI_SUCCESS;
168 }
169