2 * Copyright (C) 2021 Andreas Steffen, strongSec GmbH
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "tpm_tss_tss2_session.h"
18 #include "tpm_tss_tss2_names.h"
20 #define LABEL "TPM 2.0 - "
22 typedef struct private_tpm_tss_tss2_session_t private_tpm_tss_tss2_session_t
;
25 * Private data of an tpm_tss_tss2_session_t object.
27 struct private_tpm_tss_tss2_session_t
{
30 * Public tpm_tss_tss2_session_t interface.
32 tpm_tss_tss2_session_t
public;
35 * Session handle for protected communication with TPM 2.0
37 uint32_t session_handle
;
40 * Session key for protected communication with TPM 2.0
45 * Hash algorithm to be used for protected communication with TPM 2.0
50 * nonceCaller used for protected communication with TPM 2.0
52 TPM2B_NONCE nonceCaller
;
55 * nonceTPM used for protected communication with TPM 2.0
60 * AES-CFB key size in bytes
67 TSS2_SYS_CONTEXT
*sys_context
;
72 * Two functions shared with tpm_tss_tss2_v2.c
75 hash_algorithm_t
hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg
);
77 size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg
);
81 * Convert TPM2_ALG_ID to PRF algorithm
83 pseudo_random_function_t
prf_alg_from_tpm_alg_id(TPM2_ALG_ID alg
)
90 return PRF_HMAC_SHA2_256
;
92 return PRF_HMAC_SHA2_384
;
94 return PRF_HMAC_SHA2_512
;
100 static bool generate_nonce(size_t size
, TPM2B_NONCE
*nonce
)
102 nonce_gen_t
*nonce_gen
;
105 nonce_gen
= lib
->crypto
->create_nonce_gen(lib
->crypto
);
108 DBG1(DBG_PTS
, "no nonce generator available");
112 success
= nonce_gen
->get_nonce(nonce_gen
, nonce
->size
, nonce
->buffer
);
113 nonce_gen
->destroy(nonce_gen
);
117 DBG1(DBG_PTS
, "generation of nonce failed");
124 METHOD(tpm_tss_tss2_session_t
, set_cmd_auths
, bool,
125 private_tpm_tss_tss2_session_t
*this)
127 size_t hash_len
, param_size
, cp_size
;
128 const uint8_t *param_buffer
, *cp_buffer
;
129 uint8_t cc_buffer
[4];
130 hash_algorithm_t hash_algorithm
;
132 pseudo_random_function_t prf_alg
;
134 chunk_t data
, cp_hash
, cp_hmac
, nonce_caller
, nonce_tpm
, session_attributes
;
138 TSS2L_SYS_AUTH_COMMAND cmd
;
142 cmd
.auths
[0].sessionHandle
= this->session_handle
;
143 cmd
.auths
[0].sessionAttributes
= TPMA_SESSION_CONTINUESESSION
|
144 TPMA_SESSION_ENCRYPT
;
145 session_attributes
= chunk_create(&cmd
.auths
[0].sessionAttributes
, 1);
147 hash_len
= hash_len_from_tpm_alg_id(this->hash_alg
);
149 if (!generate_nonce(hash_len
, &this->nonceCaller
))
153 cmd
.auths
[0].nonce
.size
= this->nonceCaller
.size
;
154 memcpy(cmd
.auths
[0].nonce
.buffer
, this->nonceCaller
.buffer
,
155 this->nonceCaller
.size
);
157 rval
= Tss2_Sys_GetEncryptParam(this->sys_context
, ¶m_size
,
159 if (rval
== TSS2_SYS_RC_NO_ENCRYPT_PARAM
)
161 DBG2(DBG_PTS
, LABEL
"parameter encryption not possible");
165 rval
= Tss2_Sys_GetCommandCode(this->sys_context
, cc_buffer
);
166 if (rval
!= TSS2_RC_SUCCESS
)
168 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCommandCode failed: 0x%06x", rval
);
172 rval
= Tss2_Sys_GetCpBuffer(this->sys_context
, &cp_size
, &cp_buffer
);
173 if (rval
!= TSS2_RC_SUCCESS
)
175 DBG1(DBG_PTS
, LABEL
"Tss2_GetCpBuffer failed: 0x%06x", rval
);
180 hash_algorithm
= hash_alg_from_tpm_alg_id(this->hash_alg
);
181 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
184 DBG1(DBG_PTS
, "hasher could not be created");
188 data
= chunk_alloc(4 + cp_size
);
189 memcpy(data
.ptr
, cc_buffer
, 4);
190 memcpy(data
.ptr
+ 4, cp_buffer
, cp_size
);
192 success
= hasher
->get_hash(hasher
, data
, cpHash
.buffer
);
193 cpHash
.size
= hasher
->get_hash_size(hasher
);
194 hasher
->destroy(hasher
);
199 DBG1(DBG_PTS
, "computation of cpHash failed");
202 cp_hash
= chunk_create(cpHash
.buffer
, cpHash
.size
);
204 /* compute cp HMAC */
205 prf_alg
= prf_alg_from_tpm_alg_id(this->hash_alg
);
206 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
209 DBG1(DBG_PTS
, "could not create PRF");
212 if (!prf
->set_key(prf
, this->session_key
))
214 DBG1(DBG_PTS
, "could not set PRF key");
219 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
220 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
222 success
= prf
->get_bytes(prf
, cp_hash
, NULL
) &&
223 prf
->get_bytes(prf
, nonce_caller
, NULL
) &&
224 prf
->get_bytes(prf
, nonce_tpm
, NULL
) &&
225 prf
->get_bytes(prf
, session_attributes
, cmd
.auths
[0].hmac
.buffer
);
226 cmd
.auths
[0].hmac
.size
= prf
->get_block_size(prf
);
231 DBG1(DBG_PTS
, "cpHmac computation failed");
234 cp_hmac
= chunk_create(cmd
.auths
[0].hmac
.buffer
, cmd
.auths
[0].hmac
.size
);
235 DBG2(DBG_PTS
, LABEL
"cpHmac: %B", &cp_hmac
);
237 rval
= Tss2_Sys_SetCmdAuths(this->sys_context
, &cmd
);
238 if (rval
!= TSS2_RC_SUCCESS
)
240 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SetCmdAuths failed: 0x%06x", rval
);
248 * Key Derivation Function using Counter Mode as defined by NIST SP800-108
249 * - the label is expected to be NUL terminated
251 static bool kdf_a(TPMI_ALG_HASH hash_alg
, chunk_t key
, chunk_t label
,
252 chunk_t context_u
, chunk_t context_v
, uint32_t bytes
,
255 pseudo_random_function_t prf_alg
;
256 chunk_t count_chunk
, bits_chunk
;
257 uint32_t iterations
, counter
, count
, bits
;
262 bits
= htonl(8 * bytes
);
263 bits_chunk
= chunk_create((uint8_t*)&bits
, sizeof(bits
));
265 prf_alg
= prf_alg_from_tpm_alg_id(hash_alg
);
266 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
269 DBG1(DBG_PTS
, "could not create PRF");
272 if (!prf
->set_key(prf
, key
))
274 DBG1(DBG_PTS
, "could not set PRF key");
279 hlen
= prf
->get_block_size(prf
);
280 iterations
= (bytes
+ hlen
- 1) / hlen
;
281 *key_mat
= chunk_alloc(iterations
* hlen
);
284 for (counter
= 1; counter
<= iterations
; counter
++)
286 count
= htonl(counter
);
287 count_chunk
= chunk_create((uint8_t*)&count
, sizeof(count
));
289 if (!prf
->get_bytes(prf
, count_chunk
, NULL
) ||
290 !prf
->get_bytes(prf
, label
, NULL
) ||
291 !prf
->get_bytes(prf
, context_u
, NULL
) ||
292 !prf
->get_bytes(prf
, context_v
, NULL
) ||
293 !prf
->get_bytes(prf
, bits_chunk
, pos
))
295 DBG1(DBG_PTS
, "KDFa computation failed");
307 METHOD(tpm_tss_tss2_session_t
, get_rsp_auths
, bool,
308 private_tpm_tss_tss2_session_t
*this)
310 size_t param_size
, rp_size
, key_len
, iv_len
;
311 const uint8_t *param_buffer
, *rp_buffer
;
312 uint8_t rc_buffer
[4] = { 0 };
313 uint8_t cc_buffer
[4];
314 hash_algorithm_t hash_algorithm
;
316 pseudo_random_function_t prf_alg
;
319 chunk_t kdf_label
= chunk_from_chars('C','F','B', 0x00);
320 chunk_t data
, rp_hash
, rp_hmac
, nonce_caller
, nonce_tpm
, session_attributes
;
321 chunk_t key_mat
, aes_key
, aes_iv
;
325 TSS2L_SYS_AUTH_RESPONSE rsp
;
326 TPM2B_DIGEST rpHash
, rpHmac
;
328 rval
= Tss2_Sys_GetRspAuths(this->sys_context
, &rsp
);
329 if (rval
!= TSS2_RC_SUCCESS
)
331 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRspAuths failed: 0x%06x", rval
);
335 /* update nonceTPM */
336 memcpy(this->nonceTPM
.buffer
, rsp
.auths
[0].nonce
.buffer
,
337 rsp
.auths
[0].nonce
.size
);
338 this->nonceTPM
.size
= rsp
.auths
[0].nonce
.size
;
340 rval
= Tss2_Sys_GetRpBuffer(this->sys_context
, &rp_size
, &rp_buffer
);
341 if (rval
!= TSS2_RC_SUCCESS
)
343 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRpBuffer failed: 0x%06x", rval
);
347 rval
= Tss2_Sys_GetCommandCode(this->sys_context
, cc_buffer
);
348 if (rval
!= TSS2_RC_SUCCESS
)
350 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCommandCode failed: 0x%06x", rval
);
355 hash_algorithm
= hash_alg_from_tpm_alg_id(this->hash_alg
);
356 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
359 DBG1(DBG_PTS
, "hasher could not be created");
363 data
= chunk_alloc(4 + 4 + rp_size
);
364 memcpy(data
.ptr
, rc_buffer
, 4);
365 memcpy(data
.ptr
+ 4, cc_buffer
, 4);
366 memcpy(data
.ptr
+ 8, rp_buffer
, rp_size
);
368 success
= hasher
->get_hash(hasher
, data
, rpHash
.buffer
);
369 rpHash
.size
= hasher
->get_hash_size(hasher
);
370 hasher
->destroy(hasher
);
375 DBG1(DBG_PTS
, "computation of rpHash failed");
378 rp_hash
= chunk_create(rpHash
.buffer
, rpHash
.size
);
381 prf_alg
= prf_alg_from_tpm_alg_id(this->hash_alg
);
382 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
385 DBG1(DBG_PTS
, "could not create PRF");
388 if (!prf
->set_key(prf
, this->session_key
))
390 DBG1(DBG_PTS
, "could not set PRF key");
395 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
396 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
397 session_attributes
= chunk_create(&rsp
.auths
[0].sessionAttributes
, 1);
399 success
= prf
->get_bytes(prf
, rp_hash
, NULL
) &&
400 prf
->get_bytes(prf
, nonce_tpm
, NULL
) &&
401 prf
->get_bytes(prf
, nonce_caller
, NULL
) &&
402 prf
->get_bytes(prf
, session_attributes
, rpHmac
.buffer
);
403 rpHmac
.size
= prf
->get_block_size(prf
);
408 DBG1(DBG_PTS
, "computation of rpHmac failed");
411 rp_hmac
= chunk_create(rpHmac
.buffer
, rpHmac
.size
);
412 DBG2(DBG_PTS
, LABEL
"rpHMAC: %B", &rp_hmac
);
415 if (!memeq(rsp
.auths
[0].hmac
.buffer
, rpHmac
.buffer
, rpHmac
.size
))
417 DBG1(DBG_PTS
, LABEL
"invalid HMAC received for session 0x%08x",
418 this->session_handle
);
422 /* decrypt parameter */
423 rval
= Tss2_Sys_GetEncryptParam(this->sys_context
, ¶m_size
,
425 if (rval
!= TSS2_RC_SUCCESS
)
427 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetEncryptParam failed: 0x%06x", rval
);
431 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, ENCR_AES_CFB
,
435 DBG1(DBG_PTS
, "could not create %N crypter", encryption_algorithm_names
,
440 key_len
= crypter
->get_key_size(crypter
);
441 iv_len
= crypter
->get_iv_size(crypter
);
443 /* derive decryption key using KDFa */
444 if (!kdf_a(this->hash_alg
, this->session_key
, kdf_label
, nonce_tpm
,
445 nonce_caller
, key_len
+ iv_len
, &key_mat
))
449 aes_key
= chunk_create(key_mat
.ptr
, key_len
);
450 aes_iv
= chunk_create(key_mat
.ptr
+ key_len
, iv_len
);
452 if (!crypter
->set_key(crypter
, aes_key
))
454 crypter
->destroy(crypter
);
455 chunk_clear(&key_mat
);
459 /* copy ciphertext */
460 data
= chunk_alloc(param_size
);
461 memcpy(data
.ptr
, param_buffer
, param_size
);
463 /* decrypt ciphertext */
464 success
= crypter
->decrypt(crypter
, data
, aes_iv
, NULL
);
465 crypter
->destroy(crypter
);
466 chunk_clear(&key_mat
);
472 DBG4(DBG_PTS
, LABEL
"plaintext: %B", &data
);
474 /* copy back plaintext */
475 rval
= Tss2_Sys_SetEncryptParam(this->sys_context
, data
.len
, data
.ptr
);
478 if (rval
!= TSS2_RC_SUCCESS
)
480 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SetEncryptParam failed: 0x%06x", rval
);
488 METHOD(tpm_tss_tss2_session_t
, destroy
, void,
489 private_tpm_tss_tss2_session_t
*this)
491 if (this->session_handle
)
495 /* flush session context */
496 rval
= Tss2_Sys_FlushContext(this->sys_context
, this->session_handle
);
497 if (rval
!= TPM2_RC_SUCCESS
)
499 DBG2(DBG_PTS
, LABEL
"Tss2_Sys_FlushContext failed: 0x%06x", rval
);
501 chunk_clear(&this->session_key
);
506 static chunk_t secret_label
= chunk_from_chars('S','E','C','R','E','T', 0x00);
508 static bool rsa_salt(TPM2B_PUBLIC
*public, TPMI_ALG_HASH hash_alg
,
509 chunk_t
*secret
, TPM2B_ENCRYPTED_SECRET
*encryptedSalt
)
511 encryption_scheme_t encryption_scheme
;
512 public_key_t
*pubkey
= NULL
;
513 nonce_gen_t
*nonce_gen
;
514 chunk_t encrypted_salt
= chunk_empty
;
516 chunk_t rsa_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
521 TPM2B_PUBLIC_KEY_RSA
*rsa
;
526 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA1
;
528 case TPM2_ALG_SHA256
:
529 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA256
;
531 case TPM2_ALG_SHA384
:
532 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA384
;
534 case TPM2_ALG_SHA512
:
535 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA512
;
538 DBG1(DBG_PTS
, LABEL
"unsupported key hash algorithm");
542 hash_len
= hash_len_from_tpm_alg_id(hash_alg
);
544 /* create a salt nonce to be used as a shared secret */
545 nonce_gen
= lib
->crypto
->create_nonce_gen(lib
->crypto
);
548 DBG1(DBG_PTS
, "no nonce generator available");
551 success
= nonce_gen
->allocate_nonce(nonce_gen
, hash_len
, secret
);
552 nonce_gen
->destroy(nonce_gen
);
555 DBG1(DBG_PTS
, "generation of salt nonce failed");
559 /* get RSA public key */
560 rsa
= &public->publicArea
.unique
.rsa
;
561 rsa_modulus
= chunk_create(rsa
->buffer
, rsa
->size
);
562 exponent
= htonl(public->publicArea
.parameters
.rsaDetail
.exponent
);
565 rsa_exponent
= chunk_from_thing(exponent
);
567 pubkey
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
568 BUILD_RSA_MODULUS
, rsa_modulus
, BUILD_RSA_PUB_EXP
,
569 rsa_exponent
, BUILD_END
);
572 DBG1(DBG_PTS
, "retrieval of EK public key failed");
577 /* use RSA public key encryption to encrypt secret salt nonce */
578 success
= pubkey
->encrypt(pubkey
, encryption_scheme
, &secret_label
,
579 *secret
, &encrypted_salt
);
580 pubkey
->destroy(pubkey
);
583 DBG1(DBG_PTS
, "encryption of salt failed");
588 /* copy encryptedSalt to output parameter */
589 encryptedSalt
->size
= encrypted_salt
.len
;
590 memcpy(encryptedSalt
->secret
, encrypted_salt
.ptr
, encrypted_salt
.len
);
591 free(encrypted_salt
.ptr
);
598 * Key Derivation Function used to derive an ecc-based secret
599 * - the label is expected to be NUL terminated
601 static bool kdf_e(TPMI_ALG_HASH hash_alg
, chunk_t z
, chunk_t label
,
602 chunk_t context_u
, chunk_t context_v
, uint32_t bytes
,
605 hash_algorithm_t hash_algorithm
;
607 uint32_t iterations
, counter
, count
;
612 hash_algorithm
= hash_alg_from_tpm_alg_id(hash_alg
);
613 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
616 DBG1(DBG_PTS
, "could not create hasher");
620 hlen
= hasher
->get_hash_size(hasher
);
621 iterations
= (bytes
+ hlen
- 1) / hlen
;
622 *key_mat
= chunk_alloc(iterations
* hlen
);
625 for (counter
= 1; counter
<= iterations
; counter
++)
627 count
= htonl(counter
);
628 count_chunk
= chunk_create((uint8_t*)&count
, sizeof(count
));
630 if (!hasher
->get_hash(hasher
, count_chunk
, NULL
) ||
631 !hasher
->get_hash(hasher
, z
, NULL
) ||
632 !hasher
->get_hash(hasher
, label
, NULL
) ||
633 !hasher
->get_hash(hasher
, context_u
, NULL
) ||
634 !hasher
->get_hash(hasher
, context_v
, pos
))
636 DBG1(DBG_PTS
, "KDFe computation failed");
638 hasher
->destroy(hasher
);
643 hasher
->destroy(hasher
);
648 static bool ecc_salt(TPM2B_PUBLIC
*public, TPMI_ALG_HASH hash_alg
,
649 chunk_t
*secret
, TPM2B_ENCRYPTED_SECRET
*encryptedSalt
)
651 diffie_hellman_group_t ec_group
;
652 diffie_hellman_t
*dh
;
653 chunk_t ecdh_pubkey
= chunk_empty
, ecdh_pubkey_x
, ecdh_pubkey_y
;
654 chunk_t ecc_pubkey
= chunk_empty
, ecc_pubkey_x
, ecc_pubkey_y
;
655 chunk_t z
= chunk_empty
;
659 bool success
= FALSE
;
661 switch (public->publicArea
.parameters
.eccDetail
.curveID
)
663 case TPM2_ECC_NIST_P256
:
664 ec_group
= ECP_256_BIT
;
666 case TPM2_ECC_NIST_P384
:
667 ec_group
= ECP_384_BIT
;
669 case TPM2_ECC_NIST_P521
:
670 ec_group
= ECP_521_BIT
;
673 DBG1(DBG_PTS
, "type of ECC EK key not supported");
677 /* Generate ECDH key pair */
678 dh
= lib
->crypto
->create_dh(lib
->crypto
, ec_group
);
681 DBG1(DBG_PTS
, "DH group could not be created");
684 if (!dh
->get_my_public_value(dh
, &ecdh_pubkey
))
686 DBG1(DBG_PTS
, "DH public key could not be generated");
690 ecdh_pubkey_x
= chunk_create(ecdh_pubkey
.ptr
, ecdh_pubkey
.len
/ 2);
691 ecdh_pubkey_y
= chunk_create(ecdh_pubkey
.ptr
+ ecdh_pubkey_x
.len
,
694 /* get ECC public key */
695 ecc_pubkey_x
= chunk_create(public->publicArea
.unique
.ecc
.x
.buffer
,
696 public->publicArea
.unique
.ecc
.x
.size
);
697 ecc_pubkey_y
= chunk_create(public->publicArea
.unique
.ecc
.y
.buffer
,
698 public->publicArea
.unique
.ecc
.y
.size
);
699 ecc_pubkey
= chunk_cat("cc", ecc_pubkey_x
, ecc_pubkey_y
);
701 /* compute point multiplication of ecc_pubkey with ecdh_privkey */
702 if (!dh
->set_other_public_value(dh
, ecc_pubkey
))
704 DBG1(DBG_PTS
, "ECC public could not be set");
707 if (!dh
->get_shared_secret(dh
, &z
))
709 DBG1(DBG_PTS
, "could not create shared secret");
713 hash_len
= hash_len_from_tpm_alg_id(hash_alg
);
715 /* derive secret using KDFe */
716 if (!kdf_e(hash_alg
, z
, secret_label
, ecdh_pubkey_x
, ecc_pubkey_x
,
722 /* copy ECDH pubkey to encrypted salt parameter */
723 len
= htons(ecdh_pubkey_x
.len
);
724 encryptedSalt
->size
= 2 * sizeof(len
) + ecdh_pubkey
.len
;
725 pos
= encryptedSalt
->secret
;
726 memcpy(pos
, (uint8_t*)&len
, sizeof(len
));
728 memcpy(pos
, ecdh_pubkey_x
.ptr
, ecdh_pubkey_x
.len
);
729 pos
+= ecdh_pubkey_x
.len
;
730 memcpy(pos
, (uint8_t*)&len
, sizeof(len
));
732 memcpy(pos
, ecdh_pubkey_y
.ptr
, ecdh_pubkey_y
.len
);
738 chunk_free(&ecdh_pubkey
);
739 chunk_free(&ecc_pubkey
);
748 tpm_tss_tss2_session_t
* tpm_tss_tss2_session_create(uint32_t ek_handle
,
749 TPM2B_PUBLIC
*public, TSS2_SYS_CONTEXT
*sys_context
)
751 private_tpm_tss_tss2_session_t
*this;
752 chunk_t secret
= chunk_empty
;
753 chunk_t kdf_label
= chunk_from_chars('A','T','H', 0x00);
754 chunk_t nonce_caller
, nonce_tpm
;
758 TPM2B_ENCRYPTED_SECRET encryptedSalt
;
759 TPM2_SE sessionType
= TPM2_SE_HMAC
;
764 .set_cmd_auths
= _set_cmd_auths
,
765 .get_rsp_auths
= _get_rsp_auths
,
768 .sys_context
= sys_context
,
769 .hash_alg
= public->publicArea
.nameAlg
,
772 hash_len
= hash_len_from_tpm_alg_id(this->hash_alg
);
774 if (!generate_nonce(hash_len
, &this->nonceCaller
))
779 /* determine endorsement key type */
780 switch (public->publicArea
.type
)
783 DBG1(DBG_PTS
, LABEL
"RSA EK handle: 0x%08x", ek_handle
);
784 if (!rsa_salt(public, this->hash_alg
, &secret
, &encryptedSalt
))
790 DBG1(DBG_PTS
, LABEL
"ECC %N EK handle: 0x%08x", tpm_ecc_curve_names
,
791 public->publicArea
.parameters
.eccDetail
.curveID
, ek_handle
);
792 if (!ecc_salt(public, this->hash_alg
, &secret
, &encryptedSalt
))
798 DBG1(DBG_PTS
, LABEL
"unsupported ek key type");
802 sym
= (TPMT_SYM_DEF
*)&public->publicArea
.parameters
.asymDetail
.symmetric
;
803 DBG2(DBG_PTS
, LABEL
"AES-CFB with %u bits", sym
->keyBits
.aes
);
804 this->aes_key_len
= sym
->keyBits
.aes
/ 8;
806 rval
= Tss2_Sys_StartAuthSession(this->sys_context
, ek_handle
, TPM2_RH_NULL
,
807 NULL
, &this->nonceCaller
, &encryptedSalt
, sessionType
, sym
,
808 this->hash_alg
, &this->session_handle
, &this->nonceTPM
, NULL
);
809 if (rval
!= TSS2_RC_SUCCESS
)
811 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_StartAuthSession failed: 0x%06x", rval
);
814 DBG2(DBG_PTS
, LABEL
"session handle: 0x%08x", this->session_handle
);
816 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
817 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
819 /* derive sessionKey using KDFa */
820 if (!kdf_a(this->hash_alg
, secret
, kdf_label
, nonce_tpm
, nonce_caller
,
821 hash_len
, &this->session_key
))
825 chunk_clear(&secret
);
826 DBG4(DBG_PTS
, LABEL
"session key: %B", &this->session_key
);
828 return &this->public;
831 chunk_clear(&secret
);
836 #endif /* TSS_TSS2_V2 */