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