diff --git a/src/tss2-esys/api/Esys_HierarchyChangeAuth.c b/src/tss2-esys/api/Esys_HierarchyChangeAuth.c index 70f7210f0..873d27d9a 100644 --- a/src/tss2-esys/api/Esys_HierarchyChangeAuth.c +++ b/src/tss2-esys/api/Esys_HierarchyChangeAuth.c @@ -175,7 +175,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); 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_ObjectChangeAuth.c b/src/tss2-esys/api/Esys_ObjectChangeAuth.c index c2b95d04a..eeee9d517 100644 --- a/src/tss2-esys/api/Esys_ObjectChangeAuth.c +++ b/src/tss2-esys/api/Esys_ObjectChangeAuth.c @@ -19,6 +19,20 @@ #include "util/log.h" #include "util/aux_util.h" +/** Store command parameters inside the ESYS_CONTEXT for use during _Finish */ +static void store_input_parameters ( + ESYS_CONTEXT *esysContext, + ESYS_TR authHandle, + const TPM2B_AUTH *newAuth) +{ + esysContext->in.ObjectChangeAuth.authHandle = authHandle; + if (newAuth == NULL) + memset(&esysContext->in.ObjectChangeAuth.newAuth, 0, + sizeof(esysContext->in.ObjectChangeAuth.newAuth)); + else + esysContext->in.ObjectChangeAuth.newAuth = *newAuth; +} + /** One-Call function for TPM2_ObjectChangeAuth * * This function invokes the TPM2_ObjectChangeAuth command in a one-call @@ -148,6 +162,8 @@ Esys_ObjectChangeAuth_Async( TSS2L_SYS_AUTH_COMMAND auths; RSRC_NODE_T *objectHandleNode; RSRC_NODE_T *parentHandleNode; + TPM2B_AUTH *authCopy; + TPMI_ALG_HASH hashAlg = 0; /* Check context, sequence correctness and set state to error for now */ if (esysContext == NULL) { @@ -163,12 +179,22 @@ Esys_ObjectChangeAuth_Async( r = check_session_feasibility(shandle1, shandle2, shandle3, 1); return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); + store_input_parameters(esysContext, objectHandle, newAuth); + /* Retrieve the metadata objects for provided handles */ r = esys_GetResourceObject(esysContext, objectHandle, &objectHandleNode); return_state_if_error(r, _ESYS_STATE_INIT, "objectHandle unknown."); 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; + } + + authCopy = &esysContext->in.ObjectChangeAuth.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 +203,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 */ @@ -247,6 +273,8 @@ Esys_ObjectChangeAuth_Finish( ESYS_CONTEXT *esysContext, TPM2B_PRIVATE **outPrivate) { + ESYS_TR authHandle; + RSRC_NODE_T *authHandleNode; TSS2_RC r; LOG_TRACE("context=%p, outPrivate=%p", esysContext, outPrivate); @@ -312,6 +340,14 @@ Esys_ObjectChangeAuth_Finish( goto error_cleanup; } + /* + * Store the new auth value in the object. + */ + authHandle = esysContext->in.ObjectChangeAuth.authHandle; + r = esys_GetResourceObject(esysContext, authHandle, &authHandleNode); + return_if_error(r, "get resource"); + + authHandleNode->auth = esysContext->in.ObjectChangeAuth.newAuth; /* * Now the verification of the response (hmac check) and if necessary the * parameter decryption have to be done. diff --git a/src/tss2-esys/esys_int.h b/src/tss2-esys/esys_int.h index 49430a606..e6c669356 100644 --- a/src/tss2-esys/esys_int.h +++ b/src/tss2-esys/esys_int.h @@ -90,6 +90,12 @@ typedef struct { TPM2B_AUTH newAuth; } HierarchyChangeAuth_IN; +typedef struct { + ESYS_TR authHandle; + TPM2B_AUTH newAuth; +} ObjectChangeAuth_IN; + + typedef struct { ESYS_TR sequenceHandle; } SequenceComplete_IN; @@ -132,6 +138,7 @@ typedef union { HMAC_Start_IN HMAC_Start; MAC_Start_IN MAC_Start; HierarchyChangeAuth_IN HierarchyChangeAuth; + ObjectChangeAuth_IN ObjectChangeAuth; SequenceComplete_IN SequenceComplete; Policy_IN Policy; NV_IN NV; diff --git a/test/integration/esys-check-auth-with-trailing-zero.int.c b/test/integration/esys-check-auth-with-trailing-zero.int.c index 908b0b2dd..a9f52e587 100644 --- a/test/integration/esys-check-auth-with-trailing-zero.int.c +++ b/test/integration/esys-check-auth-with-trailing-zero.int.c @@ -21,13 +21,26 @@ * 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 @@ -41,6 +54,11 @@ test_esys_trailing_zeros_in_auth(ESYS_CONTEXT * esys_context) 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; @@ -216,8 +234,375 @@ test_esys_trailing_zeros_in_auth(ESYS_CONTEXT * esys_context) 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."); @@ -242,6 +627,29 @@ test_esys_trailing_zeros_in_auth(ESYS_CONTEXT * esys_context) } } + 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);