• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                  &param_size, &param_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                                  &param_size, &param_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, &paramSize,
679                                          &paramBuffer);
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