blob: 5880318c64b251f2759cc7755f83e862abcb958f [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-2-Clause
* Copyright (c) 2019, Intel Corporation
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tss2_sys.h"
#include "context-util.h"
#include "sys-util.h"
#include "session-util.h"
#define LOGMODULE test
#include "util/log.h"
#define TPM20_INDEX_PASSWORD_TEST 0x01500020
#define NV_DATA_SIZE 4
#define NV_DATA { 0x00, 0xff, 0x55, 0xaa }
#define SECRET_SIZE 13
#define SECRET_DATA { 's', 'h', 'a', 'r', 'e', 'd', ' ', \
's', 'e', 'c', 'r', 'e', 't', }
TSS2_RC
create_policy (TSS2_SYS_CONTEXT *sys_ctx,
TPM2B_DIGEST *authPolicy)
{
TSS2_RC rc;
SESSION *trialPolicySession = NULL;
TPM2B_NONCE nonceCaller = { 0, };
TPM2B_ENCRYPTED_SECRET encryptedSalt = { 0, };
TPMT_SYM_DEF symmetric = {
.algorithm = TPM2_ALG_NULL,
};
TSS2_TCTI_CONTEXT *tcti_ctx;
rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
if (rc != TSS2_RC_SUCCESS || tcti_ctx == NULL) {
LOG_ERROR("InitSysContext failed, exiting...");
return rc;
}
rc = create_auth_session (&trialPolicySession,
TPM2_RH_NULL,
0,
TPM2_RH_NULL,
0,
&nonceCaller,
&encryptedSalt,
TPM2_SE_TRIAL,
&symmetric,
TPM2_ALG_SHA256,
tcti_ctx);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("create_auth_session failed with rc: 0x%x", rc);
return rc;
}
rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
trialPolicySession->sessionHandle,
0,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with rc: 0x%x", rc);
return rc;
}
rc = Tss2_Sys_PolicyGetDigest (sys_ctx,
trialPolicySession->sessionHandle,
0,
authPolicy,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_PolicyGetDigest failed with rc: 0x%x", rc);
return rc;
}
rc = Tss2_Sys_FlushContext (sys_ctx,
trialPolicySession->sessionHandle);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_FlushContext failed with rc: 0x%x", rc);
return rc;
}
end_auth_session (trialPolicySession);
return rc;
}
TSS2_RC
nv_rw_with_session (
TSS2_SYS_CONTEXT *sys_ctx,
const TPM2B_DIGEST *authPolicy,
TPMA_NV nvAttributes,
TPM2_SE session_type)
{
TSS2_RC rc;
TPM2B_AUTH nvAuth = {
.size = SECRET_SIZE,
.buffer = SECRET_DATA,
};
SESSION *nvSession = NULL;
TPM2B_NAME nvName;
TPM2B_NONCE nonceCaller = { 0, };
TPM2B_MAX_NV_BUFFER nvWriteData = {
.size = NV_DATA_SIZE,
.buffer = NV_DATA,
};
TPM2B_MAX_NV_BUFFER nvReadData = { .size = TPM2B_SIZE (nvReadData), };
TPM2B_ENCRYPTED_SECRET encryptedSalt = { 0, };
TPMT_SYM_DEF symmetric = {
.algorithm = TPM2_ALG_NULL,
};
TSS2_TCTI_CONTEXT *tcti_ctx;
TSS2L_SYS_AUTH_RESPONSE nvRspAuths;
TSS2L_SYS_AUTH_COMMAND nvCmdAuths = {
.count = 1,
.auths= {
{
.nonce = {
.size = 1,
.buffer = { 0xa5, },
},
.sessionHandle = TPM2_RS_PW,
.sessionAttributes = TPMA_SESSION_CONTINUESESSION,
}
}
};
const TSS2L_SYS_AUTH_COMMAND auth_cmd_null_pwd = {
.count = 1,
.auths = {
{
.sessionHandle = TPM2_RS_PW,
},
},
};
rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
if (rc != TSS2_RC_SUCCESS || tcti_ctx == NULL) {
LOG_ERROR ("Failed to get TCTI from Sys context, got RC: 0x%x", rc);
return TSS2_SYS_RC_GENERAL_FAILURE;
}
rc = DefineNvIndex (sys_ctx,
TPM2_RH_PLATFORM,
&nvAuth,
authPolicy,
TPM20_INDEX_PASSWORD_TEST,
TPM2_ALG_SHA256,
nvAttributes,
32);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("DefineNvIndex failed with RC: 0x%x", rc);
return rc;
}
/*
* Add index and associated authorization value to
* entity table. This helps when we need
* to calculate HMACs.
*/
rc = AddEntity(TPM20_INDEX_PASSWORD_TEST, &nvAuth);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("AddEntity failed with RC: 0x%x", rc);
return rc;
}
/* Get the name of the NV index. */
rc = tpm_handle_to_name (tcti_ctx,
TPM20_INDEX_PASSWORD_TEST,
&nvName);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("tpm_handle_to_name failed with RC: 0x%x", rc);
return rc;
}
/*
* Start HMAC or real (non-trial) policy authorization session:
* it's an unbound and unsalted session, no symmetric
* encryption algorithm, and SHA256 is the session's
* hash algorithm.
*/
rc = create_auth_session (&nvSession,
TPM2_RH_NULL,
0,
TPM2_RH_NULL,
0,
&nonceCaller,
&encryptedSalt,
session_type,
&symmetric,
TPM2_ALG_SHA256,
tcti_ctx);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("create_auth_session failed with RC: 0x%x", rc);
return rc;
}
/* set handle in command auth */
nvCmdAuths.auths[0].sessionHandle = nvSession->sessionHandle;
/*
* Get the name of the session and save it in
* the nvSession structure.
*/
rc = tpm_handle_to_name (tcti_ctx,
nvSession->sessionHandle,
&nvSession->name);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("tpm_handle_to_name failed with RC: 0x%x", rc);
return rc;
}
/*
* Now setup for writing the NV index.
*/
if (session_type == TPM2_SE_POLICY) {
rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
nvSession->sessionHandle,
0,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with RC: 0x%x", rc);
return rc;
}
}
/* First call prepare in order to create cpBuffer. */
rc = Tss2_Sys_NV_Write_Prepare (sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
&nvWriteData,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_NV_Write_Prepare failed with RC: 0x%x", rc);
return rc;
}
/* Roll nonces for command */
roll_nonces (nvSession, &nvCmdAuths.auths[0].nonce);
/*
* Complete command authorization area, by computing
* HMAC and setting it in nvCmdAuths.
*/
rc = compute_command_hmac(sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
TPM2_RH_NULL,
&nvCmdAuths);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("compute_command_hmac failed with RC: 0x%x", rc);
return rc;
}
/*
* Finally!! Write the data to the NV index.
* If the command is successful, the command
* HMAC was correct.
*/
rc = TSS2_RETRY_EXP (Tss2_Sys_NV_Write (sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
&nvCmdAuths,
&nvWriteData,
0,
&nvRspAuths));
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_NV_Write failed with RC: 0x%x", rc);
return rc;
}
/* Roll nonces for response */
roll_nonces (nvSession, &nvRspAuths.auths[0].nonce);
/*
* If the command was successful, check the
* response HMAC to make sure that the
* response was received correctly.
*/
rc = check_response_hmac (sys_ctx,
&nvCmdAuths,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
TPM2_RH_NULL,
&nvRspAuths);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("check_response_hmac failed with RC: 0x%x", rc);
return rc;
}
if (session_type == TPM2_SE_POLICY) {
rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
nvSession->sessionHandle,
0,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with RC: 0x%x", rc);
return rc;
}
}
/* First call prepare in order to create cpBuffer. */
rc = Tss2_Sys_NV_Read_Prepare (sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
NV_DATA_SIZE,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_NV_Read_Prepare failed with RC: 0x%x", rc);
return rc;
}
roll_nonces (nvSession, &nvCmdAuths.auths[0].nonce);
/* End the session after next command. */
nvCmdAuths.auths[0].sessionAttributes &= ~TPMA_SESSION_CONTINUESESSION;
/*
* Complete command authorization area, by computing
* HMAC and setting it in nvCmdAuths.
*/
rc = compute_command_hmac (sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
TPM2_RH_NULL,
&nvCmdAuths);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("compute_command_hmac failed with RC: 0x%x", rc);
return rc;
}
/*
* And now read the data back.
* If the command is successful, the command
* HMAC was correct.
*/
rc = Tss2_Sys_NV_Read (sys_ctx,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
&nvCmdAuths,
NV_DATA_SIZE,
0,
&nvReadData,
&nvRspAuths);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_NV_Read failed with RC: 0x%x", rc);
return rc;
}
/* Roll nonces for response */
roll_nonces (nvSession, &nvRspAuths.auths[0].nonce);
/*
* If the command was successful, check the
* response HMAC to make sure that the
* response was received correctly.
*/
rc = check_response_hmac (sys_ctx,
&nvCmdAuths,
TPM20_INDEX_PASSWORD_TEST,
TPM20_INDEX_PASSWORD_TEST,
TPM2_RH_NULL,
&nvRspAuths);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("check_response_hmac failed with RC: 0x%x", rc);
return rc;
}
/* Check that write and read data are equal. */
if (memcmp ((void *)&nvReadData.buffer[0],
(void *)&nvWriteData.buffer[0],
nvReadData.size))
{
LOG_ERROR ("Data read not equal to data written.");
return 1;
}
/*
* Now cleanup: undefine the NV index and delete
* the NV index's entity table entry.
*/
/* Undefine the NV index. */
rc = Tss2_Sys_NV_UndefineSpace (sys_ctx,
TPM2_RH_PLATFORM,
TPM20_INDEX_PASSWORD_TEST,
&auth_cmd_null_pwd,
0);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR ("Tss2_Sys_NV_UndefineSpace failed with RC: 0x%x", rc);
return rc;
}
/* Delete the NV index's entry in the entity table. */
DeleteEntity (TPM20_INDEX_PASSWORD_TEST);
/* Remove the real session from sessions table. */
end_auth_session (nvSession);
return rc;
}
int
test_invoke (TSS2_SYS_CONTEXT *sys_ctx)
{
TSS2_RC rc;
TPM2B_DIGEST authPolicy = { 0, };
TPMA_NV nvAttributes;
LOG_INFO ("HMAC session test");
nvAttributes = TPMA_NV_AUTHREAD | TPMA_NV_AUTHWRITE | TPMA_NV_PLATFORMCREATE;
rc = nv_rw_with_session (sys_ctx, &authPolicy, nvAttributes, TPM2_SE_HMAC);
if (rc != TSS2_RC_SUCCESS)
return rc;
LOG_INFO ("Policy session test");
authPolicy.size = TPM2B_SIZE (authPolicy);
rc = create_policy (sys_ctx, &authPolicy);
if (rc != TSS2_RC_SUCCESS)
return rc;
nvAttributes = TPMA_NV_POLICYREAD | TPMA_NV_POLICYWRITE | TPMA_NV_PLATFORMCREATE;
rc = nv_rw_with_session (sys_ctx, &authPolicy, nvAttributes, TPM2_SE_POLICY);
if (rc != TSS2_RC_SUCCESS)
return rc;
return TSS2_RC_SUCCESS;
}