From d103e849516a72bb79ead75b7d85f98eae1c6401 Mon Sep 17 00:00:00 2001 From: Juergen Repp Date: Tue, 18 Jul 2023 21:22:23 +0200 Subject: [PATCH] esys: remove trailing zeros in auth value When TPM Calulates the HMAC trailing zeros are rmoved. Therfore the trailing zeros are removed in Esys_TR_SetAuth, Esys_Create, Esys_CreateLoded, Esys_NV_DefineSpace, and Esys_CreatePrimary. The removing is added to the function iesys_hash_long_auth_value. Therefore this function is renamed to iesys_adapt_auth_value. An integration test which uses trailing zeros in auth values is added. The auth value handling in ChangeAuth programs is fixed: * The trailing zeros are now removed in these programs. * The new auth value now is stored in objects where the auth value is changed with Esys_ObjectChangeAuth. * the integration test which checkd trailing zeros is extend. Fixes: #2664 Signed-off-by: Juergen Repp --- Makefile-test.am | 8 + src/tss2-esys/api/Esys_Create.c | 6 +- src/tss2-esys/api/Esys_CreateLoaded.c | 2 +- src/tss2-esys/api/Esys_CreatePrimary.c | 2 +- src/tss2-esys/api/Esys_HierarchyChangeAuth.c | 10 +- src/tss2-esys/api/Esys_NV_ChangeAuth.c | 6 + src/tss2-esys/api/Esys_NV_DefineSpace.c | 6 +- src/tss2-esys/api/Esys_ObjectChangeAuth.c | 18 +- src/tss2-esys/esys_iutil.c | 64 +- src/tss2-esys/esys_iutil.h | 5 +- src/tss2-esys/esys_tr.c | 10 +- .../esys-check-auth-with-trailing-zero.int.c | 678 ++++++++++++++++++ 12 files changed, 781 insertions(+), 34 deletions(-) create mode 100644 test/integration/esys-check-auth-with-trailing-zero.int.c diff --git a/Makefile-test.am b/Makefile-test.am index 827c4736e..9c13229c2 100644 --- a/Makefile-test.am +++ b/Makefile-test.am @@ -254,6 +254,7 @@ ESYS_TESTS_INTEGRATION_MANDATORY = \ test/integration/esys-certify-creation.int \ test/integration/esys-certifyX509.int \ test/integration/esys-certify.int \ + test/integration/esys-check-auth-with-trailing-zero.int \ test/integration/esys-clear-control.int \ test/integration/esys-clockset.int \ test/integration/esys-clockset-audit.int \ @@ -1272,6 +1273,13 @@ test_integration_esys_change_eps_int_SOURCES = \ test/integration/esys-change-eps.int.c \ test/integration/main-esys.c test/integration/test-esys.h +test_integration_esys_check_auth_with_trailing_zero_int_CFLAGS = $(TESTS_CFLAGS) +test_integration_esys_check_auth_with_trailing_zero_int_LDADD = $(TESTS_LDADD) +test_integration_esys_check_auth_with_trailing_zero_int_LDFLAGS = $(TESTS_LDFLAGS) +test_integration_esys_check_auth_with_trailing_zero_int_SOURCES = \ + test/integration/esys-check-auth-with-trailing-zero.int.c \ + test/integration/main-esys.c test/integration/test-esys.h + test_integration_esys_clear_int_CFLAGS = $(TESTS_CFLAGS) test_integration_esys_clear_int_LDADD = $(TESTS_LDADD) test_integration_esys_clear_int_LDFLAGS = $(TESTS_LDFLAGS) diff --git a/src/tss2-esys/api/Esys_Create.c b/src/tss2-esys/api/Esys_Create.c index 7e61aec52..f435688e8 100644 --- a/src/tss2-esys/api/Esys_Create.c +++ b/src/tss2-esys/api/Esys_Create.c @@ -206,10 +206,10 @@ Esys_Create_Async( store_input_parameters (esysContext, inSensitive); if (inPublic) { - r = iesys_hash_long_auth_values( + r = iesys_adapt_auth_value( &esysContext->crypto_backend, - &esysContext->in.Create.inSensitive->sensitive.userAuth, - inPublic->publicArea.nameAlg); + &esysContext->in.Create.inSensitive->sensitive.userAuth, + inPublic->publicArea.nameAlg); return_state_if_error(r, _ESYS_STATE_INIT, "Adapt auth value."); } diff --git a/src/tss2-esys/api/Esys_CreateLoaded.c b/src/tss2-esys/api/Esys_CreateLoaded.c index 66bb2129d..5b183ae19 100644 --- a/src/tss2-esys/api/Esys_CreateLoaded.c +++ b/src/tss2-esys/api/Esys_CreateLoaded.c @@ -203,7 +203,7 @@ Esys_CreateLoaded_Async( &publicArea); return_if_error(r, "Unmarshalling inPublic failed"); - r = iesys_hash_long_auth_values( + r = iesys_adapt_auth_value( &esysContext->crypto_backend, &esysContext->in.CreateLoaded.inSensitive->sensitive.userAuth, publicArea.nameAlg); diff --git a/src/tss2-esys/api/Esys_CreatePrimary.c b/src/tss2-esys/api/Esys_CreatePrimary.c index 9b551ae05..3a9ef83e2 100644 --- a/src/tss2-esys/api/Esys_CreatePrimary.c +++ b/src/tss2-esys/api/Esys_CreatePrimary.c @@ -208,7 +208,7 @@ Esys_CreatePrimary_Async( return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); store_input_parameters (esysContext, inSensitive); if (inPublic) { - r = iesys_hash_long_auth_values( + r = iesys_adapt_auth_value( &esysContext->crypto_backend, &esysContext->in.CreatePrimary.inSensitive->sensitive.userAuth, inPublic->publicArea.nameAlg); diff --git a/src/tss2-esys/api/Esys_HierarchyChangeAuth.c b/src/tss2-esys/api/Esys_HierarchyChangeAuth.c index 70f7210f0..1ab4c9343 100644 --- a/src/tss2-esys/api/Esys_HierarchyChangeAuth.c +++ b/src/tss2-esys/api/Esys_HierarchyChangeAuth.c @@ -26,11 +26,13 @@ static void store_input_parameters ( const TPM2B_AUTH *newAuth) { esysContext->in.HierarchyChangeAuth.authHandle = authHandle; - if (newAuth == NULL) + if (newAuth == NULL) { memset(&esysContext->in.HierarchyChangeAuth.newAuth, 0, sizeof(esysContext->in.HierarchyChangeAuth.newAuth)); - else + } else { esysContext->in.HierarchyChangeAuth.newAuth = *newAuth; + iesys_strip_trailing_zeros(&esysContext->in.HierarchyChangeAuth.newAuth); + } } /** One-Call function for TPM2_HierarchyChangeAuth @@ -175,7 +177,9 @@ Esys_HierarchyChangeAuth_Async( /* Check input parameters */ r = check_session_feasibility(shandle1, shandle2, shandle3, 1); return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); + store_input_parameters(esysContext, authHandle, newAuth); + iesys_strip_trailing_zeros(&esysContext->in.HierarchyChangeAuth.newAuth); /* Retrieve the metadata objects for provided handles */ r = esys_GetResourceObject(esysContext, authHandle, &authHandleNode); @@ -186,7 +190,7 @@ Esys_HierarchyChangeAuth_Async( (authHandleNode == NULL) ? TPM2_RH_NULL : authHandleNode->rsrc.handle, - newAuth); + &esysContext->in.HierarchyChangeAuth.newAuth); return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error."); /* Calculate the cpHash Values */ diff --git a/src/tss2-esys/api/Esys_NV_ChangeAuth.c b/src/tss2-esys/api/Esys_NV_ChangeAuth.c index d555adb1f..cbd9b6670 100644 --- a/src/tss2-esys/api/Esys_NV_ChangeAuth.c +++ b/src/tss2-esys/api/Esys_NV_ChangeAuth.c @@ -159,6 +159,8 @@ Esys_NV_ChangeAuth_Async( esysContext, nvIndex, newAuth); TSS2L_SYS_AUTH_COMMAND auths; RSRC_NODE_T *nvIndexNode; + TPM2B_AUTH *authCopy; + TPMI_ALG_HASH hashAlg; /* Check context, sequence correctness and set state to error for now */ if (esysContext == NULL) { @@ -174,10 +176,14 @@ Esys_NV_ChangeAuth_Async( r = check_session_feasibility(shandle1, shandle2, shandle3, 1); return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); store_input_parameters(esysContext, nvIndex, newAuth); + authCopy = &esysContext->in.HierarchyChangeAuth.newAuth; /* Retrieve the metadata objects for provided handles */ r = esys_GetResourceObject(esysContext, nvIndex, &nvIndexNode); return_state_if_error(r, _ESYS_STATE_INIT, "nvIndex unknown."); + hashAlg = nvIndexNode->rsrc.misc.rsrc_nv_pub.nvPublic.nameAlg; + r = iesys_adapt_auth_value(&esysContext->crypto_backend, authCopy, hashAlg); + return_state_if_error(r, _ESYS_STATE_INIT, "Adapt auth value"); /* Initial invocation of SAPI to prepare the command buffer with parameters */ r = Tss2_Sys_NV_ChangeAuth_Prepare(esysContext->sys, diff --git a/src/tss2-esys/api/Esys_NV_DefineSpace.c b/src/tss2-esys/api/Esys_NV_DefineSpace.c index fe4e212e9..aba3833f2 100644 --- a/src/tss2-esys/api/Esys_NV_DefineSpace.c +++ b/src/tss2-esys/api/Esys_NV_DefineSpace.c @@ -200,9 +200,9 @@ Esys_NV_DefineSpace_Async( store_input_parameters(esysContext, auth, publicInfo); if (publicInfo) { - r = iesys_hash_long_auth_values(&esysContext->crypto_backend, - &esysContext->in.NV.authData, - publicInfo->nvPublic.nameAlg); + r = iesys_adapt_auth_value(&esysContext->crypto_backend, + &esysContext->in.NV.authData, + publicInfo->nvPublic.nameAlg); return_state_if_error(r, _ESYS_STATE_INIT, "Adapt auth value."); } diff --git a/src/tss2-esys/api/Esys_ObjectChangeAuth.c b/src/tss2-esys/api/Esys_ObjectChangeAuth.c index c2b95d04a..04152fae6 100644 --- a/src/tss2-esys/api/Esys_ObjectChangeAuth.c +++ b/src/tss2-esys/api/Esys_ObjectChangeAuth.c @@ -148,6 +148,11 @@ Esys_ObjectChangeAuth_Async( TSS2L_SYS_AUTH_COMMAND auths; RSRC_NODE_T *objectHandleNode; RSRC_NODE_T *parentHandleNode; + TPM2B_AUTH authCopy = + { .size = 0, + .buffer = {} + }; + TPMI_ALG_HASH hashAlg = 0; /* Check context, sequence correctness and set state to error for now */ if (esysContext == NULL) { @@ -169,6 +174,17 @@ Esys_ObjectChangeAuth_Async( r = esys_GetResourceObject(esysContext, parentHandle, &parentHandleNode); return_state_if_error(r, _ESYS_STATE_INIT, "parentHandle unknown."); + if (objectHandleNode->rsrc.rsrcType == IESYSC_KEY_RSRC) { + hashAlg = objectHandleNode->rsrc.misc.rsrc_key_pub.publicArea.nameAlg; + } + + if (newAuth) { + authCopy = *newAuth; + }; + + r = iesys_adapt_auth_value(&esysContext->crypto_backend, &authCopy, hashAlg); + return_state_if_error(r, _ESYS_STATE_INIT, "Adapt auth value"); + /* Initial invocation of SAPI to prepare the command buffer with parameters */ r = Tss2_Sys_ObjectChangeAuth_Prepare(esysContext->sys, (objectHandleNode == NULL) @@ -177,7 +193,7 @@ Esys_ObjectChangeAuth_Async( (parentHandleNode == NULL) ? TPM2_RH_NULL : parentHandleNode->rsrc.handle, - newAuth); + &authCopy); return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error."); /* Calculate the cpHash Values */ diff --git a/src/tss2-esys/esys_iutil.c b/src/tss2-esys/esys_iutil.c index 79e614371..fb89e609d 100644 --- a/src/tss2-esys/esys_iutil.c +++ b/src/tss2-esys/esys_iutil.c @@ -1653,11 +1653,28 @@ iesys_tpm_error(TSS2_RC r) (r & TSS2_RC_LAYER_MASK) == TSS2_RESMGR_RC_LAYER)); } +/** Remove trailing spaces includes auth value. + * + * Trailing zeros will be removed. + * + * @param[in,out] auth_value The auth value to be adapted. + */ +void iesys_strip_trailing_zeros(TPM2B_DIGEST *digest) +{ + /* Remove trailing zeroes */ + if (digest) { + while (digest->size > 0 && + digest->buffer[digest->size - 1] == 0) { + digest->size--; + } + } +} -/** Replace auth value with Hash for long auth values. +/** Adapt auth value. * * if the size of auth value exceeds hash_size the auth value * will be replaced with the hash of the auth value. + * Trailing zeros will be removed. * * @param[in,out] auth_value The auth value to be adapted. * @param[in] hash_alg The hash alg used for adaption. @@ -1668,37 +1685,46 @@ iesys_tpm_error(TSS2_RC r) * computation. */ TSS2_RC -iesys_hash_long_auth_values( +iesys_adapt_auth_value( ESYS_CRYPTO_CALLBACKS *crypto_cb, TPM2B_AUTH *auth_value, TPMI_ALG_HASH hash_alg) { - TSS2_RC r; + TSS2_RC r = TSS2_RC_SUCCESS; ESYS_CRYPTO_CONTEXT_BLOB *cryptoContext; TPM2B_AUTH hash2b; size_t hash_size; - r = iesys_crypto_hash_get_digest_size(hash_alg, &hash_size); - return_if_error(r, "Get digest size."); + /* Remove trailing zeroes */ + iesys_strip_trailing_zeros(auth_value); + + if (hash_alg) { + r = iesys_crypto_hash_get_digest_size(hash_alg, &hash_size); + return_if_error(r, "Get digest size."); - if (auth_value && auth_value->size > hash_size) { - /* The auth value has to be adapted. */ - r = iesys_crypto_hash_start(crypto_cb, - &cryptoContext, hash_alg); - return_if_error(r, "crypto hash start"); + if (auth_value && auth_value->size > hash_size) { + /* The auth value has to be adapted. */ + r = iesys_crypto_hash_start(crypto_cb, + &cryptoContext, hash_alg); + return_if_error(r, "crypto hash start"); - r = iesys_crypto_hash_update(crypto_cb, - cryptoContext, &auth_value->buffer[0], - auth_value->size); - goto_if_error(r, "crypto hash update", error_cleanup); + r = iesys_crypto_hash_update(crypto_cb, + cryptoContext, &auth_value->buffer[0], + auth_value->size); + goto_if_error(r, "crypto hash update", error_cleanup); - r = iesys_crypto_hash_finish(crypto_cb, - &cryptoContext, &hash2b.buffer[0], &hash_size); - goto_if_error(r, "crypto hash finish", error_cleanup); + r = iesys_crypto_hash_finish(crypto_cb, + &cryptoContext, &hash2b.buffer[0], &hash_size); + goto_if_error(r, "crypto hash finish", error_cleanup); - memcpy(&auth_value->buffer[0], &hash2b.buffer[0], hash_size); - auth_value->size = hash_size; + memcpy(&auth_value->buffer[0], &hash2b.buffer[0], hash_size); + auth_value->size = hash_size; + + /* Remove trailing zeroes */ + iesys_strip_trailing_zeros(auth_value); + } } + return r; error_cleanup: diff --git a/src/tss2-esys/esys_iutil.h b/src/tss2-esys/esys_iutil.h index 4e9cfd996..c7bb9aff4 100644 --- a/src/tss2-esys/esys_iutil.h +++ b/src/tss2-esys/esys_iutil.h @@ -171,11 +171,14 @@ TSS2_RC iesys_get_name( bool iesys_tpm_error( TSS2_RC r); -TSS2_RC iesys_hash_long_auth_values( +TSS2_RC iesys_adapt_auth_value( ESYS_CRYPTO_CALLBACKS *crypto_cb, TPM2B_AUTH *auth_value, TPMI_ALG_HASH hash_alg); +void iesys_strip_trailing_zeros( + TPM2B_AUTH *auth_value); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/tss2-esys/esys_tr.c b/src/tss2-esys/esys_tr.c index 63c7f3896..115f2f86f 100644 --- a/src/tss2-esys/esys_tr.c +++ b/src/tss2-esys/esys_tr.c @@ -479,14 +479,20 @@ Esys_TR_SetAuth(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, name_alg = esys_object->rsrc.misc.rsrc_key_pub.publicArea.nameAlg; } else if (esys_object->rsrc.rsrcType == IESYSC_NV_RSRC) { name_alg = esys_object->rsrc.misc.rsrc_nv_pub.nvPublic.nameAlg; + } else { + name_alg = TPM2_ALG_NULL; } esys_object->auth = *authValue; - /* Adapt auth value to hash for large auth values. */ + + /* Adapt auth value. */ if (name_alg != TPM2_ALG_NULL) { - r = iesys_hash_long_auth_values(&esys_context->crypto_backend, + r = iesys_adapt_auth_value(&esys_context->crypto_backend, &esys_object->auth, name_alg); return_if_error(r, "Hashing overlength authValue failed."); + } else { + iesys_strip_trailing_zeros(&esys_object->auth); } + } return TSS2_RC_SUCCESS; } diff --git a/test/integration/esys-check-auth-with-trailing-zero.int.c b/test/integration/esys-check-auth-with-trailing-zero.int.c new file mode 100644 index 000000000..a9f52e587 --- /dev/null +++ b/test/integration/esys-check-auth-with-trailing-zero.int.c @@ -0,0 +1,678 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "tss2_esys.h" + +#include "esys_iutil.h" +#define LOGMODULE test +#include "util/log.h" +#include "util/aux_util.h" + +/** This test is intended to test trailing zeros in an auth value + * + * An primary key with an auth value with trailing zeros is created. + * A key with this primary is parent is created. + * Esys_TR_SetAuth which strips the zeros is calles. + * The key is created again. + * The creation of an session where an bind key with a trailing + * zero in the auth value is tested. + * A session where the owner hierarchy is used as bind key in + * combination with Esys_HierarchyChangeAuth is tested. + * An nv index with trailing zeros in the auth value with + * trailing zeros in combination with Esys_NV_ChangeAuth + * is tested. + * + * Tested ESYS commands: + * - Esys_Create() (M) + * - Esys_CreatePrimary() (M) + * - Esys_FlushContext() (M) + * - Esys_StartAuthSession() (M) + * - Esys_PolicyAuthValue() (M) + * - Esys_PolicyCommandcode() (M) + * - Esys_PolicyGetDigest() (M) + * - Esys_NV_DefineSpace() (M) + * - Esys_NV_Write() (M) + * - Esys_NV_Read() (M) + * - Esys_NV_UndefineSpace() (M) + * - Esys_NV_ChangeAuth() (M) + + * @param[in,out] esys_context The ESYS_CONTEXT. + * @retval EXIT_FAILURE + * @retval EXIT_SUCCESS + */ + +int +test_esys_trailing_zeros_in_auth(ESYS_CONTEXT * esys_context) +{ + TSS2_RC r; + ESYS_TR primaryHandle = ESYS_TR_NONE; + ESYS_TR session = ESYS_TR_NONE; + ESYS_TR enc_session = ESYS_TR_NONE; + ESYS_TR bind_key = ESYS_TR_NONE; + ESYS_TR key = ESYS_TR_NONE; + ESYS_TR key_sign = ESYS_TR_NONE; + ESYS_TR policySession = ESYS_TR_NONE; + ESYS_TR sessionTrial = ESYS_TR_NONE; + ESYS_TR nvHandle = ESYS_TR_NONE; + + TPM2B_PUBLIC *outPublic = NULL; + TPM2B_CREATION_DATA *creationData = NULL; + TPM2B_DIGEST *creationHash = NULL; + TPMT_TK_CREATION *creationTicket = NULL; + + TPM2B_PUBLIC *outPublicEcc = NULL; + TPM2B_CREATION_DATA *creationDataEcc = NULL; + TPM2B_DIGEST *creationHashEcc = NULL; + TPMT_TK_CREATION *creationTicketEcc = NULL; + + TPM2B_PUBLIC *outPublic2 = NULL; + TPM2B_PRIVATE *outPrivate2 = NULL; + TPM2B_CREATION_DATA *creationData2 = NULL; + TPM2B_DIGEST *creationHash2 = NULL; + TPMT_TK_CREATION *creationTicket2 = NULL; + + TPM2B_PUBLIC *outPublic3 = NULL; + TPM2B_PRIVATE *outPrivate3 = NULL; + + + TPM2B_AUTH authValuePrimary = { + .size = 6, + .buffer = {1, 2, 3, 4, 5, 0} + }; + + TPM2B_SENSITIVE_CREATE inSensitivePrimary = { + .size = 0, + .sensitive = { + .userAuth = { + .size = 0, + .buffer = {0 }, + }, + .data = { + .size = 0, + .buffer = {0}, + }, + }, + }; + + inSensitivePrimary.sensitive.userAuth = authValuePrimary; + + TPM2B_PUBLIC inPublicPrimary = { + .size = 0, + .publicArea = { + .type = TPM2_ALG_ECC, + .nameAlg = TPM2_ALG_SHA256, + .objectAttributes = (TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN), + .authPolicy = { + .size = 0, + }, + .parameters.eccDetail = { + .symmetric ={ + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB}, + .scheme = { + .scheme = TPM2_ALG_NULL + }, + .curveID = TPM2_ECC_NIST_P256, + .kdf = { + .scheme = TPM2_ALG_NULL, + .details = {}} + }, + .unique.ecc = { + .x = {.size = 0,.buffer = {}}, + .y = {.size = 0,.buffer = {}}, + }, + }, + }; + + TPM2B_DATA outsideInfo = { + .size = 0, + .buffer = {}, + }; + + TPML_PCR_SELECTION creationPCR = { + .count = 0, + }; + + r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD, + ESYS_TR_NONE, ESYS_TR_NONE, &inSensitivePrimary, + &inPublicPrimary, + &outsideInfo, &creationPCR, &primaryHandle, + &outPublicEcc, &creationDataEcc, &creationHashEcc, + &creationTicketEcc); + goto_if_error(r, "Error esys create primary", error); + + TPMA_SESSION sessionAttributes; + sessionAttributes = (TPMA_SESSION_DECRYPT | + TPMA_SESSION_ENCRYPT | + TPMA_SESSION_CONTINUESESSION); + + r = Esys_TR_SetAuth(esys_context, primaryHandle, &authValuePrimary); + goto_if_error(r, "Error: TR_SetAuth", error); + + /* Test Session with bind key */ + + static const TPMT_SYM_DEF SESSION_TEMPLATE_SYM_AES_128_CFB = + { + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB, + }; + + TPM2B_PUBLIC template = + { + .size = sizeof(TPMT_PUBLIC), + .publicArea = { + .type = TPM2_ALG_KEYEDHASH, + .nameAlg = TPM2_ALG_SHA256, + .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL, + .unique.keyedHash.size = TPM2_SHA256_DIGEST_SIZE, + }, + }; + TPM2B_SENSITIVE_CREATE sensitive = + { + .size = sizeof(TPMS_SENSITIVE_CREATE), + .sensitive.data.size = 1, + .sensitive.data.buffer[0] = 1, + .sensitive.userAuth.size = 4, + .sensitive.userAuth.buffer = { 1, 2, 3, 0 }, + }; + + r = Esys_Create(esys_context, primaryHandle, ESYS_TR_PASSWORD, ESYS_TR_NONE, + ESYS_TR_NONE, &sensitive, &template, NULL, &(TPML_PCR_SELECTION) {}, + &outPrivate3 , &outPublic3, NULL, NULL, NULL); + goto_if_error(r, "Error Esys_Create", error); + + r = Esys_Load(esys_context, primaryHandle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, + outPrivate3, outPublic3, &bind_key); + goto_if_error(r, "Error Esys_Load", error); + + TPM2B_AUTH bind_key_auth = + { + .size = 4, + .buffer = { 1, 2, 3, 0, }, + }; + + r = Esys_TR_SetAuth(esys_context, bind_key, &bind_key_auth); + goto_if_error(r, "Error Esys_TR_SetAuth", error); + + r = Esys_StartAuthSession(esys_context, primaryHandle, bind_key, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, NULL, TPM2_SE_HMAC, + &SESSION_TEMPLATE_SYM_AES_128_CFB, + TPM2_ALG_SHA256, &enc_session); + goto_if_error(r, "Error Esys_StartAuthSession", error); + + r = Esys_TRSess_SetAttributes(esys_context, enc_session, sessionAttributes, 0xff); + goto_if_error(r, "Error Esys_TRSess_SetAttributes", error); + + r = Esys_StartAuthSession(esys_context, primaryHandle, ESYS_TR_NONE, + enc_session, ESYS_TR_NONE, + ESYS_TR_NONE, NULL, TPM2_SE_POLICY, + &SESSION_TEMPLATE_SYM_AES_128_CFB, + TPM2_ALG_SHA256, &session); + goto_if_error(r, "Error Esys_StartAuthSession", error); + + r = Esys_FlushContext(esys_context, enc_session); + goto_if_error(r, "Error Esys_FlushContext", error); + enc_session = ESYS_TR_NONE; + + r = Esys_FlushContext(esys_context, session); + goto_if_error(r, "Error Esys_FlushContext", error); + enc_session = ESYS_TR_NONE; + + r = Esys_FlushContext(esys_context, bind_key); + goto_if_error(r, "Error Esys_FlushContext", error); + bind_key = ESYS_TR_NONE; + + /* Test HierarchyChangeAuth */ + + TPM2B_AUTH authKey2 = { + .size = 6, + .buffer = { 6, 7, 8, 9, 10, 0 } + }; + + TPM2B_SENSITIVE_CREATE inSensitive2 = { + .size = 0, + .sensitive = { + .userAuth = { + .size = 0, + .buffer = {0} + }, + .data = { + .size = 0, + .buffer = {} + } + } + }; + + inSensitive2.sensitive.userAuth = authKey2; + + + TPM2B_AUTH newAuth = { + .size = 6, + .buffer = {6, 7, 8, 9, 10, 0 } + }; + + TPM2B_AUTH newAuth2 = { + .size = 6, + .buffer = {11, 12, 13, 14, 15, 0 } + }; + + TPM2B_PUBLIC template_parent = { + .size = 0, + .publicArea = { + .type = TPM2_ALG_RSA, + .nameAlg = TPM2_ALG_SHA256, + .objectAttributes = (TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN), + + .authPolicy = { + .size = 0, + }, + .parameters.rsaDetail = { + .symmetric = { + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB + }, + .scheme = { + .scheme = + TPM2_ALG_NULL, + }, + .keyBits = 2048, + .exponent = 0 + }, + .unique.rsa = { + .size = 0, + .buffer = {} + , + } + } + }; + + Esys_Free(outPublic3); + outPublic3 = NULL; + Esys_Free(outPrivate3); + outPrivate3 = NULL; + + r = Esys_Create(esys_context, primaryHandle, ESYS_TR_PASSWORD, ESYS_TR_NONE, + ESYS_TR_NONE, &inSensitive2, &template_parent, NULL, &(TPML_PCR_SELECTION) {}, + &outPrivate3 , &outPublic3, NULL, NULL, NULL); + goto_if_error(r, "Error Esys_Create", error); + + r = Esys_HierarchyChangeAuth(esys_context, + ESYS_TR_RH_OWNER, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, + ESYS_TR_NONE, + &newAuth); + + r = Esys_StartAuthSession(esys_context, primaryHandle, ESYS_TR_RH_OWNER, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, NULL, TPM2_SE_HMAC, + &SESSION_TEMPLATE_SYM_AES_128_CFB, + TPM2_ALG_SHA256, &session); + goto_if_error(r, "Error Esys_StartAuthSession", error); + + r = Esys_TRSess_SetAttributes(esys_context, session, sessionAttributes, 0xff); + goto_if_error(r, "Error Esys_TRSess_SetAttributes", error); + + r = Esys_Load(esys_context, primaryHandle, session, ESYS_TR_NONE, ESYS_TR_NONE, + outPrivate3, outPublic3, &key); + goto_if_error(r, "Error Esys_Load", error); + + r = Esys_HierarchyChangeAuth(esys_context, + ESYS_TR_RH_OWNER, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, + ESYS_TR_NONE, + &newAuth2); + goto_if_error(r, "Error: HierarchyChangeAuth", error); + + Esys_Free(outPublic3); + Esys_Free(outPrivate3); + + TPM2B_PUBLIC template_sign = { + .size = 0, + .publicArea = { + .type = TPM2_ALG_ECC, + .nameAlg = TPM2_ALG_SHA256, + .objectAttributes = (TPMA_OBJECT_USERWITHAUTH | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT | + TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN), + .authPolicy = { + .size = 0, + }, + .parameters.eccDetail = { + .symmetric ={ + .algorithm = TPM2_ALG_AES, + .keyBits.aes = 128, + .mode.aes = TPM2_ALG_CFB}, + .scheme = { + .scheme = TPM2_ALG_NULL + }, + .curveID = TPM2_ECC_NIST_P256, + .kdf = { + .scheme = TPM2_ALG_NULL, + .details = {}} + }, + .unique.ecc = { + .x = {.size = 0,.buffer = {}}, + .y = {.size = 0,.buffer = {}}, + }, + }, + }; + + Esys_FlushContext(esys_context, primaryHandle); + primaryHandle = ESYS_TR_NONE; + + r = Esys_TR_SetAuth(esys_context, key, &authKey2); + goto_if_error(r, "Error Esys_", error); + + r = Esys_Create(esys_context, key, ESYS_TR_PASSWORD, session, + ESYS_TR_NONE, &inSensitive2, &template_sign, NULL, &(TPML_PCR_SELECTION) {}, + &outPrivate3 , &outPublic3, NULL, NULL, NULL); + goto_if_error(r, "Error Esys_Create", error); + + r = Esys_Load(esys_context, key, session, ESYS_TR_NONE, ESYS_TR_NONE, + outPrivate3, outPublic3, &key_sign); + goto_if_error(r, "Error Esys_Load", error); + + /* Reset auth value for storage hierarchy */ + r = Esys_HierarchyChangeAuth(esys_context, + ESYS_TR_RH_OWNER, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, + ESYS_TR_NONE, + NULL); + goto_if_error(r, "Error: HierarchyChangeAuth", error); + + /* Test NV_ChangeAuth */ + + TPM2B_NV_PUBLIC *nvPublic = NULL; + TPM2B_NAME *nvName = NULL; + TPM2B_MAX_NV_BUFFER *nv_test_data2 = NULL; + TPM2B_DIGEST *policyDigestTrial = NULL; + TPMT_SYM_DEF symmetricTrial = {.algorithm = TPM2_ALG_AES, + .keyBits = {.aes = 128}, + .mode = {.aes = TPM2_ALG_CFB} + }; + TPM2B_NONCE nonceCallerTrial = { + .size = 20, + .buffer = {11, 12, 13, 14, 15, 16, 17, 18, 19, 11, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30} + }; + + r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + &nonceCallerTrial, + TPM2_SE_TRIAL, &symmetricTrial, TPM2_ALG_SHA256, + &sessionTrial); + goto_if_error(r, "Error: During initialization of policy trial session", error); + + r = Esys_PolicyAuthValue(esys_context, + sessionTrial, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE + ); + goto_if_error(r, "Error: PolicyAuthValue", error); + + r = Esys_PolicyCommandCode(esys_context, + sessionTrial, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + TPM2_CC_NV_ChangeAuth + ); + goto_if_error(r, "Error: PolicyCommandCode", error); + + r = Esys_PolicyGetDigest(esys_context, + sessionTrial, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + &policyDigestTrial + ); + goto_if_error(r, "Error: PolicyGetDigest", error); + + r = Esys_FlushContext(esys_context, sessionTrial); + goto_if_error(r, "Flushing context", error); + sessionTrial = ESYS_TR_NONE; + + TPM2B_AUTH auth = {.size = 20, + .buffer={10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 0}}; + + TPM2B_AUTH new_auth = {.size = 20, + .buffer={30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 0}}; + + TPM2B_NV_PUBLIC publicInfo = { + .size = 0, + .nvPublic = { + .nvIndex =TPM2_NV_INDEX_FIRST, + .nameAlg = TPM2_ALG_SHA256, + .attributes = ( + TPMA_NV_OWNERWRITE | + TPMA_NV_AUTHWRITE | + TPMA_NV_WRITE_STCLEAR | + TPMA_NV_READ_STCLEAR | + TPMA_NV_AUTHREAD | + TPMA_NV_OWNERREAD + ), + .authPolicy = *policyDigestTrial, + .dataSize = 32, + } + }; + + Esys_Free(policyDigestTrial); + policyDigestTrial = NULL; + + r = Esys_NV_DefineSpace(esys_context, + ESYS_TR_RH_OWNER, + session, + ESYS_TR_NONE, + ESYS_TR_NONE, + &auth, + &publicInfo, + &nvHandle); + + goto_if_error(r, "Error esys define nv space", error); + + UINT16 offset = 0; + TPM2B_MAX_NV_BUFFER nv_test_data = + { .size = 20, + .buffer= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}; + + r = Esys_NV_Write(esys_context, + nvHandle, + nvHandle, + session, + ESYS_TR_NONE, + ESYS_TR_NONE, + &nv_test_data, + offset); + + goto_if_error(r, "Error esys nv write", error); + + r = Esys_NV_Read(esys_context, + nvHandle, + nvHandle, + session, + ESYS_TR_NONE, + ESYS_TR_NONE, + 20, + 0, + &nv_test_data2); + + goto_if_error(r, "Error esys nv read", error); + + Esys_Free(nvPublic); + Esys_Free(nvName); + Esys_Free(nv_test_data2); + nv_test_data2 = NULL; + + TPMT_SYM_DEF policySymmetric = + {.algorithm = TPM2_ALG_AES, + .keyBits = {.aes = 128}, + .mode = {.aes = TPM2_ALG_CFB} + }; + + TPM2B_NONCE policyNonceCaller = { + .size = 20, + .buffer = {11, 12, 13, 14, 15, 16, 17, 18, 19, 11, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30} + }; + + r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + &policyNonceCaller, + TPM2_SE_POLICY, &policySymmetric, TPM2_ALG_SHA256, + &policySession); + goto_if_error(r, "Error: During initialization of policy trial session", error); + + r = Esys_PolicyAuthValue(esys_context, + policySession, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE + ); + goto_if_error(r, "Error: PolicyAuthValue", error); + + r = Esys_PolicyCommandCode(esys_context, + policySession, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + TPM2_CC_NV_ChangeAuth + ); + goto_if_error(r, "Error: PolicyCommandCode", error); + + r = Esys_NV_ChangeAuth(esys_context, nvHandle, policySession, + ESYS_TR_NONE, ESYS_TR_NONE, &new_auth); + goto_if_error(r, "Error Esys_NV_ChangeAuth", error); + + r = Esys_NV_Read(esys_context, + nvHandle, + nvHandle, + session, + ESYS_TR_NONE, + ESYS_TR_NONE, + 20, + 0, + &nv_test_data2); + + goto_if_error(r, "Error esys nv read", error); + + Esys_Free(nv_test_data2); + nv_test_data2 = NULL; + + r = Esys_NV_UndefineSpace(esys_context, + ESYS_TR_RH_OWNER, + nvHandle, + session, + ESYS_TR_NONE, + ESYS_TR_NONE); + goto_if_error(r, "Error: NV_UndefineSpace", error); + + nvHandle = ESYS_TR_NONE; + + error: + + if (session != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, policySession) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup session failed."); + } + } + + if (session != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, session) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup session failed."); + } + } + + if (enc_session != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, enc_session) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup session failed."); + } + } + + if (primaryHandle != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, primaryHandle) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup primaryHandle failed."); + } + } + + if (bind_key != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, bind_key) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup primaryHandle failed."); + } + } + + if (key != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, key) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup key."); + } + } + + if (key_sign != ESYS_TR_NONE) { + if (Esys_FlushContext(esys_context, key_sign) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup key2 failed."); + } + } + + if (nvHandle != ESYS_TR_NONE) { + if (Esys_NV_UndefineSpace(esys_context, + ESYS_TR_RH_OWNER, + nvHandle, + session, + ESYS_TR_NONE, + ESYS_TR_NONE) != TSS2_RC_SUCCESS) { + LOG_ERROR("Cleanup nvHandle failed."); + } + } + + Esys_Free(outPublic); + Esys_Free(creationData); + Esys_Free(creationHash); + Esys_Free(creationTicket); + Esys_Free(outPublicEcc); + Esys_Free(creationDataEcc); + Esys_Free(creationHashEcc); + Esys_Free(creationTicketEcc); + Esys_Free(outPublic2); + Esys_Free(outPrivate2); + Esys_Free(outPublic3); + Esys_Free(outPrivate3); + Esys_Free(creationData2); + Esys_Free(creationHash2); + Esys_Free(creationTicket2); + + if (r) + return EXIT_FAILURE; + else + return EXIT_SUCCESS; +} + +int +test_invoke_esys(ESYS_CONTEXT * esys_context) { + return test_esys_trailing_zeros_in_auth(esys_context); +}