From 63cdb71769f8cada8650fd0d47174f40a49e5bce 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. 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_NV_DefineSpace.c | 6 +- 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 | 270 ++++++++++++++++++ 9 files changed, 343 insertions(+), 30 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_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/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..908b0b2dd --- /dev/null +++ b/test/integration/esys-check-auth-with-trailing-zero.int.c @@ -0,0 +1,270 @@ +/* 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. + * + * Tested ESYS commands: + * - Esys_Create() (M) + * - Esys_CreatePrimary() (M) + * - Esys_FlushContext() (M) + * - Esys_StartAuthSession() (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; + + 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; + + error: + + 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."); + } + } + + 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); +}