361 changes: 177 additions & 184 deletions tools/tpm2_createprimary.c
Expand Up @@ -50,90 +50,113 @@
#include "tpm2_alg_util.h"
#include "tpm2_tool.h"

TPMS_AUTH_COMMAND sessionData = {
.sessionHandle = TPM_RS_PW,
.nonce = TPM2B_EMPTY_INIT,
.hmac = TPM2B_EMPTY_INIT,
.sessionAttributes = SESSION_ATTRIBUTES_INIT(0)
TPM_HANDLE handle2048rsa;

typedef struct tpm_createprimary_ctx tpm_createprimary_ctx;
struct tpm_createprimary_ctx {
TSS2_SYS_CONTEXT *sapi_context;
TPMS_AUTH_COMMAND session_data;
TPM2B_PUBLIC in_public;
TPMI_ALG_PUBLIC type;
TPMI_ALG_HASH nameAlg;
TPMI_RH_HIERARCHY hierarchy;
bool is_policy_enforced;
char *context_file;
struct {
UINT8 A : 1;
UINT8 g : 1;
UINT8 G : 1;
UINT8 C : 1;
} flags;
};

TPM_HANDLE handle2048rsa;
static tpm_createprimary_ctx ctx = {
.session_data = {
.sessionHandle = TPM_RS_PW,
.nonce = TPM2B_EMPTY_INIT,
.hmac = TPM2B_EMPTY_INIT,
.sessionAttributes = SESSION_ATTRIBUTES_INIT(0),
},
.in_public = TPM2B_EMPTY_INIT,
.type = TPM_ALG_RSA,
.nameAlg = TPM_ALG_SHA1,
.hierarchy = TPM_RH_NULL,
.is_policy_enforced = false
};

int setup_alg(void) {

int setAlg(TPMI_ALG_PUBLIC type,TPMI_ALG_HASH nameAlg,TPM2B_PUBLIC *inPublic, bool is_policy_enforced)
{
switch(nameAlg)
{
switch(ctx.nameAlg) {
case TPM_ALG_SHA1:
case TPM_ALG_SHA256:
case TPM_ALG_SHA384:
case TPM_ALG_SHA512:
case TPM_ALG_SM3_256:
case TPM_ALG_NULL:
inPublic->t.publicArea.nameAlg = nameAlg;
ctx.in_public.t.publicArea.nameAlg = ctx.nameAlg;
break;
default:
LOG_ERR("nameAlg algrithm: 0x%0x not support !", nameAlg);
LOG_ERR("nameAlg algrithm: 0x%0x not support !", ctx.nameAlg);
return -1;
}

// First clear attributes bit field.
*(UINT32 *)&(inPublic->t.publicArea.objectAttributes) = 0;
inPublic->t.publicArea.objectAttributes.restricted = 1;
*(UINT32 *)&(ctx.in_public.t.publicArea.objectAttributes) = 0;
ctx.in_public.t.publicArea.objectAttributes.restricted = 1;
//check if auth policy needs to be enforced
inPublic->t.publicArea.objectAttributes.userWithAuth = !is_policy_enforced;
inPublic->t.publicArea.objectAttributes.decrypt = 1;
inPublic->t.publicArea.objectAttributes.fixedTPM = 1;
inPublic->t.publicArea.objectAttributes.fixedParent = 1;
inPublic->t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
inPublic->t.publicArea.type = type;
switch(type)
{
ctx.in_public.t.publicArea.objectAttributes.userWithAuth = !ctx.is_policy_enforced;
ctx.in_public.t.publicArea.objectAttributes.decrypt = 1;
ctx.in_public.t.publicArea.objectAttributes.fixedTPM = 1;
ctx.in_public.t.publicArea.objectAttributes.fixedParent = 1;
ctx.in_public.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
ctx.in_public.t.publicArea.type = ctx.type;

switch(ctx.type) {
case TPM_ALG_RSA:
inPublic->t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
inPublic->t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
inPublic->t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB;
inPublic->t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
inPublic->t.publicArea.parameters.rsaDetail.keyBits = 2048;
inPublic->t.publicArea.parameters.rsaDetail.exponent = 0;
inPublic->t.publicArea.unique.rsa.t.size = 0;
ctx.in_public.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
ctx.in_public.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
ctx.in_public.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB;
ctx.in_public.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
ctx.in_public.t.publicArea.parameters.rsaDetail.keyBits = 2048;
ctx.in_public.t.publicArea.parameters.rsaDetail.exponent = 0;
ctx.in_public.t.publicArea.unique.rsa.t.size = 0;
break;

case TPM_ALG_KEYEDHASH:
inPublic->t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_XOR;
inPublic->t.publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.hashAlg = TPM_ALG_SHA256;
inPublic->t.publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.kdf = TPM_ALG_KDF1_SP800_108;
inPublic->t.publicArea.unique.keyedHash.t.size = 0;
ctx.in_public.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_XOR;
ctx.in_public.t.publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.hashAlg = TPM_ALG_SHA256;
ctx.in_public.t.publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.kdf = TPM_ALG_KDF1_SP800_108;
ctx.in_public.t.publicArea.unique.keyedHash.t.size = 0;
break;

case TPM_ALG_ECC:
inPublic->t.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
inPublic->t.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
inPublic->t.publicArea.parameters.eccDetail.symmetric.mode.sym = TPM_ALG_CFB;
inPublic->t.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
inPublic->t.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256;
inPublic->t.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
inPublic->t.publicArea.unique.ecc.x.t.size = 0;
inPublic->t.publicArea.unique.ecc.y.t.size = 0;
ctx.in_public.t.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
ctx.in_public.t.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
ctx.in_public.t.publicArea.parameters.eccDetail.symmetric.mode.sym = TPM_ALG_CFB;
ctx.in_public.t.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
ctx.in_public.t.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256;
ctx.in_public.t.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
ctx.in_public.t.publicArea.unique.ecc.x.t.size = 0;
ctx.in_public.t.publicArea.unique.ecc.y.t.size = 0;
break;

case TPM_ALG_SYMCIPHER:
inPublic->t.publicArea.parameters.symDetail.sym.algorithm = TPM_ALG_AES;
inPublic->t.publicArea.parameters.symDetail.sym.keyBits.sym = 128;
inPublic->t.publicArea.parameters.symDetail.sym.mode.sym = TPM_ALG_CFB;
inPublic->t.publicArea.unique.sym.t.size = 0;
ctx.in_public.t.publicArea.parameters.symDetail.sym.algorithm = TPM_ALG_AES;
ctx.in_public.t.publicArea.parameters.symDetail.sym.keyBits.sym = 128;
ctx.in_public.t.publicArea.parameters.symDetail.sym.mode.sym = TPM_ALG_CFB;
ctx.in_public.t.publicArea.unique.sym.t.size = 0;
break;

default:
LOG_ERR("type algrithm: 0x%0x not support !", type);
LOG_ERR("type algrithm: 0x%0x not support !", ctx.type);
return -2;
}
return 0;
}

int createPrimary(TSS2_SYS_CONTEXT *sysContext, TPMI_RH_HIERARCHY hierarchy,
TPM2B_PUBLIC *inPublic, TPM2B_SENSITIVE_CREATE *inSensitive,
TPMI_ALG_PUBLIC type, TPMI_ALG_HASH nameAlg, bool is_policy_enforced) {
int create_primary(void) {
UINT32 rval;
TPM2B_SENSITIVE_CREATE inSensitive = TPM2B_EMPTY_INIT;
TPMS_AUTH_RESPONSE sessionDataOut;
TSS2_SYS_CMD_AUTHS sessionsData;
TSS2_SYS_RSP_AUTHS sessionsDataOut;
Expand All @@ -148,7 +171,7 @@ int createPrimary(TSS2_SYS_CONTEXT *sysContext, TPMI_RH_HIERARCHY hierarchy,
TPM2B_DIGEST creationHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
TPMT_TK_CREATION creationTicket = TPMT_TK_CREATION_EMPTY_INIT;

sessionDataArray[0] = &sessionData;
sessionDataArray[0] = &ctx.session_data;
sessionDataOutArray[0] = &sessionDataOut;

sessionsDataOut.rspAuths = &sessionDataOutArray[0];
Expand All @@ -157,47 +180,103 @@ int createPrimary(TSS2_SYS_CONTEXT *sysContext, TPMI_RH_HIERARCHY hierarchy,
sessionsData.cmdAuthsCount = 1;
sessionsDataOut.rspAuthsCount = 1;

inSensitive->t.sensitive.data.t.size = 0;
inSensitive->t.size = inSensitive->t.sensitive.userAuth.b.size + 2;
inSensitive.t.sensitive.data.t.size = 0;
inSensitive.t.size = inSensitive.t.sensitive.userAuth.b.size + 2;

if(setAlg(type, nameAlg, inPublic, is_policy_enforced))
if(setup_alg())
return -1;

creationPCR.count = 0;

rval = Tss2_Sys_CreatePrimary(sysContext, hierarchy, &sessionsData, inSensitive, inPublic, &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash, &creationTicket, &name, &sessionsDataOut);
if(rval != TPM_RC_SUCCESS)
{
rval = Tss2_Sys_CreatePrimary(ctx.sapi_context, ctx.hierarchy, &sessionsData,
&inSensitive, &ctx.in_public, &outsideInfo, &creationPCR,
&handle2048rsa, &outPublic, &creationData, &creationHash,
&creationTicket, &name, &sessionsDataOut);
if(rval != TPM_RC_SUCCESS) {
LOG_ERR("\nCreatePrimary Failed ! ErrorCode: 0x%0x\n", rval);
return -2;
}

tpm2_tool_output("\nCreatePrimary Succeed ! Handle: 0x%8.8x\n\n", handle2048rsa);

return 0;
}

int
execute_tool (int argc,
char *argv[],
char *envp[],
common_opts_t *opts,
TSS2_SYS_CONTEXT *sapi_context)
{
(void) envp;
(void) opts;

TPM2B_SENSITIVE_CREATE inSensitive = TPM2B_EMPTY_INIT;
static bool on_option(char key, char *value) {

bool res;

switch(key) {
case 'A':
if(strcmp(value, "o") == 0 || strcmp(value, "O") == 0)
ctx.hierarchy = TPM_RH_OWNER;
else if(strcmp(value, "p") == 0 || strcmp(value, "P") == 0)
ctx.hierarchy = TPM_RH_PLATFORM;
else if(strcmp(value, "e") == 0 || strcmp(value, "E") == 0)
ctx.hierarchy = TPM_RH_ENDORSEMENT;
else if(strcmp(value, "n") == 0 || strcmp(value, "N") == 0)
ctx.hierarchy = TPM_RH_NULL;
else {
return false;
}
ctx.flags.A = 1;
break;
case 'P':
res = tpm2_password_util_from_optarg(value, &ctx.session_data.hmac);
if (!res) {
return false;
}
break;
case 'K':
res = tpm2_password_util_from_optarg(value, &ctx.session_data.hmac);
if (!res) {
return false;
}
break;
case 'g':
ctx.nameAlg = tpm2_alg_util_from_optarg(value);
if(ctx.nameAlg == TPM_ALG_ERROR) {
return false;
}
ctx.flags.g = 1;
break;
case 'G':
ctx.type = tpm2_alg_util_from_optarg(value);
if(ctx.type == TPM_ALG_ERROR) {
return false;
}
ctx.flags.G = 1;
break;
case 'C':
ctx.context_file = value;
if(ctx.context_file == NULL || ctx.context_file[0] == '\0') {
return false;
}
ctx.flags.C = 1;
break;
case 'L':
ctx.in_public.t.publicArea.authPolicy.t.size = BUFFER_SIZE(TPM2B_DIGEST, buffer);
if(!files_load_bytes_from_path(value, ctx.in_public.t.publicArea.authPolicy.t.buffer,
&ctx.in_public.t.publicArea.authPolicy.t.size)) {
return false;
}
break;
case 'E':
ctx.is_policy_enforced = true;
break;
case 'S':
if (!tpm2_util_string_to_uint32(value, &ctx.session_data.sessionHandle)) {
return false;
}
break;
}

TPM2B_PUBLIC inPublic = TPM2B_EMPTY_INIT;
TPMI_ALG_PUBLIC type = TPM_ALG_RSA;
TPMI_ALG_HASH nameAlg = TPM_ALG_SHA1;
TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL;
return true;
}

setbuf(stdout, NULL);
setvbuf (stdout, NULL, _IONBF, BUFSIZ);
bool tpm2_tool_onstart(tpm2_options **opts) {

int opt = -1;
const char *optstring = "A:P:K:g:G:C:L:S:E";
static struct option long_options[] = {
const struct option topts[] = {
{"auth",1,NULL,'A'},
{"pwdp",1,NULL,'P'},
{"pwdk",1,NULL,'K'},
Expand All @@ -210,119 +289,33 @@ execute_tool (int argc,
{0,0,0,0}
};

*opts = tpm2_options_new("A:P:K:g:G:C:L:S:E", ARRAY_LEN(topts), topts, on_option, NULL);

return *opts != NULL;
}

int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {

UNUSED(flags);
int returnVal = 0;
int A_flag = 0,
g_flag = 0,
G_flag = 0,
C_flag = 0;
bool is_policy_enforced = false;
char *contextFile = NULL;

while((opt = getopt_long(argc,argv,optstring,long_options,NULL)) != -1)
{
switch(opt)
{
case 'A':
if(strcmp(optarg,"o") == 0 || strcmp(optarg,"O") == 0)
hierarchy = TPM_RH_OWNER;
else if(strcmp(optarg,"p") == 0 || strcmp(optarg,"P") == 0)
hierarchy = TPM_RH_PLATFORM;
else if(strcmp(optarg,"e") == 0 || strcmp(optarg,"E") == 0)
hierarchy = TPM_RH_ENDORSEMENT;
else if(strcmp(optarg,"n") == 0 || strcmp(optarg,"N") == 0)
hierarchy = TPM_RH_NULL;
else
{
return 1;
}
A_flag = 1;
break;

case 'P': {
bool res = tpm2_password_util_from_optarg(optarg, &sessionData.hmac);
if (!res) {
LOG_ERR("Invalid parent key password, got\"%s\"", optarg);
return 1;
}
} break;
case 'K': {
bool res = tpm2_password_util_from_optarg(optarg, &sessionData.hmac);
if (!res) {
LOG_ERR("Invalid new key password, got\"%s\"", optarg);
return 1;
}
} break;
case 'g':
nameAlg = tpm2_alg_util_from_optarg(optarg);
if(nameAlg == TPM_ALG_ERROR)
{
showArgError(optarg, argv[0]);
return 1;
}
tpm2_tool_output("nameAlg = 0x%4.4x\n", nameAlg);
g_flag = 1;
break;
case 'G':
type = tpm2_alg_util_from_optarg(optarg);
if(type == TPM_ALG_ERROR)
{
showArgError(optarg, argv[0]);
return 1;
}
tpm2_tool_output("type = 0x%4.4x\n", type);
G_flag = 1;
break;
case 'C':
contextFile = optarg;
if(contextFile == NULL || contextFile[0] == '\0')
{
return 1;
}
tpm2_tool_output("contextFile = %s\n", contextFile);
C_flag = 1;
break;
case 'L':
inPublic.t.publicArea.authPolicy.t.size = BUFFER_SIZE(TPM2B_DIGEST, buffer);
if(!files_load_bytes_from_path(optarg, inPublic.t.publicArea.authPolicy.t.buffer, &inPublic.t.publicArea.authPolicy.t.size))
{
return 1;
}
break;
case 'E':
is_policy_enforced = true;
break;
case 'S':
if (!tpm2_util_string_to_uint32(optarg, &sessionData.sessionHandle)) {
LOG_ERR("Could not convert session handle to number, got: \"%s\"",
optarg);
return 1;
}
break;
case ':':
LOG_ERR("Argument %c needs a value!", optopt);
return 1;
case '?':
LOG_ERR("Unknown Argument: %c", optopt);
return 1;
default:
LOG_ERR("?? getopt returned character code 0%o ??", opt);
return 1;
}
};

if(A_flag == 1 && g_flag == 1 && G_flag == 1)
{
returnVal = createPrimary(sapi_context, hierarchy, &inPublic, &inSensitive, type, nameAlg, is_policy_enforced);
ctx.sapi_context = sapi_context;

setbuf(stdout, NULL);
setvbuf (stdout, NULL, _IONBF, BUFSIZ);

if (returnVal == 0 && C_flag)
returnVal = files_save_tpm_context_to_file(sapi_context, handle2048rsa, contextFile) != true;
if(returnVal)
if(ctx.flags.A == 1 && ctx.flags.g == 1 && ctx.flags.G == 1) {
returnVal = create_primary();

if (returnVal == 0 && ctx.flags.C) {
returnVal = files_save_tpm_context_to_file(sapi_context, handle2048rsa,
ctx.context_file) != true;
}

if(returnVal) {
return 1;
}
else
{
showArgMismatch(argv[0]);
}
} else {
return 1;
}

Expand Down