接前一篇文章:tpm2-tools源码分析之tpm2_nvundefine.c(1)
本文对tpm2_nvundefine.c中的tpm2_tool_onstart函数进行详细解析。
先再次贴出该函数源码:
static bool tpm2_tool_onstart(tpm2_options **opts) {
/*
* The tool does both undefine and undefine space special and so the options
* are interpreted accordingly.
*
* Case NV_Undefine:
* 1. 'C' and 'P' correspond to either TPM2_RH_OWNER or TPM2_RH_PLATFORM
* 2. In this case, two aux sessions are allowed.
* Case NV_UndefineSpaceSpecial:
* 1. 'S' is for the NV-Index --> Object#1, Session#1.
* 2. 'C' and 'P' is defaulted to TPM2_RH_PLATFORM --> Object#2, Session#2
* 3. In this case, just one aux session is allowed.
* 4. Additional option --with-policydelete is required with tcti=none as
* the NV index isn't available to read the attribute when only
* calculating cpHash and command is not dispatched.
*/
const struct option topts[] = {
{ "hierarchy", required_argument, NULL, 'C' },
{ "auth", required_argument, NULL, 'P' },
{ "session", required_argument, NULL, 'S' },
{ "cphash", required_argument, NULL, 0 },
{ "rphash", required_argument, NULL, 1 },
{ "with-policydelete", no_argument, NULL, 2 },
{ "name", required_argument, NULL, 'n' },
};
*opts = tpm2_options_new("C:P:S:n:", ARRAY_LEN(topts), topts, on_option,
on_arg, TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI);
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_nvundefine.c)中,如下:
static bool on_option(char key, char *value) {
switch (key) {
case 'C':
ctx.is_auth_hierarchy_specified = true;
ctx.auth_hierarchy.ctx_path = value;
break;
case 'P':
ctx.auth_hierarchy.auth_str = value;
break;
case 'S':
/*
* In case of undefinespacespecial first session is expected to satisfy
* the ADMIN role in a policycommandcode session.
*/
if (!ctx.aux_session_cnt) {
ctx.policy_session.path = value;
}
ctx.aux_session_path[ctx.aux_session_cnt] = value;
if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) {
ctx.aux_session_cnt++;
} else {
LOG_ERR("Specify a max of 3 sessions");
return false;
}
break;
case 0:
ctx.cp_hash_path = value;
break;
case 1:
ctx.rp_hash_path = value;
break;
case 2:
ctx.has_policy_delete_set = true;
break;
case 'n':
ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name);
int q = tpm2_util_hex_to_byte_structure(value, &ctx.precalc_nvname.size,
ctx.precalc_nvname.name);
if (q) {
LOG_ERR("FAILED: %d", q);
return false;
}
break;
}
return true;
}
要更好地理解这些选项乃至tpm2_tool_onstart函数的功能,需要与tpm2_nvundefine命令的说明相结合来看。tpm2_nvundefine命令的详细说明参见:
tpm2-tools/tpm2_nvundefine.1.md at master · tpm2-software/tpm2-tools · GitHub
下载了源码后,在tpm2-tools/man/tpm2_nvundefine.1.md中。
其中的参数说明如下:
OPTIONS
-C, --hierarchy=OBJECT:
Specifies the hierarchy used to authorize. Supported options are: —— 指定用于授权的层级。支持的选项是:
- o for TPM_RH_OWNER
- p for TPM_RH_PLATFORM
<num>
where a hierarchy handle may be specified.-P, --auth=AUTH:
Specifies the authorization value for the hierarchy. —— 指定层次结构的授权值。
-S, --session=POLICY_SESSION:
Specify a policy session to use when the NV index has attribute
TPMA_NV_POLICY_DELETE
set. This can also be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. Note: —— 指定当NV索引设置了属性TPMA_NV_policy_DELETE时要使用的策略会话。这也可以用于指定用于参数的审计和/或加密/解密的辅助会话。注意:
If TPM2_CC_NV_UndefineSpaceSpecial is invoked then only one additional aux session can be specified. The order of how sessions are specified also matters. First specification of
-S
is interpreted as the session for satisfying the ADMIN role required for TPM2_CC_NV_UndefineSpaceSpecial. —— 如果调用了TPM2_CC_NV_UndefineSpaceSpecial,则只能指定一个额外的辅助会话。指定会话的顺序也很重要。-S的第一个规范被解释为满足TPM2_CC_NV_UndefineSpaceSpecial所需的ADMIN角色的会话。If TPM2_CC_NV_Undefine is invoked then only two additional aux sessions can be specified. —— 如果调用了TPM2_CC_NV_Undefine,则只能指定另外两个辅助会话。
--cphash=FILE
File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, it simply returns a cpHash unless rphash is also required. —— 用于记录命令参数哈希的文件路径。这通常被称为cpHash。注意:当此选项被选择时,此工具将不会实际执行命令,它只是返回一个cpHash,除非也需要rphash。
--rphash=FILE
File path to record the hash of the response parameters. This is commonly termed as rpHash. —— 用于记录响应参数哈希的文件路径。这通常被称为rpHash。
--with-policydelete=NONE
This must be specified when calculating cpHash with --tcti=none. This is a requirement because there is no way to know if the attribute TPMA_NV_POLICYDELETE has been set from the NV index name alone. —— 当当使用--tcpi=none计算cpHash时,必须指定此项。这是一个要求,因为无法知道是否仅从NV索引名称设置了属性TPMA_NV_POLICYDELETE。
-n, --name=FILE:
The name of the NV index that must be provided when only calculating the cpHash without actually dispatching the command to the TPM. —— 当仅计算cpHash而不实际将命令分派给TPM时必须提供的NV索引的名称。
ARGUMENT the command line argument specifies the NV index or offset number. —— 命令行参数指定NV索引或偏移量编号。
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_nvundefine.c中的tpm2_tool_onstart函数就基本分析完了。