• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &parametersSize, &startParams);
382         if (rval != TPM2_RC_SUCCESS)
383             return rval;
384     } else {
385         rval = Tss2_Sys_GetRpBuffer(sysContext, &parametersSize, &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