tpm2_create.c of tpm2-tools source code analysis (1)

The source file corresponding to the tpm2_create command in TPM 2.0 is tpm2_create.c, which is located under tpm2-tools/tools/ and has a total of 671 lines (version 5.5).

The function of tpm2_create is to create a key. The command description is: Create a child object. This object can be a key or a seal object. The Seal object allows sealing user data to the TPM with a maximum size of 128 bytes. Also, if -c is specified, it will load the created object.

The following uses the length of several articles to conduct an in-depth and complete analysis of the tpm2_create.c file combined with the tpm2_create command.

Let's look at the first piece of code:

// Register this tool with tpm2_tool.c
TPM2_TOOL_REGISTER("create", tpm2_tool_onstart, tpm2_tool_onrun,
tpm2_tool_onstop, NULL)

TPM2_TOOL_REGISTER is a macro definition, in tpm2-tools/tools/tpm2_tool.h, the code is as follows:

#define TPM2_TOOL_REGISTER(tool_name,tool_onstart,tool_onrun,tool_onstop,tool_onexit) \
	static const tpm2_tool tool = { \
		.name		= tool_name, \
		.onstart	= tool_onstart, \
		.onrun		= tool_onrun, \
		.onstop		= tool_onstop, \
		.onexit		= tool_onexit, \
	}; \
	static void \
	__attribute__((__constructor__)) \
	__attribute__((__used__)) \
	_tpm2_tool_init(void) \
	{ \
		tpm2_tool_register(&tool); \
	}

The TPM2_TOOLS_REGISTER macro definition is shared by commands in the entire tpm2-tools and is a framework code.

In this file tpm2_create.c, it can also be said that in the tpm2_create command, the expanded macro is:

static const tpm2_tool tool = {
    .name		= create,
	.onstart	= tool_onstart,
	.onrun		= tool_onrun,
	.onstop		= tool_onstop,
	.onexit		= NULL,
};
static void
	__attribute__((__constructor__))
	__attribute__((__used__))
    _tpm2_tool_init(void)
{
		tpm2_tool_register(&tool);
}

The definition of the tpm2_tool structure is also in tpm2-tools/tools/tpm2_tool.h, the code is as follows:

typedef struct {
	const char * name;
	tpm2_tool_onstart_t onstart;
	tpm2_tool_onrun_t onrun;
	tpm2_tool_onstop_t onstop;
	tpm2_tool_onexit_t onexit;
} tpm2_tool;

The relevant function pointers contained in it are as follows (in the same file, just above):

/**
 * An optional interface for tools to specify what options they support.
 * They are concatenated with main's options and passed to getopt_long.
 * @param opts
 *  The callee can choose to set *opts to a tpm_options pointer allocated
 *  via tpm2_options_new(). Setting *opts to NULL is not an error, and
 *  Indicates that no options are specified by the tool.
 *
 * @return
 *  True on success, false on error.
 */
typedef bool (*tpm2_tool_onstart_t)(tpm2_options **opts);

/**
 * This is the main interface for tools, after tcti and sapi/esapi initialization
 * are performed.
 * @param ectx
 *  The system/esapi api context.
 * @param flags
 *  Flags that tools may wish to respect.
 * @return
 *  A tool_rc indicating status.
 */
typedef tool_rc (*tpm2_tool_onrun_t)(ESYS_CONTEXT *ectx, tpm2_option_flags flags);

/**
 * Called after tpm2_tool_onrun() is invoked. ESAPI context is still valid during this call.
 * @param ectx
 *  The system/esapi api context.
 * @return
 *  A tool_rc indicating status.
 */
typedef tool_rc (*tpm2_tool_onstop_t)(ESYS_CONTEXT *ectx);

/**
 * Called when the tool is exiting, useful for cleanup.
 */
typedef void (*tpm2_tool_onexit_t)(void);

The tpm2_tool_register function is implemented in tpm2-tools/tools/tpm2_tools.c, the code is as follows:

/*
 * Build a list of the TPM2 tools linked into this executable
 */
#ifndef TPM2_TOOLS_MAX
#define TPM2_TOOLS_MAX 1024
#endif
static const tpm2_tool *tools[TPM2_TOOLS_MAX];
static unsigned tool_count;

void tpm2_tool_register(const tpm2_tool *tool) {

    if (tool_count < TPM2_TOOLS_MAX) {
        tools[tool_count++] = tool;
    } else {
        LOG_ERR("Over tool count");
        abort();
    }
}

Go back to tpm2_create.c to see the specific functions.

(1)tpm2_tool_onstart

The tpm2_tool_onstart function code is as follows:

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;
}

(2)tpm2_tool_onrun

The tpm2_tool_onrun function code is as follows:

static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {

    UNUSED(flags);

    /*
     * 1. Process options
     */
    tool_rc rc = check_options();
    if (rc != tool_rc_success) {
        return rc;
    }

    /*
     * 2. Process inputs
     */
    rc = process_inputs(ectx);
    if (rc != tool_rc_success) {
        return rc;
    }

    /*
     * 3. TPM2_CC_<command> call
     */
    rc = create(ectx);
    if (rc != tool_rc_success) {
        return rc;
    }

    /*
     * 4. Process outputs
     */
    return process_output(ectx);
}

(3)tpm2_tool_onstop

The tpm2_tool_onstop function code is as follows:

static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {

    UNUSED(ectx);

    /*
     * 1. Free objects
     */

    /*
     * 2. Close authorization sessions
     */
    tool_rc rc = tool_rc_success;
    tool_rc tmp_rc = tpm2_session_close(&ctx.parent.object.session);
    if (tmp_rc != tool_rc_success) {
        rc = tmp_rc;
    }

    /*
     * 3. Close auxiliary sessions
     */
    size_t i = 0;
    for(i = 0; i < ctx.aux_session_cnt; i++) {
        if (ctx.aux_session_path[i]) {
            tmp_rc = tpm2_session_close(&ctx.aux_session[i]);
            if (tmp_rc != tool_rc_success) {
                rc = tmp_rc;
            }
        }
    }

    return rc;
}

(4)tpm2_tool_onexit

The tpm2_tool_onexit function is not implemented in tpm2_create.c, that is, the tpm2_create command (the value passed in for TPM2_TOOL_REGISTER is NULL).

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/130145206