You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
432 lines
14 KiB
432 lines
14 KiB
/*
|
|
* 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 "sapi-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;
|
|
}
|