summaryrefslogtreecommitdiffstats
path: root/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c
blob: 7f247da301fe9a9d3f0ce6718a7dae39ab406396 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/** @file
  Implement TPM2 Session related command.

Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <IndustryStandard/UefiTcgPlatform.h>
#include <Library/Tpm2CommandLib.h>
#include <Library/Tpm2DeviceLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>

#pragma pack(1)

typedef struct {
  TPM2_COMMAND_HEADER       Header;
  TPMI_DH_OBJECT            TpmKey;
  TPMI_DH_ENTITY            Bind;
  TPM2B_NONCE               NonceCaller;
  TPM2B_ENCRYPTED_SECRET    Salt;
  TPM_SE                    SessionType;
  TPMT_SYM_DEF              Symmetric;
  TPMI_ALG_HASH             AuthHash;
} TPM2_START_AUTH_SESSION_COMMAND;

typedef struct {
  TPM2_RESPONSE_HEADER    Header;
  TPMI_SH_AUTH_SESSION    SessionHandle;
  TPM2B_NONCE             NonceTPM;
} TPM2_START_AUTH_SESSION_RESPONSE;

#pragma pack()

/**
  This command is used to start an authorization session using alternative methods of
  establishing the session key (sessionKey) that is used for authorization and encrypting value.

  @param[in]  TpmKey             Handle of a loaded decrypt key used to encrypt salt.
  @param[in]  Bind               Entity providing the authValue.
  @param[in]  NonceCaller        Initial nonceCaller, sets nonce size for the session.
  @param[in]  Salt               Value encrypted according to the type of tpmKey.
  @param[in]  SessionType        Indicates the type of the session.
  @param[in]  Symmetric          The algorithm and key size for parameter encryption.
  @param[in]  AuthHash           Hash algorithm to use for the session.
  @param[out] SessionHandle      Handle for the newly created session.
  @param[out] NonceTPM           The initial nonce from the TPM, used in the computation of the sessionKey.

  @retval EFI_SUCCESS            Operation completed successfully.
  @retval EFI_DEVICE_ERROR       The command was unsuccessful.
**/
EFI_STATUS
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
  )
{
  EFI_STATUS                        Status;
  TPM2_START_AUTH_SESSION_COMMAND   SendBuffer;
  TPM2_START_AUTH_SESSION_RESPONSE  RecvBuffer;
  UINT32                            SendBufferSize;
  UINT32                            RecvBufferSize;
  UINT8                             *Buffer;

  //
  // Construct command
  //
  SendBuffer.Header.tag         = SwapBytes16 (TPM_ST_NO_SESSIONS);
  SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_StartAuthSession);

  SendBuffer.TpmKey = SwapBytes32 (TpmKey);
  SendBuffer.Bind   = SwapBytes32 (Bind);
  Buffer            = (UINT8 *)&SendBuffer.NonceCaller;

  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NonceCaller->size));
  Buffer += sizeof (UINT16);
  CopyMem (Buffer, NonceCaller->buffer, NonceCaller->size);
  Buffer += NonceCaller->size;

  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Salt->size));
  Buffer += sizeof (UINT16);
  CopyMem (Buffer, Salt->secret, Salt->size);
  Buffer += Salt->size;

  *(TPM_SE *)Buffer = SessionType;
  Buffer++;

  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->algorithm));
  Buffer += sizeof (UINT16);
  switch (Symmetric->algorithm) {
    case TPM_ALG_NULL:
      break;
    case TPM_ALG_AES:
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.aes));
      Buffer += sizeof (UINT16);
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.aes));
      Buffer += sizeof (UINT16);
      break;
    case TPM_ALG_SM4:
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.SM4));
      Buffer += sizeof (UINT16);
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.SM4));
      Buffer += sizeof (UINT16);
      break;
    case TPM_ALG_SYMCIPHER:
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.sym));
      Buffer += sizeof (UINT16);
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.sym));
      Buffer += sizeof (UINT16);
      break;
    case TPM_ALG_XOR:
      WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.xor));
      Buffer += sizeof (UINT16);
      break;
    default:
      ASSERT (FALSE);
      DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm));
      return EFI_UNSUPPORTED;
  }

  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthHash));
  Buffer += sizeof (UINT16);

  SendBufferSize              = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);

  //
  // send Tpm command
  //
  RecvBufferSize = sizeof (RecvBuffer);
  Status         = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
    DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize));
    return EFI_DEVICE_ERROR;
  }

  if (SwapBytes32 (RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
    DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
    return EFI_DEVICE_ERROR;
  }

  //
  // Return the response
  //
  *SessionHandle = SwapBytes32 (RecvBuffer.SessionHandle);
  NonceTPM->size = SwapBytes16 (RecvBuffer.NonceTPM.size);
  if (NonceTPM->size > sizeof (TPMU_HA)) {
    DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - NonceTPM->size error %x\n", NonceTPM->size));
    return EFI_DEVICE_ERROR;
  }

  CopyMem (NonceTPM->buffer, &RecvBuffer.NonceTPM.buffer, NonceTPM->size);

  return EFI_SUCCESS;
}