TPM 2.0中的tpm2_getrandom命令对应的源文件就是tpm2_getrandom.c,该文件位于tpm2-tools/tools/下,一共有402行(版本5.5)。
下边用几篇文章的篇幅对tpm2_getrandom.c文件结合tpm2_getrandom命令进行深入的、完全的解析。
tpm2-tools代码链接:GitHub - tpm2-software/tpm2-tools: The source repository for the Trusted Platform Module (TPM2.0) tools
先来看第一段代码:
// Register this tool with tpm2_tool.c
TPM2_TOOL_REGISTER("getrandom", tpm2_tool_onstart, tpm2_tool_onrun,
tpm2_tool_onstop, NULL)
TPM2_TOOL_REGISTER是一个宏定义,在tpm2-tools/tools/tpm2_tool.h中,代码如下:
#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); \}
TPM2_TOOLS_REGISTER宏定义是整个tpm2-tools中的命令所共用的,是一个框架性质的代码。
在本文件tpm2_getrandom.c也可以说tpm2_getrandom命令中,宏展开后为:
static const tpm2_tool tool = { .name = getrandom, .onstart = tpm2_tool_onstart, .onrun = tpm2_tool_onrun, .onstop = tpm2_tool_onstop, .onexit = 0, };
static void
__attribute__((__constructor__))
__attribute__((__used__))
_tpm2_tool_init(void)
{ tpm2_tool_register(&tool);
}
tpm2_tool结构的定义也在tpm2-tools/tools/tpm2_tool.h中,代码如下:
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;
其中包含的相关函数指针如下(同文件中,就在上边):
/*** 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);
tpm2_tool_register函数在tpm2-tools/tools/tpm2_tools.c中实现,代码如下:
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();}
}
回到tpm2_getrandom.c,来看具体的几个函数。
(1)tpm2_tool_onstart
tpm2_tool_onstart函数代码如下:
static bool tpm2_tool_onstart(tpm2_options **opts) {const struct option topts[] = {{ "output", required_argument, NULL, 'o' },{ "force", required_argument, NULL, 'f' },{ "hex", no_argument, NULL, 0 },{ "session", required_argument, NULL, 'S' },{ "cphash", required_argument, NULL, 1 },{ "rphash", required_argument, NULL, 2 }};*opts = tpm2_options_new("S:o:f", ARRAY_LEN(topts), topts, on_option, on_args,0);return *opts != NULL;
}
(2)tpm2_tool_onrun
tpm2_tool_onrun函数代码如下:
static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {UNUSED(flags);/** 1. Process options*//** 2. Process inputs*/tool_rc rc = process_inputs(ectx);if (rc != tool_rc_success) {return rc;}/** 3. TPM2_CC_ call*/rc = get_random(ectx);if (rc != tool_rc_success) {return rc;}/** 4. Process outputs*/return process_outputs();
}
(3)tpm2_tool_onstop
tpm2_tool_onstop函数代码如下:
static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {UNUSED(ectx);/** 1. Free objects*//** 2. Close authorization sessions*//** 3. Close auxiliary sessions*/tool_rc rc = tool_rc_success;tool_rc tmp_rc = tool_rc_success;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;
}
后续文章对这几个函数进行深入解析。