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     if (esys_handle >= ESYS_TR_RH_ACT_FIRST &&
390         esys_handle <= ESYS_TR_RH_ACT_LAST) {
391         *tpm_handle = TPM2_RH_ACT_0 + (esys_handle - ESYS_TR_RH_ACT_FIRST);
392         return TPM2_RC_SUCCESS;
393     }
394     LOG_ERROR("Error: Esys invalid ESAPI handle (%x).", esys_handle);
395     return TSS2_ESYS_RC_BAD_VALUE;
396 }
397 
398 /**
399  * Determines if an ESYS_TR (UINT32) is assigned a raw TPM2_HANDLE (UINT32)
400  * hierarchy type.
401  *
402  * @param handle [in] The handle to check if it's a hierarchy or not.
403  * @return
404  *  true if it is a hierarchy, false otherwise.
405  */
406 bool
iesys_is_platform_handle(ESYS_TR handle)407 iesys_is_platform_handle(ESYS_TR handle) {
408 
409     switch(handle) {
410     case TPM2_RH_OWNER:
411     case TPM2_RH_PLATFORM:
412     case TPM2_RH_PLATFORM_NV:
413     case TPM2_RH_ENDORSEMENT:
414     case TPM2_RH_NULL:
415         LOG_WARNING("Convert handle from TPM2_RH to ESYS_TR, got: 0x%x",
416                 handle);
417         return true;
418     default:
419         return false;
420     }
421 }
422 
423 /** Get the type of a tpm handle.
424  *
425  * @parm handle[in] The tpm handle.
426  * @retval The part of the handle which represents the handle type.
427  */
428 TPM2_HT
iesys_get_handle_type(TPM2_HANDLE handle)429 iesys_get_handle_type(TPM2_HANDLE handle)
430 {
431     /* upper bytes of input data */
432     TPM2_HT ht = (TPM2_HT) ((handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT);
433     return ht;
434 }
435 
436 /** Compute name derived from public info with a tpm name.
437  *
438  * A tpm name is computed from a public info structure and compared with a
439  * second tpm name.
440  * @param[in]  publicInfo The public info for name computation.
441  * @param[in] name The name used for comparison.
442  * @retval bool indicates whether the names are equal.
443  */
444 bool
iesys_compare_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)445 iesys_compare_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
446 {
447     TSS2_RC r = TSS2_RC_SUCCESS;
448     TPM2B_NAME public_info_name;
449     if (publicInfo == NULL || name == NULL)
450         return false;
451     r = iesys_get_name(publicInfo, &public_info_name);
452     if (r != TSS2_RC_SUCCESS) {
453         LOG_DEBUG("name could not be computed.");
454         return false;
455     }
456     return cmp_TPM2B_NAME(&public_info_name, name);
457 }
458 
459 /** Compute a random salt which will be used for parameter encryption.
460  *
461  * Depending in the type of TPM key used for key exchange a salt will be computed.
462  * For an ECC key an ephemeral key will be computed. This key together with the
463  * public point of the TPMs key will be used to compute a shared secret which will
464  * be used for the key derivation of the key for parameter encryption.
465  * For an RSA key a random number will be computed to derive this key. The random
466  * number will be encrypted with the TPM key.
467  * @param[in,out]  esys_context The ESYS_CONTEXT. The generated salt will be
468  *                 stored in this context.
469  * @param[in] tpmKeyNode The esys resource object of the TPM key which will be
470  *            used for key exchange.
471  * @param[out] encryptedSalt In the case of an ECC the public point of the
472  *             ephemeral key will be marshaled into this buffer.
473  *             In the case of a TPM key the encrypted salt will be stored.
474  * @retval TSS2_RC_SUCCESS on success.
475  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
476  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
477  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
478  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
479  * @retval TSS2_SYS_RC_* for SAPI errors.
480  */
481 TSS2_RC
iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,RSRC_NODE_T * tpmKeyNode,TPM2B_ENCRYPTED_SECRET * encryptedSalt)482 iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,
483                              RSRC_NODE_T * tpmKeyNode,
484                              TPM2B_ENCRYPTED_SECRET * encryptedSalt)
485 {
486     TSS2_RC r = TSS2_RC_SUCCESS;
487     size_t keyHash_size = 0;
488     size_t cSize = 0;
489     TPM2B_ECC_PARAMETER Z; /* X coordinate of privKey*publicKey */
490     TPMS_ECC_POINT Q; /* Public point of ephemeral key */
491 
492     if (tpmKeyNode == 0) {
493         encryptedSalt->size = 0;
494         return TSS2_RC_SUCCESS;
495     }
496 
497     TPM2B_PUBLIC pub = tpmKeyNode->rsrc.misc.rsrc_key_pub;
498     if (tpmKeyNode->rsrc.rsrcType != IESYSC_KEY_RSRC) {
499         LOG_TRACE("Public info needed.");
500         return TSS2_ESYS_RC_BAD_VALUE;
501     }
502     r = iesys_crypto_hash_get_digest_size(tpmKeyNode->rsrc.misc.
503                                           rsrc_key_pub.publicArea.nameAlg,
504                                           &keyHash_size);
505     return_if_error(r, "Hash algorithm not supported.");
506 
507     switch (pub.publicArea.type) {
508     case TPM2_ALG_RSA:
509 
510         iesys_crypto_random2b((TPM2B_NONCE *) & esys_context->salt,
511                               keyHash_size);
512 
513         /* When encrypting salts, the encryption scheme of a key is ignored and
514            TPM2_ALG_OAEP is always used. */
515         pub.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_OAEP;
516         r = iesys_crypto_pk_encrypt(&pub,
517                                     keyHash_size, &esys_context->salt.buffer[0],
518                                     sizeof(TPMU_ENCRYPTED_SECRET),
519                                     (BYTE *) &encryptedSalt->secret[0], &cSize,
520                                     "SECRET");
521         return_if_error(r, "During encryption.");
522         LOGBLOB_DEBUG(&encryptedSalt->secret[0], cSize, "IESYS encrypted salt");
523         encryptedSalt->size = cSize;
524         break;
525     case TPM2_ALG_ECC:
526         r = iesys_crypto_get_ecdh_point(&pub, sizeof(TPMU_ENCRYPTED_SECRET),
527                                         &Z, &Q,
528                                         (BYTE *) &encryptedSalt->secret[0],
529                                         &cSize);
530         return_if_error(r, "During computation of ECC public key.");
531         encryptedSalt->size = cSize;
532 
533         /* Compute salt from Z with KDFe */
534         r = iesys_crypto_KDFe(tpmKeyNode->rsrc.misc.
535                               rsrc_key_pub.publicArea.nameAlg,
536                               &Z, "SECRET", &Q.x,
537                               &pub.publicArea.unique.ecc.x,
538                               keyHash_size*8,
539                               &esys_context->salt.buffer[0]);
540         return_if_error(r, "During KDFe computation.");
541         esys_context->salt.size = keyHash_size;
542         break;
543     default:
544         LOG_ERROR("Not implemented");
545         return TSS2_ESYS_RC_GENERAL_FAILURE;
546         break;
547     }
548     return r;
549 }
550 
551 /** Generate caller nonces for all sessions.
552  *
553  * For every uses session stored in context random nonce is computed.
554  * @param[in,out]  esys_context The ESYS_CONTEXT. The generated nonces will be
555  *                 stored in this context.
556  * @retval TPM2_RC_SUCCESS on success. An possible error is:
557  * @retval TSS2_ESYS_RC_BAD_VALUE if an illegal hash algorithm value is stored
558  *         in a session.
559  */
560 TSS2_RC
iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)561 iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)
562 {
563     TSS2_RC r;
564 
565     for (int i = 0; i < 3; i++) {
566         RSRC_NODE_T *session = esys_context->session_tab[i];
567         if (session == NULL)
568             continue;
569 
570         r = iesys_crypto_random2b(&session->rsrc.misc.rsrc_session.nonceCaller,
571                                   session->rsrc.misc.rsrc_session.nonceCaller.size);
572         return_if_error(r, "Error: computing caller nonce (%x).");
573     }
574     return TSS2_RC_SUCCESS;
575 }
576 
577 /** Update session attributes.
578  *
579  * In case where command does not support param encryption/decryption
580  * store the original session attributes and update them accordingly.
581  *
582  * @retval void
583  */
584 static void
iesys_update_session_flags(ESYS_CONTEXT * esys_context,IESYS_SESSION * rsrc_session)585 iesys_update_session_flags(ESYS_CONTEXT * esys_context,
586                            IESYS_SESSION *rsrc_session)
587 {
588     TSS2_RC r = TSS2_RC_SUCCESS;
589     size_t param_size;
590     const uint8_t *param_buffer;
591 
592     LOG_DEBUG("Checking if command supports enc/dec");
593 
594     rsrc_session->origSessionAttributes = rsrc_session->sessionAttributes;
595 
596     r = Tss2_Sys_GetDecryptParam(esys_context->sys,
597                                  &param_size, &param_buffer);
598     if (r == TSS2_SYS_RC_NO_DECRYPT_PARAM) {
599         LOG_DEBUG("clear TPMA_SESSION_DECRYPT flag");
600         rsrc_session->sessionAttributes &= ~(TPMA_SESSION_DECRYPT);
601     }
602 
603     r = Tss2_Sys_GetEncryptParam(esys_context->sys,
604                                  &param_size, &param_buffer);
605     if (r == TSS2_SYS_RC_NO_ENCRYPT_PARAM) {
606         LOG_DEBUG("clear TPMA_SESSION_ENCRYPT flag");
607         rsrc_session->sessionAttributes &= ~(TPMA_SESSION_ENCRYPT);
608     }
609 
610     LOG_DEBUG("Session Attrs 0x%x orig 0x%x",
611 	      rsrc_session->sessionAttributes,
612 	      rsrc_session->origSessionAttributes);
613 }
614 
615 /** Restore session attributes.
616  *
617  * Restore original session attributes altered by iesys_update_session_flags()
618  *
619  * @retval void
620  */
621 static void
iesys_restore_session_flags(ESYS_CONTEXT * esys_context)622 iesys_restore_session_flags(ESYS_CONTEXT *esys_context)
623 {
624     LOG_DEBUG("Restoring session attribs");
625 
626     for (int i = 0; i < 3; i++) {
627         RSRC_NODE_T *session = esys_context->session_tab[i];
628         if (session == NULL)
629             continue;
630         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
631         LOG_DEBUG("Orig Session %i Attrs 0x%x, altered Attrs x%x", i,
632                   rsrc_session->origSessionAttributes,
633                   rsrc_session->sessionAttributes);
634 
635         rsrc_session->sessionAttributes = rsrc_session->origSessionAttributes;
636     }
637 }
638 
639 /** Parameter encryption with AES or XOR obfuscation.
640  *
641  * One parameter of a TPM command will be encrypted with the selected method.
642  * The buffer to encrypted is determined with the SAPI function:
643  * Tss2_Sys_GetCpBuffer. If more than one encryption session es used an error
644  * will be returned. The decryption nonce of the session used for encryption
645  * will be returned and used for HMAC computation. The encryption key is
646  * derived with KDFa.
647  * @retval TSS2_RC_SUCCESS on success.
648  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
649  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
650  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
651  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
652  * @retval TSS2_SYS_RC_* for SAPI errors.
653  */
654 TSS2_RC
iesys_encrypt_param(ESYS_CONTEXT * esys_context,TPM2B_NONCE ** decryptNonce,int * decryptNonceIdx)655 iesys_encrypt_param(ESYS_CONTEXT * esys_context,
656                     TPM2B_NONCE ** decryptNonce, int *decryptNonceIdx)
657 {
658     TPM2B_NONCE *encryptNonce = NULL;
659     *decryptNonceIdx = 0;
660     *decryptNonce = NULL;
661     TSS2_RC r = TSS2_RC_SUCCESS;
662     esys_context->enc_session = NULL;
663 
664     for (int i = 0; i < 3; i++) {
665         RSRC_NODE_T *session = esys_context->session_tab[i];
666         if (session == NULL)
667             continue;
668         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
669         if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT)
670             return_if_notnull(encryptNonce, "More than one encrypt session",
671                                TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS);
672         if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT)
673             return_if_notnull(*decryptNonce, "More than one decrypt session",
674                                TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS);
675 
676         iesys_update_session_flags(esys_context, rsrc_session);
677     }
678 
679     for (int i = 0; i < 3; i++) {
680         RSRC_NODE_T *session = esys_context->session_tab[i];
681         if (session == NULL)
682             continue;
683         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
684         TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
685 
686         if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT) {
687             esys_context->encryptNonceIdx = i;
688             encryptNonce = &rsrc_session->nonceTPM;
689             esys_context->encryptNonce = encryptNonce;
690             esys_context->enc_session = rsrc_session;
691         }
692 
693         /* Session for encryption found */
694         if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT) {
695             *decryptNonceIdx = i;
696             *decryptNonce = &rsrc_session->nonceTPM;
697             size_t hlen;
698             r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
699             return_if_error(r, "get digest size");
700             size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
701             if (key_len % hlen > 0)
702                 key_len = key_len + hlen - (key_len % hlen);
703             uint8_t symKey[key_len];
704             size_t paramSize = 0;
705             const uint8_t *paramBuffer;
706 
707             r = Tss2_Sys_GetDecryptParam(esys_context->sys, &paramSize,
708                                          &paramBuffer);
709             return_if_error(r, "Encryption not possible");
710 
711             if (paramSize == 0)
712                 continue;
713 
714             BYTE encrypt_buffer[paramSize];
715             memcpy(&encrypt_buffer[0], paramBuffer, paramSize);
716             LOGBLOB_DEBUG(paramBuffer, paramSize, "param to encrypt");
717 
718             /* AES encryption with key derived with KDFa */
719             if (symDef->algorithm == TPM2_ALG_AES) {
720                 if (symDef->mode.aes != TPM2_ALG_CFB) {
721                     return_error(TSS2_ESYS_RC_BAD_VALUE,
722                                  "Invalid symmetric mode (must be CFB)");
723                 }
724                 r = iesys_crypto_KDFa(rsrc_session->authHash,
725                                       &rsrc_session->sessionValue[0],
726                                       rsrc_session->sizeSessionValue, "CFB",
727                                       &rsrc_session->nonceCaller,
728                                       &rsrc_session->nonceTPM,
729                                       symDef->keyBits.aes + AES_BLOCK_SIZE_IN_BYTES * 8,
730                                       NULL, &symKey[0], FALSE);
731                 return_if_error(r, "while computing KDFa");
732 
733                 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
734                 r = iesys_crypto_sym_aes_encrypt(&symKey[0],
735                                                  symDef->algorithm,
736                                                  symDef->keyBits.aes,
737                                                  symDef->mode.aes,
738                                                  &encrypt_buffer[0], paramSize,
739                                                  &symKey[aes_off]);
740                 return_if_error(r, "AES encryption not possible");
741             }
742             /* XOR obfuscation of parameter */
743             else if (symDef->algorithm == TPM2_ALG_XOR) {
744                 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
745                                                     &rsrc_session->sessionValue[0],
746                                                     rsrc_session->sizeSessionValue,
747                                                     &rsrc_session->nonceCaller,
748                                                     &rsrc_session->nonceTPM,
749                                                     &encrypt_buffer[0],
750                                                     paramSize);
751                 return_if_error(r, "XOR obfuscation not possible.");
752 
753             } else {
754                 return_error(TSS2_ESYS_RC_BAD_VALUE,
755                              "Invalid symmetric algorithm (should be XOR or AES)");
756             }
757             r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
758                                          &encrypt_buffer[0]);
759             return_if_error(r, "Set encrypt parameter not possible");
760 
761         }
762     }
763     return r;
764 }
765 
766 /** Parameter decryption with AES or XOR obfuscation.
767  *
768  * One parameter of a TPM response will be decrypted with the selected method.
769  * @param[in]  esys_context The ESYS_CONTEXT.
770  *
771  * @retval TSS2_RC_SUCCESS on success.
772  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
773  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
774  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
775  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
776  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
777  * @retval TSS2_SYS_RC_* for SAPI errors.
778  */
779 TSS2_RC
iesys_decrypt_param(ESYS_CONTEXT * esys_context)780 iesys_decrypt_param(ESYS_CONTEXT * esys_context)
781 {
782     TSS2_RC r;
783     const uint8_t *ciphertext;
784     size_t p2BSize;
785     size_t hlen;
786     RSRC_NODE_T *session;
787     IESYS_SESSION *rsrc_session;
788     TPMT_SYM_DEF *symDef;
789     size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
790 
791     session = esys_context->session_tab[esys_context->encryptNonceIdx];
792     rsrc_session = &session->rsrc.misc.rsrc_session;
793     symDef = &rsrc_session->symmetric;
794 
795     r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
796     return_if_error(r, "Error");
797     if (key_len % hlen > 0)
798         key_len = key_len + hlen - (key_len % hlen);
799 
800     uint8_t symKey[key_len];
801 
802     r = Tss2_Sys_GetEncryptParam(esys_context->sys, &p2BSize, &ciphertext);
803     return_if_error(r, "Getting encrypt param");
804 
805     UINT8 plaintext[p2BSize];
806     memcpy(&plaintext[0], ciphertext, p2BSize);
807 
808     if (symDef->algorithm == TPM2_ALG_AES) {
809         /* Parameter decryption with a symmetric AES key derived by KDFa */
810         if (symDef->mode.aes != TPM2_ALG_CFB) {
811             return_error(TSS2_ESYS_RC_BAD_VALUE,
812                          "Invalid symmetric mode (must be CFB)");
813         }
814         LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0],
815                       rsrc_session->sessionKey.size,
816                       "IESYS encrypt session key");
817 
818         r = iesys_crypto_KDFa(rsrc_session->authHash,
819                               &rsrc_session->sessionValue[0],
820                               rsrc_session->sizeSessionValue,
821                               "CFB", &rsrc_session->nonceTPM,
822                               &rsrc_session->nonceCaller,
823                               symDef->keyBits.aes
824                               + AES_BLOCK_SIZE_IN_BYTES * 8, NULL,
825                               &symKey[0], FALSE);
826         return_if_error(r, "KDFa error");
827         LOGBLOB_DEBUG(&symKey[0],
828                       ((symDef->keyBits.aes +
829                         AES_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8,
830                       "IESYS encrypt KDFa key");
831 
832         size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
833         r = iesys_crypto_sym_aes_decrypt(&symKey[0],
834                                      symDef->algorithm,
835                                      symDef->keyBits.aes,
836                                      symDef->mode.aes,
837                                      &plaintext[0], p2BSize,
838                                      &symKey[aes_off]);
839         return_if_error(r, "Decryption error");
840 
841         r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
842         return_if_error(r, "Setting plaintext");
843     } else if (symDef->algorithm == TPM2_ALG_XOR) {
844         /* Parameter decryption with XOR obfuscation */
845         r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
846                                             &rsrc_session->sessionValue[0],
847                                             rsrc_session->sizeSessionValue,
848                                             &rsrc_session->nonceTPM,
849                                             &rsrc_session->nonceCaller,
850                                             &plaintext[0],
851                                             p2BSize);
852         return_if_error(r, "XOR obfuscation not possible.");
853 
854         r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]);
855         return_if_error(r, "Setting plaintext");
856     } else {
857         return_error(TSS2_ESYS_RC_BAD_VALUE,
858                      "Invalid symmetric algorithm (should be XOR or AES)");
859     }
860     return TSS2_RC_SUCCESS;
861 }
862 
863 /** Check the HMAC values of the response for all sessions.
864  *
865  * The HMAC values are computed based on the session secrets, the used nonces,
866  * the session attributes, the response hash.
867  * @param[in] esys_context The ESYS_CONTEXT.
868  * @param[in] rspAuths The list of the session auth values.
869  * @param[in] rp_hashtab  The list of response hashes.
870  * @param[in] rpHashNum The number of response hashes.
871  * @retval TSS2_RC_SUCCESS on success.
872  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
873  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
874  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
875  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
876  */
877 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)878 iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,
879                      TSS2L_SYS_AUTH_RESPONSE * rspAuths,
880                      HASH_TAB_ITEM rp_hash_tab[3],
881                      uint8_t rpHashNum)
882 {
883     TSS2_RC r;
884 
885     for (int i = 0; i < rspAuths->count; i++) {
886         RSRC_NODE_T *session = esys_context->session_tab[i];
887         if (session == NULL)
888             continue;
889 
890         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
891         if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
892             /* A policy password session has no auth value */
893             if (rspAuths->auths[i].hmac.size != 0) {
894                 LOG_ERROR("PolicyPassword session's HMAC must be 0-length.");
895                 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
896             }
897             continue;
898         }
899 
900         /* Find the rpHash for the hash algorithm used by this session */
901         int hi;
902         for (hi = 0; hi < rpHashNum; hi++) {
903             if (rsrc_session->authHash == rp_hash_tab[hi].alg) {
904                 break;
905             }
906         }
907         if (hi == rpHashNum) {
908             LOG_ERROR("rpHash for alg %"PRIx16 " not found.",
909                       rsrc_session->authHash);
910             return TSS2_ESYS_RC_GENERAL_FAILURE;
911         }
912 
913         TPM2B_AUTH rp_hmac;
914         rp_hmac.size = sizeof(TPMU_HA);
915         rsrc_session->nonceTPM = rspAuths->auths[i].nonce;
916         rsrc_session->sessionAttributes =
917             rspAuths->auths[i].sessionAttributes;
918         r = iesys_crypto_authHmac(rsrc_session->authHash,
919                                   &rsrc_session->sessionValue[0],
920                                   rsrc_session->sizeHmacValue,
921                                   &rp_hash_tab[hi].digest[0],
922                                   rp_hash_tab[hi].size,
923                                   &rsrc_session->nonceTPM,
924                                   &rsrc_session->nonceCaller, NULL, NULL,
925                                   rspAuths->auths[i].sessionAttributes,
926                                   &rp_hmac);
927         return_if_error(r, "HMAC error");
928 
929         if (!cmp_TPM2B_AUTH(&rspAuths->auths[i].hmac, &rp_hmac)) {
930             LOG_ERROR("TPM's response auth is invalid for session %i", i);
931             return TSS2_ESYS_RC_RSP_AUTH_FAILED;
932         }
933     }
934     return TSS2_RC_SUCCESS;
935 }
936 /** Compute the value for check of bind authorization.
937  *
938  * This value has to be computed from the bind object in the StartAuthSession
939  * command and later checked in for corresponding object authorizations.
940  * @param[in] name The name of the bind object.
941  * @param[in] auth The authorization of the bind object.
942  * @param[out] bound_entity The value used for checking the bind authorization.
943  */
944 void
iesys_compute_bound_entity(const TPM2B_NAME * name,const TPM2B_AUTH * auth,TPM2B_NAME * bound_entity)945 iesys_compute_bound_entity(const TPM2B_NAME * name,
946                            const TPM2B_AUTH * auth, TPM2B_NAME * bound_entity)
947 {
948     UINT16 i;
949     UINT16 j = 0;
950     *bound_entity = *name;
951     memset(&bound_entity->name[bound_entity->size], 0,
952            sizeof(bound_entity->name) - bound_entity->size);
953     for (i = sizeof(bound_entity->name) - auth->size;
954          i < sizeof(bound_entity->name); i++)
955         bound_entity->name[i] ^= auth->buffer[j++];
956     bound_entity->size = sizeof(bound_entity->name);
957 }
958 
959 /** Predicate whether the authorization is for the object bound to the session.
960  *
961  * @param[in] name The name of the object.
962  * @param[in] auth The auth value of the object.
963  * @param[in] sesssion The session to be checked.
964  * @retval true if object is bind object of session.
965  * @retval false if not.
966  */
967 bool
iesys_is_object_bound(const TPM2B_NAME * name,const TPM2B_AUTH * auth,RSRC_NODE_T * session)968 iesys_is_object_bound(const TPM2B_NAME * name,
969                       const TPM2B_AUTH * auth, RSRC_NODE_T * session)
970 {
971     TPM2B_NAME tmp;
972     if (session->rsrc.misc.rsrc_session.bound_entity.size == 0)
973         /* No bind session */
974         return false;
975     iesys_compute_bound_entity(name, auth, &tmp);
976     return cmp_TPM2B_NAME(&session->rsrc.misc.rsrc_session.bound_entity, &tmp);
977 }
978 
979 /**
980  * Compute the session value
981  *
982  * This function derives the session value from the session key
983  * and the auth value. The auth value is appended to the session key.
984  * The session value is used for key derivation for parameter encryption and
985  * HMAC computation. There is one exception for HMAC key derivation: If the
986  * session is bound to an object only the session key is used. The auth value
987  * is appended only for the key used for parameter encryption.
988  * The auth value is only used if an authorization is necessary and the name
989  * of the object is not equal to the name of an used bound entity
990  * @param[in,out] session for which the session value will be computed.
991  *       The value will be stored in sessionValue of the session object.
992  *       The length of the object will be stored in sizeHmacValue and
993  *       sizeSessionValue respectively to the purpose of usage (HMAC computation
994  *       or parameter encryption).
995  * @param[in] name name of the object to be authorized (NULL if no authorization)
996  * @param[in] auth_value auth value of the object to be authorized
997  *             (NULL if no authorization)
998  */
999 void
iesys_compute_session_value(RSRC_NODE_T * session,const TPM2B_NAME * name,const TPM2B_AUTH * auth_value)1000 iesys_compute_session_value(RSRC_NODE_T * session,
1001                             const TPM2B_NAME * name,
1002                             const TPM2B_AUTH * auth_value)
1003 {
1004     if (session == NULL)
1005         return;
1006 
1007     /* First the session Key is copied into the sessionValue */
1008     session->rsrc.misc.rsrc_session.sizeSessionValue
1009         = session->rsrc.misc.rsrc_session.sessionKey.size;
1010     memcpy(&session->rsrc.misc.rsrc_session.sessionValue[0],
1011            &session->rsrc.misc.rsrc_session.sessionKey.buffer[0],
1012            session->rsrc.misc.rsrc_session.sessionKey.size);
1013 
1014      /* This requires an HMAC Session and not a password session */
1015     if (session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_HMAC &&
1016         session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_POLICY)
1017         return;
1018 
1019     session->rsrc.misc.rsrc_session.sizeHmacValue = session->rsrc.misc.rsrc_session.sizeSessionValue;
1020 
1021     if (name == NULL || auth_value == NULL)
1022         return;
1023 
1024     /* The auth value is appended to the session key */
1025     memcpy(&session->rsrc.misc.rsrc_session.
1026            sessionValue[session->rsrc.misc.rsrc_session.sessionKey.size],
1027            &auth_value->buffer[0], auth_value->size);
1028     session->rsrc.misc.rsrc_session.sizeSessionValue += auth_value->size;
1029 
1030     /* Then if we are a bound session, the auth value is not appended to the end
1031        of the session value for HMAC computation. The size of the key will not be
1032        increased.*/
1033     if (iesys_is_object_bound(name, auth_value, session))
1034         return;
1035 
1036     /* type_policy_session set to POLICY_AUTH by command PolicyAuthValue */
1037     if (session->rsrc.misc.rsrc_session.sessionType == TPM2_SE_POLICY &&
1038         session->rsrc.misc.rsrc_session.type_policy_session != POLICY_AUTH)
1039         return;
1040 
1041     session->rsrc.misc.rsrc_session.sizeHmacValue += auth_value->size;
1042 }
1043 
1044 /**
1045  * Lookup the object to a handle from inside the context.
1046  *
1047  * This function searches the esapi context for an object that corresponds to a
1048  * provided esys_handle. These objects contain information such as the
1049  * appropriate tpm handle, the public name or the stored auth values.
1050  * These esys handles refer either to an object previously initialized on the
1051  * same context, in which case this will be returned. Or they refer to a
1052  * "global", in which case the corresponding object will be created if it does
1053  * not exist yet.
1054  * @param[in,out] esys_context The esys context to issue the command on.
1055  * @param[in] esys_handle The handle to find the corresponding object for.
1056  * @param[out] esys_object The object containing the name, tpm handle and auth value
1057  * @retval TSS2_RC_SUCCESS on success.
1058  * @retval TSS2_ESYS_RC_BAD_TR if the handle is invalid.
1059  * @retval TSS2_ESYS_RC_BAD_VALUE if an unknown handle < ESYS_TR_MIN_OBJECT is
1060  *         passed.
1061  */
1062 TSS2_RC
esys_GetResourceObject(ESYS_CONTEXT * esys_context,ESYS_TR esys_handle,RSRC_NODE_T ** esys_object)1063 esys_GetResourceObject(ESYS_CONTEXT * esys_context,
1064                        ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
1065 {
1066     RSRC_NODE_T *esys_object_aux;
1067     TPM2_HANDLE tpm_handle;
1068     size_t offset = 0;
1069     TSS2_RC r;
1070 
1071     /* Sometimes the TPM API allows for optional objects. In those cases we map
1072        the object node to NULL. This will be handled accordingly by following
1073        code */
1074     if (esys_handle == ESYS_TR_NONE) {
1075         *esys_object = NULL;
1076         return TSS2_RC_SUCCESS;
1077     }
1078 
1079     /* The typical case is that we have a resource object already within the
1080        esys context's linked list. We iterate through the list and search
1081        for the corresponding object and return it if found.
1082        If no object is found, this can be an erroneous handle number or it
1083        can be because of a reference "global" object that does not require
1084        previous initialization. */
1085     for (esys_object_aux = esys_context->rsrc_list; esys_object_aux != NULL;
1086          esys_object_aux = esys_object_aux->next) {
1087         if (esys_object_aux->esys_handle == esys_handle) {
1088             *esys_object = esys_object_aux;
1089             return TPM2_RC_SUCCESS;
1090         }
1091     }
1092 
1093     /* All objects with a TR-handle larger than ESYS_TR_MIN_OBJECT must have
1094        been initialized previously. Therefore the TR handle was erroneous. */
1095     if (esys_handle >= ESYS_TR_MIN_OBJECT) {
1096         LOG_ERROR("Error: Esys handle does not exist (%x).",
1097                   TSS2_ESYS_RC_BAD_TR);
1098         return TSS2_ESYS_RC_BAD_TR;
1099     }
1100 
1101     /* There are special "global" object for the TPM, such as PCRs or
1102        hierarchies. If they do not exist yet inside the Esys context we create
1103        them here and return the newly created object. */
1104     r = iesys_handle_to_tpm_handle(esys_handle, &tpm_handle);
1105     return_if_error(r, "Unknown ESYS handle.");
1106 
1107     r = esys_CreateResourceObject(esys_context, esys_handle, &esys_object_aux);
1108     return_if_error(r, "Creating Resource Object.");
1109 
1110     esys_object_aux->rsrc.handle = tpm_handle;
1111     esys_object_aux->rsrc.rsrcType = IESYSC_WITHOUT_MISC_RSRC;
1112 
1113     r = Tss2_MU_TPM2_HANDLE_Marshal(tpm_handle,
1114                                 &esys_object_aux->rsrc.name.name[0],
1115                                 sizeof(esys_object_aux->rsrc.name.name),
1116                                 &offset);
1117     return_if_error(r, "Marshaling TPM handle.");
1118 
1119     esys_object_aux->rsrc.name.size = offset;
1120     *esys_object = esys_object_aux;
1121     return TSS2_RC_SUCCESS;
1122 }
1123 
1124 /**
1125  * Check that the esys context is ready for an _async call.
1126  *
1127  * This function will check that the sequence of invocations to the esys context
1128  * was such that an _async function can be called. This means that the internal
1129  * @state field is either @_ESYS_STATE_INIT, @_ESYS_STATE_ERRORRESPONSE,
1130  * @_ESYS_STATE_FINISHED.
1131  * @param[in,out] esys_context The esys context to issue the command on.
1132  * @retval TSS2_RC_SUCCESS on success.
1133  * @retval TSS2_RC_BAD_SEQUENCE if context is not ready for this function.
1134  */
1135 TSS2_RC
iesys_check_sequence_async(ESYS_CONTEXT * esys_context)1136 iesys_check_sequence_async(ESYS_CONTEXT * esys_context)
1137 {
1138     if (esys_context == NULL) {
1139         LOG_ERROR("esyscontext is NULL.");
1140         return TSS2_ESYS_RC_BAD_REFERENCE;
1141     }
1142 
1143     if (esys_context->state != _ESYS_STATE_INIT &&
1144         esys_context->state != _ESYS_STATE_RESUBMISSION) {
1145         LOG_ERROR("Esys called in bad sequence.");
1146         return TSS2_ESYS_RC_BAD_SEQUENCE;
1147     }
1148     esys_context->submissionCount = 1;
1149     return TSS2_RC_SUCCESS;
1150 }
1151 
1152 /** Check whether session without authorization occurs before one with.
1153  *
1154  * @param[in] session1-3 The three sessions.
1155  * @retval TPM2_RC_SUCCESS if the order is ok.
1156  * @retval TSS2_ESYS_RC_BAD_VALUE if not.
1157  */
1158 TSS2_RC
check_session_feasibility(ESYS_TR shandle1,ESYS_TR shandle2,ESYS_TR shandle3,int mandatory)1159 check_session_feasibility(ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
1160                           int mandatory)
1161 {
1162     ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
1163     bool check_none = false;
1164     for (int i = 2; i >= 0; i--) {
1165         if (handle_tab[i] != ESYS_TR_NONE)
1166             mandatory--;
1167         if (handle_tab[i] != ESYS_TR_NONE && handle_tab[i] != ESYS_TR_PASSWORD)
1168             check_none = true;
1169         else {
1170             if (check_none) {
1171                 if (handle_tab[i] == ESYS_TR_NONE) {
1172                     LOG_ERROR("Error: ESYS_TR_NONE used before other handle.");
1173                     return TSS2_ESYS_RC_BAD_VALUE;
1174                 }
1175             }
1176         }
1177     }
1178     if (mandatory > 0) {
1179         LOG_ERROR("Not enough sessions provided for the command.");
1180         return TSS2_ESYS_RC_BAD_VALUE;
1181     }
1182     return TPM2_RC_SUCCESS;
1183 }
1184 
1185 /** Compute HMAC for a session.
1186  *
1187  * The HMAC is computed from the appropriate cp hash, the caller nonce, the TPM
1188  * nonce and the session attributes. If an encrypt session is not the first
1189  * session also the encrypt and the decrypt nonce have to be included.
1190  * @param[in] session The session for which the HMAC has to be computed.
1191  * @param[in] cp_hash_tab The table of computed cp hash values.
1192  * @param[in] cpHashNum The number of computed cp hash values which depens on
1193  *            the number of used hash algorithms.
1194  * @param[in] encryptNonce The encrypt Nonce of an encryption session. Has to
1195  *            be NULL if encryption session is first session.
1196  * @param[in] decryptNonce The decrypt Nonce of an encryption session. Has to
1197  *            be NULL if encryption session is first session.
1198  * @param[out] auth The computed HMAC value.
1199  * @retval TSS2_RC_SUCCESS on success.
1200  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1201  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1202  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1203  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1204  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1205  * @retval TSS2_SYS_RC_* for SAPI errors.
1206  */
1207 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)1208 iesys_compute_hmac(RSRC_NODE_T * session,
1209                    HASH_TAB_ITEM cp_hash_tab[3],
1210                    uint8_t cpHashNum,
1211                    TPM2B_NONCE * decryptNonce,
1212                    TPM2B_NONCE * encryptNonce,
1213                    TPMS_AUTH_COMMAND * auth)
1214 {
1215     TSS2_RC r;
1216     size_t authHash_size = 0;
1217 
1218     if (session != NULL) {
1219         IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1220         r = iesys_crypto_hash_get_digest_size(rsrc_session->
1221                                               authHash, &authHash_size);
1222         return_if_error(r, "Initializing auth session");
1223 
1224         int hi = 0;
1225         for (int j = 0; j < cpHashNum; j++) {
1226             if (rsrc_session->authHash == cp_hash_tab[j].alg) {
1227                 hi = j;
1228                 break;
1229             }
1230         }
1231         auth->hmac.size = sizeof(TPMU_HA);
1232         /* if other than first session is used for for parameter encryption
1233            the corresponding nonces have to be included into the hmac
1234            computation of the first session */
1235         r = iesys_crypto_authHmac(rsrc_session->authHash,
1236                                   &rsrc_session->sessionValue[0],
1237                                   rsrc_session->sizeHmacValue,
1238                                   &cp_hash_tab[hi].digest[0],
1239                                   cp_hash_tab[hi].size,
1240                                   &rsrc_session->nonceCaller,
1241                                   &rsrc_session->nonceTPM,
1242                                   decryptNonce, encryptNonce,
1243                                   rsrc_session->sessionAttributes, &auth->hmac);
1244         return_if_error(r, "HMAC error");
1245         auth->sessionHandle = session->rsrc.handle;
1246         auth->nonce = rsrc_session->nonceCaller;
1247         auth->sessionAttributes =
1248             rsrc_session->sessionAttributes;
1249     }
1250     return TSS2_RC_SUCCESS;
1251 }
1252 
1253 /** Compute the auth values (HMACs) for all sessions.
1254  *
1255  * The caller nonce, the encrypt nonces, the cp hashes, and the HMAC values for
1256  * the command authorization are computed.
1257  * @param[in] esys_context The esys context to issue the command on.
1258  * @param[in] h1-3 The esys session resource objects.
1259  * @param[out] The list if the authorizations with the computed HMACs.
1260  * @param[out] auth The computed HMAC value.
1261  * @retval TSS2_RC_SUCCESS on success.
1262  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1263  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1264  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1265  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1266  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1267  * @retval TSS2_SYS_RC_* for SAPI errors.
1268  */
1269 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)1270 iesys_gen_auths(ESYS_CONTEXT * esys_context,
1271                 RSRC_NODE_T * h1,
1272                 RSRC_NODE_T * h2,
1273                 RSRC_NODE_T * h3,
1274                 TSS2L_SYS_AUTH_COMMAND * auths)
1275 {
1276     TSS2_RC r;
1277     TPM2B_NONCE *decryptNonce = NULL;
1278     int decryptNonceIdx = 0;
1279     int encryptNonceIdx = 0;
1280     TPM2B_NONCE *encryptNonce = NULL;
1281 
1282     RSRC_NODE_T *objects[] = { h1, h2, h3 };
1283 
1284     HASH_TAB_ITEM cp_hash_tab[3];
1285     uint8_t cpHashNum = 0;
1286 
1287     auths->count = 0;
1288     r = iesys_gen_caller_nonces(esys_context);
1289     return_if_error(r, "Error nonce generation caller");
1290     r = iesys_encrypt_param(esys_context, &decryptNonce, &decryptNonceIdx);
1291     return_if_error(r, "Error parameter encryption");
1292     r = iesys_compute_encrypt_nonce(esys_context, &encryptNonceIdx,
1293                                     &encryptNonce);
1294     return_if_error(r, "More than one crypt session");
1295 
1296     /*
1297      * TPM2.0 Architecture 19.6.5 Note 7
1298      *
1299      * If the same session (not the first session) is used for decrypt and
1300      * encrypt, its nonceTPM is only used once. If different sessions are used
1301      * for decrypt and encrypt, both nonceTPMs are included
1302      */
1303     if (decryptNonceIdx && (decryptNonceIdx == encryptNonceIdx)) {
1304         decryptNonceIdx = 0;
1305     }
1306 
1307 
1308     /* Compute cp hash values for command buffer for all used algorithms */
1309 
1310     r = iesys_compute_cp_hashtab(esys_context,
1311                                  (h1 != NULL) ? &h1->rsrc.name : NULL,
1312                                  (h2 != NULL) ? &h2->rsrc.name : NULL,
1313                                  (h3 != NULL) ? &h3->rsrc.name : NULL,
1314                                  &cp_hash_tab[0], &cpHashNum);
1315     return_if_error(r, "Error while computing cp hashes");
1316 
1317     for (int session_idx = 0; session_idx < 3; session_idx++) {
1318         auths->auths[auths->count].nonce.size = 0;
1319         auths->auths[auths->count].sessionAttributes = 0;
1320         if (esys_context->session_type[session_idx] == ESYS_TR_PASSWORD) {
1321             if (objects[session_idx] == NULL) {
1322                 auths->auths[auths->count].hmac.size = 0;
1323                 auths->count += 1;
1324             } else {
1325                 auths->auths[auths->count].sessionHandle = TPM2_RS_PW;
1326                 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1327                 auths->count += 1;
1328             }
1329             continue;
1330         }
1331         RSRC_NODE_T *session = esys_context->session_tab[session_idx];
1332         if (session != NULL) {
1333             IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1334             if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
1335                 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1336                 if (objects[session_idx] == NULL) {
1337                     auths->auths[auths->count].hmac.size = 0;
1338                 } else {
1339                     auths->auths[auths->count].hmac = objects[session_idx]->auth;
1340                 }
1341                 auths->auths[auths->count].sessionAttributes =
1342                     session->rsrc.misc.rsrc_session.sessionAttributes;
1343                 auths->count += 1;
1344                 continue;
1345             }
1346         }
1347         r = iesys_compute_hmac(esys_context->session_tab[session_idx],
1348                                &cp_hash_tab[0], cpHashNum,
1349                                (session_idx == 0
1350                                 && decryptNonceIdx > 0) ? decryptNonce : NULL,
1351                                (session_idx == 0
1352                                 && encryptNonceIdx > 0) ? encryptNonce : NULL,
1353                                &auths->auths[session_idx]);
1354         return_if_error(r, "Error while computing hmacs");
1355         if (esys_context->session_tab[session_idx] != NULL) {
1356             auths->auths[auths->count].sessionHandle = session->rsrc.handle;
1357             auths->count++;
1358         }
1359     }
1360 
1361     esys_context->encryptNonceIdx = encryptNonceIdx;
1362     esys_context->encryptNonce = encryptNonce;
1363 
1364     return TSS2_RC_SUCCESS;
1365 }
1366 
1367 /** Check the response HMACs for all sessions.
1368  *
1369  * The response HMAC values are computed. Based on these values the HMACs for
1370  * all sessions are computed and compared with the HMACs stored in the response
1371  * auth list which is determined with the SAPI function Tss2_Sys_GetRspAuths.
1372  * @param[in] esys_context The esys context which is used to get the response
1373  * auth values and the sessions.
1374  * @retval TSS2_RC_SUCCESS on success.
1375  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1376  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1377  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1378  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1379  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1380  * @retval TSS2_SYS_RC_* for SAPI errors.
1381  */
1382 TSS2_RC
iesys_check_response(ESYS_CONTEXT * esys_context)1383 iesys_check_response(ESYS_CONTEXT * esys_context)
1384 {
1385     TSS2_RC r;
1386     const uint8_t *rpBuffer;
1387     size_t rpBuffer_size;
1388     TSS2L_SYS_AUTH_RESPONSE rspAuths;
1389     HASH_TAB_ITEM rp_hash_tab[3];
1390     uint8_t rpHashNum = 0;
1391 
1392     if (esys_context->authsCount == 0) {
1393         LOG_TRACE("No auths to verify");
1394         return TSS2_RC_SUCCESS;
1395     }
1396 
1397     r = Tss2_Sys_GetRspAuths(esys_context->sys, &rspAuths);
1398     return_if_error(r, "Error: GetRspAuths");
1399 
1400     if (rspAuths.count != esys_context->authsCount) {
1401         LOG_ERROR("Number of response auths differs: %i (expected %i)",
1402                   rspAuths.count, esys_context->authsCount);
1403         return TSS2_ESYS_RC_GENERAL_FAILURE;
1404     }
1405     /*
1406      * At least one session object is defined so the rp hashes must be computed
1407      * and the HMACs of the responses have to be checked.
1408      * Encrypted response parameters will be decrypted.
1409      */
1410     if (esys_context->session_type[0] >= ESYS_TR_MIN_OBJECT ||
1411         esys_context->session_type[1] >= ESYS_TR_MIN_OBJECT ||
1412         esys_context->session_type[2] >= ESYS_TR_MIN_OBJECT) {
1413         r = Tss2_Sys_GetRpBuffer(esys_context->sys, &rpBuffer_size, &rpBuffer);
1414         return_if_error(r, "Error: get rp buffer");
1415 
1416         r = iesys_compute_rp_hashtab(esys_context,
1417                                      rpBuffer, rpBuffer_size,
1418                                      &rp_hash_tab[0], &rpHashNum);
1419         return_if_error(r, "Error: while computing response hashes");
1420 
1421         r = iesys_check_rp_hmacs(esys_context, &rspAuths, &rp_hash_tab[0],
1422                                  rpHashNum);
1423         return_if_error(r, "Error: response hmac check");
1424 
1425         if (esys_context->encryptNonce == NULL) {
1426             iesys_restore_session_flags(esys_context);
1427             return TSS2_RC_SUCCESS;
1428         }
1429 
1430         r = iesys_decrypt_param(esys_context);
1431         return_if_error(r, "Error: while decrypting parameter.");
1432         iesys_restore_session_flags(esys_context);
1433 
1434     }
1435     return TSS2_RC_SUCCESS;
1436 }
1437 
1438 /** Compute the name from the public data of a NV index.
1439  *
1440  * The name of a NV index is computed as follows:
1441  *   name =  nameAlg||Hash(nameAlg,marshal(publicArea))
1442  * @param[in] publicInfo The public information of the NV index.
1443  * @param[out] name The computed name.
1444  * @retval TSS2_RC_SUCCESS on success.
1445  * @retval TSS2_ESYS_RC_MEMORY Memory can not be allocated.
1446  * @retval TSS2_ESYS_RC_BAD_VALUE for invalid parameters.
1447  * @retval TSS2_ESYS_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1448  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library.
1449  * @retval TSS2_ESYS_RC_NOT_IMPLEMENTED if hash algorithm is not implemented.
1450  * @retval TSS2_SYS_RC_* for SAPI errors.
1451  */
1452 TSS2_RC
iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo,TPM2B_NAME * name)1453 iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo, TPM2B_NAME * name)
1454 {
1455     BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1456     size_t offset = 0;
1457     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1458     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1459     IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1460 
1461     if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1462         name->size = 0;
1463         return TSS2_RC_SUCCESS;
1464     }
1465     TSS2_RC r;
1466     r = iesys_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1467     return_if_error(r, "Crypto hash start");
1468 
1469     r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1470                                        &buffer[0], sizeof(TPMS_NV_PUBLIC),
1471                                        &offset);
1472     goto_if_error(r, "Marshaling TPMS_NV_PUBLIC", error_cleanup);
1473 
1474     r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1475     goto_if_error(r, "crypto hash update", error_cleanup);
1476 
1477     r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1478                                      &size);
1479     goto_if_error(r, "crypto hash finish", error_cleanup);
1480 
1481     offset = 0;
1482     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1483                                   &name->name[0], sizeof(TPMI_ALG_HASH),
1484                                   &offset);
1485     goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1486 
1487     name->size = size + len_alg_id;
1488     return TSS2_RC_SUCCESS;
1489 
1490 error_cleanup:
1491     if (cryptoContext)
1492         iesys_crypto_hash_abort(&cryptoContext);
1493     return r;
1494 }
1495 
1496 /** Compute the name of a TPM transient or persistent object.
1497  *
1498  * The name of a NV index is computed as follows:
1499  *   name = Hash(nameAlg,marshal(publicArea))
1500  * @param[in] publicInfo The public information of the TPM object.
1501  * @param[out] name The computed name.
1502  * @retval TPM2_RC_SUCCESS  or one of the possible errors TSS2_ESYS_RC_BAD_VALUE,
1503  * TSS2_ESYS_RC_MEMORY, TSS2_ESYS_RC_GENERAL_FAILURE, TSS2_ESYS_RC_NOT_IMPLEMENTED,
1504  * or return codes of SAPI errors.
1505  */
1506 TSS2_RC
iesys_get_name(TPM2B_PUBLIC * publicInfo,TPM2B_NAME * name)1507 iesys_get_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
1508 {
1509     BYTE buffer[sizeof(TPMT_PUBLIC)];
1510     size_t offset = 0;
1511     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1512     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1513     IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1514 
1515     if (publicInfo->publicArea.nameAlg == TPM2_ALG_NULL) {
1516         name->size = 0;
1517         return TSS2_RC_SUCCESS;
1518     }
1519     TSS2_RC r;
1520     r = iesys_crypto_hash_start(&cryptoContext, publicInfo->publicArea.nameAlg);
1521     return_if_error(r, "crypto hash start");
1522 
1523     r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicInfo->publicArea,
1524                                     &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1525     goto_if_error(r, "Marshaling TPMT_PUBLIC", error_cleanup);
1526 
1527     r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1528     goto_if_error(r, "crypto hash update", error_cleanup);
1529 
1530     r = iesys_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1531                                      &size);
1532     goto_if_error(r, "crypto hash finish", error_cleanup);
1533 
1534     offset = 0;
1535     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->publicArea.nameAlg,
1536                                   &name->name[0], sizeof(TPMI_ALG_HASH),
1537                                   &offset);
1538     goto_if_error(r, "Marshaling TPMI_ALG_HASH", error_cleanup);
1539 
1540     name->size = size + len_alg_id;
1541     return TSS2_RC_SUCCESS;
1542 
1543 error_cleanup:
1544     if (cryptoContext)
1545         iesys_crypto_hash_abort(&cryptoContext);
1546     return r;
1547 }
1548 
1549 /** Check whether the return code corresponds to an TPM error.
1550  *
1551  * if no layer is part of the return code or a layer from the resource manager
1552  * is given the function will return true.
1553  * @param[in] r The return code to be checked.
1554  * @retval true if r corresponds to an TPM error.
1555  * @retval false in other cases.
1556  */
1557 bool
iesys_tpm_error(TSS2_RC r)1558 iesys_tpm_error(TSS2_RC r)
1559 {
1560     return (r != TSS2_RC_SUCCESS &&
1561             ((r & TSS2_RC_LAYER_MASK) == 0 ||
1562              (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_TPM_RC_LAYER ||
1563              (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_RC_LAYER));
1564 }
1565 
1566 
1567 /** Replace auth value with Hash for long auth values.
1568  *
1569  * if the size of auth value exceeds hash_size the auth value
1570  * will be replaced with the hash of the auth value.
1571  *
1572  * @param[in,out] auth_value The auth value to be adapted.
1573  * @param[in] hash_alg The hash alg used for adaption.
1574  * @retval TSS2_RC_SUCCESS if the function call was a success.
1575  * @retval TSS2_ESYS_RC_BAD_VALUE if an invalid hash is passed.
1576  * @retval TSS2_ESYS_RC_MEMORY if the ESAPI cannot allocate enough memory.
1577  * @retval TSS2_ESYS_RC_GENERAL_FAILURE for a failure during digest
1578  *         computation.
1579  */
1580 TSS2_RC
iesys_hash_long_auth_values(TPM2B_AUTH * auth_value,TPMI_ALG_HASH hash_alg)1581 iesys_hash_long_auth_values(
1582     TPM2B_AUTH *auth_value,
1583     TPMI_ALG_HASH hash_alg)
1584 {
1585     TSS2_RC r;
1586     IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1587     TPM2B_AUTH hash2b;
1588     size_t hash_size;
1589 
1590     r = iesys_crypto_hash_get_digest_size(hash_alg, &hash_size);
1591     return_if_error(r, "Get digest size.");
1592 
1593     if (auth_value && auth_value->size > hash_size) {
1594         /* The auth value has to be adapted. */
1595         r = iesys_crypto_hash_start(&cryptoContext, hash_alg);
1596         return_if_error(r, "crypto hash start");
1597 
1598         r = iesys_crypto_hash_update(cryptoContext, &auth_value->buffer[0],
1599                                      auth_value->size);
1600         goto_if_error(r, "crypto hash update", error_cleanup);
1601 
1602         r = iesys_crypto_hash_finish(&cryptoContext, &hash2b.buffer[0],
1603                                      &hash_size);
1604         goto_if_error(r, "crypto hash finish", error_cleanup);
1605 
1606         memcpy(&auth_value->buffer[0], &hash2b.buffer[0], hash_size);
1607         auth_value->size = hash_size;
1608     }
1609     return r;
1610 
1611  error_cleanup:
1612     if (cryptoContext) {
1613         iesys_crypto_hash_abort(&cryptoContext);
1614     }
1615     return r;
1616 }
1617