接前一篇文章:tpm2-tools源码分析之tpm2_hash.c(1)
本文对tpm2_hash.c中的tpm2_tool_onstart函数进行详细解析。
先再次贴出该函数源码:
static bool tpm2_tool_onstart(tpm2_options **opts) {
static struct option topts[] = {
{"hierarchy", required_argument, NULL, 'C'},
{"hash-algorithm", required_argument, NULL, 'g'},
{"output", required_argument, NULL, 'o'},
{"ticket", required_argument, NULL, 't'},
{"hex", no_argument, NULL, 0 },
};
/* set up non-static defaults here */
ctx.input_file = stdin;
*opts = tpm2_options_new("C:g:o:t:", ARRAY_LEN(topts), topts, on_option,
on_args, 0);
return *opts != NULL;
}
tpm2_options结构的定义在tpm2-tools/lib/tpm2_options.h中,代码如下:
struct tpm2_options {
struct {
tpm2_option_handler on_opt;
tpm2_arg_handler on_arg;
} callbacks;
char *short_opts;
size_t len;
uint32_t flags;
struct option long_opts[];
};
typedef struct tpm2_options tpm2_options;
struct option的定义在/usr/include/bits/getopt_ext.h中,代码如下:
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
on_option函数的实现在同文件(tools/tpm2_hash.c)中,如下:
static bool on_option(char key, char *value) {
bool res;
switch (key) {
case 'C':
res = tpm2_util_handle_from_optarg(value, &ctx.hierarchy_value,
TPM2_HANDLE_FLAGS_ALL_HIERACHIES);
if (!res) {
return false;
}
break;
case 'g':
ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash);
if (ctx.halg == TPM2_ALG_ERROR) {
return false;
}
break;
case 'o':
ctx.output_hash_path = value;
break;
case 't':
ctx.output_ticket_path = value;
break;
case 0:
ctx.hex = true;
break;
}
return true;
}
要更好地理解这些选项乃至tpm2_tool_onstart函数的功能,需要与tpm2_hash命令的说明相结合来看。tpm2_hash命令的详细说明参见:
tpm2-tools/tpm2_hash.1.md at master · tpm2-software/tpm2-tools · GitHub
下载了源码后,在tpm2-tools/man/tpm2_hash.1.md中。
OPTIONS
-C, --hierarchy=OBJECT:
Hierarchy to use for the ticket. Defaults to o, TPM_RH_OWNER, when no value has been specified. Supported options are: —— 用于票证的层级。默认为o,TPM_RH_OWNER,当没有i指定任何值时。支持的选项如下:
- o for TPM_RH_OWNER
- p for TPM_RH_PLATFORM
- e for TPM_RH_ENDORSEMENT
- n for TPM_RH_NULL
-g, --hash-algorithm=ALGORITHM:
The hashing algorithm for the digest operation. —— 摘要操作的哈希算法。
--hex
Convert the output hmac to hex format without a leading "0x". —— 将输出hmac转换为不带前导“0x”的十六进制格式。
-o, --output=FILE or STDOUT:
Optional file to save the hash result. Defaults to stdout in hex form. —— 可选的保存哈希结果的文件。默认为十六进制形式的stdout(标准输出)。
-t, --ticket=TICKET_FILE
Optional file record of the ticket result. Defaults to stdout in hex form. —— 可选的记录票据结果的文件。默认为十六进制的stdout(标准输出)。
ARGUMENT or STDIN the command line argument specifies the FILE to hash. —— 命令行参数定义的哈希文件。
tpm2_options_new函数属于公共代码,在tpm2-tools/lib/tpm2_options.c中,代码如下:
tpm2_options *tpm2_options_new(const char *short_opts, size_t len,
const struct option *long_opts, tpm2_option_handler on_opt,
tpm2_arg_handler on_arg, uint32_t flags) {
tpm2_options *opts = calloc(1, sizeof(*opts) + (sizeof(*long_opts) * len));
if (!opts) {
LOG_ERR("oom");
return NULL;
}
/*
* On NULL, just make it a zero length string so we don't have to keep
* checking it for NULL.
*/
if (!short_opts) {
short_opts = "";
}
opts->short_opts = strdup(short_opts);
if (!opts->short_opts) {
LOG_ERR("oom");
free(opts);
return NULL;
}
opts->callbacks.on_opt = on_opt;
opts->callbacks.on_arg = on_arg;
opts->len = len;
opts->flags = flags;
memcpy(opts->long_opts, long_opts, len * sizeof(*long_opts));
return opts;
}
tpm2_new_options函数很容易理解,其功能是基于tpm2_tool_onstart函数中的struct option topts构建tpm2_options实例(*opts)。
至此,tpm2_hash.c中的tpm2_tool_onstart函数就基本分析完了。