1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************;
3 * Copyright (c) 2015-2018, Intel Corporation
4 *
5 * All rights reserved.
6 ***********************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <string.h>
13
14 #include "tss2_mu.h"
15 #include "sysapi_util.h"
16 #include "util/tss2_endian.h"
17 #define LOGMODULE sys
18 #include "util/log.h"
19
InitSysContextFields(_TSS2_SYS_CONTEXT_BLOB * ctx)20 void InitSysContextFields(_TSS2_SYS_CONTEXT_BLOB *ctx)
21 {
22 ctx->decryptAllowed = 0;
23 ctx->encryptAllowed = 0;
24 ctx->decryptNull = 0;
25 ctx->authAllowed = 0;
26 ctx->nextData = 0;
27 }
28
InitSysContextPtrs(_TSS2_SYS_CONTEXT_BLOB * ctx,size_t contextSize)29 void InitSysContextPtrs(
30 _TSS2_SYS_CONTEXT_BLOB *ctx,
31 size_t contextSize)
32 {
33 ctx->cmdBuffer = (UINT8 *)ctx + sizeof(_TSS2_SYS_CONTEXT_BLOB);
34 ctx->maxCmdSize = contextSize - sizeof(_TSS2_SYS_CONTEXT_BLOB);
35 }
36
GetCommandSize(_TSS2_SYS_CONTEXT_BLOB * ctx)37 UINT32 GetCommandSize(_TSS2_SYS_CONTEXT_BLOB *ctx)
38 {
39 return BE_TO_HOST_32(req_header_from_cxt(ctx)->commandSize);
40 }
41
CopyCommandHeader(_TSS2_SYS_CONTEXT_BLOB * ctx,TPM2_CC commandCode)42 TSS2_RC CopyCommandHeader(_TSS2_SYS_CONTEXT_BLOB *ctx, TPM2_CC commandCode)
43 {
44 TSS2_RC rval;
45
46 if (!ctx)
47 return TSS2_SYS_RC_BAD_REFERENCE;
48
49 ctx->nextData = 0;
50
51 rval = Tss2_MU_TPM2_ST_Marshal(TPM2_ST_NO_SESSIONS, ctx->cmdBuffer,
52 ctx->maxCmdSize,
53 &ctx->nextData);
54 if (rval)
55 return rval;
56
57 req_header_from_cxt(ctx)->commandCode = HOST_TO_BE_32(commandCode);
58 ctx->nextData = sizeof(TPM20_Header_In);
59 return rval;
60 }
61
62 static int GetNumCommandHandles(TPM2_CC commandCode);
63 static int GetNumResponseHandles(TPM2_CC commandCode);
64
CommonPreparePrologue(_TSS2_SYS_CONTEXT_BLOB * ctx,TPM2_CC commandCode)65 TSS2_RC CommonPreparePrologue(
66 _TSS2_SYS_CONTEXT_BLOB *ctx,
67 TPM2_CC commandCode)
68 {
69 int numCommandHandles;
70 TSS2_RC rval;
71
72 if (!ctx)
73 return TSS2_SYS_RC_BAD_REFERENCE;
74
75 InitSysContextFields(ctx);
76
77 /* Need to check stage here. */
78 if (ctx->previousStage != CMD_STAGE_INITIALIZE &&
79 ctx->previousStage != CMD_STAGE_RECEIVE_RESPONSE &&
80 ctx->previousStage != CMD_STAGE_PREPARE)
81 return TSS2_SYS_RC_BAD_SEQUENCE;
82
83 rval = CopyCommandHeader(ctx, commandCode);
84 if (rval)
85 return rval;
86
87 ctx->commandCode = commandCode;
88 ctx->numResponseHandles = GetNumResponseHandles(commandCode);
89 ctx->rspParamsSize = (UINT32 *)(ctx->cmdBuffer + sizeof(TPM20_Header_Out) +
90 (GetNumResponseHandles(commandCode) * sizeof(UINT32)));
91
92 numCommandHandles = GetNumCommandHandles(commandCode);
93 ctx->cpBuffer = ctx->cmdBuffer + ctx->nextData +
94 (numCommandHandles * sizeof(UINT32));
95 return rval;
96 }
97
CommonPrepareEpilogue(_TSS2_SYS_CONTEXT_BLOB * ctx)98 TSS2_RC CommonPrepareEpilogue(_TSS2_SYS_CONTEXT_BLOB *ctx)
99 {
100 ctx->cpBufferUsedSize = ctx->cmdBuffer + ctx->nextData - ctx->cpBuffer;
101 req_header_from_cxt(ctx)->commandSize = HOST_TO_BE_32(ctx->nextData);
102 ctx->previousStage = CMD_STAGE_PREPARE;
103
104 return TSS2_RC_SUCCESS;
105 }
106
CommonComplete(_TSS2_SYS_CONTEXT_BLOB * ctx)107 TSS2_RC CommonComplete(_TSS2_SYS_CONTEXT_BLOB *ctx)
108 {
109 UINT32 rspSize;
110 TPM2_ST tag;
111 size_t next = 0;
112 TSS2_RC rval;
113
114 if (!ctx)
115 return TSS2_SYS_RC_BAD_REFERENCE;
116
117 rspSize = BE_TO_HOST_32(resp_header_from_cxt(ctx)->responseSize);
118
119 if(rspSize > ctx->maxCmdSize) {
120 return TSS2_SYS_RC_MALFORMED_RESPONSE;
121 }
122
123 if (ctx->previousStage != CMD_STAGE_RECEIVE_RESPONSE)
124 return TSS2_SYS_RC_BAD_SEQUENCE;
125
126 ctx->nextData = (UINT8 *)ctx->rspParamsSize - ctx->cmdBuffer;
127
128 rval = Tss2_MU_TPM2_ST_Unmarshal(ctx->cmdBuffer,
129 ctx->maxCmdSize,
130 &next, &tag);
131 if (rval)
132 return rval;
133
134 /* Skipping over response params size field */
135 if (tag == TPM2_ST_SESSIONS)
136 rval = Tss2_MU_UINT32_Unmarshal(ctx->cmdBuffer,
137 ctx->maxCmdSize,
138 &ctx->nextData,
139 NULL);
140
141 return rval;
142 }
143
CommonOneCall(_TSS2_SYS_CONTEXT_BLOB * ctx,TSS2L_SYS_AUTH_COMMAND const * cmdAuthsArray,TSS2L_SYS_AUTH_RESPONSE * rspAuthsArray)144 TSS2_RC CommonOneCall(
145 _TSS2_SYS_CONTEXT_BLOB *ctx,
146 TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray,
147 TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray)
148 {
149 TSS2_RC rval;
150
151 if (cmdAuthsArray) {
152 rval = Tss2_Sys_SetCmdAuths((TSS2_SYS_CONTEXT *)ctx, cmdAuthsArray);
153 if (rval)
154 return rval;
155 }
156
157 rval = Tss2_Sys_Execute((TSS2_SYS_CONTEXT *)ctx);
158 if (rval)
159 return rval;
160
161 if (ctx->rsp_header.responseCode)
162 return ctx->rsp_header.responseCode;
163
164 if (BE_TO_HOST_16(resp_header_from_cxt(ctx)->tag) ==
165 TPM2_ST_SESSIONS && rspAuthsArray)
166 rval = Tss2_Sys_GetRspAuths((TSS2_SYS_CONTEXT *)ctx, rspAuthsArray);
167
168 return rval;
169 }
170
171 static const COMMAND_HANDLES commandArray[] =
172 {
173 { TPM2_CC_Startup, 0, 0 },
174 { TPM2_CC_Shutdown, 0, 0 },
175 { TPM2_CC_SelfTest, 0, 0 },
176 { TPM2_CC_IncrementalSelfTest, 0, 0 },
177 { TPM2_CC_GetTestResult, 0, 0 },
178 { TPM2_CC_StartAuthSession, 2, 1 },
179 { TPM2_CC_PolicyRestart, 1, 0 },
180 { TPM2_CC_Create, 1, 0 },
181 { TPM2_CC_Load, 1, 1 },
182 { TPM2_CC_LoadExternal, 0, 1 },
183 { TPM2_CC_ReadPublic, 1, 0 },
184 { TPM2_CC_ActivateCredential, 2, 0 },
185 { TPM2_CC_MakeCredential, 1, 0 },
186 { TPM2_CC_Unseal, 1, 0 },
187 { TPM2_CC_ObjectChangeAuth, 2, 0 },
188 { TPM2_CC_Duplicate, 2, 0 },
189 { TPM2_CC_Rewrap, 2, 0 },
190 { TPM2_CC_Import, 1, 0 },
191 { TPM2_CC_RSA_Encrypt, 1, 0 },
192 { TPM2_CC_RSA_Decrypt, 1, 0 },
193 { TPM2_CC_ECDH_KeyGen, 1, 0 },
194 { TPM2_CC_ECDH_ZGen, 1, 0 },
195 { TPM2_CC_ECC_Parameters, 0, 0 },
196 { TPM2_CC_ZGen_2Phase, 1, 0 },
197 { TPM2_CC_EncryptDecrypt, 1, 0 },
198 { TPM2_CC_EncryptDecrypt2, 1, 0 },
199 { TPM2_CC_Hash, 0, 0 },
200 { TPM2_CC_HMAC, 1, 0 },
201 { TPM2_CC_GetRandom, 0, 0 },
202 { TPM2_CC_StirRandom, 0, 0 },
203 { TPM2_CC_HMAC_Start, 1, 1 },
204 { TPM2_CC_HashSequenceStart, 0, 1 },
205 { TPM2_CC_SequenceUpdate, 1, 0 },
206 { TPM2_CC_SequenceComplete, 1, 0 },
207 { TPM2_CC_EventSequenceComplete, 2, 0 },
208 { TPM2_CC_Certify, 2, 0 },
209 { TPM2_CC_CertifyCreation, 2, 0 },
210 { TPM2_CC_Quote, 1, 0 },
211 { TPM2_CC_GetSessionAuditDigest, 3, 0 },
212 { TPM2_CC_GetCommandAuditDigest, 2, 0 },
213 { TPM2_CC_GetTime, 2, 0 },
214 { TPM2_CC_Commit, 1, 0 },
215 { TPM2_CC_EC_Ephemeral, 0, 0 },
216 { TPM2_CC_VerifySignature, 1, 0 },
217 { TPM2_CC_Sign, 1, 0 },
218 { TPM2_CC_SetCommandCodeAuditStatus, 1, 0 },
219 { TPM2_CC_PCR_Extend, 1, 0 },
220 { TPM2_CC_PCR_Event, 1, 0 },
221 { TPM2_CC_PCR_Read, 0, 0 },
222 { TPM2_CC_PCR_Allocate, 1, 0 },
223 { TPM2_CC_PCR_SetAuthPolicy, 1, 0 },
224 { TPM2_CC_PCR_SetAuthValue, 1, 0 },
225 { TPM2_CC_PCR_Reset, 1, 0 },
226 { TPM2_CC_PolicySigned, 2, 0 },
227 { TPM2_CC_PolicySecret, 2, 0 },
228 { TPM2_CC_PolicyTicket, 1, 0 },
229 { TPM2_CC_PolicyOR, 1, 0 },
230 { TPM2_CC_PolicyPCR, 1, 0 },
231 { TPM2_CC_PolicyLocality, 1, 0 },
232 { TPM2_CC_PolicyNV, 3, 0 },
233 { TPM2_CC_PolicyNvWritten, 1, 0 },
234 { TPM2_CC_PolicyCounterTimer, 1, 0 },
235 { TPM2_CC_PolicyCommandCode, 1, 0 },
236 { TPM2_CC_PolicyPhysicalPresence, 1, 0 },
237 { TPM2_CC_PolicyCpHash, 1, 0 },
238 { TPM2_CC_PolicyNameHash, 1, 0 },
239 { TPM2_CC_PolicyDuplicationSelect, 1, 0 },
240 { TPM2_CC_PolicyAuthorize, 1, 0 },
241 { TPM2_CC_PolicyAuthValue, 1, 0 },
242 { TPM2_CC_PolicyPassword, 1, 0 },
243 { TPM2_CC_PolicyGetDigest, 1, 0 },
244 { TPM2_CC_PolicyTemplate, 1, 0 },
245 { TPM2_CC_CreatePrimary, 1, 1 },
246 { TPM2_CC_HierarchyControl, 1, 0 },
247 { TPM2_CC_SetPrimaryPolicy, 1, 0 },
248 { TPM2_CC_ChangePPS, 1, 0 },
249 { TPM2_CC_ChangeEPS, 1, 0 },
250 { TPM2_CC_Clear, 1, 0 },
251 { TPM2_CC_ClearControl, 1, 0 },
252 { TPM2_CC_HierarchyChangeAuth, 1, 0 },
253 { TPM2_CC_DictionaryAttackLockReset, 1, 0 },
254 { TPM2_CC_DictionaryAttackParameters, 1, 0 },
255 { TPM2_CC_PP_Commands, 1, 0 },
256 { TPM2_CC_SetAlgorithmSet, 1, 0 },
257 { TPM2_CC_FieldUpgradeStart, 2, 0 },
258 { TPM2_CC_FieldUpgradeData, 0, 0 },
259 { TPM2_CC_FirmwareRead, 0, 0 },
260 { TPM2_CC_ContextSave, 1, 0 },
261 { TPM2_CC_ContextLoad, 0, 1 },
262 { TPM2_CC_FlushContext, 1, 0 },
263 { TPM2_CC_EvictControl, 2, 0 },
264 { TPM2_CC_ReadClock, 0, 0 },
265 { TPM2_CC_ClockSet, 1, 0 },
266 { TPM2_CC_ClockRateAdjust, 1, 0 },
267 { TPM2_CC_GetCapability, 0, 0 },
268 { TPM2_CC_TestParms, 0, 0 },
269 { TPM2_CC_NV_DefineSpace, 1, 0 },
270 { TPM2_CC_NV_UndefineSpace, 2, 0 },
271 { TPM2_CC_NV_UndefineSpaceSpecial, 2, 0 },
272 { TPM2_CC_NV_ReadPublic, 1, 0 },
273 { TPM2_CC_NV_Write, 2, 0 },
274 { TPM2_CC_NV_Increment, 2, 0 },
275 { TPM2_CC_NV_Extend, 2, 0 },
276 { TPM2_CC_NV_SetBits, 2, 0 },
277 { TPM2_CC_NV_WriteLock, 2, 0 },
278 { TPM2_CC_NV_GlobalWriteLock, 1, 0 },
279 { TPM2_CC_NV_Read, 2, 0 },
280 { TPM2_CC_NV_ReadLock, 2, 0 },
281 { TPM2_CC_NV_ChangeAuth, 1, 0 },
282 { TPM2_CC_NV_Certify, 3, 0 },
283 { TPM2_CC_CreateLoaded, 1, 1 },
284 { TPM2_CC_PolicyAuthorizeNV, 3, 0 },
285 { TPM2_CC_AC_GetCapability, 1, 0 },
286 { TPM2_CC_AC_Send, 3, 0 },
287 { TPM2_CC_Policy_AC_SendSelect, 1, 0 }
288 };
289
GetNumHandles(TPM2_CC commandCode,bool req)290 static int GetNumHandles(TPM2_CC commandCode, bool req)
291 {
292 uint8_t i;
293
294 for (i = 0; i < sizeof(commandArray) / sizeof(COMMAND_HANDLES); i++) {
295 if (commandCode == commandArray[i].commandCode) {
296 if (req)
297 return commandArray[i].numCommandHandles;
298 else
299 return commandArray[i].numResponseHandles;
300 }
301 }
302
303 return 0;
304 }
305
GetNumCommandHandles(TPM2_CC commandCode)306 static int GetNumCommandHandles(TPM2_CC commandCode)
307 {
308 return GetNumHandles(commandCode, 1);
309 }
310
GetNumResponseHandles(TPM2_CC commandCode)311 static int GetNumResponseHandles(TPM2_CC commandCode)
312 {
313 return GetNumHandles(commandCode, 0);
314 }
315
316 #ifdef DISABLE_WEAK_CRYPTO
IsAlgorithmWeak(TPM2_ALG_ID algorithm,TPM2_KEY_SIZE key_size)317 bool IsAlgorithmWeak(TPM2_ALG_ID algorithm, TPM2_KEY_SIZE key_size)
318 {
319 switch (algorithm) {
320 case TPM2_ALG_RSA:
321 if (key_size < 2048) {
322 LOG_ERROR("Error: weak algorithm");
323 return true;
324 }
325 break;
326 case TPM2_ALG_AES:
327 case TPM2_ALG_SM4:
328 case TPM2_ALG_CAMELLIA:
329 case TPM2_ALG_SYMCIPHER:
330 if (key_size < 128) {
331 LOG_ERROR("Error: weak algorithm");
332 return true;
333 }
334 break;
335 case TPM2_ALG_SHA1:
336 LOG_ERROR("Error: weak algorithm");
337 return true;
338 break;
339 }
340
341 return false;
342 }
343
ValidatePublicTemplate(const TPM2B_PUBLIC * pub)344 TSS2_RC ValidatePublicTemplate(const TPM2B_PUBLIC *pub)
345 {
346 const TPMT_PUBLIC *tmpl = &pub->publicArea;
347
348 switch (tmpl->type) {
349 case TPM2_ALG_RSA:
350 if (IsAlgorithmWeak(tmpl->type, tmpl->parameters.rsaDetail.keyBits) ||
351 IsAlgorithmWeak(tmpl->parameters.rsaDetail.symmetric.algorithm,
352 tmpl->parameters.rsaDetail.symmetric.keyBits.sym))
353 return TSS2_SYS_RC_BAD_VALUE;
354 break;
355 case TPM2_ALG_ECC:
356 if (IsAlgorithmWeak(tmpl->parameters.eccDetail.symmetric.algorithm,
357 tmpl->parameters.eccDetail.symmetric.keyBits.sym))
358 return TSS2_SYS_RC_BAD_VALUE;
359 break;
360 case TPM2_ALG_AES:
361 case TPM2_ALG_SM4:
362 case TPM2_ALG_CAMELLIA:
363 case TPM2_ALG_SYMCIPHER:
364 if (IsAlgorithmWeak(tmpl->type,
365 tmpl->parameters.symDetail.sym.keyBits.sym))
366 return TSS2_SYS_RC_BAD_VALUE;
367 break;
368 default:
369 if (IsAlgorithmWeak(tmpl->type, 0))
370 return TSS2_SYS_RC_BAD_VALUE;
371
372 if (IsAlgorithmWeak(tmpl->nameAlg, 0))
373 return TSS2_SYS_RC_BAD_VALUE;
374
375 }
376 return TSS2_RC_SUCCESS;
377 }
378
ValidateNV_Public(const TPM2B_NV_PUBLIC * nv_public_info)379 TSS2_RC ValidateNV_Public(const TPM2B_NV_PUBLIC *nv_public_info)
380 {
381 const TPMS_NV_PUBLIC *nv_public = &nv_public_info->nvPublic;
382
383 if (IsAlgorithmWeak(nv_public->nameAlg, 0))
384 return TSS2_SYS_RC_BAD_VALUE;
385
386 return TSS2_RC_SUCCESS;
387 }
388
ValidateTPML_PCR_SELECTION(const TPML_PCR_SELECTION * pcr_selection)389 TSS2_RC ValidateTPML_PCR_SELECTION(const TPML_PCR_SELECTION *pcr_selection)
390 {
391
392 UINT16 i;
393
394 for (i = 0; i < pcr_selection->count; i++) {
395 const TPMS_PCR_SELECTION *selection = &pcr_selection->pcrSelections[i];
396
397 if (IsAlgorithmWeak(selection->hash, 0))
398 return TSS2_SYS_RC_BAD_VALUE;
399 }
400
401 return TSS2_RC_SUCCESS;
402 }
403
404 #else
IsAlgorithmWeak(TPM2_ALG_ID algorithm,TPM2_KEY_SIZE key_size)405 bool IsAlgorithmWeak(TPM2_ALG_ID algorithm, TPM2_KEY_SIZE key_size)
406 {
407 (void) algorithm;
408 (void) key_size;
409
410 return false;
411 }
412
ValidateNV_Public(const TPM2B_NV_PUBLIC * nv_public_info)413 TSS2_RC ValidateNV_Public(const TPM2B_NV_PUBLIC *nv_public_info)
414 {
415 (void) nv_public_info;
416
417 return TSS2_RC_SUCCESS;
418 }
419
ValidatePublicTemplate(const TPM2B_PUBLIC * pub)420 TSS2_RC ValidatePublicTemplate(const TPM2B_PUBLIC *pub)
421 {
422 (void) pub;
423
424 return TSS2_RC_SUCCESS;
425 }
426
ValidateTPML_PCR_SELECTION(const TPML_PCR_SELECTION * pcr_selection)427 TSS2_RC ValidateTPML_PCR_SELECTION(const TPML_PCR_SELECTION *pcr_selection)
428 {
429 (void) pcr_selection;
430
431 return TSS2_RC_SUCCESS;
432 }
433 #endif
434