tpm2-tools源码分析之tpm2_sign.c(2)

接前一篇文章:tpm2-tools源码分析之tpm2_sign.c(1)

本文对tpm2_sign.c中的tpm2_tool_onstart函数进行详细解析。

先再次贴出该函数源码:

static bool tpm2_tool_onstart(tpm2_options **opts) {

    static const struct option topts[] = {
      { "auth",           required_argument, 0, 'p' },
      { "hash-algorithm", required_argument, 0, 'g' },
      { "scheme",         required_argument, 0, 's' },
      { "digest",         no_argument,       0, 'd' },
      { "signature",      required_argument, 0, 'o' },
      { "ticket",         required_argument, 0, 't' },
      { "key-context",    required_argument, 0, 'c' },
      { "format",         required_argument, 0, 'f' },
      { "cphash",         required_argument, 0,  0  },
      { "commit-index",   required_argument, 0,  1  },
    };

    *opts = tpm2_options_new("p:g:dt:o:c:f:s:", ARRAY_LEN(topts), topts,
            on_option, on_args, 0);

    return *opts != 0;
}

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_sign.c)中,如下:

static bool on_option(char key, char *value) {

    switch (key) {
    case 'c':
        ctx.signing_key.ctx_path = value;
        break;
    case 'p':
        ctx.signing_key.auth_str = value;
        break;
    case 'g':
        ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash);
        if (ctx.halg == TPM2_ALG_ERROR) {
            LOG_ERR("Could not convert to number or lookup algorithm, got: "
                    "\"%s\"", value);
            return false;
        }
        break;
    case 's': {
        ctx.sig_scheme = tpm2_alg_util_from_optarg(value,
                tpm2_alg_util_flags_sig);
        if (ctx.sig_scheme == TPM2_ALG_ERROR) {
            LOG_ERR("Unknown signing scheme, got: \"%s\"", value);
            return false;
        }
    }
        break;
    case 'd':
        ctx.is_input_msg_digest = true;
        break;
    case 't': {
        bool result = files_load_validation(value, &ctx.validation);
        if (!result) {
            return false;
        }
        ctx.is_hash_ticket_specified = true;
    }
        break;
    case 'o':
        ctx.output_path = value;
        break;
    case 0:
        ctx.cp_hash_path = value;
        break;
    case 1:
        ctx.commit_index = value;
        break;
    case 'f':
        ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value);

        if (ctx.sig_format == signature_format_err) {
            return false;
        }
        /* no default */
    }

    return true;
}

要更好地理解这些选项乃至tpm2_tool_onstart函数的功能,需要与tpm2_sign命令的说明相结合来看。tpm2_sign命令的详细说明参见:

tpm2-tools/tpm2_sign.1.md at master · tpm2-software/tpm2-tools · GitHub

下载了源码后,在tpm2-tools/man/tpm2_sign.1.md中。

其中的参数说明如下:

OPTIONS

  • -c--key-context=OBJECT:

    Context object pointing to the the key used for signing. Either a file or a handle number. See section "Context Object Format". —— 指向用于签名的密钥的上下文对象。文件号或句柄号。

  • -p--authAUTH:

    Optional authorization value to use the key specified by -c. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". —— 使用-c指定的密钥的可选授权值。授权值应遵循“授权格式标准”。

  • -g--hash-algorithm=ALGORITHM:

    The hash algorithm used to digest the message. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. —— 用于摘要消息的哈希算法。

  • -s--scheme=ALGORITHM:

    The signing scheme used to sign the message. Optional.

    Signing schemes should follow the "formatting standards", see section "Algorithm Specifiers". —— 用于对消息进行签名的签名方案。可选。

    If specified, the signature scheme must match the key type. If left unspecified, a default signature scheme for the key type will be used. —— 如果指定,则签名方案必须与密钥类型匹配。如果未指定,则将使用密钥类型的默认签名方案。

  • -d--digest:

    Indicate that FILE is a file containing the digest of the message. When this option and -t is specified, a warning is generated and the validation ticket (-t) is ignored. You cannot use this option to sign a digest against a restricted signing key. —— 指示FILE是一个包含消息摘要的文件。当指定此选项和-t时,将生成一个警告,并忽略验证票证(-t)。不能使用此选项根据受限制的签名密钥对摘要进行签名。

  • -t--ticket=FILE:

    The ticket file, containing the validation structure, optional. —— 票据文件,包含验证结构,可选。

  • -o--signature=FILE:

    The signature file, records the signature structure. —— 签名文件,记录签名结构。

  • -f--format=FORMAT:

    Format selection for the signature output file. See section "Signature Format Specifiers". —— 签名输出文件的格式选择。

  • --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。

  • --commit-index=NATURALNUMBER

    The commit counter value to determine the key index to use in an ECDAA signing scheme. The default counter value is 0. —— 提交计数器值,用于确定要在ECDAA签名方案中使用的密钥索引。默认计数值为0。

  • ARGUMENT the command line argument specifies the file data for sign. —— 命令行参数指定的要签名的文件数据。

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_sign.c中的tpm2_tool_onstart函数就基本分析完了。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/130628082