blob: 087f3bc21cd1389f65cbba4dcdfa1ffaa622e0c8 [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,
Juergen Reppff821bd2017-12-11 15:21:42 +0100248 const uint8_t * rpBuffer,
249 size_t rpBuffer_size,
250 HASH_TAB_ITEM rp_hash_tab[3], uint8_t * rpHashNum)
251{
252 uint8_t rcBuffer[4] = { 0 };
253 uint8_t ccBuffer[4];
254 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
255 return_if_error(r, "Error: get command code");
256
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200257 for (int i = 0; i < esys_context->authsCount; i++) {
Juergen Reppff821bd2017-12-11 15:21:42 +0100258 RSRC_NODE_T *session = esys_context->session_tab[i];
Andreas Fuchs4ee237b2018-02-23 11:11:40 +0100259 if (session == NULL)
260 continue;
Juergen Reppff821bd2017-12-11 15:21:42 +0100261 bool rpHashFound = false;
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200262 /* We do not want to compute cpHashes multiple times for the same
263 algorithm to save time and space */
Juergen Reppff821bd2017-12-11 15:21:42 +0100264 for (int j = 0; j < *rpHashNum; j++)
265 if (rp_hash_tab[j].alg == session->rsrc.misc.rsrc_session.authHash) {
266 rpHashFound = true;
267 break;
268 }
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200269 /* If not, we compute it and append it to the list */
Juergen Reppff821bd2017-12-11 15:21:42 +0100270 if (!rpHashFound) {
271 rp_hash_tab[*rpHashNum].size = sizeof(TPMU_HA);
272 r = iesys_crypto_rpHash(session->rsrc.misc.rsrc_session.authHash,
273 rcBuffer, ccBuffer, rpBuffer, rpBuffer_size,
274 &rp_hash_tab[*rpHashNum].digest[0],
275 &rp_hash_tab[*rpHashNum].size);
276 return_if_error(r, "crypto rpHash");
277 rp_hash_tab[*rpHashNum].alg =
278 session->rsrc.misc.rsrc_session.authHash;
279 *rpHashNum += 1;
280 }
281 }
282 return TPM2_RC_SUCCESS;
283}
284
285TSS2_RC
Juergen Reppff821bd2017-12-11 15:21:42 +0100286esys_CreateResourceObject(ESYS_CONTEXT * esys_context,
287 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
288{
289 RSRC_NODE_T *new_esys_object = calloc(1, sizeof(RSRC_NODE_T));
290 if (new_esys_object == NULL)
291 return_error(TSS2_ESYS_RC_MEMORY, "Out of memory.");
292 if (esys_context->rsrc_list == NULL) {
293 esys_context->rsrc_list = new_esys_object;
294 new_esys_object->next = NULL;
295 } else {
296 new_esys_object->next = esys_context->rsrc_list;
297 esys_context->rsrc_list = new_esys_object;
298 }
299 *esys_object = new_esys_object;
300 new_esys_object->esys_handle = esys_handle;
301 return TSS2_RC_SUCCESS;
302}
303
304TSS2_RC
305iesys_handle_to_tpm_handle(ESYS_TR esys_handle, TPM2_HANDLE * tpm_handle)
306{
307 /* Since ESYS_TR_PCR0 is equal zero only <= ESYS_TR_PCR31 has to be checked */
308 if (esys_handle <= ESYS_TR_PCR31) {
309 *tpm_handle = (TPM2_HANDLE) esys_handle;
310 return TPM2_RC_SUCCESS;
311 }
312 if (esys_handle == ESYS_TR_RH_OWNER) {
313 *tpm_handle = TPM2_RH_OWNER;
314 return TPM2_RC_SUCCESS;
315 }
316 if (esys_handle == ESYS_TR_RH_NULL) {
317 *tpm_handle = TPM2_RH_NULL;
318 return TPM2_RC_SUCCESS;
319 }
320 if (esys_handle == ESYS_TR_RH_LOCKOUT) {
321 *tpm_handle = TPM2_RH_LOCKOUT;
322 return TPM2_RC_SUCCESS;
323 }
324 if (esys_handle == ESYS_TR_RH_ENDORSEMENT) {
325 *tpm_handle = TPM2_RH_ENDORSEMENT;
326 return TPM2_RC_SUCCESS;
327 }
328 if (esys_handle == ESYS_TR_RH_PLATFORM) {
329 *tpm_handle = TPM2_RH_PLATFORM;
330 return TPM2_RC_SUCCESS;
331 }
332 if (esys_handle == ESYS_TR_RH_PLATFORM_NV) {
333 *tpm_handle = TPM2_RH_PLATFORM_NV;
334 return TPM2_RC_SUCCESS;
335 }
336 LOG_ERROR("Error: Esys invalid ESAPI handle (%x).", esys_handle);
337 return TSS2_ESYS_RC_BAD_VALUE;
338}
339
340TPM2_HT
341iesys_get_handle_type(TPM2_HANDLE handle)
342{
343 TPM2_HT ht = (TPM2_HT) ((handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT); /* upper bytes of input data */
344 return ht;
345}
346
347bool
Juergen Reppff821bd2017-12-11 15:21:42 +0100348iesys_compare_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
349{
350 TSS2_RC r = TSS2_RC_SUCCESS;
351 TPM2B_NAME public_info_name;
352 if (publicInfo == NULL || name == NULL)
353 return false;
354 r = iesys_get_name(publicInfo, &public_info_name);
355 if (r != TSS2_RC_SUCCESS) {
356 LOG_DEBUG("name could not be computed.");
357 return false;
358 }
359 return cmp_TPM2B_NAME(&public_info_name, name);
360}
361
362TSS2_RC
363iesys_compute_encrypted_salt(ESYS_CONTEXT * esys_context,
364 RSRC_NODE_T * tpmKeyNode,
365 TPM2B_ENCRYPTED_SECRET * encryptedSalt)
366{
367 TSS2_RC r = TSS2_RC_SUCCESS;
Juergen Reppff821bd2017-12-11 15:21:42 +0100368 size_t keyHash_size = 0;
369 size_t cSize = 0;
Juergen Repp4a738892018-04-24 12:05:48 +0200370 TPM2B_ECC_PARAMETER Z; /* X coordinate of privKey*publicKey */
371 TPMS_ECC_POINT Q; /* Public point of ephemeral key */
372
373 if (tpmKeyNode == 0) {
374 encryptedSalt->size = 0;
375 return TSS2_RC_SUCCESS;
376 }
377
378 TPM2B_PUBLIC *pub = &tpmKeyNode->rsrc.misc.rsrc_key_pub;
379 if (tpmKeyNode->rsrc.rsrcType != IESYSC_KEY_RSRC) {
380 LOG_TRACE("Public info needed.");
381 return TSS2_ESYS_RC_BAD_VALUE;
382 }
383 r = iesys_crypto_hash_get_digest_size(tpmKeyNode->rsrc.misc.
384 rsrc_key_pub.publicArea.nameAlg,
385 &keyHash_size);
386 return_if_error(r, "Hash algorithm not supported.");
387
388 switch (pub->publicArea.type) {
389 case TPM2_ALG_RSA:
390 iesys_crypto_random2b((TPM2B_NONCE *) & esys_context->salt,
391 keyHash_size);
Juergen Reppff821bd2017-12-11 15:21:42 +0100392
393 /* When encrypting salts, the encryption scheme of a key is ignored and
394 TPM2_ALG_OAEP is always used. */
Juergen Repp4a738892018-04-24 12:05:48 +0200395 pub->publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_OAEP;
396 r = iesys_crypto_pk_encrypt(pub,
Juergen Reppff821bd2017-12-11 15:21:42 +0100397 keyHash_size, &esys_context->salt.buffer[0],
398 sizeof(TPMU_ENCRYPTED_SECRET),
399 (BYTE *) &encryptedSalt->secret[0], &cSize,
400 "SECRET");
401 return_if_error(r, "During encryption.");
402 LOGBLOB_DEBUG(&encryptedSalt->secret[0], cSize, "IESYS encrypted salt");
403 encryptedSalt->size = cSize;
Juergen Repp4a738892018-04-24 12:05:48 +0200404 break;
405 case TPM2_ALG_ECC:
406 r = iesys_crypto_get_ecdh_point(pub, sizeof(TPMU_ENCRYPTED_SECRET),
407 &Z, &Q,
408 (BYTE *) &encryptedSalt->secret[0],
409 &cSize);
410
411 return_if_error(r, "During computation of ECC public key.");
412 encryptedSalt->size = cSize;
413
414 /* Compute salt from Z with KDFe */
415 r = iesys_cryptogcry_KDFe(tpmKeyNode->rsrc.misc.
416 rsrc_key_pub.publicArea.nameAlg,
417 &Z, "SECRET", &Q.x,
418 &pub->publicArea.unique.ecc.x,
419 keyHash_size*8,
420 &esys_context->salt.buffer[0]);
421 return_if_error(r, "During KDFe computation.");
422 esys_context->salt.size = keyHash_size;
423 break;
424 default:
425 LOG_ERROR("Not implemented");
426 return TSS2_ESYS_RC_GENERAL_FAILURE;
427 break;
Juergen Reppff821bd2017-12-11 15:21:42 +0100428 }
429 return r;
430}
431
432TSS2_RC
433iesys_gen_caller_nonces(ESYS_CONTEXT * esys_context)
434{
435 TSS2_RC r;
436 size_t authHash_size = 0;
437
438 for (int i = 0; i < 3; i++) {
439 RSRC_NODE_T *session = esys_context->session_tab[i];
440 if (session == NULL)
441 continue;
442 r = iesys_crypto_hash_get_digest_size(session->rsrc.misc.rsrc_session.
443 authHash, &authHash_size);
444 return_if_error(r, "Error: initialize auth session.");
445
446 r = iesys_crypto_random2b(&session->rsrc.misc.rsrc_session.nonceCaller,
447 authHash_size);
448 return_if_error(r, "Error: computing caller nonce (%x).");
449 }
450 return TSS2_RC_SUCCESS;
451}
452
453TSS2_RC
454iesys_encrypt_param(ESYS_CONTEXT * esys_context,
455 TPM2B_NONCE ** decryptNonce, int *decryptNonceIdx)
456{
457 uint8_t ccBuffer[4];
458 const uint8_t *cpBuffer;
459 size_t cpBuffer_size;
460 TPM2B_NONCE *encryptNonce = NULL;
Juergen Reppff821bd2017-12-11 15:21:42 +0100461 TSS2_RC r = Tss2_Sys_GetCommandCode(esys_context->sys, &ccBuffer[0]);
462 return_if_error(r, "Error: get command code");
463 *decryptNonceIdx = 0;
464 *decryptNonce = NULL;
465 r = Tss2_Sys_GetCpBuffer(esys_context->sys, &cpBuffer_size, &cpBuffer);
466 return_if_error(r, "Error: get cp buffer");
467 for (int i = 0; i < 3; i++) {
468 RSRC_NODE_T *session = esys_context->session_tab[i];
469 if (session == NULL)
470 continue;
471 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
472 TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
473 if (rsrc_session->sessionAttributes & TPMA_SESSION_ENCRYPT) {
474 return_if_notnull(encryptNonce, "More than one encrypt session",
475 TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS);
476 esys_context->encryptNonceIdx = i;
477 encryptNonce = &rsrc_session->nonceTPM;
478 esys_context->encryptNonce = encryptNonce;
479 }
480 if (rsrc_session->sessionAttributes & TPMA_SESSION_DECRYPT) {
481 return_if_notnull(*decryptNonce, "More than one decrypt session",
482 TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS);
483 *decryptNonceIdx = i;
484 *decryptNonce = &rsrc_session->nonceTPM;
485 size_t hlen;
486 r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
487 return_if_error(r, "get digest size");
488 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
489 if (key_len % hlen > 0)
490 key_len = key_len + hlen - (key_len % hlen);
491 uint8_t symKey[key_len];
Juergen Reppf29cfef2018-03-27 14:18:07 +0200492 size_t paramSize = 0;
493 const uint8_t *paramBuffer;
494 r = Tss2_Sys_GetDecryptParam(esys_context->sys, &paramSize,
495 &paramBuffer);
496 return_if_error(r, "Encrypt parameter not possible");
497
498 BYTE encrypt_buffer[paramSize];
499 memcpy(&encrypt_buffer[0], paramBuffer, paramSize);
500 LOGBLOB_DEBUG(paramBuffer, paramSize, "param to encrypt");
Juergen Reppff821bd2017-12-11 15:21:42 +0100501 if (symDef->algorithm == TPM2_ALG_AES) {
502 if (symDef->mode.aes != TPM2_ALG_CFB) {
503 return_error(TSS2_ESYS_RC_BAD_VALUE,
504 "Invalid symmetric mode (must be CFB)");
505 }
506 r = iesys_crypto_KDFa(rsrc_session->authHash,
507 &rsrc_session->sessionValue[0],
508 rsrc_session->sizeSessionValue, "CFB",
509 &rsrc_session->nonceCaller,
510 &rsrc_session->nonceTPM,
511 symDef->keyBits.aes + AES_BLOCK_SIZE_IN_BYTES * 8,
Juergen Reppf29cfef2018-03-27 14:18:07 +0200512 NULL, &symKey[0], FALSE);
Juergen Reppff821bd2017-12-11 15:21:42 +0100513 return_if_error(r, "while computing KDFa");
Juergen Reppf29cfef2018-03-27 14:18:07 +0200514
Juergen Reppff821bd2017-12-11 15:21:42 +0100515 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
516 r = iesys_crypto_sym_aes_encrypt(&symKey[0],
517 symDef->algorithm,
518 symDef->keyBits.aes,
519 symDef->mode.aes,
520 AES_BLOCK_SIZE_IN_BYTES,
521 &encrypt_buffer[0], paramSize,
Juergen Repp131e29f2018-04-24 14:43:39 +0200522 &symKey[aes_off]);
Juergen Reppff821bd2017-12-11 15:21:42 +0100523 return_if_error(r, "AES encryption not possible");
524 r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
525 &encrypt_buffer[0]);
526 return_if_error(r, "Set encrypt parameter not possible");
527
528 } else if (symDef->algorithm == TPM2_ALG_XOR) {
Juergen Reppf29cfef2018-03-27 14:18:07 +0200529 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
530 &rsrc_session->sessionValue[0],
531 rsrc_session->sizeSessionValue,
532 &rsrc_session->nonceCaller,
533 &rsrc_session->nonceTPM,
534 &encrypt_buffer[0],
535 paramSize);
536 return_if_error(r, "XOR obfuscation not possible.");
537 r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize,
538 &encrypt_buffer[0]);
539 return_if_error(r, "Set encrypt parameter not possible");
540
Juergen Reppff821bd2017-12-11 15:21:42 +0100541 } else {
542 return_error(TSS2_ESYS_RC_BAD_VALUE,
543 "Invalid symmetric algorithm (should be XOR or AES)");
544 }
545 }
546 }
547 return r;
548}
549
550TSS2_RC
551iesys_decrypt_param(ESYS_CONTEXT * esys_context,
552 const uint8_t * rpBuffer, size_t rpBuffer_size)
553{
554 size_t hlen;
555 RSRC_NODE_T *session;
556 session = esys_context->session_tab[esys_context->encryptNonceIdx];
557 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
558 TPMT_SYM_DEF *symDef = &rsrc_session->symmetric;
559 TSS2_RC r = iesys_crypto_hash_get_digest_size(rsrc_session->authHash, &hlen);
560 return_if_error(r, "Error");
561 size_t key_len = TPM2_MAX_SYM_KEY_BYTES + TPM2_MAX_SYM_BLOCK_SIZE;
562
563 if (key_len % hlen > 0)
564 key_len = key_len + hlen - (key_len % hlen);
565 uint8_t symKey[key_len];
Juergen Reppf29cfef2018-03-27 14:18:07 +0200566 UINT16 p2BSize = 0;
567 size_t offset = 0;
568 r = Tss2_MU_UINT16_Unmarshal(rpBuffer, rpBuffer_size, &offset, &p2BSize);
569 return_if_error(r, "Unmarshal error");
570 if (p2BSize > rpBuffer_size) {
571 return_error(TSS2_ESYS_RC_BAD_VALUE,
572 "Invalid length encrypted response.");
573 }
574 LOGBLOB_DEBUG(rpBuffer, p2BSize, "IESYS encrypt data");
Juergen Reppff821bd2017-12-11 15:21:42 +0100575 if (symDef->algorithm == TPM2_ALG_AES) {
576 if (symDef->mode.aes != TPM2_ALG_CFB) {
577 return_error(TSS2_ESYS_RC_BAD_VALUE,
578 "Invalid symmetric mode (must be CFB)");
579 }
580 LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0],
581 rsrc_session->sessionKey.size,
582 "IESYS encrypt session key");
583
584 r = iesys_crypto_KDFa(rsrc_session->authHash,
585 &rsrc_session->sessionValue[0],
586 rsrc_session->sizeSessionValue,
587 "CFB", &rsrc_session->nonceTPM,
588 &rsrc_session->nonceCaller,
589 symDef->keyBits.aes
590 + AES_BLOCK_SIZE_IN_BYTES * 8, NULL,
Juergen Reppf29cfef2018-03-27 14:18:07 +0200591 &symKey[0], FALSE);
Juergen Reppff821bd2017-12-11 15:21:42 +0100592 return_if_error(r, "KDFa error");
593 LOGBLOB_DEBUG(&symKey[0],
594 ((symDef->keyBits.aes +
595 AES_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8,
596 "IESYS encrypt KDFa key");
Juergen Reppf29cfef2018-03-27 14:18:07 +0200597
Juergen Reppff821bd2017-12-11 15:21:42 +0100598 size_t aes_off = ( symDef->keyBits.aes + 7) / 8;
599 r = iesys_crypto_sym_aes_decrypt(&symKey[0],
600 symDef->algorithm,
601 symDef->keyBits.aes,
602 symDef->mode.aes,
603 AES_BLOCK_SIZE_IN_BYTES,
604 (uint8_t *) & rpBuffer[2], p2BSize,
Juergen Repp131e29f2018-04-24 14:43:39 +0200605 &symKey[aes_off]);
Juergen Reppff821bd2017-12-11 15:21:42 +0100606 return_if_error(r, "Decryption error");
Juergen Reppf29cfef2018-03-27 14:18:07 +0200607
Juergen Reppff821bd2017-12-11 15:21:42 +0100608 } else if (symDef->algorithm == TPM2_ALG_XOR) {
Juergen Reppf29cfef2018-03-27 14:18:07 +0200609 r = iesys_xor_parameter_obfuscation(rsrc_session->authHash,
610 &rsrc_session->sessionValue[0],
611 rsrc_session->sizeSessionValue,
612 &rsrc_session->nonceTPM,
613 &rsrc_session->nonceCaller,
614 (uint8_t *) & rpBuffer[2],
615 p2BSize);
616 return_if_error(r, "XOR obfuscation not possible.");
617
Juergen Reppff821bd2017-12-11 15:21:42 +0100618 } else {
619 return_error(TSS2_ESYS_RC_BAD_VALUE,
620 "Invalid symmetric algorithm (should be XOR or AES)");
621 }
622 return TSS2_RC_SUCCESS;
623}
624
625TSS2_RC
626iesys_check_rp_hmacs(ESYS_CONTEXT * esys_context,
627 TSS2L_SYS_AUTH_RESPONSE * rspAuths,
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200628 HASH_TAB_ITEM rp_hash_tab[3], uint8_t rpHashNum)
Juergen Reppff821bd2017-12-11 15:21:42 +0100629{
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200630 TSS2_RC r;
631
Juergen Reppff821bd2017-12-11 15:21:42 +0100632 for (int i = 0; i < rspAuths->count; i++) {
633 RSRC_NODE_T *session = esys_context->session_tab[i];
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200634 if (session == NULL)
635 continue;
Juergen Reppaad3a852018-03-19 16:21:20 +0100636
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200637 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
638 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
639 /* A policy password session has no auth value */
640 if (rspAuths->auths[i].hmac.size != 0) {
641 LOG_ERROR("PolicyPassword session's HMAC must be 0-length.");
642 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
Juergen Reppff821bd2017-12-11 15:21:42 +0100643 }
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200644 continue;
Juergen Reppff821bd2017-12-11 15:21:42 +0100645 }
646
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200647 /* Find the rpHash for the hash algorithm used by this session */
648 int hi;
649 for (hi = 0; hi < rpHashNum; hi++) {
650 if (rsrc_session->authHash == rp_hash_tab[hi].alg) {
651 break;
652 }
653 }
654 if (hi == rpHashNum) {
655 LOG_ERROR("rpHash for alg %"PRIx16 " not found.",
656 rsrc_session->authHash);
657 return TSS2_ESYS_RC_GENERAL_FAILURE;
658 }
659
660 TPM2B_AUTH rp_hmac;
661 rp_hmac.size = sizeof(TPMU_HA);
662 rsrc_session->nonceTPM = rspAuths->auths[i].nonce;
663 rsrc_session->sessionAttributes =
664 rspAuths->auths[i].sessionAttributes;
665 r = iesys_crypto_authHmac(rsrc_session->authHash,
666 &rsrc_session->sessionValue[0],
667 rsrc_session->sizeSessionValue,
668 &rp_hash_tab[hi].digest[0],
669 rp_hash_tab[hi].size,
670 &rsrc_session->nonceTPM,
671 &rsrc_session->nonceCaller, NULL, NULL,
672 rspAuths->auths[i].sessionAttributes,
673 &rp_hmac);
674 return_if_error(r, "HMAC error");
675
676 if (!cmp_TPM2B_AUTH(&rspAuths->auths[i].hmac, &rp_hmac)) {
677 LOG_ERROR("TPM's response auth is invalid for session %i", i);
678 return TSS2_ESYS_RC_RSP_AUTH_FAILED;
679 }
Juergen Reppff821bd2017-12-11 15:21:42 +0100680 }
681 return TSS2_RC_SUCCESS;
682}
683
684void
685iesys_compute_bound_entity(const TPM2B_NAME * name,
686 const TPM2B_AUTH * auth, TPM2B_NAME * bound_entity)
687{
688 UINT16 i;
689 UINT16 j = 0;
690 *bound_entity = *name;
691 memset(&bound_entity->name[bound_entity->size], 0,
692 sizeof(bound_entity->name) - bound_entity->size);
693 for (i = sizeof(bound_entity->name) - auth->size;
694 i < sizeof(bound_entity->name); i++)
695 bound_entity->name[i] ^= auth->buffer[j++];
696 bound_entity->size = sizeof(bound_entity->name);
697}
698
699bool
700iesys_is_object_bound(const TPM2B_NAME * name,
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200701 const TPM2B_AUTH * auth, RSRC_NODE_T * session)
Juergen Reppff821bd2017-12-11 15:21:42 +0100702{
703 TPM2B_NAME tmp;
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200704 if (session->rsrc.misc.rsrc_session.bound_entity.size == 0)
705 /* No bind session */
706 return false;
Juergen Reppff821bd2017-12-11 15:21:42 +0100707 iesys_compute_bound_entity(name, auth, &tmp);
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200708 return cmp_TPM2B_NAME(&session->rsrc.misc.rsrc_session.bound_entity, &tmp);
Juergen Reppff821bd2017-12-11 15:21:42 +0100709}
710
711/**
712 * Compute the session value
713 *
714 * This function derives the session value from the session key
715 * and the auth value.
716 * The auth value is only used if an authorization is necessary and the name
717 * of the object is not equal to the name of an used bound entity
718 * @param[in] session for which the session value will be computed
719 * @param[in] name name of the object to be authorized (NULL if no authorization)
720 * @param[in] auth-value auth value of the object to be authorized
721 * (NULL if no authorization)
722 */
723void
724iesys_compute_session_value(RSRC_NODE_T * session,
725 const TPM2B_NAME * name,
726 const TPM2B_AUTH * auth_value)
727{
Juergen Reppff821bd2017-12-11 15:21:42 +0100728 if (session == NULL)
729 return;
730
731 /* First the session Key is copied into the sessionValue */
732 session->rsrc.misc.rsrc_session.sizeSessionValue
733 = session->rsrc.misc.rsrc_session.sessionKey.size;
734 memcpy(&session->rsrc.misc.rsrc_session.sessionValue[0],
735 &session->rsrc.misc.rsrc_session.sessionKey.buffer[0],
736 session->rsrc.misc.rsrc_session.sessionKey.size);
737
738 /* Then if we are a bound session, the auth value is appended to the end
739 of the session value. */
740 if (name == NULL)
741 return;
742 /* This requires an HMAC Session and not a password session */
743 if (session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_HMAC &&
744 session->rsrc.misc.rsrc_session.sessionType != TPM2_SE_POLICY)
745 return;
746 if (iesys_is_object_bound(name, auth_value,
Juergen Repp5a7c4f42018-04-24 14:50:59 +0200747 session) &&
Juergen Reppff821bd2017-12-11 15:21:42 +0100748 /* type_policy_session set to POLICY_AUTH by command PolicyAuthValue */
749 (session->rsrc.misc.rsrc_session.type_policy_session != POLICY_AUTH))
750 return;
751
752 memcpy(&session->rsrc.misc.rsrc_session.
753 sessionValue[session->rsrc.misc.rsrc_session.sessionKey.size],
754 &auth_value->buffer[0], auth_value->size);
755 session->rsrc.misc.rsrc_session.sizeSessionValue += auth_value->size;
756}
757
758/**
759 * Lookup the object to a handle from inside the context.
760 *
761 * This function searches the esapi context for an object that corresponds to a
762 * provided esys_handle. These objects contain information such as the
763 * appropriate tpm handle, the public name or the stored auth values.
764 * These esys handles refer either to an object previously initialized on the
765 * same context, in which case this will be returned. Or they refer to a
766 * "global", in which case the corresponding object will be created if it does
767 * not exist yet.
768 * @param[in,out] esys_context The esys context to issue the command on.
769 * @param[in] esys_handle The handle to find the corresponding object for.
770 * @param[out] esys_object The object containing the name, tpm handle and auth value
771 * @returns TSS2_RC_SUCCESS on success
772 * TSS2_ESYS_RC_BAD_TR if the handle is invalid
773 */
774TSS2_RC
775esys_GetResourceObject(ESYS_CONTEXT * esys_context,
776 ESYS_TR esys_handle, RSRC_NODE_T ** esys_object)
777{
778 RSRC_NODE_T *esys_object_aux;
779 TPM2_HANDLE tpm_handle;
780 size_t offset = 0;
781 TSS2_RC r;
782
783 /* Sometimes the TPM API allows for optional objects. In those cases we map
784 the object node to NULL. This will be handled accordingly by following
785 code */
786 if (esys_handle == ESYS_TR_NONE) {
787 *esys_object = NULL;
788 return TSS2_RC_SUCCESS;
789 }
790
791 /* The typical case is that we have a resource object already within the
792 esys context's linked list. We iterate through the list and search
793 for the corresponding object and return it if found.
dantpmf6ef2472018-04-06 15:21:59 -0700794 If no object is found, this can be an erroneous handle number or it
Juergen Reppff821bd2017-12-11 15:21:42 +0100795 can be because of a reference "global" object that does not require
796 previous initialization. */
797 for (esys_object_aux = esys_context->rsrc_list; esys_object_aux != NULL;
798 esys_object_aux = esys_object_aux->next) {
799 if (esys_object_aux->esys_handle == esys_handle) {
800 *esys_object = esys_object_aux;
801 return TPM2_RC_SUCCESS;
802 }
803 }
804
805 /* All objects with a TR-handle larger than ESYS_TR_MIN_OBJECT must have
dantpmf6ef2472018-04-06 15:21:59 -0700806 been initialized previously. Therefore the TR handle was erroneous. */
Juergen Reppff821bd2017-12-11 15:21:42 +0100807 if (esys_handle >= ESYS_TR_MIN_OBJECT) {
808 LOG_ERROR("Error: Esys handle does not exist (%x).",
809 TSS2_ESYS_RC_BAD_TR);
810 return TSS2_ESYS_RC_BAD_TR;
811 }
812
813 /* There are special "global" object for the TPM, such as PCRs or
814 hierarchies. If they do not exist yet inside the Esys context we create
815 them here and return the newly created object. */
816 r = iesys_handle_to_tpm_handle(esys_handle, &tpm_handle);
817 return_if_error(r, "Unknown ESYS handle.");
818
819 r = esys_CreateResourceObject(esys_context, esys_handle, &esys_object_aux);
820 return_if_error(r, "Creating Resource Object.");
821
822 esys_object_aux->rsrc.handle = tpm_handle;
823 esys_object_aux->rsrc.rsrcType = IESYSC_WITHOUT_MISC_RSRC;
824
825 r = Tss2_MU_TPM2_HANDLE_Marshal(tpm_handle,
826 &esys_object_aux->rsrc.name.name[0],
827 sizeof(esys_object_aux->rsrc.name.name),
828 &offset);
829 return_if_error(r, "Marshalling TPM handle.");
830
831 esys_object_aux->rsrc.name.size = offset;
832 *esys_object = esys_object_aux;
833 return TSS2_RC_SUCCESS;
834}
835
836/**
837 * Check that the esys context is ready for an _async call.
838 *
839 * This function will check that the sequence of invocations to the esys context
840 * was such that an _async function can be called. This means that the internal
841 * @state field is either @_ESYS_STATE_INIT, @_ESYS_STATE_ERRORRESPONSE,
842 * @_ESYS_STATE_FINISHED.
843 * @param[in,out] esys_context The esys context to issue the command on.
844 * @returns TSS2_RC_SUCCESS on success
845 * TSS2_RC_BAD_SEQUENCE if context is not ready for this function
846 */
847TSS2_RC
848iesys_check_sequence_async(ESYS_CONTEXT * esys_context)
849{
850 if (esys_context == NULL) {
851 LOG_ERROR("esyscontext is NULL.");
852 return TSS2_ESYS_RC_BAD_REFERENCE;
853 }
854
855 if (esys_context->state != _ESYS_STATE_INIT &&
Juergen Reppff821bd2017-12-11 15:21:42 +0100856 esys_context->state != _ESYS_STATE_RESUBMISSION) {
857 LOG_ERROR("Esys called in bad sequence.");
858 return TSS2_ESYS_RC_BAD_SEQUENCE;
859 }
860//TODO: Check if RESUBMISSION BELONGS HERE OR RATHER INTO THE FINISH METHOD.
861 if (esys_context->state == _ESYS_STATE_RESUBMISSION) {
862 esys_context->submissionCount++;
863 LOG_DEBUG("The command will be resubmitted for the %i time.",
864 esys_context->submissionCount);
865 } else {
Andreas Fuchs631d7e62018-03-19 10:54:56 +0100866 esys_context->submissionCount = 1;
Juergen Reppff821bd2017-12-11 15:21:42 +0100867 }
868 return TSS2_RC_SUCCESS;
869}
870
871TSS2_RC
dantpmf6ef2472018-04-06 15:21:59 -0700872check_session_feasibility(ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3,
Juergen Reppff821bd2017-12-11 15:21:42 +0100873 int mandatory)
874{
875 ESYS_TR handle_tab[3] = { shandle1, shandle2, shandle3 };
876 bool check_none = false;
877 for (int i = 2; i >= 0; i--) {
878 if (handle_tab[i] != ESYS_TR_NONE)
879 mandatory--;
880 if (handle_tab[i] != ESYS_TR_NONE && handle_tab[i] != ESYS_TR_PASSWORD)
881 check_none = true;
882 else {
883 if (check_none) {
884 if (handle_tab[i] == ESYS_TR_NONE) {
885 LOG_ERROR("Error: ESYS_TR_NONE used before other handle.");
886 return TSS2_ESYS_RC_BAD_VALUE;
887 }
888 }
889 }
890 }
891 if (mandatory > 0) {
892 LOG_ERROR("Not enough sessions provided for the command.");
893 return TSS2_ESYS_RC_BAD_VALUE;
894 }
895 return TPM2_RC_SUCCESS;
896}
897
898TSS2_RC
899iesys_compute_hmacs(RSRC_NODE_T * session,
900 HASH_TAB_ITEM cp_hash_tab[3],
901 uint8_t cpHashNum,
902 TPM2B_NONCE * decryptNonce,
903 TPM2B_NONCE * encryptNonce, TPMS_AUTH_COMMAND * auth)
904{
905 TSS2_RC r;
906 size_t authHash_size = 0;
907
908 if (session != NULL) {
909 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
910 r = iesys_crypto_hash_get_digest_size(rsrc_session->
911 authHash, &authHash_size);
912 return_if_error(r, "Initializing auth session");
913
914 int hi = 0;
915 for (int j = 0; cpHashNum < 3; j++) {
916 if (rsrc_session->authHash == cp_hash_tab[j].alg) {
917 hi = j;
918 break;
919 }
920 }
921 auth->hmac.size = sizeof(TPMU_HA);
922 /* if other than first session is used for for parameter encryption
923 the corresponding nonces have to be included into the hmac
924 computation of the first session */
925 r = iesys_crypto_authHmac(rsrc_session->authHash,
926 &rsrc_session->sessionValue[0],
927 rsrc_session->sizeSessionValue,
928 &cp_hash_tab[hi].digest[0],
929 cp_hash_tab[hi].size,
930 &rsrc_session->nonceCaller,
931 &rsrc_session->nonceTPM,
932 decryptNonce, encryptNonce,
933 rsrc_session->sessionAttributes, &auth->hmac);
934 return_if_error(r, "HMAC error");
935 auth->sessionHandle = session->rsrc.handle;
936 auth->nonce = rsrc_session->nonceCaller;
937 auth->sessionAttributes =
938 rsrc_session->sessionAttributes;
939 }
940 return TSS2_RC_SUCCESS;
941}
942
943TSS2_RC
944iesys_gen_auths(ESYS_CONTEXT * esys_context,
945 RSRC_NODE_T * h1,
946 RSRC_NODE_T * h2,
947 RSRC_NODE_T * h3,
948 TSS2L_SYS_AUTH_COMMAND * auths)
949{
950 TSS2_RC r;
951 TPM2B_NONCE *decryptNonce = NULL;
952 int decryptNonceIdx = 0;
953 int encryptNonceIdx = 0;
954 TPM2B_NONCE *encryptNonce = NULL;
955
956 RSRC_NODE_T *objects[] = { h1, h2, h3 };
957
958 HASH_TAB_ITEM cp_hash_tab[3];
959 uint8_t cpHashNum = 0;
960
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +0100961 auths->count = 0;
Juergen Reppff821bd2017-12-11 15:21:42 +0100962 r = iesys_gen_caller_nonces(esys_context);
963 return_if_error(r, "Error nonce generation caller");
964 r = iesys_encrypt_param(esys_context, &decryptNonce, &decryptNonceIdx);
965 return_if_error(r, "Error parameter encryption");
966 r = iesys_compute_encrypt_nonce(esys_context, &encryptNonceIdx,
967 &encryptNonce);
968 return_if_error(r, "More than one crypt session");
969
970 /* Compute cp hash values for command buffer for all used algorithms */
971
972 r = iesys_compute_cp_hashtab(esys_context,
973 (h1 != NULL) ? &h1->rsrc.name : NULL,
974 (h2 != NULL) ? &h2->rsrc.name : NULL,
975 (h3 != NULL) ? &h3->rsrc.name : NULL,
976 &cp_hash_tab[0], &cpHashNum);
977 return_if_error(r, "Error while computing cp hashes");
978
979 for (int session_idx = 0; session_idx < 3; session_idx++) {
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +0100980 auths->auths[auths->count].nonce.size = 0;
981 auths->auths[auths->count].sessionAttributes = 0;
Juergen Reppff821bd2017-12-11 15:21:42 +0100982 if (esys_context->session_type[session_idx] == ESYS_TR_PASSWORD) {
983 if (objects[session_idx] == NULL) {
984 auths->auths[auths->count].hmac.size = 0;
985 auths->count += 1;
986 } else {
987 auths->auths[auths->count].sessionHandle = TPM2_RS_PW;
988 auths->auths[auths->count].hmac = objects[session_idx]->auth;
989 auths->count += 1;
990 }
991 continue;
992 }
993 RSRC_NODE_T *session = esys_context->session_tab[session_idx];
994 if (session != NULL) {
995 IESYS_SESSION *rsrc_session = &session->rsrc.misc.rsrc_session;
996 if (rsrc_session->type_policy_session == POLICY_PASSWORD) {
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +0100997 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
Juergen Reppff821bd2017-12-11 15:21:42 +0100998 if (objects[session_idx] == NULL) {
999 auths->auths[auths->count].hmac.size = 0;
1000 auths->count += 1;
1001 } else {
1002 auths->auths[auths->count].hmac = objects[session_idx]->auth;
1003 auths->count += 1;
1004 }
1005 continue;
1006 }
1007 }
1008 r = iesys_compute_hmacs(esys_context->session_tab[session_idx],
1009 &cp_hash_tab[0], cpHashNum,
1010 (session_idx == 0
1011 && decryptNonceIdx > 0) ? decryptNonce : NULL,
1012 (session_idx == 0
1013 && encryptNonceIdx > 0) ? encryptNonce : NULL,
1014 &auths->auths[session_idx]);
1015 return_if_error(r, "Error while computing hmacs");
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001016 if (esys_context->session_tab[session_idx] != NULL) {
1017 auths->auths[auths->count].sessionHandle = session->rsrc.handle;
Juergen Reppff821bd2017-12-11 15:21:42 +01001018 auths->count++;
Andreas Fuchsc5a73eb2018-03-19 16:01:00 +01001019 }
Juergen Reppff821bd2017-12-11 15:21:42 +01001020 }
1021
1022 esys_context->encryptNonceIdx = encryptNonceIdx;
1023 esys_context->encryptNonce = encryptNonce;
1024
1025 return TSS2_RC_SUCCESS;
1026}
1027
1028TSS2_RC
Juergen Repp109de7d2018-02-23 13:42:08 +01001029iesys_check_response(ESYS_CONTEXT * esys_context)
1030{
1031 TSS2_RC r;
1032 const uint8_t *rpBuffer;
1033 size_t rpBuffer_size;
Andreas Fuchs1c4a8112018-03-29 16:58:07 +02001034 TSS2L_SYS_AUTH_RESPONSE rspAuths;
Juergen Repp109de7d2018-02-23 13:42:08 +01001035 HASH_TAB_ITEM rp_hash_tab[3];
Juergen Repp109de7d2018-02-23 13:42:08 +01001036 uint8_t rpHashNum = 0;
Andreas Fuchsac2b4dc2018-03-29 23:24:59 +02001037
1038 if (esys_context->authsCount == 0) {
1039 LOG_TRACE("No auths to verify");
1040 return TSS2_RC_SUCCESS;
1041 }
1042
Juergen Repp109de7d2018-02-23 13:42:08 +01001043 r = Tss2_Sys_GetRspAuths(esys_context->sys, &rspAuths);
1044 return_if_error(r, "Error: GetRspAuths");
1045
1046 if (rspAuths.count != esys_context->authsCount) {
1047 LOG_ERROR("Number of response auths differs: %i (expected %i)",
1048 rspAuths.count, esys_context->authsCount);
1049 return TSS2_ESYS_RC_GENERAL_FAILURE;
1050 }
1051 /*
1052 * At least one session object is defined so the rp hashes must be computed
1053 * and the HMACs of the responses have to be checked.
1054 * Encrypted response parameters will be decrypted.
1055 */
1056 if (esys_context->session_type[0] >= ESYS_TR_MIN_OBJECT ||
1057 esys_context->session_type[1] >= ESYS_TR_MIN_OBJECT ||
1058 esys_context->session_type[2] >= ESYS_TR_MIN_OBJECT) {
1059 r = Tss2_Sys_GetRpBuffer(esys_context->sys, &rpBuffer_size, &rpBuffer);
1060 return_if_error(r, "Error: get rp buffer");
1061
1062 r = iesys_compute_rp_hashtab(esys_context,
Juergen Repp5a7c4f42018-04-24 14:50:59 +02001063 rpBuffer, rpBuffer_size,
Juergen Repp109de7d2018-02-23 13:42:08 +01001064 &rp_hash_tab[0], &rpHashNum);
1065 return_if_error(r, "Error: while computing response hashes");
1066
Juergen Repp5a7c4f42018-04-24 14:50:59 +02001067 r = iesys_check_rp_hmacs(esys_context, &rspAuths, &rp_hash_tab[0],
1068 rpHashNum);
Juergen Repp109de7d2018-02-23 13:42:08 +01001069 return_if_error(r, "Error: response hmac check");
1070
1071 if (esys_context->encryptNonce != NULL) {
1072 r = iesys_decrypt_param(esys_context, rpBuffer, rpBuffer_size);
1073 return_if_error(r, "Error: while decrypting parameter.");
1074 }
1075 }
1076 return TSS2_RC_SUCCESS;
1077}
1078
1079TSS2_RC
Juergen Reppff821bd2017-12-11 15:21:42 +01001080iesys_nv_get_name(TPM2B_NV_PUBLIC * publicInfo, TPM2B_NAME * name)
1081{
1082 BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1083 size_t offset = 0;
1084 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1085 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1086 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1087
1088 if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1089 name->size = 0;
1090 return TSS2_RC_SUCCESS;
1091 }
1092 TSS2_RC r;
1093 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1094 return_if_error(r, "Crypto hash start");
1095
1096 r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1097 &buffer[0], sizeof(TPMS_NV_PUBLIC),
1098 &offset);
1099 return_if_error(r, "Marshaling TPMS_NV_PUBLIC");
1100
1101 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1102 return_if_error(r, "crypto hash update");
1103
1104 r = iesys_cryptogcry_hash_finish(&cryptoContext, &name->name[len_alg_id],
1105 &size);
1106 return_if_error(r, "crypto hash finish");
1107
1108 offset = 0;
1109 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1110 &name->name[0], sizeof(TPMI_ALG_HASH),
1111 &offset);
dantpmf6ef2472018-04-06 15:21:59 -07001112 return_if_error(r, "Marshaling TPMI_ALG_HASH");
Juergen Reppff821bd2017-12-11 15:21:42 +01001113
1114 name->size = size + len_alg_id;
1115 return TSS2_RC_SUCCESS;
1116}
1117
1118TSS2_RC
1119iesys_get_name(TPM2B_PUBLIC * publicInfo, TPM2B_NAME * name)
1120{
1121 BYTE buffer[sizeof(TPMT_PUBLIC)];
1122 size_t offset = 0;
1123 size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1124 size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1125 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
1126
1127 if (publicInfo->publicArea.nameAlg == TPM2_ALG_NULL) {
1128 name->size = 0;
1129 return TSS2_RC_SUCCESS;
1130 }
1131 TSS2_RC r;
1132 r = iesys_crypto_hash_start(&cryptoContext, publicInfo->publicArea.nameAlg);
1133 return_if_error(r, "crypto hash start");
1134
1135 r = Tss2_MU_TPMT_PUBLIC_Marshal(&publicInfo->publicArea,
1136 &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1137 return_if_error(r, "Marshaling TPMT_PUBLIC");
1138
1139 r = iesys_crypto_hash_update(cryptoContext, &buffer[0], offset);
1140 return_if_error(r, "crypto hash update");
1141
1142 r = iesys_cryptogcry_hash_finish(&cryptoContext, &name->name[len_alg_id],
1143 &size);
1144 return_if_error(r, "crypto hash finish");
1145
1146 offset = 0;
1147 r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->publicArea.nameAlg,
1148 &name->name[0], sizeof(TPMI_ALG_HASH),
1149 &offset);
1150 return_if_error(r, "Marshaling TPMI_ALG_HASH");
1151
1152 name->size = size + len_alg_id;
1153 return TSS2_RC_SUCCESS;
1154}