1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3 * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4 * All rights reserved.
5 ******************************************************************************/
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include <inttypes.h>
11
12 #include "tss2_esys.h"
13 #include "esys_mu.h"
14
15 #include "esys_iutil.h"
16 #include "esys_int.h"
17 #define LOGMODULE esys
18 #include "util/log.h"
19 #include "util/aux_util.h"
20
21 /**
22 * Compare variables of type UINT16.
23 * @param[in] in1 Variable to be compared with:
24 * @param[in] in2
25 */
26 static bool
cmp_UINT16(const UINT16 * in1,const UINT16 * in2)27 cmp_UINT16(const UINT16 * in1, const UINT16 * in2)
28 {
29 LOG_TRACE("call");
30 if (*in1 == *in2)
31 return true;
32 else {
33 LOG_TRACE("cmp false");
34 return false;
35 }
36 }
37
38 /**
39 * Compare two arrays of type BYTE.
40 * @param[in] in1 array to be compared with:.
41 * @param[in] in2
42 */
43
44 static bool
cmp_BYTE_array(const BYTE * in1,size_t count1,const BYTE * in2,size_t count2)45 cmp_BYTE_array(const BYTE * in1, size_t count1, const BYTE * in2, size_t count2)
46 {
47 if (count1 != count2) {
48 LOG_TRACE("cmp false");
49 return false;
50 }
51
52 if (memcmp(in1, in2, count2) != 0) {
53 LOG_TRACE("cmp false");
54 return false;
55 }
56
57 return true;
58 }
59
60 /**
61 * Compare two variables of type TPM2B_DIGEST.
62 * @param[in] in1 variable to be compared with:
63 * @param[in] in2
64 */
65 static bool
cmp_TPM2B_DIGEST(const TPM2B_DIGEST * in1,const TPM2B_DIGEST * in2)66 cmp_TPM2B_DIGEST(const TPM2B_DIGEST * in1, const TPM2B_DIGEST * in2)
67 {
68 LOG_TRACE("call");
69
70 if (!cmp_UINT16(&in1->size, &in2->size)) {
71 LOG_TRACE("cmp false");
72 return false;
73 }
74
75 return cmp_BYTE_array((BYTE *) & in1->buffer, in1->size,
76 (BYTE *) & in2->buffer, in2->size);
77
78 return true;
79 }
80
81 /**
82 * Compare two variables of type TPM2B_NAME.
83 * @param[in] in1 variable to be compared with:
84 * @param[in] in2
85 */
86 static bool
cmp_TPM2B_NAME(const TPM2B_NAME * in1,const TPM2B_NAME * in2)87 cmp_TPM2B_NAME(const TPM2B_NAME * in1, const TPM2B_NAME * in2)
88 {
89 LOG_TRACE("call");
90
91 if (!cmp_UINT16(&in1->size, &in2->size)) {
92 LOG_TRACE("cmp false");
93 return false;
94 }
95
96 return cmp_BYTE_array((BYTE *) & in1->name, in1->size, (BYTE *) & in2->name,
97 in2->size);
98
99 return true;
100 }
101
102 /**
103 * Compare two structures of type TPM2B_AUTH.
104 * @param[in] in1 Structure to be compared with:
105 * @param[in] in1
106 */
107 static bool
cmp_TPM2B_AUTH(const TPM2B_AUTH * in1,const TPM2B_AUTH * in2)108 cmp_TPM2B_AUTH(const TPM2B_AUTH * in1, const TPM2B_AUTH * in2)
109 {
110 LOG_TRACE("call");
111 return cmp_TPM2B_DIGEST(in1, in2);
112 }
113
114 TSS2_RC
init_session_tab(ESYS_CONTEXT * esys_context,ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3)115 init_session_tab(ESYS_CONTEXT *esys_context,
116 ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3)
117 {
118 TSS2_RC r = TPM2_RC_SUCCESS;
119 ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
120 for (int i = 0; i < 3; i++) {
121 esys_context->session_type[i] = handle_tab[i];
122 if (handle_tab[i] == ESYS_TR_NONE || handle_tab[i] == ESYS_TR_PASSWORD) {
123 esys_context->session_tab[i] = NULL;
124 } else {
125 r = esys_GetResourceObject(esys_context, handle_tab[i],
126 &esys_context->session_tab[i]);
127 return_if_error(r, "Unknown resource.");
128
129 if (esys_context->session_tab[i]->rsrc.rsrcType != IESYSC_SESSION_RSRC) {
130 LOG_ERROR("Error: ESYS_TR is not a session resource.");
131 return TSS2_ESYS_RC_BAD_TR;
132 }
133 }
134
135 }
136 return r;
137 }
138
139 /** Delete all resource objects stored in the esys context.
140 *
141 * All resource objects stored in a linked list of the esys context are deleted.
142 * @param[in,out] esys_context The ESYS_CONTEXT
143 */
144 void
iesys_DeleteAllResourceObjects(ESYS_CONTEXT * esys_context)145 iesys_DeleteAllResourceObjects(ESYS_CONTEXT * esys_context)
146 {
147 RSRC_NODE_T *node_rsrc;
148 RSRC_NODE_T *next_node_rsrc;
149 for (node_rsrc = esys_context->rsrc_list; node_rsrc != NULL;
150 node_rsrc = next_node_rsrc) {
151 next_node_rsrc = node_rsrc->next;
152 SAFE_FREE(node_rsrc);
153 }
154 esys_context->rsrc_list = NULL;
155 }
156 /** Compute the TPM nonce of the session used for parameter encryption.
157 *
158 * Since only encryption session can be used an error is signaled if
159 * more encryption sessions are used.
160 * @param[in] esys_context The ESYS_CONTEXT
161 * @param[out] encryptNonceIndex The number of the session used for encryption.
162 * @param[out] encryptNonce The nonce used for encryption by TPM.
163 * @retval TSS2_RC_SUCCESS on Success.
164 * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS if more than one encrypt
165 * session is used.
166 */
167 TSS2_RC
iesys_compute_encrypt_nonce(ESYS_CONTEXT * esys_context,int * encryptNonceIdx,TPM2B_NONCE ** encryptNonce)168 iesys_compute_encrypt_nonce(ESYS_CONTEXT * esys_context,
169 int *encryptNonceIdx, TPM2B_NONCE ** encryptNonce)
170 {
171 for (int i = 0; i < 3; i++) {
172 RSRC_NODE_T *session = esys_context->session_tab[i];
173 if (session != NULL) {
174 if (session->rsrc.misc.rsrc_session.
175 sessionAttributes & TPMA_SESSION_ENCRYPT) {
176 if (*encryptNonce != NULL) {
177 /* Encrypt nonce already found */
178 return_error(TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS,
179 "More than one encrypt session");
180 }
181 *encryptNonceIdx = i;
182 *encryptNonce = &session->rsrc.misc.rsrc_session.nonceTPM;
183 }
184 }
185 }
186 return TSS2_RC_SUCCESS;
187 }
188
189 /** Computation of the command parameter(cp) hashes.
190 *
191 * The command parameter(cp) hash of the command is computed for every
192 * session. If the sessions use different hash algorithms then different cp
193 * hashes must be calculated.
194 * The names of objects with an auth index and the command buffer are used
195 * to compute the cp hash with the hash algorithm of the corresponding session.
196 * The result is stored in table together with the used hash algorithm.
197 * @param[in] esys_context The ESYS_CONTEXT
198 * @param[in] name1 The name of the first object with an auth index.
199 * @param[in] name2 The name of the second object with an auth index.
200 * @param[in] name3 The name of the third object with an auth index.
201 * @param[3] [out] cp_hash_tab An array with all cp hashes.
202 * The used hash algorithm is stored in this table to find the
203 * appropriate values for a session.
204 * @param[out] cpHashNum Number of computed cp hash values. This value
205 * corresponds to the number of used hash algorithms.
206 * @retval TSS2_RC_SUCCESS on success,
207 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
208 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if a hash algorithm is not implemented.
209 * @retval TSS2_SYS_RC_* for SAPI errors.
210 */
211 TSS2_RC
iesys_compute_cp_hashtab(ESYS_CONTEXT * esys_context,const TPM2B_NAME * name1,const TPM2B_NAME * name2,const TPM2B_NAME * name3,HASH_TAB_ITEM cp_hash_tab[3],uint8_t * cpHashNum)212 iesys_compute_cp_hashtab(ESYS_CONTEXT * esys_context,
213 const TPM2B_NAME * name1,
214 const TPM2B_NAME * name2,
215 const TPM2B_NAME * name3,
216 HASH_TAB_ITEM cp_hash_tab[3], uint8_t * cpHashNum)
217 {
218 uint8_t ccBuffer[4];
219 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
220 return_if_error(r, "Error: get command code");
221 const uint8_t *cpBuffer;
222 size_t cpBuffer_size;
223 r = Tss2_Sys_GetCpBuffer(esys_context->sys, &cpBuffer_size, &cpBuffer);
224 return_if_error(r, "Error: get cp buffer");
225 *cpHashNum = 0;
226 for (int i = 0; i < 3; i++) {
227 RSRC_NODE_T *session = esys_context->session_tab[i];
228 bool cpHashFound = false;
229 if (session != NULL) {
230 /* We do not want to compute cpHashes multiple times for the same
231 algorithm to save time and space */
232 for (int j = 0; j < *cpHashNum; j++)
233 /* Check if cpHash for this algorithm was already computed */
234 if (cp_hash_tab[j].alg ==
235 session->rsrc.misc.rsrc_session.authHash) {
236 cpHashFound = true;
237 break;
238 }
239 /* If not, we compute it and append it to the list */
240 if (!cpHashFound) {
241 cp_hash_tab[*cpHashNum].size = sizeof(TPMU_HA);
242 r = iesys_crypto_cpHash(session->rsrc.misc.rsrc_session.
243 authHash, ccBuffer, name1, name2, name3,
244 cpBuffer, cpBuffer_size,
245 &cp_hash_tab[*cpHashNum].digest[0],
246 &cp_hash_tab[*cpHashNum].size);
247 return_if_error(r, "crypto cpHash");
248
249 cp_hash_tab[*cpHashNum].alg =
250 session->rsrc.misc.rsrc_session.authHash;
251 *cpHashNum += 1;
252 }
253 }
254 }
255 return r;
256 }
257
258 /** Computation of the response parameter (rp) hashes.
259 * The response parameter (rp) hash of the response is computed for every
260 * session. If the sessions use different hash algorithms then different rp
261 * hashes must be calculated.
262 * The names of objects with an auth index and the command buffer are used
263 * to compute the cp hash with the hash algorithm of the corresponding session.
264 * The result is stored in table together with the used hash algorithm.
265 * @param[in] esys_context The ESYS_CONTEXT
266 * @param[in] rspAuths List of response
267 * @param[in] const uint8_t * rpBuffer The pointer to the response buffer
268 * @param[in] size_t rpBuffer_size The size of the response.
269 * @param[out] HASH_TAB_ITEM rp_hash_tab[3] An array with all rp hashes.
270 * The used hash algorithm is stored in this table to find the
271 * appropriate values for a session.
272 * @param[out] uint8_t Number of computed rp hash values. This value
273 * corresponds to the number of used hash algorithms.
274 * @retval TSS2_RC_SUCCESS on success.
275 * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters.
276 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if a hash algorithm is not implemented.
277 * @retval TSS2_SYS_RC_* for SAPI errors.
278 */
279 TSS2_RC
iesys_compute_rp_hashtab(ESYS_CONTEXT * esys_context,const uint8_t * rpBuffer,size_t rpBuffer_size,HASH_TAB_ITEM rp_hash_tab[3],uint8_t * rpHashNum)280 iesys_compute_rp_hashtab(ESYS_CONTEXT * esys_context,
281 const uint8_t * rpBuffer,
282 size_t rpBuffer_size,
283 HASH_TAB_ITEM rp_hash_tab[3], uint8_t * rpHashNum)
284 {
285 uint8_t rcBuffer[4] = { 0 };
286 uint8_t ccBuffer[4];
287 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
288 return_if_error(r, "Error: get command code");
289
290 for (int i = 0; i < esys_context->authsCount; i++) {
291 RSRC_NODE_T *session = esys_context->session_tab[i];
292 if (session == NULL)
293 continue;
294 bool rpHashFound = false;
295 /* We do not want to compute cpHashes multiple times for the same
296 algorithm to save time and space */
297 for (int j = 0; j < *rpHashNum; j++)
298 if (rp_hash_tab[j].alg == session->rsrc.misc.rsrc_session.authHash) {
299 rpHashFound = true;
300 break;
301 }
302 /* If not, we compute it and append it to the list */
303 if (!rpHashFound) {
304 rp_hash_tab[*rpHashNum].size = sizeof(TPMU_HA);
305 r = iesys_crypto_rpHash(session->rsrc.misc.rsrc_session.authHash,
306 rcBuffer, ccBuffer, rpBuffer, rpBuffer_size,
307 &rp_hash_tab[*rpHashNum].digest[0],
308 &rp_hash_tab[*rpHashNum].size);
309 return_if_error(r, "crypto rpHash");
310 rp_hash_tab[*rpHashNum].alg =
311 session->rsrc.misc.rsrc_session.authHash;
312 *rpHashNum += 1;
313 }
314 }
315 return TPM2_RC_SUCCESS;
316 }
317 /** Create an esys resource object corresponding to a TPM object.
318 *
319 * The esys object is appended to the resource list stored in the esys context
320 * (rsrc_list).
321 * @param[in] esys_context The ESYS_CONTEXT
322 * @param[in] esys_handle The esys handle which will be used for this object.
323 * @param[out] esys_object The new resource object.
324 * @retval TSS2_RC_SUCCESS on success.
325 * @retval TSS2_ESYS_RC_MEMORY if the object can not be allocated.
326 */
327 TSS2_RC
esys_CreateResourceObject(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,RSRC_NODE_T ** esys_object)328 esys_CreateResourceObject(ESYS_CONTEXT * esys_context,
329 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
330 {
331 RSRC_NODE_T *new_esys_object = calloc(1, sizeof(RSRC_NODE_T));
332 if (new_esys_object == NULL)
333 return_error(TSS2_ESYS_RC_MEMORY, "Out of memory.");
334 if (esys_context->rsrc_list == NULL) {
335 /* The first object of the list will be added */
336 esys_context->rsrc_list = new_esys_object;
337 new_esys_object->next = NULL;
338 } else {
339 /* The new object will become the first element of the list */
340 new_esys_object->next = esys_context->rsrc_list;
341 esys_context->rsrc_list = new_esys_object;
342 }
343 *esys_object = new_esys_object;
344 new_esys_object->esys_handle = esys_handle;
345 return TSS2_RC_SUCCESS;
346 }
347
348 /** Compute tpm handle for standard esys handles.
349 *
350 * The tpm handle ist computed for esys handles representing pcr registers and
351 * hierarchies.
352 * @parm esys_handle [in] The esys handle.
353 * @parm tpm_handle [out] The corresponding tpm handle.
354 * @retval TSS2_RC_SUCCESS on success.
355 * @retval TSS2_ESYS_RC_BAD_VALUE if no standard handle is passed.
356 */
357 TSS2_RC
iesys_handle_to_tpm_handle(ESYS_TR esys_handle,TPM2_HANDLE * tpm_handle)358 iesys_handle_to_tpm_handle(ESYS_TR esys_handle, TPM2_HANDLE * tpm_handle)
359 {
360 /* Since ESYS_TR_PCR0 is equal zero only <= ESYS_TR_PCR31 has to be checked */
361 if (esys_handle <= ESYS_TR_PCR31) {
362 *tpm_handle = (TPM2_HANDLE) esys_handle;
363 return TPM2_RC_SUCCESS;
364 }
365 if (esys_handle == ESYS_TR_RH_OWNER) {
366 *tpm_handle = TPM2_RH_OWNER;
367 return TPM2_RC_SUCCESS;
368 }
369 if (esys_handle == ESYS_TR_RH_NULL) {
370 *tpm_handle = TPM2_RH_NULL;
371 return TPM2_RC_SUCCESS;
372 }
373 if (esys_handle == ESYS_TR_RH_LOCKOUT) {
374 *tpm_handle = TPM2_RH_LOCKOUT;
375 return TPM2_RC_SUCCESS;
376 }
377 if (esys_handle == ESYS_TR_RH_ENDORSEMENT) {
378 *tpm_handle = TPM2_RH_ENDORSEMENT;
379 return TPM2_RC_SUCCESS;
380 }
381 if (esys_handle == ESYS_TR_RH_PLATFORM) {
382 *tpm_handle = TPM2_RH_PLATFORM;
383 return TPM2_RC_SUCCESS;
384 }
385 if (esys_handle == ESYS_TR_RH_PLATFORM_NV) {
386 *tpm_handle = TPM2_RH_PLATFORM_NV;
387 return TPM2_RC_SUCCESS;
388 }
389 LOG_ERROR("Error: Esys invalid ESAPI handle (%x).", esys_handle);
390 return TSS2_ESYS_RC_BAD_VALUE;
391 }
392 /** Get the type of a tpm handle.
393 *
394 * @parm handle[in] The tpm handle.
395 * @retval The part of the handle which represents the handle type.
396 */
397 TPM2_HT
iesys_get_handle_type(TPM2_HANDLE handle)398 iesys_get_handle_type(TPM2_HANDLE handle)
399 {
400 /* upper bytes of input data */
401 TPM2_HT ht = (TPM2_HT) ((handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT);
402 return ht;
403 }
404
405 /** Compute name derived from public info with a tpm name.
406 *
407 * A tpm name is computed from a public info structure and compared with a
408 * second tpm name.
409 * @param[in] publicInfo The public info for name computation.
410 * @param[in] name The name used for comparison.
411 * @retval bool indicates whether the names are equal.
412 */
413 bool
iesys_compare_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)414 iesys_compare_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
415 {
416 TSS2_RC r = TSS2_RC_SUCCESS;
417 TPM2B_NAME public_info_name;
418 if (publicInfo == NULL || name == NULL)
419 return false;
420 r = iesys_get_name(publicInfo, &public_info_name);
421 if (r != TSS2_RC_SUCCESS) {
422 LOG_DEBUG("name could not be computed.");
423 return false;
424 }
425 return cmp_TPM2B_NAME(&public_info_name, name);
426 }
427
428 /** Compute a random salt which will be used for parameter encryption.
429 *
430 * Depending in the type of TPM key used for key exchange a salt will be computed.
431 * For an ECC key an ephemeral key will be computed. This key together with the
432 * public point of the TPMs key will be used to compute a shared secret which will
433 * be used for the key derivation of the key for parameter encryption.
434 * For an RSA key a random number will be computed to derive this key. The random
435 * number will be encrypted with the TPM key.
436 * @param[in,out] esys_context The ESYS_CONTEXT. The generated salt will be
437 * stored in this context.
438 * @param[in] tpmKeyNode The esys resource object of the TPM key which will be
439 * used for key exchange.
440 * @param[out] encryptedSalt In the case of an ECC the public point of the
441 * ephemeral key will be marshaled into this buffer.
442 * In the case of a TPM key the encrypted salt will be stored.
443 * @retval TSS2_RC_SUCCESS on success.
444 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
445 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
446 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
447 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
448 * @retval TSS2_SYS_RC_* for SAPI errors.
449 */
450 TSS2_RC
iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,RSRC_NODE_T * tpmKeyNode,TPM2B_ENCRYPTED_SECRET * encryptedSalt)451 iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,
452 RSRC_NODE_T * tpmKeyNode,
453 TPM2B_ENCRYPTED_SECRET * encryptedSalt)
454 {
455 TSS2_RC r = TSS2_RC_SUCCESS;
456 size_t keyHash_size = 0;
457 size_t cSize = 0;
458 TPM2B_ECC_PARAMETER Z; /* X coordinate of privKey*publicKey */
459 TPMS_ECC_POINT Q; /* Public point of ephemeral key */
460
461 if (tpmKeyNode == 0) {
462 encryptedSalt->size = 0;
463 return TSS2_RC_SUCCESS;
464 }
465
466 TPM2B_PUBLIC pub = tpmKeyNode->rsrc.misc.rsrc_key_pub;
467 if (tpmKeyNode->rsrc.rsrcType != IESYSC_KEY_RSRC) {
468 LOG_TRACE("Public info needed.");
469 return TSS2_ESYS_RC_BAD_VALUE;
470 }
471 r = iesys_crypto_hash_get_digest_size(tpmKeyNode->rsrc.misc.
472 rsrc_key_pub.publicArea.nameAlg,
473 &keyHash_size);
474 return_if_error(r, "Hash algorithm not supported.");
475
476 switch (pub.publicArea.type) {
477 case TPM2_ALG_RSA:
478
479 iesys_crypto_random2b((TPM2B_NONCE *) & esys_context->salt,
480 keyHash_size);
481
482 /* When encrypting salts, the encryption scheme of a key is ignored and
483 TPM2_ALG_OAEP is always used. */
484 pub.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_OAEP;
485 r = iesys_crypto_pk_encrypt(&pub,
486 keyHash_size, &esys_context->salt.buffer[0],
487 sizeof(TPMU_ENCRYPTED_SECRET),
488 (BYTE *) &encryptedSalt->secret[0], &cSize,
489 "SECRET");
490 return_if_error(r, "During encryption.");
491 LOGBLOB_DEBUG(&encryptedSalt->secret[0], cSize, "IESYS encrypted salt");
492 encryptedSalt->size = cSize;
493 break;
494 case TPM2_ALG_ECC:
495 r = iesys_crypto_get_ecdh_point(&pub, sizeof(TPMU_ENCRYPTED_SECRET),
496 &Z, &Q,
497 (BYTE *) &encryptedSalt->secret[0],
498 &cSize);
499 return_if_error(r, "During computation of ECC public key.");
500 encryptedSalt->size = cSize;
501
502 /* Compute salt from Z with KDFe */
503 r = iesys_crypto_KDFe(tpmKeyNode->rsrc.misc.
504 rsrc_key_pub.publicArea.nameAlg,
505 &Z, "SECRET", &Q.x,
506 &pub.publicArea.unique.ecc.x,
507 keyHash_size*8,
508 &esys_context->salt.buffer[0]);
509 return_if_error(r, "During KDFe computation.");
510 esys_context->salt.size = keyHash_size;
511 break;
512 default:
513 LOG_ERROR("Not implemented");
514 return TSS2_ESYS_RC_GENERAL_FAILURE;
515 break;
516 }
517 return r;
518 }
519
520 /** Generate caller nonces for all sessions.
521 *
522 * For every uses session stored in context random nonce is computed.
523 * @param[in,out] esys_context The ESYS_CONTEXT. The generated nonces will be
524 * stored in this context.
525 * @retval TPM2_RC_SUCCESS on success. An possible error is:
526 * @retval TSS2_ESYS_RC_BAD_VALUE if an illegal hash algorithm value is stored
527 * in a session.
528 */
529 TSS2_RC
iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)530 iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)
531 {
532 TSS2_RC r;
533
534 for (int i = 0; i < 3; i++) {
535 RSRC_NODE_T *session = esys_context->session_tab[i];
536 if (session == NULL)
537 continue;
538
539 r = iesys_crypto_random2b(&session->rsrc.misc.rsrc_session.nonceCaller,
540 session->rsrc.misc.rsrc_session.nonceCaller.size);
541 return_if_error(r, "Error: computing caller nonce (%x).");
542 }
543 return TSS2_RC_SUCCESS;
544 }
545
546 /** Update session attributes.
547 *
548 * In case where command does not support param encryption/decryption
549 * store the original session attributes and update them accordingly.
550 * Return true is command support param encryption.
551 *
552 * @retval TRUE if command support param encryption
553 * @retval FLASE if command does not support param encryption
554 */
555 static void
iesys_update_session_flags(ESYS_CONTEXT * esys_context,IESYS_SESSION * rsrc_session)556 iesys_update_session_flags(ESYS_CONTEXT * esys_context,
557 IESYS_SESSION *rsrc_session)
558 {
559 TSS2_RC r = TSS2_RC_SUCCESS;
560 size_t param_size;
561 const uint8_t *param_buffer;
562
563 LOG_DEBUG("Checking if command supports enc/dec");
564
565 rsrc_session->origSessionAttributes = rsrc_session->sessionAttributes;
566
567 r = Tss2_Sys_GetDecryptParam(esys_context->sys,
568 ¶m_size, ¶m_buffer);
569 if (r == TSS2_SYS_RC_NO_DECRYPT_PARAM) {
570 LOG_DEBUG("clear TPMA_SESSION_DECRYPT flag");
571 rsrc_session->sessionAttributes &= ~(TPMA_SESSION_DECRYPT);
572 }
573
574 r = Tss2_Sys_GetEncryptParam(esys_context->sys,
575 ¶m_size, ¶m_buffer);
576 if (r == TSS2_SYS_RC_NO_ENCRYPT_PARAM) {
577 LOG_DEBUG("clear TPMA_SESSION_ENCRYPT flag");
578 rsrc_session->sessionAttributes &= ~(TPMA_SESSION_ENCRYPT);
579 }
580
581 LOG_DEBUG("Session Attrs 0x%x orig 0x%x",
582 rsrc_session->sessionAttributes,
583 rsrc_session->origSessionAttributes);
584 }
585
586 /** Restore session attributes.
587 *
588 * Restore original session attributes altered by iesys_update_session_flags()
589 *
590 * @retval void
591 */
592 static void
iesys_restore_session_flags(ESYS_CONTEXT * esys_context)593 iesys_restore_session_flags(ESYS_CONTEXT *esys_context)
594 {
595 LOG_DEBUG("Restoring session attribs");
596
597 for (int i = 0; i < 3; i++) {
598 RSRC_NODE_T *session = esys_context->session_tab[i];
599 if (session == NULL)
600 continue;
601 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
602 LOG_DEBUG("Orig Session %i Attrs 0x%x, altered Attrs x%x", i,
603 rsrc_session->origSessionAttributes,
604 rsrc_session->sessionAttributes);
605
606 rsrc_session->sessionAttributes = rsrc_session->origSessionAttributes;
607 }
608 }
609
610 /** Parameter encryption with AES or XOR obfuscation.
611 *
612 * One parameter of a TPM command will be encrypted with the selected method.
613 * The buffer to encrypted is determined with the SAPI function:
614 * Tss2_Sys_GetCpBuffer. If more than one encryption session es used an error
615 * will be returned. The decryption nonce of the session used for encryption
616 * will be returned and used for HMAC computation. The encryption key is
617 * derived with KDFa.
618 * @retval TSS2_RC_SUCCESS on success.
619 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
620 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
621 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
622 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
623 * @retval TSS2_SYS_RC_* for SAPI errors.
624 */
625 TSS2_RC
iesys_encrypt_param(ESYS_CONTEXT * esys_context,TPM2B_NONCE ** decryptNonce,int * decryptNonceIdx)626 iesys_encrypt_param(ESYS_CONTEXT * esys_context,
627 TPM2B_NONCE ** decryptNonce, int *decryptNonceIdx)
628 {
629 TPM2B_NONCE *encryptNonce = NULL;
630 *decryptNonceIdx = 0;
631 *decryptNonce = NULL;
632 TSS2_RC r = TSS2_RC_SUCCESS;
633 esys_context->enc_session = NULL;
634
635 for (int i = 0; i < 3; i++) {
636 RSRC_NODE_T *session = esys_context->session_tab[i];
637 if (session == NULL)
638 continue;
639 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
640 if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT)
641 return_if_notnull(encryptNonce, "More than one encrypt session",
642 TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS);
643 if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT)
644 return_if_notnull(*decryptNonce, "More than one decrypt session",
645 TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS);
646
647 iesys_update_session_flags(esys_context, rsrc_session);
648 }
649
650 for (int i = 0; i < 3; i++) {
651 RSRC_NODE_T *session = esys_context->session_tab[i];
652 if (session == NULL)
653 continue;
654 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
655 TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
656
657 if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT) {
658 esys_context->encryptNonceIdx = i;
659 encryptNonce = &rsrc_session->nonceTPM;
660 esys_context->encryptNonce = encryptNonce;
661 esys_context->enc_session = rsrc_session;
662 }
663
664 /* Session for encryption found */
665 if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT) {
666 *decryptNonceIdx = i;
667 *decryptNonce = &rsrc_session->nonceTPM;
668 size_t hlen;
669 r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
670 return_if_error(r, "get digest size");
671 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
672 if (key_len % hlen > 0)
673 key_len = key_len + hlen - (key_len % hlen);
674 uint8_t symKey[key_len];
675 size_t paramSize = 0;
676 const uint8_t *paramBuffer;
677
678 r = Tss2_Sys_GetDecryptParam(esys_context->sys, ¶mSize,
679 ¶mBuffer);
680 return_if_error(r, "Encryption not possible");
681
682 if (paramSize == 0)
683 continue;
684
685 BYTE encrypt_buffer[paramSize];
686 memcpy(&encrypt_buffer[0], paramBuffer, paramSize);
687 LOGBLOB_DEBUG(paramBuffer, paramSize, "param to encrypt");
688
689 /* AES encryption with key derived with KDFa */
690 if (symDef->algorithm == TPM2_ALG_AES) {
691 if (symDef->mode.aes != TPM2_ALG_CFB) {
692 return_error(TSS2_ESYS_RC_BAD_VALUE,
693 "Invalid symmetric mode (must be CFB)");
694 }
695 r = iesys_crypto_KDFa(rsrc_session->authHash,
696 &rsrc_session->sessionValue[0],
697 rsrc_session->sizeSessionValue, "CFB",
698 &rsrc_session->nonceCaller,
699 &rsrc_session->nonceTPM,
700 symDef->keyBits.aes + AES_BLOCK_SIZE_IN_BYTES * 8,
701 NULL, &symKey[0], FALSE);
702 return_if_error(r, "while computing KDFa");
703
704 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
705 r = iesys_crypto_sym_aes_encrypt(&symKey[0],
706 symDef->algorithm,
707 symDef->keyBits.aes,
708 symDef->mode.aes,
709 AES_BLOCK_SIZE_IN_BYTES,
710 &encrypt_buffer[0], paramSize,
711 &symKey[aes_off]);
712 return_if_error(r, "AES encryption not possible");
713 }
714 /* XOR obfuscation of parameter */
715 else if (symDef->algorithm == TPM2_ALG_XOR) {
716 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
717 &rsrc_session->sessionValue[0],
718 rsrc_session->sizeSessionValue,
719 &rsrc_session->nonceCaller,
720 &rsrc_session->nonceTPM,
721 &encrypt_buffer[0],
722 paramSize);
723 return_if_error(r, "XOR obfuscation not possible.");
724
725 } else {
726 return_error(TSS2_ESYS_RC_BAD_VALUE,
727 "Invalid symmetric algorithm (should be XOR or AES)");
728 }
729 r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
730 &encrypt_buffer[0]);
731 return_if_error(r, "Set encrypt parameter not possible");
732
733 }
734 }
735 return r;
736 }
737
738 /** Parameter decryption with AES or XOR obfuscation.
739 *
740 * One parameter of a TPM response will be decrypted with the selected method.
741 * @param[in] esys_context The ESYS_CONTEXT.
742 *
743 * @retval TSS2_RC_SUCCESS on success.
744 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
745 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
746 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
747 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
748 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
749 * @retval TSS2_SYS_RC_* for SAPI errors.
750 */
751 TSS2_RC
iesys_decrypt_param(ESYS_CONTEXT * esys_context)752 iesys_decrypt_param(ESYS_CONTEXT * esys_context)
753 {
754 TSS2_RC r;
755 const uint8_t *ciphertext;
756 size_t p2BSize;
757 size_t hlen;
758 RSRC_NODE_T *session;
759 IESYS_SESSION *rsrc_session;
760 TPMT_SYM_DEF *symDef;
761 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
762
763 session = esys_context->session_tab[esys_context->encryptNonceIdx];
764 rsrc_session = &session->rsrc.misc.rsrc_session;
765 symDef = &rsrc_session->symmetric;
766
767 r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
768 return_if_error(r, "Error");
769 if (key_len % hlen > 0)
770 key_len = key_len + hlen - (key_len % hlen);
771
772 uint8_t symKey[key_len];
773
774 r = Tss2_Sys_GetEncryptParam(esys_context->sys, &p2BSize, &ciphertext);
775 return_if_error(r, "Getting encrypt param");
776
777 UINT8 plaintext[p2BSize];
778 memcpy(&plaintext[0], ciphertext, p2BSize);
779
780 if (symDef->algorithm == TPM2_ALG_AES) {
781 /* Parameter decryption with a symmetric AES key derived by KDFa */
782 if (symDef->mode.aes != TPM2_ALG_CFB) {
783 return_error(TSS2_ESYS_RC_BAD_VALUE,
784 "Invalid symmetric mode (must be CFB)");
785 }
786 LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0],
787 rsrc_session->sessionKey.size,
788 "IESYS encrypt session key");
789
790 r = iesys_crypto_KDFa(rsrc_session->authHash,
791 &rsrc_session->sessionValue[0],
792 rsrc_session->sizeSessionValue,
793 "CFB", &rsrc_session->nonceTPM,
794 &rsrc_session->nonceCaller,
795 symDef->keyBits.aes
796 + AES_BLOCK_SIZE_IN_BYTES * 8, NULL,
797 &symKey[0], FALSE);
798 return_if_error(r, "KDFa error");
799 LOGBLOB_DEBUG(&symKey[0],
800 ((symDef->keyBits.aes +
801 AES_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8,
802 "IESYS encrypt KDFa key");
803
804 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
805 r = iesys_crypto_sym_aes_decrypt(&symKey[0],
806 symDef->algorithm,
807 symDef->keyBits.aes,
808 symDef->mode.aes,
809 AES_BLOCK_SIZE_IN_BYTES,
810 &plaintext[0], p2BSize,
811 &symKey[aes_off]);
812 return_if_error(r, "Decryption error");
813
814 r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
815 return_if_error(r, "Setting plaintext");
816 } else if (symDef->algorithm == TPM2_ALG_XOR) {
817 /* Parameter decryption with XOR obfuscation */
818 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
819 &rsrc_session->sessionValue[0],
820 rsrc_session->sizeSessionValue,
821 &rsrc_session->nonceTPM,
822 &rsrc_session->nonceCaller,
823 &plaintext[0],
824 p2BSize);
825 return_if_error(r, "XOR obfuscation not possible.");
826
827 r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
828 return_if_error(r, "Setting plaintext");
829 } else {
830 return_error(TSS2_ESYS_RC_BAD_VALUE,
831 "Invalid symmetric algorithm (should be XOR or AES)");
832 }
833 return TSS2_RC_SUCCESS;
834 }
835
836 /** Check the HMAC values of the response for all sessions.
837 *
838 * The HMAC values are computed based on the session secrets, the used nonces,
839 * the session attributes, the response hash.
840 * @param[in] esys_context The ESYS_CONTEXT.
841 * @param[in] rspAuths The list of the session auth values.
842 * @param[in] rp_hashtab The list of response hashes.
843 * @param[in] rpHashNum The number of response hashes.
844 * @retval TSS2_RC_SUCCESS on success.
845 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
846 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
847 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
848 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
849 */
850 TSS2_RC
iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,TSS2L_SYS_AUTH_RESPONSE * rspAuths,HASH_TAB_ITEM rp_hash_tab[3],uint8_t rpHashNum)851 iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,
852 TSS2L_SYS_AUTH_RESPONSE * rspAuths,
853 HASH_TAB_ITEM rp_hash_tab[3],
854 uint8_t rpHashNum)
855 {
856 TSS2_RC r;
857
858 for (int i = 0; i < rspAuths->count; i++) {
859 RSRC_NODE_T *session = esys_context->session_tab[i];
860 if (session == NULL)
861 continue;
862
863 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
864 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
865 /* A policy password session has no auth value */
866 if (rspAuths->auths[i].hmac.size != 0) {
867 LOG_ERROR("PolicyPassword session's HMAC must be 0-length.");
868 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
869 }
870 continue;
871 }
872
873 /* Find the rpHash for the hash algorithm used by this session */
874 int hi;
875 for (hi = 0; hi < rpHashNum; hi++) {
876 if (rsrc_session->authHash == rp_hash_tab[hi].alg) {
877 break;
878 }
879 }
880 if (hi == rpHashNum) {
881 LOG_ERROR("rpHash for alg %"PRIx16 " not found.",
882 rsrc_session->authHash);
883 return TSS2_ESYS_RC_GENERAL_FAILURE;
884 }
885
886 TPM2B_AUTH rp_hmac;
887 rp_hmac.size = sizeof(TPMU_HA);
888 rsrc_session->nonceTPM = rspAuths->auths[i].nonce;
889 rsrc_session->sessionAttributes =
890 rspAuths->auths[i].sessionAttributes;
891 r = iesys_crypto_authHmac(rsrc_session->authHash,
892 &rsrc_session->sessionValue[0],
893 rsrc_session->sizeHmacValue,
894 &rp_hash_tab[hi].digest[0],
895 rp_hash_tab[hi].size,
896 &rsrc_session->nonceTPM,
897 &rsrc_session->nonceCaller, NULL, NULL,
898 rspAuths->auths[i].sessionAttributes,
899 &rp_hmac);
900 return_if_error(r, "HMAC error");
901
902 if (!cmp_TPM2B_AUTH(&rspAuths->auths[i].hmac, &rp_hmac)) {
903 LOG_ERROR("TPM's response auth is invalid for session %i", i);
904 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
905 }
906 }
907 return TSS2_RC_SUCCESS;
908 }
909 /** Compute the value for check of bind authorization.
910 *
911 * This value has to be computed from the bind object in the StartAuthSession
912 * command and later checked in for corresponding object authorizations.
913 * @param[in] name The name of the bind object.
914 * @param[in] auth The authorization of the bind object.
915 * @param[out] bound_entity The value used for checking the bind authorization.
916 */
917 void
iesys_compute_bound_entity(const TPM2B_NAME * name,const TPM2B_AUTH * auth,TPM2B_NAME * bound_entity)918 iesys_compute_bound_entity(const TPM2B_NAME * name,
919 const TPM2B_AUTH * auth, TPM2B_NAME * bound_entity)
920 {
921 UINT16 i;
922 UINT16 j = 0;
923 *bound_entity = *name;
924 memset(&bound_entity->name[bound_entity->size], 0,
925 sizeof(bound_entity->name) - bound_entity->size);
926 for (i = sizeof(bound_entity->name) - auth->size;
927 i < sizeof(bound_entity->name); i++)
928 bound_entity->name[i] ^= auth->buffer[j++];
929 bound_entity->size = sizeof(bound_entity->name);
930 }
931
932 /** Predicate whether the authorization is for the object bound to the session.
933 *
934 * @param[in] name The name of the object.
935 * @param[in] auth The auth value of the object.
936 * @param[in] sesssion The session to be checked.
937 * @retval true if object is bind object of session.
938 * @retval false if not.
939 */
940 bool
iesys_is_object_bound(const TPM2B_NAME * name,const TPM2B_AUTH * auth,RSRC_NODE_T * session)941 iesys_is_object_bound(const TPM2B_NAME * name,
942 const TPM2B_AUTH * auth, RSRC_NODE_T * session)
943 {
944 TPM2B_NAME tmp;
945 if (session->rsrc.misc.rsrc_session.bound_entity.size == 0)
946 /* No bind session */
947 return false;
948 iesys_compute_bound_entity(name, auth, &tmp);
949 return cmp_TPM2B_NAME(&session->rsrc.misc.rsrc_session.bound_entity, &tmp);
950 }
951
952 /**
953 * Compute the session value
954 *
955 * This function derives the session value from the session key
956 * and the auth value. The auth value is appended to the session key.
957 * The session value is used for key derivation for parameter encryption and
958 * HMAC computation. There is one exception for HMAC key derivation: If the
959 * session is bound to an object only the session key is used. The auth value
960 * is appended only for the key used for parameter encryption.
961 * The auth value is only used if an authorization is necessary and the name
962 * of the object is not equal to the name of an used bound entity
963 * @param[in,out] session for which the session value will be computed.
964 * The value will be stored in sessionValue of the session object.
965 * The length of the object will be stored in sizeHmacValue and
966 * sizeSessionValue respectively to the purpose of usage (HMAC computation
967 * or parameter encryption).
968 * @param[in] name name of the object to be authorized (NULL if no authorization)
969 * @param[in] auth_value auth value of the object to be authorized
970 * (NULL if no authorization)
971 */
972 void
iesys_compute_session_value(RSRC_NODE_T * session,const TPM2B_NAME * name,const TPM2B_AUTH * auth_value)973 iesys_compute_session_value(RSRC_NODE_T * session,
974 const TPM2B_NAME * name,
975 const TPM2B_AUTH * auth_value)
976 {
977 if (session == NULL)
978 return;
979
980 /* First the session Key is copied into the sessionValue */
981 session->rsrc.misc.rsrc_session.sizeSessionValue
982 = session->rsrc.misc.rsrc_session.sessionKey.size;
983 memcpy(&session->rsrc.misc.rsrc_session.sessionValue[0],
984 &session->rsrc.misc.rsrc_session.sessionKey.buffer[0],
985 session->rsrc.misc.rsrc_session.sessionKey.size);
986
987 /* This requires an HMAC Session and not a password session */
988 if (session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_HMAC &&
989 session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_POLICY)
990 return;
991
992 session->rsrc.misc.rsrc_session.sizeHmacValue = session->rsrc.misc.rsrc_session.sizeSessionValue;
993
994 if (name == NULL || auth_value == NULL)
995 return;
996
997 /* The auth value is appended to the session key */
998 memcpy(&session->rsrc.misc.rsrc_session.
999 sessionValue[session->rsrc.misc.rsrc_session.sessionKey.size],
1000 &auth_value->buffer[0], auth_value->size);
1001 session->rsrc.misc.rsrc_session.sizeSessionValue += auth_value->size;
1002
1003 /* Then if we are a bound session, the auth value is not appended to the end
1004 of the session value for HMAC computation. The size of the key will not be
1005 increased.*/
1006 if (iesys_is_object_bound(name, auth_value, session))
1007 return;
1008
1009 /* type_policy_session set to POLICY_AUTH by command PolicyAuthValue */
1010 if (session->rsrc.misc.rsrc_session.sessionType == TPM2_SE_POLICY &&
1011 session->rsrc.misc.rsrc_session.type_policy_session != POLICY_AUTH)
1012 return;
1013
1014 session->rsrc.misc.rsrc_session.sizeHmacValue += auth_value->size;
1015 }
1016
1017 /**
1018 * Lookup the object to a handle from inside the context.
1019 *
1020 * This function searches the esapi context for an object that corresponds to a
1021 * provided esys_handle. These objects contain information such as the
1022 * appropriate tpm handle, the public name or the stored auth values.
1023 * These esys handles refer either to an object previously initialized on the
1024 * same context, in which case this will be returned. Or they refer to a
1025 * "global", in which case the corresponding object will be created if it does
1026 * not exist yet.
1027 * @param[in,out] esys_context The esys context to issue the command on.
1028 * @param[in] esys_handle The handle to find the corresponding object for.
1029 * @param[out] esys_object The object containing the name, tpm handle and auth value
1030 * @retval TSS2_RC_SUCCESS on success.
1031 * @retval TSS2_ESYS_RC_BAD_TR if the handle is invalid.
1032 * @retval TSS2_ESYS_RC_BAD_VALUE if an unknown handle < ESYS_TR_MIN_OBJECT is
1033 * passed.
1034 */
1035 TSS2_RC
esys_GetResourceObject(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,RSRC_NODE_T ** esys_object)1036 esys_GetResourceObject(ESYS_CONTEXT * esys_context,
1037 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
1038 {
1039 RSRC_NODE_T *esys_object_aux;
1040 TPM2_HANDLE tpm_handle;
1041 size_t offset = 0;
1042 TSS2_RC r;
1043
1044 /* Sometimes the TPM API allows for optional objects. In those cases we map
1045 the object node to NULL. This will be handled accordingly by following
1046 code */
1047 if (esys_handle == ESYS_TR_NONE) {
1048 *esys_object = NULL;
1049 return TSS2_RC_SUCCESS;
1050 }
1051
1052 /* The typical case is that we have a resource object already within the
1053 esys context's linked list. We iterate through the list and search
1054 for the corresponding object and return it if found.
1055 If no object is found, this can be an erroneous handle number or it
1056 can be because of a reference "global" object that does not require
1057 previous initialization. */
1058 for (esys_object_aux = esys_context->rsrc_list; esys_object_aux != NULL;
1059 esys_object_aux = esys_object_aux->next) {
1060 if (esys_object_aux->esys_handle == esys_handle) {
1061 *esys_object = esys_object_aux;
1062 return TPM2_RC_SUCCESS;
1063 }
1064 }
1065
1066 /* All objects with a TR-handle larger than ESYS_TR_MIN_OBJECT must have
1067 been initialized previously. Therefore the TR handle was erroneous. */
1068 if (esys_handle >= ESYS_TR_MIN_OBJECT) {
1069 LOG_ERROR("Error: Esys handle does not exist (%x).",
1070 TSS2_ESYS_RC_BAD_TR);
1071 return TSS2_ESYS_RC_BAD_TR;
1072 }
1073
1074 /* There are special "global" object for the TPM, such as PCRs or
1075 hierarchies. If they do not exist yet inside the Esys context we create
1076 them here and return the newly created object. */
1077 r = iesys_handle_to_tpm_handle(esys_handle, &tpm_handle);
1078 return_if_error(r, "Unknown ESYS handle.");
1079
1080 r = esys_CreateResourceObject(esys_context, esys_handle, &esys_object_aux);
1081 return_if_error(r, "Creating Resource Object.");
1082
1083 esys_object_aux->rsrc.handle = tpm_handle;
1084 esys_object_aux->rsrc.rsrcType = IESYSC_WITHOUT_MISC_RSRC;
1085
1086 r = Tss2_MU_TPM2_HANDLE_Marshal(tpm_handle,
1087 &esys_object_aux->rsrc.name.name[0],
1088 sizeof(esys_object_aux->rsrc.name.name),
1089 &offset);
1090 return_if_error(r, "Marshaling TPM handle.");
1091
1092 esys_object_aux->rsrc.name.size = offset;
1093 *esys_object = esys_object_aux;
1094 return TSS2_RC_SUCCESS;
1095 }
1096
1097 /**
1098 * Check that the esys context is ready for an _async call.
1099 *
1100 * This function will check that the sequence of invocations to the esys context
1101 * was such that an _async function can be called. This means that the internal
1102 * @state field is either @_ESYS_STATE_INIT, @_ESYS_STATE_ERRORRESPONSE,
1103 * @_ESYS_STATE_FINISHED.
1104 * @param[in,out] esys_context The esys context to issue the command on.
1105 * @retval TSS2_RC_SUCCESS on success.
1106 * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function.
1107 */
1108 TSS2_RC
iesys_check_sequence_async(ESYS_CONTEXT * esys_context)1109 iesys_check_sequence_async(ESYS_CONTEXT * esys_context)
1110 {
1111 if (esys_context == NULL) {
1112 LOG_ERROR("esyscontext is NULL.");
1113 return TSS2_ESYS_RC_BAD_REFERENCE;
1114 }
1115
1116 if (esys_context->state != _ESYS_STATE_INIT &&
1117 esys_context->state != _ESYS_STATE_RESUBMISSION) {
1118 LOG_ERROR("Esys called in bad sequence.");
1119 return TSS2_ESYS_RC_BAD_SEQUENCE;
1120 }
1121 esys_context->submissionCount = 1;
1122 return TSS2_RC_SUCCESS;
1123 }
1124
1125 /** Check whether session without authorization occurs before one with.
1126 *
1127 * @param[in] session1-3 The three sessions.
1128 * @retval TPM2_RC_SUCCESS if the order is ok.
1129 * @retval TSS2_ESYS_RC_BAD_VALUE if not.
1130 */
1131 TSS2_RC
check_session_feasibility(ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3,int mandatory)1132 check_session_feasibility(ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
1133 int mandatory)
1134 {
1135 ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
1136 bool check_none = false;
1137 for (int i = 2; i >= 0; i--) {
1138 if (handle_tab[i] != ESYS_TR_NONE)
1139 mandatory--;
1140 if (handle_tab[i] != ESYS_TR_NONE && handle_tab[i] != ESYS_TR_PASSWORD)
1141 check_none = true;
1142 else {
1143 if (check_none) {
1144 if (handle_tab[i] == ESYS_TR_NONE) {
1145 LOG_ERROR("Error: ESYS_TR_NONE used before other handle.");
1146 return TSS2_ESYS_RC_BAD_VALUE;
1147 }
1148 }
1149 }
1150 }
1151 if (mandatory > 0) {
1152 LOG_ERROR("Not enough sessions provided for the command.");
1153 return TSS2_ESYS_RC_BAD_VALUE;
1154 }
1155 return TPM2_RC_SUCCESS;
1156 }
1157
1158 /** Compute HMAC for a session.
1159 *
1160 * The HMAC is computed from the appropriate cp hash, the caller nonce, the TPM
1161 * nonce and the session attributes. If an encrypt session is not the first
1162 * session also the encrypt and the decrypt nonce have to be included.
1163 * @param[in] session The session for which the HMAC has to be computed.
1164 * @param[in] cp_hash_tab The table of computed cp hash values.
1165 * @param[in] cpHashNum The number of computed cp hash values which depens on
1166 * the number of used hash algorithms.
1167 * @param[in] encryptNonce The encrypt Nonce of an encryption session. Has to
1168 * be NULL if encryption session is first session.
1169 * @param[in] decryptNonce The decrypt Nonce of an encryption session. Has to
1170 * be NULL if encryption session is first session.
1171 * @param[out] auth The computed HMAC value.
1172 * @retval TSS2_RC_SUCCESS on success.
1173 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1174 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1175 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1176 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1177 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1178 * @retval TSS2_SYS_RC_* for SAPI errors.
1179 */
1180 TSS2_RC
iesys_compute_hmac(RSRC_NODE_T * session,HASH_TAB_ITEM cp_hash_tab[3],uint8_t cpHashNum,TPM2B_NONCE * decryptNonce,TPM2B_NONCE * encryptNonce,TPMS_AUTH_COMMAND * auth)1181 iesys_compute_hmac(RSRC_NODE_T * session,
1182 HASH_TAB_ITEM cp_hash_tab[3],
1183 uint8_t cpHashNum,
1184 TPM2B_NONCE * decryptNonce,
1185 TPM2B_NONCE * encryptNonce,
1186 TPMS_AUTH_COMMAND * auth)
1187 {
1188 TSS2_RC r;
1189 size_t authHash_size = 0;
1190
1191 if (session != NULL) {
1192 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1193 r = iesys_crypto_hash_get_digest_size(rsrc_session->
1194 authHash, &authHash_size);
1195 return_if_error(r, "Initializing auth session");
1196
1197 int hi = 0;
1198 for (int j = 0; j < cpHashNum; j++) {
1199 if (rsrc_session->authHash == cp_hash_tab[j].alg) {
1200 hi = j;
1201 break;
1202 }
1203 }
1204 auth->hmac.size = sizeof(TPMU_HA);
1205 /* if other than first session is used for for parameter encryption
1206 the corresponding nonces have to be included into the hmac
1207 computation of the first session */
1208 r = iesys_crypto_authHmac(rsrc_session->authHash,
1209 &rsrc_session->sessionValue[0],
1210 rsrc_session->sizeHmacValue,
1211 &cp_hash_tab[hi].digest[0],
1212 cp_hash_tab[hi].size,
1213 &rsrc_session->nonceCaller,
1214 &rsrc_session->nonceTPM,
1215 decryptNonce, encryptNonce,
1216 rsrc_session->sessionAttributes, &auth->hmac);
1217 return_if_error(r, "HMAC error");
1218 auth->sessionHandle = session->rsrc.handle;
1219 auth->nonce = rsrc_session->nonceCaller;
1220 auth->sessionAttributes =
1221 rsrc_session->sessionAttributes;
1222 }
1223 return TSS2_RC_SUCCESS;
1224 }
1225
1226 /** Compute the auth values (HMACs) for all sessions.
1227 *
1228 * The caller nonce, the encrypt nonces, the cp hashes, and the HMAC values for
1229 * the command authorization are computed.
1230 * @param[in] esys_context The esys context to issue the command on.
1231 * @param[in] h1-3 The esys session resource objects.
1232 * @param[out] The list if the authorizations with the computed HMACs.
1233 * @param[out] auth The computed HMAC value.
1234 * @retval TSS2_RC_SUCCESS on success.
1235 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1236 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1237 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1238 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1239 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1240 * @retval TSS2_SYS_RC_* for SAPI errors.
1241 */
1242 TSS2_RC
iesys_gen_auths(ESYS_CONTEXT * esys_context,RSRC_NODE_T * h1,RSRC_NODE_T * h2,RSRC_NODE_T * h3,TSS2L_SYS_AUTH_COMMAND * auths)1243 iesys_gen_auths(ESYS_CONTEXT * esys_context,
1244 RSRC_NODE_T * h1,
1245 RSRC_NODE_T * h2,
1246 RSRC_NODE_T * h3,
1247 TSS2L_SYS_AUTH_COMMAND * auths)
1248 {
1249 TSS2_RC r;
1250 TPM2B_NONCE *decryptNonce = NULL;
1251 int decryptNonceIdx = 0;
1252 int encryptNonceIdx = 0;
1253 TPM2B_NONCE *encryptNonce = NULL;
1254
1255 RSRC_NODE_T *objects[] = { h1, h2, h3 };
1256
1257 HASH_TAB_ITEM cp_hash_tab[3];
1258 uint8_t cpHashNum = 0;
1259
1260 auths->count = 0;
1261 r = iesys_gen_caller_nonces(esys_context);
1262 return_if_error(r, "Error nonce generation caller");
1263 r = iesys_encrypt_param(esys_context, &decryptNonce, &decryptNonceIdx);
1264 return_if_error(r, "Error parameter encryption");
1265 r = iesys_compute_encrypt_nonce(esys_context, &encryptNonceIdx,
1266 &encryptNonce);
1267 return_if_error(r, "More than one crypt session");
1268
1269 /* Compute cp hash values for command buffer for all used algorithms */
1270
1271 r = iesys_compute_cp_hashtab(esys_context,
1272 (h1 != NULL) ? &h1->rsrc.name : NULL,
1273 (h2 != NULL) ? &h2->rsrc.name : NULL,
1274 (h3 != NULL) ? &h3->rsrc.name : NULL,
1275 &cp_hash_tab[0], &cpHashNum);
1276 return_if_error(r, "Error while computing cp hashes");
1277
1278 for (int session_idx = 0; session_idx < 3; session_idx++) {
1279 auths->auths[auths->count].nonce.size = 0;
1280 auths->auths[auths->count].sessionAttributes = 0;
1281 if (esys_context->session_type[session_idx] == ESYS_TR_PASSWORD) {
1282 if (objects[session_idx] == NULL) {
1283 auths->auths[auths->count].hmac.size = 0;
1284 auths->count += 1;
1285 } else {
1286 auths->auths[auths->count].sessionHandle = TPM2_RS_PW;
1287 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1288 auths->count += 1;
1289 }
1290 continue;
1291 }
1292 RSRC_NODE_T *session = esys_context->session_tab[session_idx];
1293 if (session != NULL) {
1294 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1295 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
1296 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1297 if (objects[session_idx] == NULL) {
1298 auths->auths[auths->count].hmac.size = 0;
1299 } else {
1300 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1301 }
1302 auths->auths[auths->count].sessionAttributes =
1303 session->rsrc.misc.rsrc_session.sessionAttributes;
1304 auths->count += 1;
1305 continue;
1306 }
1307 }
1308 r = iesys_compute_hmac(esys_context->session_tab[session_idx],
1309 &cp_hash_tab[0], cpHashNum,
1310 (session_idx == 0
1311 && decryptNonceIdx > 0) ? decryptNonce : NULL,
1312 (session_idx == 0
1313 && encryptNonceIdx > 0) ? encryptNonce : NULL,
1314 &auths->auths[session_idx]);
1315 return_if_error(r, "Error while computing hmacs");
1316 if (esys_context->session_tab[session_idx] != NULL) {
1317 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1318 auths->count++;
1319 }
1320 }
1321
1322 esys_context->encryptNonceIdx = encryptNonceIdx;
1323 esys_context->encryptNonce = encryptNonce;
1324
1325 return TSS2_RC_SUCCESS;
1326 }
1327
1328 /** Check the response HMACs for all sessions.
1329 *
1330 * The response HMAC values are computed. Based on these values the HMACs for
1331 * all sessions are computed and compared with the HMACs stored in the response
1332 * auth list which is determined with the SAPI function Tss2_Sys_GetRspAuths.
1333 * @param[in] esys_context The esys context which is used to get the response
1334 * auth values and the sessions.
1335 * @retval TSS2_RC_SUCCESS on success.
1336 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1337 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1338 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1339 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1340 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1341 * @retval TSS2_SYS_RC_* for SAPI errors.
1342 */
1343 TSS2_RC
iesys_check_response(ESYS_CONTEXT * esys_context)1344 iesys_check_response(ESYS_CONTEXT * esys_context)
1345 {
1346 TSS2_RC r;
1347 const uint8_t *rpBuffer;
1348 size_t rpBuffer_size;
1349 TSS2L_SYS_AUTH_RESPONSE rspAuths;
1350 HASH_TAB_ITEM rp_hash_tab[3];
1351 uint8_t rpHashNum = 0;
1352
1353 if (esys_context->authsCount == 0) {
1354 LOG_TRACE("No auths to verify");
1355 return TSS2_RC_SUCCESS;
1356 }
1357
1358 r = Tss2_Sys_GetRspAuths(esys_context->sys, &rspAuths);
1359 return_if_error(r, "Error: GetRspAuths");
1360
1361 if (rspAuths.count != esys_context->authsCount) {
1362 LOG_ERROR("Number of response auths differs: %i (expected %i)",
1363 rspAuths.count, esys_context->authsCount);
1364 return TSS2_ESYS_RC_GENERAL_FAILURE;
1365 }
1366 /*
1367 * At least one session object is defined so the rp hashes must be computed
1368 * and the HMACs of the responses have to be checked.
1369 * Encrypted response parameters will be decrypted.
1370 */
1371 if (esys_context->session_type[0] >= ESYS_TR_MIN_OBJECT ||
1372 esys_context->session_type[1] >= ESYS_TR_MIN_OBJECT ||
1373 esys_context->session_type[2] >= ESYS_TR_MIN_OBJECT) {
1374 r = Tss2_Sys_GetRpBuffer(esys_context->sys, &rpBuffer_size, &rpBuffer);
1375 return_if_error(r, "Error: get rp buffer");
1376
1377 r = iesys_compute_rp_hashtab(esys_context,
1378 rpBuffer, rpBuffer_size,
1379 &rp_hash_tab[0], &rpHashNum);
1380 return_if_error(r, "Error: while computing response hashes");
1381
1382 r = iesys_check_rp_hmacs(esys_context, &rspAuths, &rp_hash_tab[0],
1383 rpHashNum);
1384 return_if_error(r, "Error: response hmac check");
1385
1386 if (esys_context->encryptNonce == NULL) {
1387 iesys_restore_session_flags(esys_context);
1388 return TSS2_RC_SUCCESS;
1389 }
1390
1391 r = iesys_decrypt_param(esys_context);
1392 return_if_error(r, "Error: while decrypting parameter.");
1393 iesys_restore_session_flags(esys_context);
1394
1395 }
1396 return TSS2_RC_SUCCESS;
1397 }
1398
1399 /** Compute the name from the public data of a NV index.
1400 *
1401 * The name of a NV index is computed as follows:
1402 * name = nameAlg||Hash(nameAlg,marshal(publicArea))
1403 * @param[in] publicInfo The public information of the NV index.
1404 * @param[out] name The computed name.
1405 * @retval TSS2_RC_SUCCESS on success.
1406 * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1407 * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1408 * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1409 * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1410 * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1411 * @retval TSS2_SYS_RC_* for SAPI errors.
1412 */
1413 TSS2_RC
iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo,TPM2B_NAME * name)1414 iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo, TPM2B_NAME * name)
1415 {
1416 BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1417 size_t offset = 0;
1418 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1419 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1420 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1421
1422 if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1423 name->size = 0;
1424 return TSS2_RC_SUCCESS;
1425 }
1426 TSS2_RC r;
1427 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1428 return_if_error(r, "Crypto hash start");
1429
1430 r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1431 &buffer[0], sizeof(TPMS_NV_PUBLIC),
1432 &offset);
1433 goto_if_error(r, "Marshaling TPMS_NV_PUBLIC", error_cleanup);
1434
1435 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1436 goto_if_error(r, "crypto hash update", error_cleanup);
1437
1438 r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1439 &size);
1440 goto_if_error(r, "crypto hash finish", error_cleanup);
1441
1442 offset = 0;
1443 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1444 &name->name[0], sizeof(TPMI_ALG_HASH),
1445 &offset);
1446 goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1447
1448 name->size = size + len_alg_id;
1449 return TSS2_RC_SUCCESS;
1450
1451 error_cleanup:
1452 if (cryptoContext)
1453 iesys_crypto_hash_abort(&cryptoContext);
1454 return r;
1455 }
1456
1457 /** Compute the name of a TPM transient or persistent object.
1458 *
1459 * The name of a NV index is computed as follows:
1460 * name = Hash(nameAlg,marshal(publicArea))
1461 * @param[in] publicInfo The public information of the TPM object.
1462 * @param[out] name The computed name.
1463 * @retval TPM2_RC_SUCCESS or one of the possible errors TSS2_ESYS_RC_BAD_VALUE,
1464 * TSS2_ESYS_RC_MEMORY, TSS2_ESYS_RC_GENERAL_FAILURE, TSS2_ESYS_RC_NOT_IMPLEMENTED,
1465 * or return codes of SAPI errors.
1466 */
1467 TSS2_RC
iesys_get_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)1468 iesys_get_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
1469 {
1470 BYTE buffer[sizeof(TPMT_PUBLIC)];
1471 size_t offset = 0;
1472 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1473 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1474 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1475
1476 if (publicInfo->publicArea.nameAlg == TPM2_ALG_NULL) {
1477 name->size = 0;
1478 return TSS2_RC_SUCCESS;
1479 }
1480 TSS2_RC r;
1481 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->publicArea.nameAlg);
1482 return_if_error(r, "crypto hash start");
1483
1484 r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicInfo->publicArea,
1485 &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1486 goto_if_error(r, "Marshaling TPMT_PUBLIC", error_cleanup);
1487
1488 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1489 goto_if_error(r, "crypto hash update", error_cleanup);
1490
1491 r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1492 &size);
1493 goto_if_error(r, "crypto hash finish", error_cleanup);
1494
1495 offset = 0;
1496 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->publicArea.nameAlg,
1497 &name->name[0], sizeof(TPMI_ALG_HASH),
1498 &offset);
1499 goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1500
1501 name->size = size + len_alg_id;
1502 return TSS2_RC_SUCCESS;
1503
1504 error_cleanup:
1505 if (cryptoContext)
1506 iesys_crypto_hash_abort(&cryptoContext);
1507 return r;
1508 }
1509
1510 /** Check whether the return code corresponds to an TPM error.
1511 *
1512 * if no layer is part of the return code or a layer from the resource manager
1513 * is given the function will return true.
1514 * @param[in] r The return code to be checked.
1515 * @retval true if r corresponds to an TPM error.
1516 * @retval false in other cases.
1517 */
1518 bool
iesys_tpm_error(TSS2_RC r)1519 iesys_tpm_error(TSS2_RC r)
1520 {
1521 return (r != TSS2_RC_SUCCESS &&
1522 ((r & TSS2_RC_LAYER_MASK) == 0 ||
1523 (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_TPM_RC_LAYER ||
1524 (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_RC_LAYER));
1525 }
1526