接前一篇文章:tpm2-tools源码分析之tpm2_create.c(2)
本文对tpm2_create.c中的tpm2_tool_onrun函数进行详细解析。
先再次贴出该函数源码:
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_ call
*/
rc = create(ectx);
if (rc != tool_rc_success) {
return rc;
}
/*
* 4. Process outputs
*/
return process_output(ectx);
}
根据tpm2_tool_onrun函数中的注释,此函数分为4个步骤即调用了4个函数:check_options、process_inputs、load、process_outputs。实际上这个流程也是一个通用流程。
(1)check_options函数
check_option函数的作用是选项检查与处理。它在同文件(tpm2_create.c)中,代码如下:
static tool_rc check_options(void) {
if (!ctx.parent.ctx_path) {
LOG_ERR("Must specify parent object via -C.");
return tool_rc_option_error;
}
if (ctx.object.is_sealing_input_specified && ctx.object.is_object_alg_specified) {
LOG_ERR("Cannot specify -G and -i together.");
return tool_rc_option_error;
}
if (ctx.cp_hash_path && !ctx.rp_hash_path &&
(ctx.object.public_path || ctx.object.private_path ||
ctx.object.creation_data_file || ctx.object.creation_hash_file ||
ctx.object.creation_ticket_file || ctx.object.ctx_path)) {
LOG_ERR("CpHash Error: Cannot specify pub, priv, creation - data, hash, ticket");
return tool_rc_option_error;
}
if (ctx.format_set && !ctx.output_path) {
LOG_ERR("Cannot specify --format/-f without specifying --output/-o");
return tool_rc_option_error;
}
return tool_rc_success;
}
重点说一下ctx。ctx在同文件(tools/tpm2_create.c)中定义并初始化,代码如下:
#define DEFAULT_KEY_ALG "rsa2048"
static tpm_create_ctx ctx = {
.object = {
.alg = DEFAULT_KEY_ALG,
.creation_pcr = { .count = 0 },
.object_handle = ESYS_TR_NONE,
.outside_info.size = 0,
},
.aux_session_handle[0] = ESYS_TR_NONE,
.aux_session_handle[1] = ESYS_TR_NONE,
.cp_hash.size = 0,
.is_command_dispatch = true,
.parameter_hash_algorithm = TPM2_ALG_ERROR,
.format = pubkey_format_tss,
};
ctx是tpm_create_ctx结构的成员,该结构也在同文件中定义,代码如下:
typedef struct tpm_create_ctx tpm_create_ctx;
#define MAX_AUX_SESSIONS 2
#define MAX_SESSIONS 3
struct tpm_create_ctx {
/*
* Inputs
*/
struct {
const char *ctx_path;
const char *auth_str;
tpm2_loaded_object object;
} parent;
struct {
char *sealed_data;
char *auth_str;
TPM2B_SENSITIVE_CREATE sensitive;
TPM2B_PUBLIC in_public;
TPM2B_DATA outside_info;
TPML_PCR_SELECTION creation_pcr;
char *outside_info_data;
char *alg;
char *attrs;
char *name_alg;
char *policy;
bool is_object_alg_specified;
bool is_sealing_input_specified;
/*
* Outputs
*/
char *public_path;
TPM2B_PUBLIC *out_public;
const char *ctx_path;
char *private_path;
TPM2B_PRIVATE *out_private;
char *creation_data_file;
TPM2B_CREATION_DATA *creation_data;
char *creation_hash_file;
TPM2B_DIGEST *creation_hash;
char *creation_ticket_file;
TPMT_TK_CREATION *creation_ticket;
char *template_data_path;
ESYS_TR object_handle;
} object;
bool is_createloaded;
/*
* Parameter hashes
*/
const char *cp_hash_path;
TPM2B_DIGEST cp_hash;
const char *rp_hash_path;
TPM2B_DIGEST rp_hash;
TPMI_ALG_HASH parameter_hash_algorithm;
bool is_command_dispatch;
/*
* Aux sessions
*/
uint8_t aux_session_cnt;
tpm2_session *aux_session[MAX_AUX_SESSIONS];
const char *aux_session_path[MAX_AUX_SESSIONS];
ESYS_TR aux_session_handle[MAX_AUX_SESSIONS];
/*
* Formated public key output
*/
char *output_path;
bool format_set;
tpm2_convert_pubkey_fmt format;
};
回到check_options函数中,一上来先做检查,要求ctx.parent.ctx_path(要创建的对象的父级)必须不能为空。接下来要求ctx.object.is_sealing_input_specified(要密封的数据文件)和ctx.object.is_object_alg_specified(与此对象关联的密钥算法)不能同时指定。
再往下是一个大段判断,意思是当ctx.cp_hash_path(记录命令参数哈希的文件路径)不为空即被指定,并且ctx.rp_hash_path(记录响应参数哈希的文件路径)为空即未被指定时,ctx.object.public_path(包含已创建对象的公共部分的输出文件)、ctx.object.private_path(包含对象敏感部分的输出文件)、ctx.object.creation_data_file(保存创建数据以供认证的文件)、ctx.object.creation_hash_file(用于保存创建哈希以供认证的文件)、ctx.object.creation_ticket_file(保存创建ticket以供认证的文件)、ctx.object.ctx_path(包含密钥上下文的输出文件)都必须为空。
ctx.cp_hash_path、ctx.rp_hash_path等成员均在tpm2_tool_onstart函数中的tpm2_options_new函数中设置的on_option函数中赋值(详见前一篇文章)。实际上是要求命令行在带有“--cphash=FILE”且为带有“--rphash=FILE”时必须不能带有“--public=FILE(-u FILE)”、--private=FILE(-r FILE)”、“--creation-data=FILE”、“--creation-hash=FILE(-d FILE)”、“--creation-ticket=FILE(-t FILE)”、“--key-context=FILE(-c FILE)”。
接下来继续进行参数检查。要求当ctx.format_set(公钥输出文件的格式选择)不为空时ctx.output_path(记录对象的公共部分的文件路径)必须也不为空。ctx.format_set、ctx.output_path也是在tpm2_tool_onstart函数中的tpm2_options_new函数中设置的on_option函数中赋值(详见前一篇文章)。实际上是要求命令行在带有“--format=FILE(-f FILE)”时必须带有“---output=FILE(-o FILE)”。
至此,tpm2_tool_onrun函数的第1个函数check_options函数就分析完了。下一篇文章起分析余下的函数。