1/** @file
2  Implement TPM2 Session related command.
3
4Copyright (c) 2014, Intel Corporation. All rights reserved. <BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT 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
24typedef 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
35typedef 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**/
60EFI_STATUS
61EFIAPI
62Tpm2StartAuthSession (
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