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..4fa81cc91 100644 --- a/src/tss2-esys/esys_tr.c +++ b/src/tss2-esys/esys_tr.c @@ -481,12 +481,18 @@ Esys_TR_SetAuth(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, name_alg = esys_object->rsrc.misc.rsrc_nv_pub.nvPublic.nameAlg; } esys_object->auth = *authValue; + /* Adapt auth value to hash for large auth values. */ 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."); } + /* Remove trailing zeroes */ + while (esys_object->auth.size > 0 && + esys_object->auth.buffer[esys_object->auth.size - 1] == 0) { + esys_object->auth.size--; + } } 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..fbb0aa260 --- /dev/null +++ b/test/integration/esys-check-auth-with-trailing-zero.int.c @@ -0,0 +1,352 @@ +/* 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_SetAut which strips the zeros is calles. + * The key is created again. + * + * 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; + + 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_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 inPublicEcc = { + .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 = {}}, + }, + }, + }; + LOG_INFO("\nECC key will be created."); + + 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, &inPublicEcc, + &outsideInfo, &creationPCR, &primaryHandle, + &outPublicEcc, &creationDataEcc, &creationHashEcc, + &creationTicketEcc); + goto_if_error(r, "Error esys create primary", error); + + + TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES, + .keyBits = {.aes = 128}, + .mode = {.aes = TPM2_ALG_CFB}}; + + TPMA_SESSION sessionAttributes; + sessionAttributes = (TPMA_SESSION_DECRYPT | + TPMA_SESSION_ENCRYPT | + TPMA_SESSION_CONTINUESESSION); + TPM2_SE sessionType = TPM2_SE_HMAC; + TPMI_ALG_HASH authHash = TPM2_ALG_SHA256; + + r = Esys_StartAuthSession(esys_context, + primaryHandle, + ESYS_TR_NONE, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + NULL, + sessionType, &symmetric, authHash, &enc_session); + + goto_if_error(r, "Error Esys_StartAuthSession enc_session", error); + + goto_if_error(r, "Error Esys_StartAuthSessiony", 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, + sessionType, &symmetric, authHash, &session); + + goto_if_error(r, "Error Esys_StartAuthSessiony", error); + r = Esys_TRSess_SetAttributes(esys_context, session, sessionAttributes, + 0xff); + goto_if_error(r, "Error Esys_TRSess_SetAttributes", error); + + TPM2B_AUTH authKey2 = { + .size = 6, + .buffer = {6, 7, 8, 9, 10, 11} + }; + + TPM2B_SENSITIVE_CREATE inSensitive2 = { + .size = 0, + .sensitive = { + .userAuth = { + .size = 0, + .buffer = {0} + }, + .data = { + .size = 0, + .buffer = {} + } + } + }; + + inSensitive2.sensitive.userAuth = authKey2; + + TPM2B_PUBLIC inPublic2 = { + .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 = {} + , + } + } + }; + + TPM2B_DATA outsideInfo2 = { + .size = 0, + .buffer = {} + , + }; + + TPML_PCR_SELECTION creationPCR2 = { + .count = 0, + }; + + r = Esys_Create(esys_context, + primaryHandle, + session, + ESYS_TR_NONE, ESYS_TR_NONE, + &inSensitive2, + &inPublic2, + &outsideInfo2, + &creationPCR2, + &outPrivate2, + &outPublic2, + &creationData2, &creationHash2, &creationTicket2); + goto_if_error(r, "Error esys create with trailing zero", error); + + Esys_Free(outPublic2); + Esys_Free(outPrivate2); + Esys_Free(creationData2); + Esys_Free(creationTicket2); + Esys_Free(creationHash2); + + r = Esys_Create(esys_context, + primaryHandle, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, ESYS_TR_NONE, + &inSensitive2, + &inPublic2, + &outsideInfo2, + &creationPCR2, + &outPrivate2, + &outPublic2, + &creationData2, &creationHash2, &creationTicket2); + goto_if_error(r, "Error esys create with trailing zero", error); + + Esys_Free(outPublic2); + Esys_Free(outPrivate2); + Esys_Free(creationData2); + Esys_Free(creationTicket2); + Esys_Free(creationHash2); + + r = Esys_TR_SetAuth(esys_context, primaryHandle, &authValuePrimary); + goto_if_error(r, "Error: TR_SetAuth", error); + + r = Esys_Create(esys_context, + primaryHandle, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, ESYS_TR_NONE, + &inSensitive2, + &inPublic2, + &outsideInfo2, + &creationPCR2, + &outPrivate2, + &outPublic2, + &creationData2, &creationHash2, &creationTicket2); + goto_if_error(r, "Error esys create with trailing zero", error); + + Esys_Free(outPublic2); + Esys_Free(outPrivate2); + Esys_Free(creationData2); + Esys_Free(creationTicket2); + Esys_Free(creationHash2); + + r = Esys_Create(esys_context, + primaryHandle, + session, + ESYS_TR_NONE, ESYS_TR_NONE, + &inSensitive2, + &inPublic2, + &outsideInfo2, + &creationPCR2, + &outPrivate2, + &outPublic2, + &creationData2, &creationHash2, &creationTicket2); + goto_if_error(r, "Error esys create without trailing zero ", error); + + 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."); + } + } + + 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(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); +}