1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************
3 * Copyright (c) 2017-2018, Intel Corporation
4 *
5 * All rights reserved.
6 ***********************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include <inttypes.h>
12
13 #include "session-util.h"
14 #include "sapi-util.h"
15 #include "context-util.h"
16 #include "util/tss2_endian.h"
17 #define LOGMODULE test
18 #include "util/log.h"
19
20 static SESSION *sessions = NULL;
21
22 SESSION *
get_session(TPMI_SH_AUTH_SESSION hndl)23 get_session(TPMI_SH_AUTH_SESSION hndl)
24 {
25 SESSION *s;
26
27 HASH_FIND_INT(sessions, &hndl, s);
28 return s;
29 }
30
31 static TSS2_RC
start_auth_session(SESSION * session,TSS2_TCTI_CONTEXT * tctiContext)32 start_auth_session(
33 SESSION *session,
34 TSS2_TCTI_CONTEXT *tctiContext)
35 {
36 TSS2_RC rval;
37 TPM2B_ENCRYPTED_SECRET key;
38 char label[] = "ATH";
39 TSS2_SYS_CONTEXT *tmp_context;
40 UINT16 bytes;
41
42 key.size = 0;
43
44 tmp_context = sapi_init_from_tcti_ctx(tctiContext);
45 if (tmp_context == NULL)
46 return TSS2_SYS_RC_GENERAL_FAILURE;
47
48 if (session->nonceOlder.size == 0)
49 session->nonceOlder.size = GetDigestSize(session->authHash);
50
51 memset(session->nonceOlder.buffer, '\0', session->nonceOlder.size);
52 session->nonceNewer.size = session->nonceOlder.size;
53 session->nonceTpmDecrypt.size = 0;
54 session->nonceTpmEncrypt.size = 0;
55
56 rval = Tss2_Sys_StartAuthSession(
57 tmp_context, session->tpmKey, session->bind, 0,
58 &session->nonceOlder, &session->encryptedSalt,
59 session->sessionType, &session->symmetric,
60 session->authHash, &session->sessionHandle,
61 &session->nonceNewer, 0);
62 if (rval != TPM2_RC_SUCCESS)
63 goto out;
64
65 if (session->tpmKey == TPM2_RH_NULL)
66 session->salt.size = 0;
67
68 if (session->bind == TPM2_RH_NULL)
69 session->authValueBind.size = 0;
70
71 session->sessionKey.size = 0;
72 if (session->tpmKey == TPM2_RH_NULL && session->bind == TPM2_RH_NULL)
73 goto out;
74
75 /* Generate the key used as input to the KDF. */
76 rval = ConcatSizedByteBuffer((TPM2B_MAX_BUFFER *)&key,
77 (TPM2B *)&session->authValueBind);
78 if (rval != TPM2_RC_SUCCESS) {
79 Tss2_Sys_FlushContext(tmp_context, session->sessionHandle);
80 goto out;
81 }
82
83 rval = ConcatSizedByteBuffer((TPM2B_MAX_BUFFER *)&key,
84 (TPM2B *)&session->salt);
85 if (rval != TPM2_RC_SUCCESS) {
86 Tss2_Sys_FlushContext(tmp_context, session->sessionHandle);
87 goto out;
88 }
89
90 bytes = GetDigestSize(session->authHash) * 8;
91
92 rval = KDFa(session->authHash, (TPM2B *)&key, label,
93 (TPM2B *)&session->nonceNewer,
94 (TPM2B *)&session->nonceOlder,
95 bytes, (TPM2B_MAX_BUFFER *)&session->sessionKey);
96 out:
97 sapi_teardown(tmp_context);
98 return rval;
99 }
100
101 static TSS2_RC
compute_session_auth(TSS2_SYS_CONTEXT * sysContext,SESSION * session,TPMS_AUTH_COMMAND * pSessionDataIn,bool command,TPM2_HANDLE handle1,TPM2_HANDLE handle2,TPM2_HANDLE handle3,TPM2B_MAX_BUFFER * hmacKey)102 compute_session_auth(
103 TSS2_SYS_CONTEXT *sysContext,
104 SESSION *session,
105 TPMS_AUTH_COMMAND *pSessionDataIn,
106 bool command,
107 TPM2_HANDLE handle1,
108 TPM2_HANDLE handle2,
109 TPM2_HANDLE handle3,
110 TPM2B_MAX_BUFFER *hmacKey)
111 {
112 TPM2B_DIGEST *buffer_list[7];
113 TPM2B_DIGEST pHash = TPM2B_DIGEST_INIT;
114 TPM2B sessionAttributesByteBuffer = {
115 .size = 1,
116 .buffer = pSessionDataIn->sessionAttributes
117 };
118 UINT16 i;
119 TSS2_RC rval;
120 TPM2_CC cmdCode;
121
122 rval = tpm_calc_phash(sysContext, handle1, handle2, handle3,
123 session->authHash, command, &pHash);
124 if (rval != TPM2_RC_SUCCESS)
125 return rval;
126
127 rval = Tss2_Sys_GetCommandCode(sysContext, (UINT8 *)&cmdCode);
128 if (rval != TPM2_RC_SUCCESS)
129 return rval;
130
131 /* cmdCode comes back as BigEndian; not suited for comparisons below. */
132 cmdCode = BE_TO_HOST_32(cmdCode);
133 LOGBLOB_DEBUG(hmacKey->buffer, hmacKey->size, "hmacKey=");
134
135 i = 0;
136 buffer_list[i++] = (TPM2B_DIGEST *)&pHash;
137 buffer_list[i++] = (TPM2B_DIGEST *)&session->nonceNewer;
138 buffer_list[i++] = (TPM2B_DIGEST *)&session->nonceOlder;
139 buffer_list[i++] = (TPM2B_DIGEST *)&session->nonceTpmDecrypt;
140 buffer_list[i++] = (TPM2B_DIGEST *)&session->nonceTpmEncrypt;
141 buffer_list[i++] = (TPM2B_DIGEST *)&sessionAttributesByteBuffer;
142 buffer_list[i++] = 0;
143
144 for (int j = 0; buffer_list[j] != 0; j++) {
145 LOGBLOB_DEBUG(&buffer_list[j]->buffer[0],
146 buffer_list[j]->size, "bufferlist[%d]:", j);
147 ;
148 }
149
150 rval = hmac(session->authHash, hmacKey->buffer,
151 hmacKey->size, buffer_list,
152 (TPM2B_DIGEST *)&pSessionDataIn->hmac);
153
154 if (rval != TPM2_RC_SUCCESS) {
155 LOGBLOB_ERROR(pSessionDataIn->hmac.buffer,
156 pSessionDataIn->hmac.size,
157 "HMAC Failed rval = %d !!!", rval);
158 return rval;
159 }
160 return rval;
161 }
162
163 TSS2_RC
compute_command_hmac(TSS2_SYS_CONTEXT * sysContext,TPM2_HANDLE handle1,TPM2_HANDLE handle2,TPM2_HANDLE handle3,TSS2L_SYS_AUTH_COMMAND * pSessionsDataIn)164 compute_command_hmac(
165 TSS2_SYS_CONTEXT *sysContext,
166 TPM2_HANDLE handle1,
167 TPM2_HANDLE handle2,
168 TPM2_HANDLE handle3,
169 TSS2L_SYS_AUTH_COMMAND *pSessionsDataIn)
170 {
171 TPM2_HANDLE handles[3] = {handle1, handle2, handle3};
172 ENTITY *entity;
173 SESSION *session;
174 TPM2B_MAX_BUFFER hmac_key;
175 TSS2_RC rval = TPM2_RC_SUCCESS;
176 unsigned int i;
177 unsigned int count = pSessionsDataIn->count;
178
179 if (count > 3) {
180 LOG_ERROR("Bad value for session count: %" PRIu16, count);
181 return TSS2_SYS_RC_GENERAL_FAILURE;
182 }
183
184 for (i = 0; i < count; i++) {
185 if (handles[i] == TPM2_RH_NULL)
186 break;
187
188 entity = GetEntity(handles[i]);
189 if (!entity)
190 return TSS2_SYS_RC_GENERAL_FAILURE;
191
192 session = get_session(pSessionsDataIn->auths[i].sessionHandle);
193 if (!session)
194 return TPM2_RC_SUCCESS;
195
196 CopySizedByteBuffer((TPM2B *)&hmac_key, (TPM2B *)&session->sessionKey);
197
198 if (handles[i] != session->bind || handles[i] == TPM2_RH_NULL)
199 ConcatSizedByteBuffer(&hmac_key, (TPM2B *)&entity->entityAuth);
200
201 rval = compute_session_auth(sysContext,
202 session,
203 &pSessionsDataIn->auths[i],
204 true,
205 handle1,
206 handle2,
207 handle3,
208 &hmac_key);
209 if (rval != TPM2_RC_SUCCESS)
210 break;
211 }
212 return rval;
213 }
214
check_response_hmac(TSS2_SYS_CONTEXT * sysContext,TSS2L_SYS_AUTH_COMMAND * pSessionsDataIn,TPM2_HANDLE handle1,TPM2_HANDLE handle2,TPM2_HANDLE handle3,TSS2L_SYS_AUTH_RESPONSE * pSessionsDataOut)215 TSS2_RC check_response_hmac(
216 TSS2_SYS_CONTEXT *sysContext,
217 TSS2L_SYS_AUTH_COMMAND *pSessionsDataIn,
218 TPM2_HANDLE handle1,
219 TPM2_HANDLE handle2,
220 TPM2_HANDLE handle3,
221 TSS2L_SYS_AUTH_RESPONSE *pSessionsDataOut)
222 {
223 TPM2_HANDLE handles[3] = {handle1, handle2, handle3};
224 ENTITY *entity;
225 SESSION *session;
226 TPM2B_MAX_BUFFER hmac_key;
227 TSS2_RC rval = TPM2_RC_SUCCESS;
228 unsigned int i;
229 unsigned int count = pSessionsDataIn->count;
230
231 if (count > 3) {
232 LOG_ERROR("Bad value for session count: %" PRIu16, count);
233 return TSS2_SYS_RC_GENERAL_FAILURE;
234 }
235
236 for (i = 0; i < count; i++) {
237 if (handles[i] == TPM2_RH_NULL)
238 break;
239
240 entity = GetEntity(handles[i]);
241 if (!entity)
242 return TSS2_SYS_RC_GENERAL_FAILURE;
243
244 session = get_session(pSessionsDataIn->auths[i].sessionHandle);
245 if (!session)
246 return TPM2_RC_SUCCESS;
247
248 CopySizedByteBuffer((TPM2B *)&hmac_key, (TPM2B *)&session->sessionKey);
249
250 if (handles[i] != session->bind)
251 ConcatSizedByteBuffer(&hmac_key, (TPM2B *)&entity->entityAuth);
252
253 rval = compute_session_auth(sysContext,
254 session,
255 &pSessionsDataIn->auths[i],
256 false,
257 handle1,
258 handle2,
259 handle3,
260 &hmac_key);
261
262 if (rval != TPM2_RC_SUCCESS)
263 return rval;
264
265 rval = CompareSizedByteBuffer((TPM2B *)&pSessionsDataIn->auths[i].hmac,
266 (TPM2B *)&pSessionsDataOut->auths[i].hmac);
267 if (rval != TPM2_RC_SUCCESS)
268 return TSS2_SYS_RC_GENERAL_FAILURE;
269 }
270 return rval;
271 }
272
create_auth_session(SESSION ** psession,TPMI_DH_OBJECT tpmKey,TPM2B_MAX_BUFFER * salt,TPMI_DH_ENTITY bind,TPM2B_AUTH * bindAuth,TPM2B_NONCE * nonceCaller,TPM2B_ENCRYPTED_SECRET * encryptedSalt,TPM2_SE sessionType,TPMT_SYM_DEF * symmetric,TPMI_ALG_HASH algId,TSS2_TCTI_CONTEXT * tctiContext)273 TSS2_RC create_auth_session(
274 SESSION **psession,
275 TPMI_DH_OBJECT tpmKey,
276 TPM2B_MAX_BUFFER *salt,
277 TPMI_DH_ENTITY bind,
278 TPM2B_AUTH *bindAuth,
279 TPM2B_NONCE *nonceCaller,
280 TPM2B_ENCRYPTED_SECRET *encryptedSalt,
281 TPM2_SE sessionType,
282 TPMT_SYM_DEF *symmetric,
283 TPMI_ALG_HASH algId,
284 TSS2_TCTI_CONTEXT *tctiContext)
285 {
286 TSS2_RC rval;
287 SESSION *session, *tmp;
288
289 if (psession == NULL)
290 return TSS2_SYS_RC_BAD_REFERENCE;
291
292 session = calloc(1, sizeof(SESSION));
293
294 if (!session)
295 return TSS2_SYS_RC_GENERAL_FAILURE;
296
297 session->bind = bind;
298 session->tpmKey = tpmKey;
299 CopySizedByteBuffer((TPM2B *)&session->nonceOlder, (TPM2B *)nonceCaller);
300 CopySizedByteBuffer((TPM2B *)&session->encryptedSalt, (TPM2B *)encryptedSalt);
301 session->sessionType = sessionType;
302 session->symmetric.algorithm = symmetric->algorithm;
303 session->symmetric.keyBits.sym = symmetric->keyBits.sym;
304 session->symmetric.mode.sym = symmetric->mode.sym;
305 session->authHash = algId;
306 if (bindAuth != NULL)
307 CopySizedByteBuffer((TPM2B *)&session->authValueBind, (TPM2B *)bindAuth);
308
309 if (session->tpmKey != TPM2_RH_NULL)
310 CopySizedByteBuffer((TPM2B *)&session->salt, (TPM2B *)salt);
311
312 rval = start_auth_session(session, tctiContext);
313 if (rval != TSS2_RC_SUCCESS) {
314 free(session);
315 return rval;
316 }
317 /* Make sure this session handle is not already in the table */
318 HASH_FIND_INT(sessions, &session->sessionHandle, tmp);
319 if (tmp)
320 HASH_DEL(sessions, tmp);
321
322 HASH_ADD_INT(sessions, sessionHandle, session);
323 *psession = session;
324 return TSS2_RC_SUCCESS;
325 }
326
end_auth_session(SESSION * session)327 void end_auth_session(SESSION *session)
328 {
329 HASH_DEL(sessions, session);
330 free(session);
331 }
332
roll_nonces(SESSION * session,TPM2B_NONCE * new_nonce)333 void roll_nonces(SESSION *session, TPM2B_NONCE *new_nonce)
334 {
335 session->nonceOlder = session->nonceNewer;
336 session->nonceNewer = *new_nonce;
337 }
338
339 TSS2_RC
tpm_calc_phash(TSS2_SYS_CONTEXT * sysContext,TPM2_HANDLE handle1,TPM2_HANDLE handle2,TPM2_HANDLE handle3,TPMI_ALG_HASH authHash,bool command,TPM2B_DIGEST * pHash)340 tpm_calc_phash(
341 TSS2_SYS_CONTEXT *sysContext,
342 TPM2_HANDLE handle1,
343 TPM2_HANDLE handle2,
344 TPM2_HANDLE handle3,
345 TPMI_ALG_HASH authHash,
346 bool command,
347 TPM2B_DIGEST *pHash)
348 {
349 TSS2_RC rval = TPM2_RC_SUCCESS;
350 TSS2_TCTI_CONTEXT *tcti_context;
351 UINT32 i;
352 TPM2B_NAME name1, name2, name3;
353 TPM2B_MAX_BUFFER hashInput;
354 UINT8 *hashInputPtr;
355 size_t parametersSize;
356 const uint8_t *startParams;
357 TPM2_CC cmdCode;
358
359 name1.size = 0;
360 name2.size = 0;
361 name3.size = 0;
362 hashInput.size = 0;
363
364 rval = Tss2_Sys_GetTctiContext(sysContext, &tcti_context);
365 if (rval != TPM2_RC_SUCCESS)
366 return rval;
367
368 if (command) {
369 rval = tpm_handle_to_name(tcti_context, handle1, &name1);
370 if (rval != TPM2_RC_SUCCESS)
371 return rval;
372
373 rval = tpm_handle_to_name(tcti_context, handle2, &name2);
374 if (rval != TPM2_RC_SUCCESS)
375 return rval;
376
377 rval = tpm_handle_to_name(tcti_context, handle3, &name3);
378 if (rval != TPM2_RC_SUCCESS)
379 return rval;
380
381 rval = Tss2_Sys_GetCpBuffer(sysContext, ¶metersSize, &startParams);
382 if (rval != TPM2_RC_SUCCESS)
383 return rval;
384 } else {
385 rval = Tss2_Sys_GetRpBuffer(sysContext, ¶metersSize, &startParams);
386 if (rval != TPM2_RC_SUCCESS)
387 return rval;
388
389 hashInputPtr = &(hashInput.buffer[hashInput.size]);
390 /* This is response code. Assuming 0 (success) */
391 *(UINT32 *)hashInputPtr = 0;
392 hashInput.size += 4;
393 }
394
395 rval = Tss2_Sys_GetCommandCode(sysContext, (UINT8 *)&cmdCode);
396 if (rval != TPM2_RC_SUCCESS)
397 return rval;
398
399 hashInputPtr = &(hashInput.buffer[hashInput.size]);
400 *(UINT32 *)hashInputPtr = cmdCode;
401 hashInput.size += 4;
402
403 rval = ConcatSizedByteBuffer(&hashInput, (TPM2B *)&name1);
404 if (rval != TPM2_RC_SUCCESS)
405 return rval;
406
407 rval = ConcatSizedByteBuffer(&hashInput, (TPM2B *)&name2);
408 if (rval != TPM2_RC_SUCCESS)
409 return rval;
410
411 rval = ConcatSizedByteBuffer(&hashInput, (TPM2B *)&name3);
412 if (rval != TPM2_RC_SUCCESS)
413 return rval;
414
415 if (hashInput.size + parametersSize > sizeof(hashInput.buffer))
416 return TSS2_SYS_RC_INSUFFICIENT_BUFFER;
417
418 for(i = 0; i < parametersSize; i++)
419 hashInput.buffer[hashInput.size + i ] = startParams[i];
420
421 hashInput.size += (UINT16)parametersSize;
422 LOGBLOB_DEBUG(&hashInput.buffer[0], hashInput.size, "PHASH input bytes=");
423
424 if (hashInput.size > sizeof(hashInput.buffer))
425 return TSS2_SYS_RC_INSUFFICIENT_BUFFER;
426
427 rval = hash(authHash, hashInput.buffer, hashInput.size, pHash);
428 if (rval != TPM2_RC_SUCCESS)
429 return rval;
430
431 LOGBLOB_DEBUG(&pHash->buffer[0], pHash->size, "PHASH =");
432 return rval;
433 }
434
tpm_handle_to_name(TSS2_TCTI_CONTEXT * tcti_context,TPM2_HANDLE handle,TPM2B_NAME * name)435 UINT32 tpm_handle_to_name(
436 TSS2_TCTI_CONTEXT *tcti_context,
437 TPM2_HANDLE handle,
438 TPM2B_NAME *name)
439 {
440 TSS2_RC rval;
441 TPM2B_NAME qualified_name = TPM2B_NAME_INIT;
442 TPM2B_PUBLIC public;
443 TPM2B_NV_PUBLIC nvPublic;
444 TSS2_SYS_CONTEXT *sysContext;
445 UINT8 *namePtr;
446
447 if (!tcti_context || !name)
448 return TSS2_SYS_RC_BAD_VALUE;
449
450 namePtr = name->name;
451
452 if (handle == TPM2_RH_NULL) {
453 name->size = 0;
454 return TSS2_RC_SUCCESS;
455 }
456
457 switch(handle >> TPM2_HR_SHIFT)
458 {
459 case TPM2_HT_NV_INDEX:
460 sysContext = sapi_init_from_tcti_ctx(tcti_context);
461 if (sysContext == NULL)
462 return TSS2_SYS_RC_GENERAL_FAILURE;
463
464 nvPublic.size = 0;
465 rval = Tss2_Sys_NV_ReadPublic(sysContext, handle, 0,
466 &nvPublic, name, 0);
467 sapi_teardown(sysContext);
468 break;
469
470 case TPM2_HT_TRANSIENT:
471 case TPM2_HT_PERSISTENT:
472 sysContext = sapi_init_from_tcti_ctx(tcti_context);
473 if (sysContext == NULL)
474 return TSS2_SYS_RC_GENERAL_FAILURE;
475
476 public.size = 0;
477 rval = Tss2_Sys_ReadPublic(sysContext, handle, 0,
478 &public, name, &qualified_name, 0);
479 sapi_teardown(sysContext);
480 break;
481
482 default:
483 rval = TPM2_RC_SUCCESS;
484 name->size = sizeof(TPM2_HANDLE);
485 *(TPM2_HANDLE *)namePtr = BE_TO_HOST_32(handle);
486 }
487 return rval;
488 }
489
490 TSS2_RC
KDFa(TPMI_ALG_HASH hash,TPM2B * key,const char * label,TPM2B * contextU,TPM2B * contextV,UINT16 bits,TPM2B_MAX_BUFFER * result_key)491 KDFa(
492 TPMI_ALG_HASH hash,
493 TPM2B *key,
494 const char *label,
495 TPM2B *contextU,
496 TPM2B *contextV,
497 UINT16 bits,
498 TPM2B_MAX_BUFFER *result_key)
499 {
500 TPM2B_DIGEST digest;
501 TPM2B_DIGEST tpm2blabel, tpm2bbits, tpm2bctr;
502 TPM2B_DIGEST *buffer_list[8];
503 UINT32 counter;
504 TSS2_RC rval;
505 int i, j;
506 UINT16 bytes = bits / 8;
507
508 result_key->size = 0;
509 tpm2bctr.size = 4;
510 tpm2bbits.size = 4;
511 counter = BE_TO_HOST_32(bits);
512 memcpy(tpm2bbits.buffer, &counter, 4);
513 tpm2blabel.size = strlen(label) + 1;
514 memcpy(tpm2blabel.buffer, label, tpm2blabel.size);
515
516 LOG_DEBUG("KDFA, hash = %4.4x", hash);
517 LOGBLOB_DEBUG(&key->buffer[0], key->size, "KDFA, key =");
518 LOGBLOB_DEBUG(&tpm2blabel.buffer[0], tpm2blabel.size, "KDFA, tpm2blabel =");
519 LOGBLOB_DEBUG(&contextU->buffer[0], contextU->size, "KDFA, contextU =");
520 LOGBLOB_DEBUG(&contextV->buffer[0], contextV->size, "KDFA, contextV =");
521
522 for (i = 1, j = 0; result_key->size < bytes; j = 0) {
523 counter = BE_TO_HOST_32(i++);
524 memcpy(tpm2bctr.buffer, &counter, 4);
525 buffer_list[j++] = (TPM2B_DIGEST *)&tpm2bctr;
526 buffer_list[j++] = (TPM2B_DIGEST *)&tpm2blabel;
527 buffer_list[j++] = (TPM2B_DIGEST *)contextU;
528 buffer_list[j++] = (TPM2B_DIGEST *)contextV;
529 buffer_list[j++] = (TPM2B_DIGEST *)&tpm2bbits;
530 buffer_list[j++] = NULL;
531
532 for (j = 0; buffer_list[j] != NULL; j++) {
533 LOGBLOB_DEBUG(&buffer_list[j]->buffer[0], buffer_list[j]->size, "bufferlist[%d]:", j);
534 ;
535 }
536
537 rval = hmac(hash, key->buffer, key->size, buffer_list, &digest);
538 if (rval != TPM2_RC_SUCCESS) {
539 LOGBLOB_ERROR(digest.buffer, digest.size, "HMAC Failed rval = %d", rval);
540 return rval;
541 }
542
543 ConcatSizedByteBuffer(result_key, (TPM2B *)&digest);
544 }
545
546 /* Truncate the result to the desired size. */
547 result_key->size = bytes;
548 LOGBLOB_DEBUG(result_key->buffer, result_key->size, "KDFA, key = ");
549 return TPM2_RC_SUCCESS;
550 }
551
552 static TSS2_RC
gen_session_key(SESSION * session,TPM2B_MAX_BUFFER * session_key,TPM2B_IV * iv,TPM2B_AUTH * auth_value)553 gen_session_key(
554 SESSION *session,
555 TPM2B_MAX_BUFFER *session_key,
556 TPM2B_IV *iv,
557 TPM2B_AUTH *auth_value)
558 {
559 TSS2_RC rval = TSS2_RC_SUCCESS;
560 UINT32 aes_block_size = 16;
561 TPM2B_MAX_BUFFER key, sessionValue;
562
563 if (iv == NULL || session_key == NULL)
564 return TSS2_SYS_RC_BAD_VALUE;
565
566 CopySizedByteBuffer((TPM2B *)&sessionValue, (TPM2B *)&session->sessionKey);
567 CatSizedByteBuffer((TPM2B *)&sessionValue, (TPM2B *)auth_value);
568
569 rval = KDFa (session->authHash,
570 (TPM2B *)&sessionValue,
571 "CFB",
572 (TPM2B *)&session->nonceNewer,
573 (TPM2B *)&session->nonceOlder,
574 session->symmetric.keyBits.sym + aes_block_size * 8,
575 &key);
576 if (rval != TSS2_RC_SUCCESS)
577 return rval;
578
579 if (key.size != (session->symmetric.keyBits.sym / 8) + aes_block_size)
580 return TSS2_SYS_RC_GENERAL_FAILURE;
581
582 iv->size = aes_block_size;
583 session_key->size = (session->symmetric.keyBits.sym) / 8;
584 UINT16 total_size = session_key->size + iv->size;
585 if (iv->size > sizeof (iv->buffer) ||
586 (total_size) > TPM2_MAX_DIGEST_BUFFER)
587 return TSS2_SYS_RC_GENERAL_FAILURE;
588
589 memcpy (iv->buffer, &key.buffer[session_key->size], iv->size);
590 memcpy (session_key->buffer, key.buffer, session_key->size);
591 return rval;
592 }
593
594 static TSS2_RC
encrypt_param_cfb(SESSION * session,TPM2B_MAX_BUFFER * encrypted_data,TPM2B_MAX_BUFFER * clear_data,TPM2B_AUTH * auth_value)595 encrypt_param_cfb(
596 SESSION *session,
597 TPM2B_MAX_BUFFER *encrypted_data,
598 TPM2B_MAX_BUFFER *clear_data,
599 TPM2B_AUTH *auth_value)
600 {
601 TSS2_RC rval = TSS2_RC_SUCCESS;
602 TPM2B_MAX_BUFFER encryptKey = TPM2B_MAX_BUFFER_INIT;
603 TPM2B_IV iv = TPM2B_IV_INIT;
604
605 rval = gen_session_key(session, &encryptKey, &iv, auth_value);
606 if (rval)
607 return rval;
608
609 return encrypt_cfb(encrypted_data, clear_data, &encryptKey, &iv);
610 }
611
612 static TSS2_RC
decrypt_param_cfb(SESSION * session,TPM2B_MAX_BUFFER * clear_data,TPM2B_MAX_BUFFER * encrypted_data,TPM2B_AUTH * auth_value)613 decrypt_param_cfb(
614 SESSION *session,
615 TPM2B_MAX_BUFFER *clear_data,
616 TPM2B_MAX_BUFFER *encrypted_data,
617 TPM2B_AUTH *auth_value)
618 {
619 TSS2_RC rval = TSS2_RC_SUCCESS;
620 TPM2B_MAX_BUFFER encryptKey = TPM2B_MAX_BUFFER_INIT;
621 TPM2B_IV iv = TPM2B_IV_INIT;
622
623 rval = gen_session_key(session, &encryptKey, &iv, auth_value);
624 if (rval)
625 return rval;
626
627 return decrypt_cfb(clear_data, encrypted_data, &encryptKey, &iv);
628 }
629
630 static TSS2_RC
encrypt_decrypt_xor(SESSION * session,TPM2B_MAX_BUFFER * output_data,TPM2B_MAX_BUFFER * input_data,TPM2B_AUTH * auth_value)631 encrypt_decrypt_xor(
632 SESSION *session,
633 TPM2B_MAX_BUFFER *output_data,
634 TPM2B_MAX_BUFFER *input_data,
635 TPM2B_AUTH *auth_value)
636 {
637 TSS2_RC rval = TSS2_RC_SUCCESS;
638 TPM2B_MAX_BUFFER key;
639 TPM2B_MAX_BUFFER mask = { .size = 0, .buffer = 0 };
640 UINT16 i;
641 UINT16 size = input_data->size;
642
643 if (size > TPM2_MAX_DIGEST_BUFFER) {
644 LOG_ERROR("Bad value for inputData size: %" PRIu16, size);
645 return TSS2_SYS_RC_GENERAL_FAILURE;
646 }
647
648 CopySizedByteBuffer((TPM2B *)&key, (TPM2B *)&session->sessionKey);
649 CatSizedByteBuffer((TPM2B *)&key, (TPM2B *)auth_value);
650
651 rval = KDFa(session->authHash,
652 (TPM2B *)&key,
653 "XOR",
654 (TPM2B *)&session->nonceNewer,
655 (TPM2B *)&session->nonceOlder,
656 input_data->size * 8, &mask);
657
658 if (rval)
659 return rval;
660
661 for (i = 0; i < size; i++)
662 output_data->buffer[i] = input_data->buffer[i] ^ mask.buffer[i];
663
664 output_data->size = size;
665
666 return rval;
667 }
668
669 TSS2_RC
encrypt_command_param(SESSION * session,TPM2B_MAX_BUFFER * encrypted_data,TPM2B_MAX_BUFFER * clear_data,TPM2B_AUTH * auth_value)670 encrypt_command_param(
671 SESSION *session,
672 TPM2B_MAX_BUFFER *encrypted_data,
673 TPM2B_MAX_BUFFER *clear_data,
674 TPM2B_AUTH *auth_value)
675 {
676 return session->symmetric.algorithm == TPM2_ALG_AES ?
677 encrypt_param_cfb(session, encrypted_data, clear_data, auth_value) :
678 encrypt_decrypt_xor(session, encrypted_data, clear_data, auth_value);
679 }
680
681 TSS2_RC
decrypt_response_param(SESSION * session,TPM2B_MAX_BUFFER * clear_data,TPM2B_MAX_BUFFER * encrypted_data,TPM2B_AUTH * auth_value)682 decrypt_response_param(
683 SESSION *session,
684 TPM2B_MAX_BUFFER *clear_data,
685 TPM2B_MAX_BUFFER *encrypted_data,
686 TPM2B_AUTH *auth_value)
687 {
688 return session->symmetric.algorithm == TPM2_ALG_AES ?
689 decrypt_param_cfb(session, clear_data, encrypted_data, auth_value) :
690 encrypt_decrypt_xor(session, clear_data, encrypted_data, auth_value);
691 }
692