接前一篇文章:tpm2-tools源码分析之tpm2_create.c(1)
本文对tpm2_create.c中的tpm2_tool_onstart函数进行详细解析。
先再次贴出该函数源码:
static bool tpm2_tool_onstart(tpm2_options **opts) {
static struct option topts[] = {
{ "parent-auth", required_argument, NULL, 'P' },
{ "key-auth", required_argument, NULL, 'p' },
{ "hash-algorithm", required_argument, NULL, 'g' },
{ "key-algorithm", required_argument, NULL, 'G' },
{ "attributes", required_argument, NULL, 'a' },
{ "sealing-input", required_argument, NULL, 'i' },
{ "policy", required_argument, NULL, 'L' },
{ "public", required_argument, NULL, 'u' },
{ "private", required_argument, NULL, 'r' },
{ "parent-context", required_argument, NULL, 'C' },
{ "key-context", required_argument, NULL, 'c' },
{ "creation-data", required_argument, NULL, 0 },
{ "template-data", required_argument, NULL, 1 },
{ "creation-ticket",required_argument, NULL, 't' },
{ "creation-hash", required_argument, NULL, 'd' },
{ "outside-info", required_argument, NULL, 'q' },
{ "pcr-list", required_argument, NULL, 'l' },
{ "cphash", required_argument, NULL, 2 },
{ "rphash", required_argument, NULL, 3 },
{ "session", required_argument, NULL, 'S' },
{ "format", required_argument, NULL, 'f' },
{ "output", required_argument, NULL, 'o' },
};
*opts = tpm2_options_new("P:p:g:G:a:i:L:u:r:C:c:t:d:q:l:S:o:f:",
ARRAY_LEN(topts), topts, on_option, NULL, 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/tpm_create.c)中,如下:
static bool on_option(char key, char *value) {
switch (key) {
case 'P':
ctx.parent.auth_str = value;
break;
case 'p':
ctx.object.auth_str = value;
break;
case 'g':
ctx.object.name_alg = value;
break;
case 'G':
ctx.object.alg = value;
ctx.object.is_object_alg_specified = true;
break;
case 'a':
ctx.object.attrs = value;
break;
case 'i':
ctx.object.sealed_data = strcmp("-", value) ? value : NULL;
ctx.object.alg = "keyedhash";
ctx.object.is_sealing_input_specified = true;
bool res = load_sensitive();
if (!res) {
return false;
}
break;
case 'L':
ctx.object.policy = value;
break;
case 'u':
ctx.object.public_path = value;
break;
case 'r':
ctx.object.private_path = value;
break;
case 'C':
ctx.parent.ctx_path = value;
break;
case 'c':
ctx.object.ctx_path = value;
break;
case 0:
ctx.object.creation_data_file = value;
break;
case 1:
ctx.object.template_data_path = value;
break;
case 't':
ctx.object.creation_ticket_file = value;
break;
case 'd':
ctx.object.creation_hash_file = value;
break;
case 'q':
ctx.object.outside_info_data = value;
break;
case 'l':
if (!pcr_parse_selections(value, &ctx.object.creation_pcr)) {
LOG_ERR("Could not parse pcr selections, got: \"%s\"", value);
return false;
}
break;
case 2:
ctx.cp_hash_path = value;
break;
case 3:
ctx.rp_hash_path = value;
break;
case 'S':
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 'f':
ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value);
if (ctx.format == pubkey_format_err) {
return false;
}
ctx.format_set = true;
break;
case 'o':
ctx.output_path = value;
break;
/* no default */
};
return true;
}
要更好地理解这些选项乃至tpm2_tool_onstart函数的功能,需要与tpm2_create命令的说明相结合来看。tpm2_creat命令的详细说明参见:
tpm2-tools/tpm2_create.1.md at master · tpm2-software/tpm2-tools · GitHub
下载了源码后,在tpm2-tools/man/tpm2_createprimary.1.md文件中。
其中的参数说明如下:
OPTIONS
These options for creating the TPM entity:
-C, --parent-context=OBJECT:
The parent of the object to be created. —— 要创建的对象的父级。
-P, --parent-auth=AUTH:
The authorization value of the parent object specified with -C. —— 使用-C指定的父对象的授权值。
-p, --key-auth=AUTH:
The authorization value for the created object. —— 创建对象的授权值。
-g, --hash-algorithm=ALGORITHM:
The hash algorithm for generating the objects name. This is optional and defaults to sha256 when not specified. —— 用于生成对象名称的哈希算法。这是可选的,未指定时默认为sha256。
-G, --key-algorithm=ALGORITHM:
The key algorithm associated with this object. It defaults to "rsa" if not specified. —— 与此对象关联的密钥算法。如果未指定,则默认为“rsa”。
-a, --attributes=ATTRIBUTES:
The object attributes, optional. The default for created objects is: —— 对象属性,可选。默认为:
TPMA_OBJECT_SIGN_ENCRYPT|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM| TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN| TPMA_OBJECT_USERWITHAUTH
When -i is specified for sealing,
TPMA_OBJECT_SIGN_ENCRYPT
andTPMA_OBJECT_DECRYPT
are removed from the default attribute set. The algorithm is set in a way where the the object is only good for sealing and unsealing. I.e. one cannot use an object for sealing and cryptography operations. —— 当 –i 被指定为密封时,TPMA_OBJECT_SIGN_ENCRYPT 和TPMA_OBJECT_DECRYPT从默认属性集中删除。该算法以对象仅对密封和解封有效的方式设置。即不能使用对象进行密封加密操作。When -L is specified for adding policy based authorization information AND no string password is specified, the attribute
TPMA_OBJECT_USERWITHAUTH
is cleared unless an explicit choice is made by setting of the attribute with -a option. This prevents creation of objects with inadvertent auth model where in user intended to enforce a policy but inadvertently created an object with empty auth which can be used instead of policy authorization. —— 指定-L并且未指定字符串密码为添加基于策略的授权信息时,除非通过使用-a选项设置属性做出明确选择,否则将清除属性TPMA_OBJECT_USERWITHAUTH。这可以防止创建具有无意身份验证模型的对象,其中用户打算强制执行策略,但无意中创建了具有空身份验证的对象,该对象可用于代替策略授权。-i, --sealing-input=FILE or STDIN:
The data file to be sealed, optional. If file is -, read from stdin. When sealing data only the TPM_ALG_KEYEDHASH algorithm with a NULL scheme is allowed. Thus, -G cannot be specified. —— 要密封的数据文件,可选。如果文件是 -,从标准输入读取。密封数据时,仅允许使用 NULL 方案的TPM_ALG_KEYEDHASH算法。因此,无法指定-G 。
-L, --policy=FILE or HEX_STRING:
The input policy file or a hex string, optional. —— 输入策略文件,可选。
-u, --public=FILE:
The output file which contains the public portion of the created object, optional. —— 包含已创建对象的公共部分的输出文件,可选。
-r, --private=FILE:
The output file which contains the sensitive portion of the object, optional. —— 包含对象敏感部分的输出文件,可选。可以移出TPM的对象需要受到保护其机密性和完整性。此blob包含对象的敏感部分。对象的敏感部分受到父对象的保护,使用父对象的对称加密细节来加密敏感数据并对其进行HMAC。
-c, --key-context=FILE:
The output file which contains the key context, optional. The key context is analogous to the context file produced by tpm2_load(1), however is generated via a tpm2_createloaded(1) command. This option can be used to avoid the normal tpm2_create(1) and tpm2_load(1) command sequences and do it all in one command, atomically. —— 包含密钥上下文的输出文件,可选。key-context类似于tpm2_load生成的上下文文件,但是是通过tpm2_createloaded命令生成的。此选项可用于避免正常的tpm2_create和tpm2_load命令序列,并以原子方式在一个命令中完成所有操作。
--creation-data=FILE:
An optional file output that saves the creation data for certification. —— 一个可选的文件输出,保存创建数据以供认证。
- --template-data=FILE:
An optional file output that saves the key template data (TPM2B_PUBLIC) to be used in tpm2_policytemplate. —— 一个可选的文件输出,保存要在tpm2_policytemplate中使用的密钥模板数据 (TPM2B_PUBLIC) 。
-t, --creation-ticket=FILE:
An optional file output that saves the creation ticket for certification. —— 一个可选的文件输出,用于保存创建ticket以供认证。
-d, --creation-hash=FILE:
An optional file output that saves the creation hash for certification. —— 一个可选的文件输出,用于保存创建哈希以供认证。
-q, --outside-info=HEX_STR_OR_FILE:
An optional hex string or path to add unique data to the creation data. Note that it does not contribute in creating statistically unique object. —— 用于将唯一数据添加到创建数据的可选十六进制字符串或路径。它不会有助于创建统计上唯一的对象。
-l, --pcr-list=PCR:
The list of PCR banks and selected PCRs' ids for each bank to be included in the creation data for certification. —— PCR banks列表和每个banks的选定 PCR 的 ID ,将包含在创建数据中以进行认证。
--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. —— 记录命令参数哈希的文件路径。这通常称为cpHash。注意:选择此选项时,该工具不会实际执行命令,它只是返回一个cpHash。
--rphash=FILE
File path to record the hash of the response parameters. This is commonly termed as rpHash. —— 记录响应参数哈希的文件路径。这通常被称为rpHash。
-S, --session=FILE:
The session created using tpm2_startauthsession. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption/decryption of the parameters. —— 使用tpm2_startauthsession创建的会话。可以指定其中的多个。例如,您可以有一个会话用于审计,另一个用于参数的加密/解密。
pubkey options
Public key format.
-o, --output=FILE:
The output file path, recording the public portion of the object. —— 输出文件路径,记录对象的公共部分。
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_create.c中的tpm2_tool_onstart函数就基本分析完了。