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

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

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

先再次贴出该函数源码:

static bool tpm2_tool_onstart(tpm2_options **opts) {

    const struct option topts[] = {
            { "digest",         required_argument, NULL, 'd' },
            { "hash-algorithm", required_argument, NULL, 'g' },
            { "message",        required_argument, NULL, 'm' },
            { "format",         required_argument, NULL,  0  },
            { "scheme",         required_argument, NULL, 'f' },
            { "signature",      required_argument, NULL, 's' },
            { "ticket",         required_argument, NULL, 't' },
            { "key-context",    required_argument, NULL, 'c' },
    };


    *opts = tpm2_options_new("g:m:d:f:s:t:c:", 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/tpm2_verifysignature.c)中,如下:

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

    switch (key) {
    case 'c':
        ctx.context_arg = 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("Unable to convert algorithm, got: \"%s\"", value);
            return false;
        }
        ctx.flags.halg = 1;
    }
        break;
    case 'm': {
        ctx.msg_file_path = value;
        ctx.flags.msg = 1;
    }
        break;
    case 'd': {
        ctx.msg_hash = malloc(sizeof(TPM2B_DIGEST));
        ctx.msg_hash->size = sizeof(ctx.msg_hash->buffer);
        if (!files_load_bytes_from_path(value, ctx.msg_hash->buffer,
                &ctx.msg_hash->size)) {
            LOG_ERR("Could not load digest from file!");
            return false;
        }
        ctx.flags.digest = 1;
    }
        break;
    case 0:
	LOG_WARN("Option \"--format\" is deprecated, use \"--scheme\"");
        /* falls through */
    case 'f':
        ctx.format = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig);
        if (ctx.format == TPM2_ALG_ERROR) {
            LOG_ERR("Unknown signing scheme, got: \"%s\"", value);
            return false;
        }

        ctx.flags.fmt = 1;
        break;
    case 's':
        ctx.sig_file_path = value;
        ctx.flags.sig = 1;
        break;
    case 't':
        ctx.out_file_path = value;
        ctx.flags.ticket = 1;
        break;
        /* no default */
    }

    return true;
}

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

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

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

其中的参数说明如下:

OPTIONS

  • -c--key-context=OBJECT:

    Context object for the key context used for the operation. Either a file or a handle number. See section "Context Object Format". —— 用于操作的密钥上下文的上下文对象。文件号或句柄号。

  • -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. —— 用于摘要消息的哈希算法。

  • -m--message=FILE:

    The message file, containing the content to be digested. —— 消息文件,包含要被摘要的内容。

  • -d--digest=FILE:

    The input hash file, containing the hash of the message. If this option is selected, then the message (-m) and algorithm (-g) options do not need to be specified. —— 输入哈希文件,包含消息的哈希。如果此选项被选择,则不需要指定消息(-m)和算法(-g)选项。

  • -s--signature=FILE:

    The input signature file of the signature to be validated. —— 要验证其签名的输入签名文件。

  • -f--scheme=SCHEME:

    The signing scheme that was used to sign the message. This option should only be specified if the signature comes in from a non tss standard, like openssl. See "Signature format specifiers" for more details. The tss format contains the signature metadata required to understand it's signature scheme.

    Signing schemes should follow the "formatting standards", see section "Algorithm Specifiers". —— 用于对消息进行签名的签名方案。只有当签名来自非tss标准(如openssl)时,才应指定此选项。

  • --format=SCHEME:

    Deprecated. Same as --scheme. —— 已弃用。与--scheme相同。

  • -t--ticket=FILE:

    The ticket file to record the validation structure. —— 记录验证结构的票据文件。

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

猜你喜欢

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