接前一篇文章:tpm2-tools源码分析之tpm2_load.c(2)
本文对tpm2_load.c中的tpm2_tool_onrun函数进行i详细解析。
先再次贴出该函数源码:
static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {UNUSED(flags);/** 1. Process options*/tool_rc rc = check_options(ectx);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 = load(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_options函数的作用是选项检查与处理。它在同文件(tpm2_load.c)中,代码如下:
static tool_rc check_options(ESYS_CONTEXT *ectx) {UNUSED(ectx);tool_rc rc = tool_rc_success;if (!ctx.object.privpath) {LOG_ERR("Expected private object portion via -r");rc = tool_rc_option_error;}/** Check for TSS PEM file input:* 1. It is specified with the -r,--private option alone.* 2. The parent and public objects are implicit and read directly from* the TSS PEM.*/ctx.is_tss_pem =(!ctx.parent.ctx_path && !ctx.object.pubpath && ctx.object.privpath);if (!ctx.is_tss_pem) {if (!ctx.parent.ctx_path) {LOG_ERR("Expected parent object via -C or a PEM file with -r");rc = tool_rc_option_error;}if (!ctx.object.pubpath) {LOG_ERR("Expected public object portion via -u or a PEM file with -r");rc = tool_rc_option_error;}}if (!ctx.contextpath && !ctx.cp_hash_path) {LOG_ERR("Expected option -c");rc = tool_rc_option_error;}if (ctx.contextpath && ctx.cp_hash_path) {LOG_ERR("Cannot output contextpath when calculating cp_hash");rc = tool_rc_option_error;}return rc;
}
重点说一下ctx。ctx在同文件(tools/tpm2_load.c)中定义并初始化,代码如下:
static tpm_load_ctx ctx = {.parameter_hash_algorithm = TPM2_ALG_ERROR,
};
ctx是tpm_load_ctx结构的成员,该结构也在同文件中定义,代码如下:
typedef struct tpm_tool_ctx tpm_load_ctx;
struct tpm_tool_ctx {/** Inputs*/struct {const char *ctx_path;const char *auth_str;tpm2_loaded_object object;} parent;struct {const char *pubpath;TPM2B_PUBLIC public;const char *privpath;TPM2B_PRIVATE private;ESYS_TR handle;} object;bool is_tss_pem;/** Outputs*/const char *namepath;const char *contextpath;/** Parameter hashes*/const char *cp_hash_path;TPM2B_DIGEST cp_hash;bool is_command_dispatch;TPMI_ALG_HASH parameter_hash_algorithm;
};
回到check_options函数中,一上来先做检查,要求ctx.object.privpath不能为空。ctx.object.privpath在tpm2_tool_onstart函数中的tpm2_options_new函数中设置的on_option函数中赋值(详见前一篇文章)。实际上是要求命令行必须带有“-r FILE”或“--private=FILE”。
接下来检查TSS PEM文件输入。代码片断如下:
/** Check for TSS PEM file input:* 1. It is specified with the -r,--private option alone.* 2. The parent and public objects are implicit and read directly from* the TSS PEM.*/ctx.is_tss_pem =(!ctx.parent.ctx_path && !ctx.object.pubpath && ctx.object.privpath);
ctx.is_tss_pem的值只在ctx.parent.ctx_path为空并且ctx.object.pubpath为空并且ctx.object.privpath不为空的情况下才能为真,其它情况都为假。ctx.object.privpath上边检查中已经保证了;ctx.parent.ctx_path的值是通过命令行带上“-C OBJECT”或“--parent-context=OBJECT”选项传入的;而ctx.object.pubpath则是通过命令行带上“-u FILE”或“--public=FILE”选项传入的。
接下来,如果ctx.is_tss_pem为假,则要求ctx.parent.ctx_path必须不为空并且tx.object.pubpath也必须不为空,即命令行中必须带有“-C OBJECT”或“--parent-context=OBJECT”和-u FILE”或“--public=FILE”。
最后检查的ctx.contextpath与ctx.cp_hash_path之间的相互约束,代码片断如下:
if (!ctx.contextpath && !ctx.cp_hash_path) {LOG_ERR("Expected option -c");rc = tool_rc_option_error;}if (ctx.contextpath && ctx.cp_hash_path) {LOG_ERR("Cannot output contextpath when calculating cp_hash");rc = tool_rc_option_error;}
ctx.contextpath和ctx.cp_hash_path不能同时为空,也不能同时不为空。这就是说命令行选项中“-c, --key-context=FILE”与“--cphash=FILE”必须指定其一。
至此,tpm2_tool_onrun函数的第1个函数check_options函数就分析完了。下一篇文章起分析余下的函数。