144 changes: 53 additions & 91 deletions tools/tpm2_createprimary.c
Expand Up @@ -38,7 +38,6 @@
#include <string.h>

#include <sapi/tpm20.h>
#include <tcti/tcti_socket.h>

#include "files.h"
#include "log.h"
Expand All @@ -54,43 +53,22 @@
typedef struct tpm_createprimary_ctx tpm_createprimary_ctx;
struct tpm_createprimary_ctx {
TPMS_AUTH_COMMAND session_data;
TPM2B_SENSITIVE_CREATE sensitive;
TPM2B_PUBLIC public;
TPMI_ALG_HASH halg;
TPMI_RH_HIERARCHY hierarchy;
tpm2_hierearchy_pdata objdata;
char *context_file;
TPM2_HANDLE handle;
struct {
UINT8 H :1;
UINT8 g :1;
UINT8 G :1;
} flags;
};

#define PUBLIC_AREA_TPMA_OBJECT_DEFAULT_INIT { \
.publicArea = { \
.type = TPM2_ALG_RSA, \
.objectAttributes = \
TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT \
|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT \
|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH \
}, \
}

static tpm_createprimary_ctx ctx = {
.session_data = {
.sessionHandle = TPM2_RS_PW,
.nonce = TPM2B_EMPTY_INIT,
.hmac = TPM2B_EMPTY_INIT,
.sessionAttributes = 0,
},
.sensitive = TPM2B_SENSITIVE_CREATE_EMPTY_INIT,
.public = PUBLIC_AREA_TPMA_OBJECT_DEFAULT_INIT,
.halg = TPM2_ALG_SHA1,
.hierarchy = TPM2_RH_NULL
.session_data = TPMS_AUTH_COMMAND_INIT(TPM2_RS_PW),
.objdata = TPM2_HIERARCHY_DATA_INIT
};

