The source file corresponding to the tpm2_create command in TPM 2.0 is tpm2_create.c, which is located under tpm2-tools/tools/ and has a total of 671 lines (version 5.5).
The function of tpm2_create is to create a key. The command description is: Create a child object. This object can be a key or a seal object. The Seal object allows sealing user data to the TPM with a maximum size of 128 bytes. Also, if -c is specified, it will load the created object.
The following uses the length of several articles to conduct an in-depth and complete analysis of the tpm2_create.c file combined with the tpm2_create command.
Let's look at the first piece of code:
// Register this tool with tpm2_tool.c
TPM2_TOOL_REGISTER("create", tpm2_tool_onstart, tpm2_tool_onrun,
tpm2_tool_onstop, NULL)
TPM2_TOOL_REGISTER is a macro definition, in tpm2-tools/tools/tpm2_tool.h, the code is as follows:
#define TPM2_TOOL_REGISTER(tool_name,tool_onstart,tool_onrun,tool_onstop,tool_onexit) \
static const tpm2_tool tool = { \
.name = tool_name, \
.onstart = tool_onstart, \
.onrun = tool_onrun, \
.onstop = tool_onstop, \
.onexit = tool_onexit, \
}; \
static void \
__attribute__((__constructor__)) \
__attribute__((__used__)) \
_tpm2_tool_init(void) \
{ \
tpm2_tool_register(&tool); \
}
The TPM2_TOOLS_REGISTER macro definition is shared by commands in the entire tpm2-tools and is a framework code.
In this file tpm2_create.c, it can also be said that in the tpm2_create command, the expanded macro is:
static const tpm2_tool tool = {
.name = create,
.onstart = tool_onstart,
.onrun = tool_onrun,
.onstop = tool_onstop,
.onexit = NULL,
};
static void
__attribute__((__constructor__))
__attribute__((__used__))
_tpm2_tool_init(void)
{
tpm2_tool_register(&tool);
}
The definition of the tpm2_tool structure is also in tpm2-tools/tools/tpm2_tool.h, the code is as follows:
typedef struct {
const char * name;
tpm2_tool_onstart_t onstart;
tpm2_tool_onrun_t onrun;
tpm2_tool_onstop_t onstop;
tpm2_tool_onexit_t onexit;
} tpm2_tool;
The relevant function pointers contained in it are as follows (in the same file, just above):
/**
* An optional interface for tools to specify what options they support.
* They are concatenated with main's options and passed to getopt_long.
* @param opts
* The callee can choose to set *opts to a tpm_options pointer allocated
* via tpm2_options_new(). Setting *opts to NULL is not an error, and
* Indicates that no options are specified by the tool.
*
* @return
* True on success, false on error.
*/
typedef bool (*tpm2_tool_onstart_t)(tpm2_options **opts);
/**
* This is the main interface for tools, after tcti and sapi/esapi initialization
* are performed.
* @param ectx
* The system/esapi api context.
* @param flags
* Flags that tools may wish to respect.
* @return
* A tool_rc indicating status.
*/
typedef tool_rc (*tpm2_tool_onrun_t)(ESYS_CONTEXT *ectx, tpm2_option_flags flags);
/**
* Called after tpm2_tool_onrun() is invoked. ESAPI context is still valid during this call.
* @param ectx
* The system/esapi api context.
* @return
* A tool_rc indicating status.
*/
typedef tool_rc (*tpm2_tool_onstop_t)(ESYS_CONTEXT *ectx);
/**
* Called when the tool is exiting, useful for cleanup.
*/
typedef void (*tpm2_tool_onexit_t)(void);
The tpm2_tool_register function is implemented in tpm2-tools/tools/tpm2_tools.c, the code is as follows:
/*
* Build a list of the TPM2 tools linked into this executable
*/
#ifndef TPM2_TOOLS_MAX
#define TPM2_TOOLS_MAX 1024
#endif
static const tpm2_tool *tools[TPM2_TOOLS_MAX];
static unsigned tool_count;
void tpm2_tool_register(const tpm2_tool *tool) {
if (tool_count < TPM2_TOOLS_MAX) {
tools[tool_count++] = tool;
} else {
LOG_ERR("Over tool count");
abort();
}
}
Go back to tpm2_create.c to see the specific functions.
(1)tpm2_tool_onstart
The tpm2_tool_onstart function code is as follows:
static bool tpm2_tool_onstart(tpm2_options **opts) {
static struct option topts[] = {
{ "parent-auth", required_argument, NULL, 'P' },
{ "key-auth", required_argument, NULL, 'p' },
{ "hash-algorithm", required_argument, NULL, 'g' },
{ "key-algorithm", required_argument, NULL, 'G' },
{ "attributes", required_argument, NULL, 'a' },
{ "sealing-input", required_argument, NULL, 'i' },
{ "policy", required_argument, NULL, 'L' },
{ "public", required_argument, NULL, 'u' },
{ "private", required_argument, NULL, 'r' },
{ "parent-context", required_argument, NULL, 'C' },
{ "key-context", required_argument, NULL, 'c' },
{ "creation-data", required_argument, NULL, 0 },
{ "template-data", required_argument, NULL, 1 },
{ "creation-ticket",required_argument, NULL, 't' },
{ "creation-hash", required_argument, NULL, 'd' },
{ "outside-info", required_argument, NULL, 'q' },
{ "pcr-list", required_argument, NULL, 'l' },
{ "cphash", required_argument, NULL, 2 },
{ "rphash", required_argument, NULL, 3 },
{ "session", required_argument, NULL, 'S' },
{ "format", required_argument, NULL, 'f' },
{ "output", required_argument, NULL, 'o' },
};
*opts = tpm2_options_new("P:p:g:G:a:i:L:u:r:C:c:t:d:q:l:S:o:f:",
ARRAY_LEN(topts), topts, on_option, NULL, 0);
return *opts != NULL;
}
(2)tpm2_tool_onrun
The tpm2_tool_onrun function code is as follows:
static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
UNUSED(flags);
/*
* 1. Process options
*/
tool_rc rc = check_options();
if (rc != tool_rc_success) {
return rc;
}
/*
* 2. Process inputs
*/
rc = process_inputs(ectx);
if (rc != tool_rc_success) {
return rc;
}
/*
* 3. TPM2_CC_<command> call
*/
rc = create(ectx);
if (rc != tool_rc_success) {
return rc;
}
/*
* 4. Process outputs
*/
return process_output(ectx);
}
(3)tpm2_tool_onstop
The tpm2_tool_onstop function code is as follows:
static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {
UNUSED(ectx);
/*
* 1. Free objects
*/
/*
* 2. Close authorization sessions
*/
tool_rc rc = tool_rc_success;
tool_rc tmp_rc = tpm2_session_close(&ctx.parent.object.session);
if (tmp_rc != tool_rc_success) {
rc = tmp_rc;
}
/*
* 3. Close auxiliary sessions
*/
size_t i = 0;
for(i = 0; i < ctx.aux_session_cnt; i++) {
if (ctx.aux_session_path[i]) {
tmp_rc = tpm2_session_close(&ctx.aux_session[i]);
if (tmp_rc != tool_rc_success) {
rc = tmp_rc;
}
}
}
return rc;
}
(4)tpm2_tool_onexit
The tpm2_tool_onexit function is not implemented in tpm2_create.c, that is, the tpm2_create command (the value passed in for TPM2_TOOL_REGISTER is NULL).