blob: 2df69426a1a8dde641fff9d99181fd5228e4d144 [file] [log] [blame]
Juergen Reppff821bd2017-12-11 15:21:42 +01001/*******************************************************************************
2 * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 *******************************************************************************/
Juergen Repp62097182018-03-19 18:04:42 +010027#include <inttypes.h>
28
Juergen Reppff821bd2017-12-11 15:21:42 +010029#include "tss2_esys.h"
30#include "esys_mu.h"
Juergen Repp62097182018-03-19 18:04:42 +010031
32#include "esys_iutil.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010033#include "esys_int.h"
Juergen Repp62097182018-03-19 18:04:42 +010034#define LOGMODULE esys
Philip Triccaa7c51ce2018-03-10 18:28:25 -080035#include "util/log.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010036
37/**
38 * Compare variables of type UINT16.
39 * @param[in] in1 Variable to be compared with:
40 * @param[in] in2
41 */
42bool
43cmp_UINT16(const UINT16 * in1, const UINT16 * in2)
44{
45 LOG_TRACE("call");
46 if (*in1 == *in2)
47 return true;
48 else {
49 LOG_TRACE("cmp false");
50 return false;
51 }
52}
53
54/**
55 * Compare variables of type BYTE.
56 * @param[in] in1 Variable to be compared with:
57 * @param[in] in2
58 */
59bool
60cmp_BYTE(const BYTE * in1, const BYTE * in2)
61{
62 LOG_TRACE("call");
63 if (*in1 == *in2)
64 return true;
65 else {
66 LOG_TRACE("cmp false");
67 return false;
68 }
69}
70
71/**
72 * Compare two arrays of type BYTE.
73 * @param[in] in1 array to be compared with:.
74 * @param[in] in2
75 */
76
77bool
78cmp_BYTE_array(const BYTE * in1, size_t count1, const BYTE * in2, size_t count2)
79{
80 if (count1 != count2) {
81 LOG_TRACE("cmp false");
82 return false;
83 }
84 for (size_t i = 0; i < count1; i++) {
85 if (!cmp_BYTE(&in1[i], &in2[i])) {
86 LOG_TRACE("cmp false");
87 return false;
88 }
89 }
90 return true;
91}
92
93/**
94 * Compare two variables of type TPM2B_DIGEST.
95 * @param[in] in1 variable to be compared with:
96 * @param[in] in2
97 */
98bool
99cmp_TPM2B_DIGEST(const TPM2B_DIGEST * in1, const TPM2B_DIGEST * in2)
100{
101 LOG_TRACE("call");
102
103 if (!cmp_UINT16(&in1->size, &in2->size)) {
104 LOG_TRACE("cmp false");
105 return false;
106 }
107
108 return cmp_BYTE_array((BYTE *) & in1->buffer, in1->size,
109 (BYTE *) & in2->buffer, in2->size);
110
111 return true;
112}
113
114/**
115 * Compare two variables of type TPM2B_NAME.
116 * @param[in] in1 variable to be compared with:
117 * @param[in] in2
118 */
119bool
120cmp_TPM2B_NAME(const TPM2B_NAME * in1, const TPM2B_NAME * in2)
121{
122 LOG_TRACE("call");
123
124 if (!cmp_UINT16(&in1->size, &in2->size)) {
125 LOG_TRACE("cmp false");
126 return false;
127 }
128
129 return cmp_BYTE_array((BYTE *) & in1->name, in1->size, (BYTE *) & in2->name,
130 in2->size);
131
132 return true;
133}
134
135/**
136 * Compare two structures of type TPM2B_AUTH.
137 * @param[in] in1 Structure to be compared with:
138 * @param[in] in1
139 */
140bool
141cmp_TPM2B_AUTH(const TPM2B_AUTH * in1, const TPM2B_AUTH * in2)
142{
143 LOG_TRACE("call");
144 return cmp_TPM2B_DIGEST(in1, in2);
145}
146
147TSS2_RC
148init_session_tab(ESYS_CONTEXT *esys_context,
149 ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3)
150{
151 TSS2_RC r = TPM2_RC_SUCCESS;
152 ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
153 for (int i = 0; i < 3; i++) {
154 esys_context->session_type[i] = handle_tab[i];
155 if (handle_tab[i] == ESYS_TR_NONE || handle_tab[i] == ESYS_TR_PASSWORD) {
156 esys_context->session_tab[i] = NULL;
157 } else {
158 r = esys_GetResourceObject(esys_context, handle_tab[i],
159 &esys_context->session_tab[i]);
160 return_if_error(r, "Unknown resource.");
161 }
162 }
163 return r;
164}
165
166void
167iesys_DeleteAllResourceObjects(ESYS_CONTEXT * esys_context)
168{
169 RSRC_NODE_T *node_rsrc;
170 RSRC_NODE_T *next_node_rsrc;
171 for (node_rsrc = esys_context->rsrc_list; node_rsrc != NULL;
172 node_rsrc = next_node_rsrc) {
173 next_node_rsrc = node_rsrc->next;
174 SAFE_FREE(node_rsrc);
175 }
176}
177
178TSS2_RC
179iesys_compute_encrypt_nonce(ESYS_CONTEXT * esys_context,
180 int *encryptNonceIdx, TPM2B_NONCE ** encryptNonce)
181{
182 for (int i = 0; i < 3; i++) {
183 RSRC_NODE_T *session = esys_context->session_tab[i];
184 if (session != NULL) {
185 if (session->rsrc.misc.rsrc_session.
186 sessionAttributes & TPMA_SESSION_ENCRYPT) {
187 if (*encryptNonce != NULL) {
188 return_error(TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS,
189 "More than one encrypt session");
190 }
191 *encryptNonceIdx = i;
192 *encryptNonce = &session->rsrc.misc.rsrc_session.nonceTPM;
193 }
194 }
195 }
196 return TSS2_RC_SUCCESS;
197}
198
199TSS2_RC
200iesys_compute_cp_hashtab(ESYS_CONTEXT * esys_context,
201 const TPM2B_NAME * name1,
202 const TPM2B_NAME * name2,
203 const TPM2B_NAME * name3,
204 HASH_TAB_ITEM cp_hash_tab[3], uint8_t * cpHashNum)
205{
206 uint8_t ccBuffer[4];
207 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
208 return_if_error(r, "Error: get command code");
209 const uint8_t *cpBuffer;
210 size_t cpBuffer_size;
211 r = Tss2_Sys_GetCpBuffer(esys_context->sys, &cpBuffer_size, &cpBuffer);
212 return_if_error(r, "Error: get cp buffer");
213 *cpHashNum = 0;
214 for (int i = 0; i < 3; i++) {
215 RSRC_NODE_T *session = esys_context->session_tab[i];
216 bool cpHashFound = false;
217 if (session != NULL) {
218 /* We do not want to compute cpHashes multiple times for the same
219 algorithm to save time and space */
220 for (int j = 0; j < *cpHashNum; j++)
221 /* Check if cpHash for this algorithm was already computed */
222 if (cp_hash_tab[j].alg ==
223 session->rsrc.misc.rsrc_session.authHash) {
224 cpHashFound = true;
225 break;
226 }
227 /* If not, we compute it and append it to the list */
228 if (!cpHashFound) {
229 cp_hash_tab[*cpHashNum].size = sizeof(TPMU_HA);
230 r = iesys_crypto_cpHash(session->rsrc.misc.rsrc_session.
231 authHash, ccBuffer, name1, name2, name3,
232 cpBuffer, cpBuffer_size,
233 &cp_hash_tab[*cpHashNum].digest[0],
234 &cp_hash_tab[*cpHashNum].size);
235 return_if_error(r, "crypto cpHash");
236
237 cp_hash_tab[*cpHashNum].alg =
238 session->rsrc.misc.rsrc_session.authHash;
239 *cpHashNum += 1;
240 }
241 }
242 }
243 return r;
244}
245
246TSS2_RC
247iesys_compute_rp_hashtab(ESYS_CONTEXT * esys_context,
248 TSS2L_SYS_AUTH_RESPONSE * rspAuths,
249 const uint8_t * rpBuffer,
250 size_t rpBuffer_size,
251 HASH_TAB_ITEM rp_hash_tab[3], uint8_t * rpHashNum)
252{
253 uint8_t rcBuffer[4] = { 0 };
254 uint8_t ccBuffer[4];
255 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
256 return_if_error(r, "Error: get command code");
257
258 for (int i = 0; i < rspAuths->count; i++) {
259 RSRC_NODE_T *session = esys_context->session_tab[i];
Andreas Fuchs4ee237b2018-02-23 11:11:40 +0100260 if (session == NULL)
261 continue;
Juergen Reppff821bd2017-12-11 15:21:42 +0100262 bool rpHashFound = false;
263 for (int j = 0; j < *rpHashNum; j++)
264 if (rp_hash_tab[j].alg == session->rsrc.misc.rsrc_session.authHash) {
265 rpHashFound = true;
266 break;
267 }
268 if (!rpHashFound) {
269 rp_hash_tab[*rpHashNum].size = sizeof(TPMU_HA);
270 r = iesys_crypto_rpHash(session->rsrc.misc.rsrc_session.authHash,
271 rcBuffer, ccBuffer, rpBuffer, rpBuffer_size,
272 &rp_hash_tab[*rpHashNum].digest[0],
273 &rp_hash_tab[*rpHashNum].size);
274 return_if_error(r, "crypto rpHash");
275 rp_hash_tab[*rpHashNum].alg =
276 session->rsrc.misc.rsrc_session.authHash;
277 *rpHashNum += 1;
278 }
279 }
280 return TPM2_RC_SUCCESS;
281}
282
283TSS2_RC
284GetTpmHandle(ESYS_CONTEXT * esys_context,
285 ESYS_TR esys_handle, TPM2_RH * tpm_handle)
286{
287 RSRC_NODE_T *esys_object;
288 TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object);
289 return_if_error(r, "Getting Resource Object");
290 if (esys_object == NULL)
291 return_error(TSS2_ESYS_RC_BAD_TR, "Handle for bad TR requested.");
292 *tpm_handle = esys_object->rsrc.handle;
293 return TPM2_RC_SUCCESS;
294}
295
296TSS2_RC
297esys_CreateResourceObject(ESYS_CONTEXT * esys_context,
298 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
299{
300 RSRC_NODE_T *new_esys_object = calloc(1, sizeof(RSRC_NODE_T));
301 if (new_esys_object == NULL)
302 return_error(TSS2_ESYS_RC_MEMORY, "Out of memory.");
303 if (esys_context->rsrc_list == NULL) {
304 esys_context->rsrc_list = new_esys_object;
305 new_esys_object->next = NULL;
306 } else {
307 new_esys_object->next = esys_context->rsrc_list;
308 esys_context->rsrc_list = new_esys_object;
309 }
310 *esys_object = new_esys_object;
311 new_esys_object->esys_handle = esys_handle;
312 return TSS2_RC_SUCCESS;
313}
314
315TSS2_RC
316iesys_handle_to_tpm_handle(ESYS_TR esys_handle, TPM2_HANDLE * tpm_handle)
317{
318 /* Since ESYS_TR_PCR0 is equal zero only <= ESYS_TR_PCR31 has to be checked */
319 if (esys_handle <= ESYS_TR_PCR31) {
320 *tpm_handle = (TPM2_HANDLE) esys_handle;
321 return TPM2_RC_SUCCESS;
322 }
323 if (esys_handle == ESYS_TR_RH_OWNER) {
324 *tpm_handle = TPM2_RH_OWNER;
325 return TPM2_RC_SUCCESS;
326 }
327 if (esys_handle == ESYS_TR_RH_NULL) {
328 *tpm_handle = TPM2_RH_NULL;
329 return TPM2_RC_SUCCESS;
330 }
331 if (esys_handle == ESYS_TR_RH_LOCKOUT) {
332 *tpm_handle = TPM2_RH_LOCKOUT;
333 return TPM2_RC_SUCCESS;
334 }
335 if (esys_handle == ESYS_TR_RH_ENDORSEMENT) {
336 *tpm_handle = TPM2_RH_ENDORSEMENT;
337 return TPM2_RC_SUCCESS;
338 }
339 if (esys_handle == ESYS_TR_RH_PLATFORM) {
340 *tpm_handle = TPM2_RH_PLATFORM;
341 return TPM2_RC_SUCCESS;
342 }
343 if (esys_handle == ESYS_TR_RH_PLATFORM_NV) {
344 *tpm_handle = TPM2_RH_PLATFORM_NV;
345 return TPM2_RC_SUCCESS;
346 }
347 LOG_ERROR("Error: Esys invalid ESAPI handle (%x).", esys_handle);
348 return TSS2_ESYS_RC_BAD_VALUE;
349}
350
351TPM2_HT
352iesys_get_handle_type(TPM2_HANDLE handle)
353{
354 TPM2_HT ht = (TPM2_HT) ((handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT); /* upper bytes of input data */
355 return ht;
356}
357
358bool
359esys_tpm_handle_with_context(TPM2_HANDLE handle)
360{
361 TPM2_HT ht = iesys_get_handle_type(handle);
362 switch (ht) {
363 case TPM2_HT_TRANSIENT:
364 case TPM2_HT_HMAC_SESSION:
365 case TPM2_HT_POLICY_SESSION:
366 return true;
367 default:
368 return false;
369 }
370}
371
372bool
373esys_handle_with_context(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle)
374{
375 TPM2_RH tpm_handle;
376 TSS2_RC r = GetTpmHandle(esys_context, esys_handle, &tpm_handle);
377 if (r != TSS2_RC_SUCCESS)
378 return false;
379 return (esys_tpm_handle_with_context(tpm_handle));
380}
381
382bool
383esys_flush_context(TPM2_HANDLE handle)
384{
385 TPM2_HT ht = iesys_get_handle_type(handle);
386 switch (ht) {
387 case TPM2_HT_TRANSIENT:
388 return true;
389 default:
390 return false;
391 }
392}
393
394TSS2_RC
395iesys_get_nv_name(TPMS_NV_PUBLIC * nvPublic, TPM2B_NAME * name)
396{
397 BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
398 size_t max_size_hash = sizeof(TPMU_HA);
399 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
400 size_t offset = 0;
401 TSS2_RC r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(nvPublic,
402 buffer,
403 sizeof(TPMS_NV_PUBLIC),
404 &offset);
405 return_if_error(r, "Error: During nv public marshal");
406
407 r = iesys_crypto_hash_start(&cryptoContext, nvPublic->nameAlg);
408 return_if_error(r, "Error: During hash start");
409
410 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
411 return_if_error(r, "Error: During hash update");
412
413 r = iesys_crypto_hash_finish(&cryptoContext, &name->name[2],
414 &max_size_hash);
415 return_if_error(r, "Error: During hash finish");
416
417 name->size = (UINT16) offset + 2;
418 return TSS2_RC_SUCCESS;
419}
420
421TSS2_RC
Juergen Reppff821bd2017-12-11 15:21:42 +0100422iesys_get_object_name(TPM2B_PUBLIC * publicArea2B, TPM2B_NAME * name)
423{
424 BYTE buffer[sizeof(TPMT_PUBLIC)];
425 size_t offset = 0;
426 size_t max_size_hash = sizeof(TPMU_HA);
427 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
428 TSS2_RC r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicArea2B->publicArea,
429 buffer, sizeof(TPMT_PUBLIC),
430 &offset);
431 return_if_error(r, "Error: During nv public marshal");
432
433 r = iesys_crypto_hash_start(&cryptoContext,
434 publicArea2B->publicArea.nameAlg);
435 return_if_error(r, "Error: During hash start");
436
437 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
438 return_if_error(r, "Error: During hash update");
439
440 r = iesys_crypto_hash_finish(&cryptoContext, &name->name[2],
441 &max_size_hash);
442 return_if_error(r, "Error: During hash finish");
443
444 name->size = (UINT16) offset + 2;
445 offset = 0;
446 r = Tss2_MU_UINT16_Marshal(publicArea2B->publicArea.nameAlg, &name->name[0], 2,
447 &offset);
448 return_if_error(r, "Error: During UINT16 marshal");
449 return TSS2_RC_SUCCESS;
450}
451
452TSS2_RC
453iesys_create_NV_resource(TPMS_NV_PUBLIC * nvPublic,
454 IESYS_RESOURCE ** nvResource)
455{
456 *nvResource = calloc(1, sizeof(IESYS_RESOURCE));
457 return_if_null(nvResource, "Out of Memory", TSS2_ESYS_RC_MEMORY);
458 (*nvResource)->rsrcType = IESYSC_NV_RSRC;
459 (*nvResource)->authValueSet = 0;
460 (*nvResource)->handle = nvPublic->nvIndex;
461 (*nvResource)->misc.rsrc_nv_pub.nvPublic = *nvPublic;
462 (*nvResource)->misc.rsrc_nv_pub.size = 0;
463 return iesys_get_nv_name(nvPublic, &(*nvResource)->name);
464}
465
Juergen Reppff821bd2017-12-11 15:21:42 +0100466bool
467iesys_compare_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
468{
469 TSS2_RC r = TSS2_RC_SUCCESS;
470 TPM2B_NAME public_info_name;
471 if (publicInfo == NULL || name == NULL)
472 return false;
473 r = iesys_get_name(publicInfo, &public_info_name);
474 if (r != TSS2_RC_SUCCESS) {
475 LOG_DEBUG("name could not be computed.");
476 return false;
477 }
478 return cmp_TPM2B_NAME(&public_info_name, name);
479}
480
481TSS2_RC
482iesys_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;
Juergen Reppff821bd2017-12-11 15:21:42 +0100487 size_t keyHash_size = 0;
488 size_t cSize = 0;
489 if (tpmKeyNode != NULL) {
490 if (tpmKeyNode->rsrc.rsrcType != IESYSC_KEY_RSRC) {
491 LOG_TRACE("Public info needed.");
492 return TSS2_ESYS_RC_BAD_VALUE;
493 }
494 r = iesys_crypto_hash_get_digest_size(tpmKeyNode->rsrc.misc.
495 rsrc_key_pub.publicArea.nameAlg,
496 &keyHash_size);
497 return_if_error(r, "Hash algorithm not supported.");
498 iesys_crypto_random2b((TPM2B_NONCE *) & esys_context->salt, keyHash_size);
499
500 /* When encrypting salts, the encryption scheme of a key is ignored and
501 TPM2_ALG_OAEP is always used. */
502 TPM2B_PUBLIC pub = tpmKeyNode->rsrc.misc.rsrc_key_pub;
503 pub.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_OAEP;
504 r = iesys_crypto_pk_encrypt(&pub,
505 keyHash_size, &esys_context->salt.buffer[0],
506 sizeof(TPMU_ENCRYPTED_SECRET),
507 (BYTE *) &encryptedSalt->secret[0], &cSize,
508 "SECRET");
509 return_if_error(r, "During encryption.");
510 LOGBLOB_DEBUG(&encryptedSalt->secret[0], cSize, "IESYS encrypted salt");
511 encryptedSalt->size = cSize;
512 } else {
513 encryptedSalt->size = 0;
514 }
515 return r;
516}
517
518TSS2_RC
519iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)
520{
521 TSS2_RC r;
522 size_t authHash_size = 0;
523
524 for (int i = 0; i < 3; i++) {
525 RSRC_NODE_T *session = esys_context->session_tab[i];
526 if (session == NULL)
527 continue;
528 r = iesys_crypto_hash_get_digest_size(session->rsrc.misc.rsrc_session.
529 authHash, &authHash_size);
530 return_if_error(r, "Error: initialize auth session.");
531
532 r = iesys_crypto_random2b(&session->rsrc.misc.rsrc_session.nonceCaller,
533 authHash_size);
534 return_if_error(r, "Error: computing caller nonce (%x).");
535 }
536 return TSS2_RC_SUCCESS;
537}
538
539TSS2_RC
540iesys_encrypt_param(ESYS_CONTEXT * esys_context,
541 TPM2B_NONCE ** decryptNonce, int *decryptNonceIdx)
542{
543 uint8_t ccBuffer[4];
544 const uint8_t *cpBuffer;
545 size_t cpBuffer_size;
546 TPM2B_NONCE *encryptNonce = NULL;
Juergen Reppff821bd2017-12-11 15:21:42 +0100547 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
548 return_if_error(r, "Error: get command code");
549 *decryptNonceIdx = 0;
550 *decryptNonce = NULL;
551 r = Tss2_Sys_GetCpBuffer(esys_context->sys, &cpBuffer_size, &cpBuffer);
552 return_if_error(r, "Error: get cp buffer");
553 for (int i = 0; i < 3; i++) {
554 RSRC_NODE_T *session = esys_context->session_tab[i];
555 if (session == NULL)
556 continue;
557 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
558 TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
559 if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT) {
560 return_if_notnull(encryptNonce, "More than one encrypt session",
561 TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS);
562 esys_context->encryptNonceIdx = i;
563 encryptNonce = &rsrc_session->nonceTPM;
564 esys_context->encryptNonce = encryptNonce;
565 }
566 if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT) {
567 return_if_notnull(*decryptNonce, "More than one decrypt session",
568 TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS);
569 *decryptNonceIdx = i;
570 *decryptNonce = &rsrc_session->nonceTPM;
571 size_t hlen;
572 r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
573 return_if_error(r, "get digest size");
574 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
575 if (key_len % hlen > 0)
576 key_len = key_len + hlen - (key_len % hlen);
577 uint8_t symKey[key_len];
578 if (symDef->algorithm == TPM2_ALG_AES) {
579 if (symDef->mode.aes != TPM2_ALG_CFB) {
580 return_error(TSS2_ESYS_RC_BAD_VALUE,
581 "Invalid symmetric mode (must be CFB)");
582 }
583 r = iesys_crypto_KDFa(rsrc_session->authHash,
584 &rsrc_session->sessionValue[0],
585 rsrc_session->sizeSessionValue, "CFB",
586 &rsrc_session->nonceCaller,
587 &rsrc_session->nonceTPM,
588 symDef->keyBits.aes + AES_BLOCK_SIZE_IN_BYTES * 8,
589 NULL, &symKey[0]);
590 return_if_error(r, "while computing KDFa");
591 const uint8_t *paramBuffer;
592 size_t paramSize = 0;
593 r = Tss2_Sys_GetDecryptParam(esys_context->sys, &paramSize,
594 &paramBuffer);
595 return_if_error(r, "Encrypt parameter not possible");
596 BYTE encrypt_buffer[paramSize];
597 memcpy(&encrypt_buffer[0], paramBuffer, paramSize);
598 LOGBLOB_DEBUG(paramBuffer, paramSize, "param to encrypt");
599 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
600 r = iesys_crypto_sym_aes_encrypt(&symKey[0],
601 symDef->algorithm,
602 symDef->keyBits.aes,
603 symDef->mode.aes,
604 AES_BLOCK_SIZE_IN_BYTES,
605 &encrypt_buffer[0], paramSize,
606 &symKey[aes_off],
607 AES_BLOCK_SIZE_IN_BYTES);
608 return_if_error(r, "AES encryption not possible");
609 r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
610 &encrypt_buffer[0]);
611 return_if_error(r, "Set encrypt parameter not possible");
612
613 } else if (symDef->algorithm == TPM2_ALG_XOR) {
614 return_error(TSS2_ESYS_RC_NOT_IMPLEMENTED,
615 "XOR obfuscation not implemented.");
616 } else {
617 return_error(TSS2_ESYS_RC_BAD_VALUE,
618 "Invalid symmetric algorithm (should be XOR or AES)");
619 }
620 }
621 }
622 return r;
623}
624
625TSS2_RC
626iesys_decrypt_param(ESYS_CONTEXT * esys_context,
627 const uint8_t * rpBuffer, size_t rpBuffer_size)
628{
629 size_t hlen;
630 RSRC_NODE_T *session;
631 session = esys_context->session_tab[esys_context->encryptNonceIdx];
632 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
633 TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
634 TSS2_RC r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
635 return_if_error(r, "Error");
636 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
637
638 if (key_len % hlen > 0)
639 key_len = key_len + hlen - (key_len % hlen);
640 uint8_t symKey[key_len];
641 if (symDef->algorithm == TPM2_ALG_AES) {
642 if (symDef->mode.aes != TPM2_ALG_CFB) {
643 return_error(TSS2_ESYS_RC_BAD_VALUE,
644 "Invalid symmetric mode (must be CFB)");
645 }
646 LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0],
647 rsrc_session->sessionKey.size,
648 "IESYS encrypt session key");
649
650 r = iesys_crypto_KDFa(rsrc_session->authHash,
651 &rsrc_session->sessionValue[0],
652 rsrc_session->sizeSessionValue,
653 "CFB", &rsrc_session->nonceTPM,
654 &rsrc_session->nonceCaller,
655 symDef->keyBits.aes
656 + AES_BLOCK_SIZE_IN_BYTES * 8, NULL,
657 &symKey[0]);
658 return_if_error(r, "KDFa error");
659 LOGBLOB_DEBUG(&symKey[0],
660 ((symDef->keyBits.aes +
661 AES_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8,
662 "IESYS encrypt KDFa key");
663 UINT16 p2BSize = 0;
664 size_t offset = 0;
665 r = Tss2_MU_UINT16_Unmarshal(rpBuffer, rpBuffer_size, &offset, &p2BSize);
666 return_if_error(r, "Unmarshal error");
667 if (p2BSize > rpBuffer_size) {
668 return_error(TSS2_ESYS_RC_BAD_VALUE,
669 "Invalid length encrypted response.");
670 }
671 LOGBLOB_DEBUG(rpBuffer, p2BSize, "IESYS encrypt data");
672 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
673 r = iesys_crypto_sym_aes_decrypt(&symKey[0],
674 symDef->algorithm,
675 symDef->keyBits.aes,
676 symDef->mode.aes,
677 AES_BLOCK_SIZE_IN_BYTES,
678 (uint8_t *) & rpBuffer[2], p2BSize,
679 &symKey[aes_off],
680 AES_BLOCK_SIZE_IN_BYTES);
681 return_if_error(r, "Decryption error");
682 } else if (symDef->algorithm == TPM2_ALG_XOR) {
683 return_error(TSS2_ESYS_RC_NOT_IMPLEMENTED,
684 "XOR obfuscation not implemented.");
685 } else {
686 return_error(TSS2_ESYS_RC_BAD_VALUE,
687 "Invalid symmetric algorithm (should be XOR or AES)");
688 }
689 return TSS2_RC_SUCCESS;
690}
691
692TSS2_RC
693iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,
694 TSS2L_SYS_AUTH_RESPONSE * rspAuths,
695 HASH_TAB_ITEM rp_hash_tab[3])
696{
697 for (int i = 0; i < rspAuths->count; i++) {
698 RSRC_NODE_T *session = esys_context->session_tab[i];
699 if (session != NULL) {
700 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
Juergen Reppaad3a852018-03-19 16:21:20 +0100701 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
702 if (rspAuths->auths[i].hmac.size != 0) {
703 LOG_ERROR("Error: hmac size not equal 0 in response.");
704 return TSS2_ESYS_RC_BAD_VALUE;
705 }
706 return TSS2_RC_SUCCESS;
707 }
708
Juergen Reppff821bd2017-12-11 15:21:42 +0100709 int hi = 0;
710 for (int j = 0; j < 3; j++) {
711 if (rsrc_session->authHash == rp_hash_tab[j].alg) {
712 hi = j;
713 break;
714 }
715 }
716 TPM2B_AUTH rp_hmac;
717 rp_hmac.size = sizeof(TPMU_HA);
718 rsrc_session->nonceTPM = rspAuths->auths[i].nonce;
719 rsrc_session->sessionAttributes =
720 rspAuths->auths[i].sessionAttributes;
721 // TODO check: auths.auths[i].hmac.size = sizeof(TPMU_HA);
722 TSS2_RC r =
723 iesys_crypto_authHmac(rsrc_session->authHash,
724 &rsrc_session->sessionValue[0],
725 rsrc_session->sizeSessionValue,
726 &rp_hash_tab[hi].digest[0],
727 rp_hash_tab[hi].size,
728 &rsrc_session->nonceTPM,
729 &rsrc_session->nonceCaller, NULL, NULL,
730 rspAuths->auths[i].sessionAttributes,
731 &rp_hmac);
732 return_if_error(r, "HMAC error");
733 if (!cmp_TPM2B_AUTH(&rspAuths->auths[i].hmac, &rp_hmac)) {
734 LOG_ERROR("Error: Invalid hmac response.");
735 return TSS2_ESYS_RC_BAD_VALUE;
736 }
737 }
738
739 }
740 return TSS2_RC_SUCCESS;
741}
742
743void
744iesys_compute_bound_entity(const TPM2B_NAME * name,
745 const TPM2B_AUTH * auth, TPM2B_NAME * bound_entity)
746{
747 UINT16 i;
748 UINT16 j = 0;
749 *bound_entity = *name;
750 memset(&bound_entity->name[bound_entity->size], 0,
751 sizeof(bound_entity->name) - bound_entity->size);
752 for (i = sizeof(bound_entity->name) - auth->size;
753 i < sizeof(bound_entity->name); i++)
754 bound_entity->name[i] ^= auth->buffer[j++];
755 bound_entity->size = sizeof(bound_entity->name);
756}
757
758bool
759iesys_is_object_bound(const TPM2B_NAME * name,
760 const TPM2B_AUTH * auth, const TPM2B_NAME * bound_entity)
761{
762 TPM2B_NAME tmp;
763 iesys_compute_bound_entity(name, auth, &tmp);
764 return cmp_TPM2B_NAME(bound_entity, &tmp);
765}
766
767/**
768 * Compute the session value
769 *
770 * This function derives the session value from the session key
771 * and the auth value.
772 * The auth value is only used if an authorization is necessary and the name
773 * of the object is not equal to the name of an used bound entity
774 * @param[in] session for which the session value will be computed
775 * @param[in] name name of the object to be authorized (NULL if no authorization)
776 * @param[in] auth-value auth value of the object to be authorized
777 * (NULL if no authorization)
778 */
779void
780iesys_compute_session_value(RSRC_NODE_T * session,
781 const TPM2B_NAME * name,
782 const TPM2B_AUTH * auth_value)
783{
Juergen Reppff821bd2017-12-11 15:21:42 +0100784 if (session == NULL)
785 return;
786
787 /* First the session Key is copied into the sessionValue */
788 session->rsrc.misc.rsrc_session.sizeSessionValue
789 = session->rsrc.misc.rsrc_session.sessionKey.size;
790 memcpy(&session->rsrc.misc.rsrc_session.sessionValue[0],
791 &session->rsrc.misc.rsrc_session.sessionKey.buffer[0],
792 session->rsrc.misc.rsrc_session.sessionKey.size);
793
794 /* Then if we are a bound session, the auth value is appended to the end
795 of the session value. */
796 if (name == NULL)
797 return;
798 /* This requires an HMAC Session and not a password session */
799 if (session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_HMAC &&
800 session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_POLICY)
801 return;
802 if (iesys_is_object_bound(name, auth_value,
803 &session->rsrc.misc.rsrc_session.bound_entity) &&
804 /* type_policy_session set to POLICY_AUTH by command PolicyAuthValue */
805 (session->rsrc.misc.rsrc_session.type_policy_session != POLICY_AUTH))
806 return;
807
808 memcpy(&session->rsrc.misc.rsrc_session.
809 sessionValue[session->rsrc.misc.rsrc_session.sessionKey.size],
810 &auth_value->buffer[0], auth_value->size);
811 session->rsrc.misc.rsrc_session.sizeSessionValue += auth_value->size;
812}
813
814/**
815 * Lookup the object to a handle from inside the context.
816 *
817 * This function searches the esapi context for an object that corresponds to a
818 * provided esys_handle. These objects contain information such as the
819 * appropriate tpm handle, the public name or the stored auth values.
820 * These esys handles refer either to an object previously initialized on the
821 * same context, in which case this will be returned. Or they refer to a
822 * "global", in which case the corresponding object will be created if it does
823 * not exist yet.
824 * @param[in,out] esys_context The esys context to issue the command on.
825 * @param[in] esys_handle The handle to find the corresponding object for.
826 * @param[out] esys_object The object containing the name, tpm handle and auth value
827 * @returns TSS2_RC_SUCCESS on success
828 * TSS2_ESYS_RC_BAD_TR if the handle is invalid
829 */
830TSS2_RC
831esys_GetResourceObject(ESYS_CONTEXT * esys_context,
832 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
833{
834 RSRC_NODE_T *esys_object_aux;
835 TPM2_HANDLE tpm_handle;
836 size_t offset = 0;
837 TSS2_RC r;
838
839 /* Sometimes the TPM API allows for optional objects. In those cases we map
840 the object node to NULL. This will be handled accordingly by following
841 code */
842 if (esys_handle == ESYS_TR_NONE) {
843 *esys_object = NULL;
844 return TSS2_RC_SUCCESS;
845 }
846
847 /* The typical case is that we have a resource object already within the
848 esys context's linked list. We iterate through the list and search
849 for the corresponding object and return it if found.
850 If no object is found, this can be an erronous handle number or it
851 can be because of a reference "global" object that does not require
852 previous initialization. */
853 for (esys_object_aux = esys_context->rsrc_list; esys_object_aux != NULL;
854 esys_object_aux = esys_object_aux->next) {
855 if (esys_object_aux->esys_handle == esys_handle) {
856 *esys_object = esys_object_aux;
857 return TPM2_RC_SUCCESS;
858 }
859 }
860
861 /* All objects with a TR-handle larger than ESYS_TR_MIN_OBJECT must have
862 been initialized previously. Therefore the TR handle was erronous. */
863 if (esys_handle >= ESYS_TR_MIN_OBJECT) {
864 LOG_ERROR("Error: Esys handle does not exist (%x).",
865 TSS2_ESYS_RC_BAD_TR);
866 return TSS2_ESYS_RC_BAD_TR;
867 }
868
869 /* There are special "global" object for the TPM, such as PCRs or
870 hierarchies. If they do not exist yet inside the Esys context we create
871 them here and return the newly created object. */
872 r = iesys_handle_to_tpm_handle(esys_handle, &tpm_handle);
873 return_if_error(r, "Unknown ESYS handle.");
874
875 r = esys_CreateResourceObject(esys_context, esys_handle, &esys_object_aux);
876 return_if_error(r, "Creating Resource Object.");
877
878 esys_object_aux->rsrc.handle = tpm_handle;
879 esys_object_aux->rsrc.rsrcType = IESYSC_WITHOUT_MISC_RSRC;
880
881 r = Tss2_MU_TPM2_HANDLE_Marshal(tpm_handle,
882 &esys_object_aux->rsrc.name.name[0],
883 sizeof(esys_object_aux->rsrc.name.name),
884 &offset);
885 return_if_error(r, "Marshalling TPM handle.");
886
887 esys_object_aux->rsrc.name.size = offset;
888 *esys_object = esys_object_aux;
889 return TSS2_RC_SUCCESS;
890}
891
892/**
893 * Check that the esys context is ready for an _async call.
894 *
895 * This function will check that the sequence of invocations to the esys context
896 * was such that an _async function can be called. This means that the internal
897 * @state field is either @_ESYS_STATE_INIT, @_ESYS_STATE_ERRORRESPONSE,
898 * @_ESYS_STATE_FINISHED.
899 * @param[in,out] esys_context The esys context to issue the command on.
900 * @returns TSS2_RC_SUCCESS on success
901 * TSS2_RC_BAD_SEQUENCE if context is not ready for this function
902 */
903TSS2_RC
904iesys_check_sequence_async(ESYS_CONTEXT * esys_context)
905{
906 if (esys_context == NULL) {
907 LOG_ERROR("esyscontext is NULL.");
908 return TSS2_ESYS_RC_BAD_REFERENCE;
909 }
910
911 if (esys_context->state != _ESYS_STATE_INIT &&
Juergen Reppff821bd2017-12-11 15:21:42 +0100912 esys_context->state != _ESYS_STATE_RESUBMISSION) {
913 LOG_ERROR("Esys called in bad sequence.");
914 return TSS2_ESYS_RC_BAD_SEQUENCE;
915 }
916//TODO: Check if RESUBMISSION BELONGS HERE OR RATHER INTO THE FINISH METHOD.
917 if (esys_context->state == _ESYS_STATE_RESUBMISSION) {
918 esys_context->submissionCount++;
919 LOG_DEBUG("The command will be resubmitted for the %i time.",
920 esys_context->submissionCount);
921 } else {
Andreas Fuchs631d7e62018-03-19 10:54:56 +0100922 esys_context->submissionCount = 1;
Juergen Reppff821bd2017-12-11 15:21:42 +0100923 }
924 return TSS2_RC_SUCCESS;
925}
926
927TSS2_RC
928check_session_feasability(ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
929 int mandatory)
930{
931 ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
932 bool check_none = false;
933 for (int i = 2; i >= 0; i--) {
934 if (handle_tab[i] != ESYS_TR_NONE)
935 mandatory--;
936 if (handle_tab[i] != ESYS_TR_NONE && handle_tab[i] != ESYS_TR_PASSWORD)
937 check_none = true;
938 else {
939 if (check_none) {
940 if (handle_tab[i] == ESYS_TR_NONE) {
941 LOG_ERROR("Error: ESYS_TR_NONE used before other handle.");
942 return TSS2_ESYS_RC_BAD_VALUE;
943 }
944 }
945 }
946 }
947 if (mandatory > 0) {
948 LOG_ERROR("Not enough sessions provided for the command.");
949 return TSS2_ESYS_RC_BAD_VALUE;
950 }
951 return TPM2_RC_SUCCESS;
952}
953
954TSS2_RC
955iesys_compute_hmacs(RSRC_NODE_T * session,
956 HASH_TAB_ITEM cp_hash_tab[3],
957 uint8_t cpHashNum,
958 TPM2B_NONCE * decryptNonce,
959 TPM2B_NONCE * encryptNonce, TPMS_AUTH_COMMAND * auth)
960{
961 TSS2_RC r;
962 size_t authHash_size = 0;
963
964 if (session != NULL) {
965 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
966 r = iesys_crypto_hash_get_digest_size(rsrc_session->
967 authHash, &authHash_size);
968 return_if_error(r, "Initializing auth session");
969
970 int hi = 0;
971 for (int j = 0; cpHashNum < 3; j++) {
972 if (rsrc_session->authHash == cp_hash_tab[j].alg) {
973 hi = j;
974 break;
975 }
976 }
977 auth->hmac.size = sizeof(TPMU_HA);
978 /* if other than first session is used for for parameter encryption
979 the corresponding nonces have to be included into the hmac
980 computation of the first session */
981 r = iesys_crypto_authHmac(rsrc_session->authHash,
982 &rsrc_session->sessionValue[0],
983 rsrc_session->sizeSessionValue,
984 &cp_hash_tab[hi].digest[0],
985 cp_hash_tab[hi].size,
986 &rsrc_session->nonceCaller,
987 &rsrc_session->nonceTPM,
988 decryptNonce, encryptNonce,
989 rsrc_session->sessionAttributes, &auth->hmac);
990 return_if_error(r, "HMAC error");
991 auth->sessionHandle = session->rsrc.handle;
992 auth->nonce = rsrc_session->nonceCaller;
993 auth->sessionAttributes =
994 rsrc_session->sessionAttributes;
995 }
996 return TSS2_RC_SUCCESS;
997}
998
999TSS2_RC
1000iesys_gen_auths(ESYS_CONTEXT * esys_context,
1001 RSRC_NODE_T * h1,
1002 RSRC_NODE_T * h2,
1003 RSRC_NODE_T * h3,
1004 TSS2L_SYS_AUTH_COMMAND * auths)
1005{
1006 TSS2_RC r;
1007 TPM2B_NONCE *decryptNonce = NULL;
1008 int decryptNonceIdx = 0;
1009 int encryptNonceIdx = 0;
1010 TPM2B_NONCE *encryptNonce = NULL;
1011
1012 RSRC_NODE_T *objects[] = { h1, h2, h3 };
1013
1014 HASH_TAB_ITEM cp_hash_tab[3];
1015 uint8_t cpHashNum = 0;
1016
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001017 auths->count = 0;
Juergen Reppff821bd2017-12-11 15:21:42 +01001018 r = iesys_gen_caller_nonces(esys_context);
1019 return_if_error(r, "Error nonce generation caller");
1020 r = iesys_encrypt_param(esys_context, &decryptNonce, &decryptNonceIdx);
1021 return_if_error(r, "Error parameter encryption");
1022 r = iesys_compute_encrypt_nonce(esys_context, &encryptNonceIdx,
1023 &encryptNonce);
1024 return_if_error(r, "More than one crypt session");
1025
1026 /* Compute cp hash values for command buffer for all used algorithms */
1027
1028 r = iesys_compute_cp_hashtab(esys_context,
1029 (h1 != NULL) ? &h1->rsrc.name : NULL,
1030 (h2 != NULL) ? &h2->rsrc.name : NULL,
1031 (h3 != NULL) ? &h3->rsrc.name : NULL,
1032 &cp_hash_tab[0], &cpHashNum);
1033 return_if_error(r, "Error while computing cp hashes");
1034
1035 for (int session_idx = 0; session_idx < 3; session_idx++) {
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001036 auths->auths[auths->count].nonce.size = 0;
1037 auths->auths[auths->count].sessionAttributes = 0;
Juergen Reppff821bd2017-12-11 15:21:42 +01001038 if (esys_context->session_type[session_idx] == ESYS_TR_PASSWORD) {
1039 if (objects[session_idx] == NULL) {
1040 auths->auths[auths->count].hmac.size = 0;
1041 auths->count += 1;
1042 } else {
1043 auths->auths[auths->count].sessionHandle = TPM2_RS_PW;
1044 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1045 auths->count += 1;
1046 }
1047 continue;
1048 }
1049 RSRC_NODE_T *session = esys_context->session_tab[session_idx];
1050 if (session != NULL) {
1051 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
1052 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001053 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
Juergen Reppff821bd2017-12-11 15:21:42 +01001054 if (objects[session_idx] == NULL) {
1055 auths->auths[auths->count].hmac.size = 0;
1056 auths->count += 1;
1057 } else {
1058 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1059 auths->count += 1;
1060 }
1061 continue;
1062 }
1063 }
1064 r = iesys_compute_hmacs(esys_context->session_tab[session_idx],
1065 &cp_hash_tab[0], cpHashNum,
1066 (session_idx == 0
1067 && decryptNonceIdx > 0) ? decryptNonce : NULL,
1068 (session_idx == 0
1069 && encryptNonceIdx > 0) ? encryptNonce : NULL,
1070 &auths->auths[session_idx]);
1071 return_if_error(r, "Error while computing hmacs");
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001072 if (esys_context->session_tab[session_idx] != NULL) {
1073 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
Juergen Reppff821bd2017-12-11 15:21:42 +01001074 auths->count++;
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001075 }
Juergen Reppff821bd2017-12-11 15:21:42 +01001076 }
1077
1078 esys_context->encryptNonceIdx = encryptNonceIdx;
1079 esys_context->encryptNonce = encryptNonce;
1080
1081 return TSS2_RC_SUCCESS;
1082}
1083
1084TSS2_RC
Juergen Repp109de7d2018-02-23 13:42:08 +01001085iesys_check_response(ESYS_CONTEXT * esys_context)
1086{
1087 TSS2_RC r;
1088 const uint8_t *rpBuffer;
1089 size_t rpBuffer_size;
1090 TSS2L_SYS_AUTH_RESPONSE rspAuths = {0};
1091 HASH_TAB_ITEM rp_hash_tab[3];
Juergen Repp109de7d2018-02-23 13:42:08 +01001092 uint8_t rpHashNum = 0;
1093 r = Tss2_Sys_GetRspAuths(esys_context->sys, &rspAuths);
1094 return_if_error(r, "Error: GetRspAuths");
1095
1096 if (rspAuths.count != esys_context->authsCount) {
1097 LOG_ERROR("Number of response auths differs: %i (expected %i)",
1098 rspAuths.count, esys_context->authsCount);
1099 return TSS2_ESYS_RC_GENERAL_FAILURE;
1100 }
1101 /*
1102 * At least one session object is defined so the rp hashes must be computed
1103 * and the HMACs of the responses have to be checked.
1104 * Encrypted response parameters will be decrypted.
1105 */
1106 if (esys_context->session_type[0] >= ESYS_TR_MIN_OBJECT ||
1107 esys_context->session_type[1] >= ESYS_TR_MIN_OBJECT ||
1108 esys_context->session_type[2] >= ESYS_TR_MIN_OBJECT) {
1109 r = Tss2_Sys_GetRpBuffer(esys_context->sys, &rpBuffer_size, &rpBuffer);
1110 return_if_error(r, "Error: get rp buffer");
1111
1112 r = iesys_compute_rp_hashtab(esys_context,
1113 &rspAuths, rpBuffer, rpBuffer_size,
1114 &rp_hash_tab[0], &rpHashNum);
1115 return_if_error(r, "Error: while computing response hashes");
1116
1117 r = iesys_check_rp_hmacs(esys_context, &rspAuths, &rp_hash_tab[0]);
1118 return_if_error(r, "Error: response hmac check");
1119
1120 if (esys_context->encryptNonce != NULL) {
1121 r = iesys_decrypt_param(esys_context, rpBuffer, rpBuffer_size);
1122 return_if_error(r, "Error: while decrypting parameter.");
1123 }
1124 }
1125 return TSS2_RC_SUCCESS;
1126}
1127
1128TSS2_RC
Juergen Reppff821bd2017-12-11 15:21:42 +01001129iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo, TPM2B_NAME * name)
1130{
1131 BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1132 size_t offset = 0;
1133 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1134 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1135 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1136
1137 if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1138 name->size = 0;
1139 return TSS2_RC_SUCCESS;
1140 }
1141 TSS2_RC r;
1142 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1143 return_if_error(r, "Crypto hash start");
1144
1145 r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1146 &buffer[0], sizeof(TPMS_NV_PUBLIC),
1147 &offset);
1148 return_if_error(r, "Marshaling TPMS_NV_PUBLIC");
1149
1150 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1151 return_if_error(r, "crypto hash update");
1152
1153 r = iesys_cryptogcry_hash_finish(&cryptoContext, &name->name[len_alg_id],
1154 &size);
1155 return_if_error(r, "crypto hash finish");
1156
1157 offset = 0;
1158 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1159 &name->name[0], sizeof(TPMI_ALG_HASH),
1160 &offset);
1161 return_if_error(r, "Marhsaling TPMI_ALG_HASH");
1162
1163 name->size = size + len_alg_id;
1164 return TSS2_RC_SUCCESS;
1165}
1166
1167TSS2_RC
1168iesys_get_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
1169{
1170 BYTE buffer[sizeof(TPMT_PUBLIC)];
1171 size_t offset = 0;
1172 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1173 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1174 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1175
1176 if (publicInfo->publicArea.nameAlg == TPM2_ALG_NULL) {
1177 name->size = 0;
1178 return TSS2_RC_SUCCESS;
1179 }
1180 TSS2_RC r;
1181 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->publicArea.nameAlg);
1182 return_if_error(r, "crypto hash start");
1183
1184 r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicInfo->publicArea,
1185 &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1186 return_if_error(r, "Marshaling TPMT_PUBLIC");
1187
1188 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1189 return_if_error(r, "crypto hash update");
1190
1191 r = iesys_cryptogcry_hash_finish(&cryptoContext, &name->name[len_alg_id],
1192 &size);
1193 return_if_error(r, "crypto hash finish");
1194
1195 offset = 0;
1196 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->publicArea.nameAlg,
1197 &name->name[0], sizeof(TPMI_ALG_HASH),
1198 &offset);
1199 return_if_error(r, "Marshaling TPMI_ALG_HASH");
1200
1201 name->size = size + len_alg_id;
1202 return TSS2_RC_SUCCESS;
1203}