static bool setup_alg(TPMI_ALG_HASH halg, TPM2B_PUBLIC *public) {

static bool set_name_alg(TPMI_ALG_HASH halg, TPM2B_PUBLIC *public) {

switch(halg) {
case TPM2_ALG_SHA1:
Expand All @@ -100,14 +78,19 @@ static bool setup_alg(TPMI_ALG_HASH halg, TPM2B_PUBLIC *public) {
case TPM2_ALG_SM3_256:
case TPM2_ALG_NULL:
public->publicArea.nameAlg = halg;
break;
default:
LOG_ERR("name algorithm \"%s\" not supported!",
tpm2_alg_util_algtostr(halg));
return false;
return true;
}

switch(public->publicArea.type) {
LOG_ERR("name algorithm \"%s\" not supported!",
tpm2_alg_util_algtostr(halg));

return false;
}

static bool set_alg(TPMI_ALG_PUBLIC type, TPM2B_PUBLIC *public) {


switch(type) {
case TPM2_ALG_RSA: {
TPMS_RSA_PARMS *r = &public->publicArea.parameters.rsaDetail;
r->symmetric.algorithm = TPM2_ALG_AES;
Expand Down Expand Up @@ -150,51 +133,20 @@ static bool setup_alg(TPMI_ALG_HASH halg, TPM2B_PUBLIC *public) {
return false;
}

public->publicArea.type = type;

return true;
}

static bool create_primary(TSS2_SYS_CONTEXT *sapi_context) {

bool res = setup_alg(ctx.halg, &ctx.public);
if (!res) {
return false;
}

TPM2B_DATA outside_info = TPM2B_EMPTY_INIT;
TPML_PCR_SELECTION creation_pcr = { .count = 0 };
TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
TPM2B_PUBLIC out_public = TPM2B_EMPTY_INIT;
TPM2B_CREATION_DATA createion_data = TPM2B_EMPTY_INIT;
TPM2B_DIGEST creation_hash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
TPMT_TK_CREATION creation_ticket = TPMT_TK_CREATION_EMPTY_INIT;

TSS2L_SYS_AUTH_COMMAND sessionsData =
TSS2L_SYS_AUTH_COMMAND_INIT(1, {ctx.session_data});

TSS2L_SYS_AUTH_RESPONSE sessionsDataOut;
TSS2_RC rval = TSS2_RETRY_EXP(
Tss2_Sys_CreatePrimary(sapi_context, ctx.hierarchy, &sessionsData,
&ctx.sensitive, &ctx.public, &outside_info,
&creation_pcr, &ctx.handle, &out_public, &createion_data,
&creation_hash, &creation_ticket, &name, &sessionsDataOut));
if (rval != TPM2_RC_SUCCESS) {
LOG_PERR(Tss2_Sys_CreatePrimary, rval);
return false;
}

tpm2_util_tpma_object_to_yaml(ctx.public.publicArea.objectAttributes);
tpm2_tool_output("handle: 0x%X", ctx.handle);

return true;
}

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

bool res;

switch (key) {
case 'H':
res = tpm2_hierarchy_from_optarg(value, &ctx.hierarchy,
res = tpm2_hierarchy_from_optarg(value, &ctx.objdata.in.hierarchy,
TPM2_HIERARCHY_FLAGS_ALL);
if (!res) {
return false;
Expand All @@ -210,52 +162,60 @@ static bool on_option(char key, char *value) {
break;
case 'K':
res = tpm2_password_util_from_optarg(value,
&ctx.sensitive.sensitive.userAuth);
&ctx.objdata.in.sensitive.sensitive.userAuth);
if (!res) {
LOG_ERR("Invalid new key password, got\"%s\"", value);
return false;
}
break;
case 'g':
ctx.halg = tpm2_alg_util_from_optarg(value);
if (ctx.halg == TPM2_ALG_ERROR) {
case 'g': {
TPMI_ALG_HASH halg = tpm2_alg_util_from_optarg(value);
if (halg == TPM2_ALG_ERROR) {
LOG_ERR("Invalid hash algorithm, got\"%s\"", value);
return false;
}

res = set_name_alg(halg, &ctx.objdata.in.public);
if (!res) {
return false;
}
ctx.flags.g = 1;
break;
case 'G':
ctx.public.publicArea.type = tpm2_alg_util_from_optarg(value);
if (ctx.public.publicArea.type == TPM2_ALG_ERROR) {
} break;
case 'G': {
TPMI_ALG_PUBLIC type = tpm2_alg_util_from_optarg(value);
if (type == TPM2_ALG_ERROR) {
LOG_ERR("Invalid key algorithm, got\"%s\"", value);
return false;
}

res = set_alg(type, &ctx.objdata.in.public);
if (!res) {
return false;
}
ctx.flags.G = 1;
break;
} break;
case 'C':
ctx.context_file = value;
if (ctx.context_file == NULL || ctx.context_file[0] == '\0') {
return false;
}
break;
case 'L':
ctx.public.publicArea.authPolicy.size = BUFFER_SIZE(TPM2B_DIGEST,
buffer);
case 'L': {
TPM2B_DIGEST *auth_policy = &ctx.objdata.in.public.publicArea.authPolicy;
auth_policy->size = BUFFER_SIZE(TPM2B_DIGEST, buffer);
if (!files_load_bytes_from_path(value,
ctx.public.publicArea.authPolicy.buffer,
&ctx.public.publicArea.authPolicy.size)) {
auth_policy->buffer, &auth_policy->size)) {
return false;
}
break;
} break;
case 'A': {
bool res = tpm2_attr_util_obj_from_optarg(value,
&ctx.public.publicArea.objectAttributes);
&ctx.objdata.in.public.publicArea.objectAttributes);
if (!res) {
LOG_ERR("Invalid object attribute, got\"%s\"", value);
return false;
}
}
break;
} break;
case 'S': {
tpm2_session *s = tpm2_session_restore(value);
if (!s) {
Expand All @@ -264,8 +224,7 @@ static bool on_option(char key, char *value) {

ctx.session_data.sessionHandle = tpm2_session_get_handle(s);
tpm2_session_free(&s);
}
break;
} break;
}

return true;
Expand All @@ -291,27 +250,30 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
return *opts != NULL;
}

static inline bool valid_ctx(struct tpm_createprimary_ctx ctx) {
static inline bool valid_ctx(void) {
return (ctx.flags.H && ctx.flags.g && ctx.flags.G);
}

int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
UNUSED(flags);

if (!valid_ctx(ctx)) {
if (!valid_ctx()) {
return 1;
}

bool result = create_primary(sapi_context);
bool result = tpm2_hierarrchy_create_primary(sapi_context, &ctx.session_data, &ctx.objdata);
if (!result) {
return 1;
}

tpm2_util_tpma_object_to_yaml(ctx.objdata.in.public.publicArea.objectAttributes);
tpm2_tool_output("handle: 0x%X", ctx.objdata.out.handle);

if (!ctx.context_file) {
return 0;
}

result = files_save_tpm_context_to_path(sapi_context, ctx.handle,
result = files_save_tpm_context_to_path(sapi_context, ctx.objdata.out.handle,
ctx.context_file);

/* 0 on success, 1 otherwise */
Expand Down