2 * Copyright (C) 2021 Andreas Steffen
4 * Copyright (C) secunet Security Networks AG
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "tpm_tss_tss2_session.h"
20 #include "tpm_tss_tss2_names.h"
22 #define LABEL "TPM 2.0 - "
24 typedef struct private_tpm_tss_tss2_session_t private_tpm_tss_tss2_session_t
;
27 * Private data of an tpm_tss_tss2_session_t object.
29 struct private_tpm_tss_tss2_session_t
{
32 * Public tpm_tss_tss2_session_t interface.
34 tpm_tss_tss2_session_t
public;
37 * Session handle for protected communication with TPM 2.0
39 uint32_t session_handle
;
42 * Session key for protected communication with TPM 2.0
47 * Hash algorithm to be used for protected communication with TPM 2.0
52 * nonceCaller used for protected communication with TPM 2.0
54 TPM2B_NONCE nonceCaller
;
57 * nonceTPM used for protected communication with TPM 2.0
62 * AES-CFB key size in bytes
69 TSS2_SYS_CONTEXT
*sys_context
;
74 * Two functions shared with tpm_tss_tss2_v2.c
77 hash_algorithm_t
hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg
);
79 size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg
);
83 * Convert TPM2_ALG_ID to PRF algorithm
85 static pseudo_random_function_t
prf_alg_from_tpm_alg_id(TPM2_ALG_ID alg
)
92 return PRF_HMAC_SHA2_256
;
94 return PRF_HMAC_SHA2_384
;
96 return PRF_HMAC_SHA2_512
;
102 static bool generate_nonce(size_t size
, TPM2B_NONCE
*nonce
)
104 nonce_gen_t
*nonce_gen
;
107 nonce_gen
= lib
->crypto
->create_nonce_gen(lib
->crypto
);
110 DBG1(DBG_PTS
, "no nonce generator available");
114 success
= nonce_gen
->get_nonce(nonce_gen
, nonce
->size
, nonce
->buffer
);
115 nonce_gen
->destroy(nonce_gen
);
119 DBG1(DBG_PTS
, "generation of nonce failed");
126 METHOD(tpm_tss_tss2_session_t
, set_cmd_auths
, bool,
127 private_tpm_tss_tss2_session_t
*this)
129 size_t hash_len
, param_size
, cp_size
;
130 const uint8_t *param_buffer
, *cp_buffer
;
131 uint8_t cc_buffer
[4];
132 hash_algorithm_t hash_algorithm
;
134 pseudo_random_function_t prf_alg
;
136 chunk_t data
, cp_hash
, cp_hmac
, nonce_caller
, nonce_tpm
, session_attributes
;
140 TSS2L_SYS_AUTH_COMMAND cmd
;
144 cmd
.auths
[0].sessionHandle
= this->session_handle
;
145 cmd
.auths
[0].sessionAttributes
= TPMA_SESSION_CONTINUESESSION
|
146 TPMA_SESSION_ENCRYPT
;
147 session_attributes
= chunk_create(&cmd
.auths
[0].sessionAttributes
, 1);
149 hash_len
= hash_len_from_tpm_alg_id(this->hash_alg
);
151 if (!generate_nonce(hash_len
, &this->nonceCaller
))
155 cmd
.auths
[0].nonce
.size
= this->nonceCaller
.size
;
156 memcpy(cmd
.auths
[0].nonce
.buffer
, this->nonceCaller
.buffer
,
157 this->nonceCaller
.size
);
159 rval
= Tss2_Sys_GetEncryptParam(this->sys_context
, ¶m_size
,
161 if (rval
== TSS2_SYS_RC_NO_ENCRYPT_PARAM
)
163 DBG2(DBG_PTS
, LABEL
"parameter encryption not possible");
167 rval
= Tss2_Sys_GetCommandCode(this->sys_context
, cc_buffer
);
168 if (rval
!= TSS2_RC_SUCCESS
)
170 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCommandCode failed: 0x%06x", rval
);
174 rval
= Tss2_Sys_GetCpBuffer(this->sys_context
, &cp_size
, &cp_buffer
);
175 if (rval
!= TSS2_RC_SUCCESS
)
177 DBG1(DBG_PTS
, LABEL
"Tss2_GetCpBuffer failed: 0x%06x", rval
);
182 hash_algorithm
= hash_alg_from_tpm_alg_id(this->hash_alg
);
183 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
186 DBG1(DBG_PTS
, "hasher could not be created");
190 data
= chunk_alloc(4 + cp_size
);
191 memcpy(data
.ptr
, cc_buffer
, 4);
192 memcpy(data
.ptr
+ 4, cp_buffer
, cp_size
);
194 success
= hasher
->get_hash(hasher
, data
, cpHash
.buffer
);
195 cpHash
.size
= hasher
->get_hash_size(hasher
);
196 hasher
->destroy(hasher
);
201 DBG1(DBG_PTS
, "computation of cpHash failed");
204 cp_hash
= chunk_create(cpHash
.buffer
, cpHash
.size
);
206 /* compute cp HMAC */
207 prf_alg
= prf_alg_from_tpm_alg_id(this->hash_alg
);
208 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
211 DBG1(DBG_PTS
, "could not create PRF");
214 if (!prf
->set_key(prf
, this->session_key
))
216 DBG1(DBG_PTS
, "could not set PRF key");
221 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
222 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
224 success
= prf
->get_bytes(prf
, cp_hash
, NULL
) &&
225 prf
->get_bytes(prf
, nonce_caller
, NULL
) &&
226 prf
->get_bytes(prf
, nonce_tpm
, NULL
) &&
227 prf
->get_bytes(prf
, session_attributes
, cmd
.auths
[0].hmac
.buffer
);
228 cmd
.auths
[0].hmac
.size
= prf
->get_block_size(prf
);
233 DBG1(DBG_PTS
, "cpHmac computation failed");
236 cp_hmac
= chunk_create(cmd
.auths
[0].hmac
.buffer
, cmd
.auths
[0].hmac
.size
);
237 DBG2(DBG_PTS
, LABEL
"cpHmac: %B", &cp_hmac
);
239 rval
= Tss2_Sys_SetCmdAuths(this->sys_context
, &cmd
);
240 if (rval
!= TSS2_RC_SUCCESS
)
242 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SetCmdAuths failed: 0x%06x", rval
);
250 * Key Derivation Function using Counter Mode as defined by NIST SP800-108
251 * - the label is expected to be NUL terminated
253 static bool kdf_a(TPMI_ALG_HASH hash_alg
, chunk_t key
, chunk_t label
,
254 chunk_t context_u
, chunk_t context_v
, uint32_t bytes
,
257 pseudo_random_function_t prf_alg
;
258 chunk_t count_chunk
, bits_chunk
;
259 uint32_t iterations
, counter
, count
, bits
;
264 bits
= htonl(8 * bytes
);
265 bits_chunk
= chunk_create((uint8_t*)&bits
, sizeof(bits
));
267 prf_alg
= prf_alg_from_tpm_alg_id(hash_alg
);
268 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
271 DBG1(DBG_PTS
, "could not create PRF");
274 if (!prf
->set_key(prf
, key
))
276 DBG1(DBG_PTS
, "could not set PRF key");
281 hlen
= prf
->get_block_size(prf
);
282 iterations
= (bytes
+ hlen
- 1) / hlen
;
283 *key_mat
= chunk_alloc(iterations
* hlen
);
286 for (counter
= 1; counter
<= iterations
; counter
++)
288 count
= htonl(counter
);
289 count_chunk
= chunk_create((uint8_t*)&count
, sizeof(count
));
291 if (!prf
->get_bytes(prf
, count_chunk
, NULL
) ||
292 !prf
->get_bytes(prf
, label
, NULL
) ||
293 !prf
->get_bytes(prf
, context_u
, NULL
) ||
294 !prf
->get_bytes(prf
, context_v
, NULL
) ||
295 !prf
->get_bytes(prf
, bits_chunk
, pos
))
297 DBG1(DBG_PTS
, "KDFa computation failed");
309 METHOD(tpm_tss_tss2_session_t
, get_rsp_auths
, bool,
310 private_tpm_tss_tss2_session_t
*this)
312 size_t param_size
, rp_size
, key_len
, iv_len
;
313 const uint8_t *param_buffer
, *rp_buffer
;
314 uint8_t rc_buffer
[4] = { 0 };
315 uint8_t cc_buffer
[4];
316 hash_algorithm_t hash_algorithm
;
318 pseudo_random_function_t prf_alg
;
321 chunk_t kdf_label
= chunk_from_chars('C','F','B', 0x00);
322 chunk_t data
, rp_hash
, rp_hmac
, nonce_caller
, nonce_tpm
, session_attributes
;
323 chunk_t key_mat
, aes_key
, aes_iv
;
327 TSS2L_SYS_AUTH_RESPONSE rsp
;
328 TPM2B_DIGEST rpHash
, rpHmac
;
330 rval
= Tss2_Sys_GetRspAuths(this->sys_context
, &rsp
);
331 if (rval
!= TSS2_RC_SUCCESS
)
333 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRspAuths failed: 0x%06x", rval
);
337 /* update nonceTPM */
338 memcpy(this->nonceTPM
.buffer
, rsp
.auths
[0].nonce
.buffer
,
339 rsp
.auths
[0].nonce
.size
);
340 this->nonceTPM
.size
= rsp
.auths
[0].nonce
.size
;
342 rval
= Tss2_Sys_GetRpBuffer(this->sys_context
, &rp_size
, &rp_buffer
);
343 if (rval
!= TSS2_RC_SUCCESS
)
345 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRpBuffer failed: 0x%06x", rval
);
349 rval
= Tss2_Sys_GetCommandCode(this->sys_context
, cc_buffer
);
350 if (rval
!= TSS2_RC_SUCCESS
)
352 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCommandCode failed: 0x%06x", rval
);
357 hash_algorithm
= hash_alg_from_tpm_alg_id(this->hash_alg
);
358 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
361 DBG1(DBG_PTS
, "hasher could not be created");
365 data
= chunk_alloc(4 + 4 + rp_size
);
366 memcpy(data
.ptr
, rc_buffer
, 4);
367 memcpy(data
.ptr
+ 4, cc_buffer
, 4);
368 memcpy(data
.ptr
+ 8, rp_buffer
, rp_size
);
370 success
= hasher
->get_hash(hasher
, data
, rpHash
.buffer
);
371 rpHash
.size
= hasher
->get_hash_size(hasher
);
372 hasher
->destroy(hasher
);
377 DBG1(DBG_PTS
, "computation of rpHash failed");
380 rp_hash
= chunk_create(rpHash
.buffer
, rpHash
.size
);
383 prf_alg
= prf_alg_from_tpm_alg_id(this->hash_alg
);
384 prf
= lib
->crypto
->create_prf(lib
->crypto
, prf_alg
);
387 DBG1(DBG_PTS
, "could not create PRF");
390 if (!prf
->set_key(prf
, this->session_key
))
392 DBG1(DBG_PTS
, "could not set PRF key");
397 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
398 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
399 session_attributes
= chunk_create(&rsp
.auths
[0].sessionAttributes
, 1);
401 success
= prf
->get_bytes(prf
, rp_hash
, NULL
) &&
402 prf
->get_bytes(prf
, nonce_tpm
, NULL
) &&
403 prf
->get_bytes(prf
, nonce_caller
, NULL
) &&
404 prf
->get_bytes(prf
, session_attributes
, rpHmac
.buffer
);
405 rpHmac
.size
= prf
->get_block_size(prf
);
410 DBG1(DBG_PTS
, "computation of rpHmac failed");
413 rp_hmac
= chunk_create(rpHmac
.buffer
, rpHmac
.size
);
414 DBG2(DBG_PTS
, LABEL
"rpHMAC: %B", &rp_hmac
);
417 if (!memeq(rsp
.auths
[0].hmac
.buffer
, rpHmac
.buffer
, rpHmac
.size
))
419 DBG1(DBG_PTS
, LABEL
"invalid HMAC received for session 0x%08x",
420 this->session_handle
);
424 /* decrypt parameter */
425 rval
= Tss2_Sys_GetEncryptParam(this->sys_context
, ¶m_size
,
427 if (rval
!= TSS2_RC_SUCCESS
)
429 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetEncryptParam failed: 0x%06x", rval
);
433 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, ENCR_AES_CFB
,
437 DBG1(DBG_PTS
, "could not create %N crypter", encryption_algorithm_names
,
442 key_len
= crypter
->get_key_size(crypter
);
443 iv_len
= crypter
->get_iv_size(crypter
);
445 /* derive decryption key using KDFa */
446 if (!kdf_a(this->hash_alg
, this->session_key
, kdf_label
, nonce_tpm
,
447 nonce_caller
, key_len
+ iv_len
, &key_mat
))
451 aes_key
= chunk_create(key_mat
.ptr
, key_len
);
452 aes_iv
= chunk_create(key_mat
.ptr
+ key_len
, iv_len
);
454 if (!crypter
->set_key(crypter
, aes_key
))
456 crypter
->destroy(crypter
);
457 chunk_clear(&key_mat
);
461 /* copy ciphertext */
462 data
= chunk_alloc(param_size
);
463 memcpy(data
.ptr
, param_buffer
, param_size
);
465 /* decrypt ciphertext */
466 success
= crypter
->decrypt(crypter
, data
, aes_iv
, NULL
);
467 crypter
->destroy(crypter
);
468 chunk_clear(&key_mat
);
474 DBG4(DBG_PTS
, LABEL
"plaintext: %B", &data
);
476 /* copy back plaintext */
477 rval
= Tss2_Sys_SetEncryptParam(this->sys_context
, data
.len
, data
.ptr
);
480 if (rval
!= TSS2_RC_SUCCESS
)
482 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SetEncryptParam failed: 0x%06x", rval
);
490 METHOD(tpm_tss_tss2_session_t
, destroy
, void,
491 private_tpm_tss_tss2_session_t
*this)
493 if (this->session_handle
)
497 /* flush session context */
498 rval
= Tss2_Sys_FlushContext(this->sys_context
, this->session_handle
);
499 if (rval
!= TPM2_RC_SUCCESS
)
501 DBG2(DBG_PTS
, LABEL
"Tss2_Sys_FlushContext failed: 0x%06x", rval
);
503 chunk_clear(&this->session_key
);
508 static chunk_t secret_label
= chunk_from_chars('S','E','C','R','E','T', 0x00);
510 static bool rsa_salt(TPM2B_PUBLIC
*public, TPMI_ALG_HASH hash_alg
,
511 chunk_t
*secret
, TPM2B_ENCRYPTED_SECRET
*encryptedSalt
)
513 encryption_scheme_t encryption_scheme
;
514 public_key_t
*pubkey
= NULL
;
515 nonce_gen_t
*nonce_gen
;
516 chunk_t encrypted_salt
= chunk_empty
;
518 chunk_t rsa_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
523 TPM2B_PUBLIC_KEY_RSA
*rsa
;
528 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA1
;
530 case TPM2_ALG_SHA256
:
531 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA256
;
533 case TPM2_ALG_SHA384
:
534 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA384
;
536 case TPM2_ALG_SHA512
:
537 encryption_scheme
= ENCRYPT_RSA_OAEP_SHA512
;
540 DBG1(DBG_PTS
, LABEL
"unsupported key hash algorithm");
544 hash_len
= hash_len_from_tpm_alg_id(hash_alg
);
546 /* create a salt nonce to be used as a shared secret */
547 nonce_gen
= lib
->crypto
->create_nonce_gen(lib
->crypto
);
550 DBG1(DBG_PTS
, "no nonce generator available");
553 success
= nonce_gen
->allocate_nonce(nonce_gen
, hash_len
, secret
);
554 nonce_gen
->destroy(nonce_gen
);
557 DBG1(DBG_PTS
, "generation of salt nonce failed");
561 /* get RSA public key */
562 rsa
= &public->publicArea
.unique
.rsa
;
563 rsa_modulus
= chunk_create(rsa
->buffer
, rsa
->size
);
564 exponent
= htonl(public->publicArea
.parameters
.rsaDetail
.exponent
);
567 rsa_exponent
= chunk_from_thing(exponent
);
569 pubkey
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
570 BUILD_RSA_MODULUS
, rsa_modulus
, BUILD_RSA_PUB_EXP
,
571 rsa_exponent
, BUILD_END
);
574 DBG1(DBG_PTS
, "retrieval of EK public key failed");
579 /* use RSA public key encryption to encrypt secret salt nonce */
580 success
= pubkey
->encrypt(pubkey
, encryption_scheme
, &secret_label
,
581 *secret
, &encrypted_salt
);
582 pubkey
->destroy(pubkey
);
585 DBG1(DBG_PTS
, "encryption of salt failed");
590 /* copy encryptedSalt to output parameter */
591 encryptedSalt
->size
= encrypted_salt
.len
;
592 memcpy(encryptedSalt
->secret
, encrypted_salt
.ptr
, encrypted_salt
.len
);
593 free(encrypted_salt
.ptr
);
600 * Key Derivation Function used to derive an ecc-based secret
601 * - the label is expected to be NUL terminated
603 static bool kdf_e(TPMI_ALG_HASH hash_alg
, chunk_t z
, chunk_t label
,
604 chunk_t context_u
, chunk_t context_v
, uint32_t bytes
,
607 hash_algorithm_t hash_algorithm
;
609 uint32_t iterations
, counter
, count
;
614 hash_algorithm
= hash_alg_from_tpm_alg_id(hash_alg
);
615 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_algorithm
);
618 DBG1(DBG_PTS
, "could not create hasher");
622 hlen
= hasher
->get_hash_size(hasher
);
623 iterations
= (bytes
+ hlen
- 1) / hlen
;
624 *key_mat
= chunk_alloc(iterations
* hlen
);
627 for (counter
= 1; counter
<= iterations
; counter
++)
629 count
= htonl(counter
);
630 count_chunk
= chunk_create((uint8_t*)&count
, sizeof(count
));
632 if (!hasher
->get_hash(hasher
, count_chunk
, NULL
) ||
633 !hasher
->get_hash(hasher
, z
, NULL
) ||
634 !hasher
->get_hash(hasher
, label
, NULL
) ||
635 !hasher
->get_hash(hasher
, context_u
, NULL
) ||
636 !hasher
->get_hash(hasher
, context_v
, pos
))
638 DBG1(DBG_PTS
, "KDFe computation failed");
640 hasher
->destroy(hasher
);
645 hasher
->destroy(hasher
);
650 static bool ecc_salt(TPM2B_PUBLIC
*public, TPMI_ALG_HASH hash_alg
,
651 chunk_t
*secret
, TPM2B_ENCRYPTED_SECRET
*encryptedSalt
)
653 key_exchange_method_t ec_ke_method
;
655 chunk_t ecdh_pubkey
= chunk_empty
, ecdh_pubkey_x
, ecdh_pubkey_y
;
656 chunk_t ecc_pubkey
= chunk_empty
, ecc_pubkey_x
, ecc_pubkey_y
;
657 chunk_t z
= chunk_empty
;
661 bool success
= FALSE
;
663 switch (public->publicArea
.parameters
.eccDetail
.curveID
)
665 case TPM2_ECC_NIST_P256
:
666 ec_ke_method
= ECP_256_BIT
;
668 case TPM2_ECC_NIST_P384
:
669 ec_ke_method
= ECP_384_BIT
;
671 case TPM2_ECC_NIST_P521
:
672 ec_ke_method
= ECP_521_BIT
;
675 DBG1(DBG_PTS
, "type of ECC EK key not supported");
679 /* Generate ECDH key pair */
680 ke
= lib
->crypto
->create_ke(lib
->crypto
, ec_ke_method
);
683 DBG1(DBG_PTS
, "DH group could not be created");
686 if (!ke
->get_public_key(ke
, &ecdh_pubkey
))
688 DBG1(DBG_PTS
, "DH public key could not be generated");
692 ecdh_pubkey_x
= chunk_create(ecdh_pubkey
.ptr
, ecdh_pubkey
.len
/ 2);
693 ecdh_pubkey_y
= chunk_create(ecdh_pubkey
.ptr
+ ecdh_pubkey_x
.len
,
696 /* get ECC public key */
697 ecc_pubkey_x
= chunk_create(public->publicArea
.unique
.ecc
.x
.buffer
,
698 public->publicArea
.unique
.ecc
.x
.size
);
699 ecc_pubkey_y
= chunk_create(public->publicArea
.unique
.ecc
.y
.buffer
,
700 public->publicArea
.unique
.ecc
.y
.size
);
701 ecc_pubkey
= chunk_cat("cc", ecc_pubkey_x
, ecc_pubkey_y
);
703 /* compute point multiplication of ecc_pubkey with ecdh_privkey */
704 if (!ke
->set_public_key(ke
, ecc_pubkey
))
706 DBG1(DBG_PTS
, "ECC public could not be set");
709 if (!ke
->get_shared_secret(ke
, &z
))
711 DBG1(DBG_PTS
, "could not create shared secret");
715 hash_len
= hash_len_from_tpm_alg_id(hash_alg
);
717 /* derive secret using KDFe */
718 if (!kdf_e(hash_alg
, z
, secret_label
, ecdh_pubkey_x
, ecc_pubkey_x
,
724 /* copy ECDH pubkey to encrypted salt parameter */
725 len
= htons(ecdh_pubkey_x
.len
);
726 encryptedSalt
->size
= 2 * sizeof(len
) + ecdh_pubkey
.len
;
727 pos
= encryptedSalt
->secret
;
728 memcpy(pos
, (uint8_t*)&len
, sizeof(len
));
730 memcpy(pos
, ecdh_pubkey_x
.ptr
, ecdh_pubkey_x
.len
);
731 pos
+= ecdh_pubkey_x
.len
;
732 memcpy(pos
, (uint8_t*)&len
, sizeof(len
));
734 memcpy(pos
, ecdh_pubkey_y
.ptr
, ecdh_pubkey_y
.len
);
740 chunk_free(&ecdh_pubkey
);
741 chunk_free(&ecc_pubkey
);
750 tpm_tss_tss2_session_t
* tpm_tss_tss2_session_create(uint32_t ek_handle
,
751 TPM2B_PUBLIC
*public, TSS2_SYS_CONTEXT
*sys_context
)
753 private_tpm_tss_tss2_session_t
*this;
754 chunk_t secret
= chunk_empty
;
755 chunk_t kdf_label
= chunk_from_chars('A','T','H', 0x00);
756 chunk_t nonce_caller
, nonce_tpm
;
760 TPM2B_ENCRYPTED_SECRET encryptedSalt
;
761 TPM2_SE sessionType
= TPM2_SE_HMAC
;
766 .set_cmd_auths
= _set_cmd_auths
,
767 .get_rsp_auths
= _get_rsp_auths
,
770 .sys_context
= sys_context
,
771 .hash_alg
= public->publicArea
.nameAlg
,
774 hash_len
= hash_len_from_tpm_alg_id(this->hash_alg
);
776 if (!generate_nonce(hash_len
, &this->nonceCaller
))
781 /* determine endorsement key type */
782 switch (public->publicArea
.type
)
785 DBG1(DBG_PTS
, LABEL
"RSA EK handle: 0x%08x", ek_handle
);
786 if (!rsa_salt(public, this->hash_alg
, &secret
, &encryptedSalt
))
792 DBG1(DBG_PTS
, LABEL
"ECC %N EK handle: 0x%08x", tpm_ecc_curve_names
,
793 public->publicArea
.parameters
.eccDetail
.curveID
, ek_handle
);
794 if (!ecc_salt(public, this->hash_alg
, &secret
, &encryptedSalt
))
800 DBG1(DBG_PTS
, LABEL
"unsupported ek key type");
804 sym
= (TPMT_SYM_DEF
*)&public->publicArea
.parameters
.asymDetail
.symmetric
;
805 DBG2(DBG_PTS
, LABEL
"AES-CFB with %u bits", sym
->keyBits
.aes
);
806 this->aes_key_len
= sym
->keyBits
.aes
/ 8;
808 rval
= Tss2_Sys_StartAuthSession(this->sys_context
, ek_handle
, TPM2_RH_NULL
,
809 NULL
, &this->nonceCaller
, &encryptedSalt
, sessionType
, sym
,
810 this->hash_alg
, &this->session_handle
, &this->nonceTPM
, NULL
);
811 if (rval
!= TSS2_RC_SUCCESS
)
813 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_StartAuthSession failed: 0x%06x", rval
);
816 DBG2(DBG_PTS
, LABEL
"session handle: 0x%08x", this->session_handle
);
818 nonce_tpm
= chunk_create(this->nonceTPM
.buffer
, this->nonceTPM
.size
);
819 nonce_caller
= chunk_create(this->nonceCaller
.buffer
, this->nonceCaller
.size
);
821 /* derive sessionKey using KDFa */
822 if (!kdf_a(this->hash_alg
, secret
, kdf_label
, nonce_tpm
, nonce_caller
,
823 hash_len
, &this->session_key
))
827 chunk_clear(&secret
);
828 DBG4(DBG_PTS
, LABEL
"session key: %B", &this->session_key
);
830 return &this->public;
833 chunk_clear(&secret
);
838 #endif /* TSS_TSS2_V2 */