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 ¶m_size, ¶m_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 ¶m_size, ¶m_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, ¶mSize,
708 ¶mBuffer);
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