Skip to content

Commit 996c543

Browse files
JuergenReppSITAndreasFuchsTPM
authored andcommitted
FAPI: Enable usage of existing NV indexes for Fapi_NvCreate
Fapi_NvCreate can now create FAPI objects in keystore for existing NV indexes unless the NV index is defined with a policy which does not match the policy defined by Fapi_CreateNv. If a policy is defined but the attributes NV_AUTHWRITE and NV_AUTHREAD are set the object will be created without a policy in keystore. In other cases with a policy Fapi_NvCreate will return TSS2_FAPI_RC_BAD_VALUE. Signed-off-by: Juergen Repp <juergen_repp@web.de>
1 parent d963db1 commit 996c543

4 files changed

Lines changed: 189 additions & 11 deletions

File tree

src/tss2-fapi/api/Fapi_CreateNv.c

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,12 @@ Fapi_CreateNv_Finish(
296296
IFAPI_OBJECT *hierarchy = &nvCmd->auth_object;
297297
IFAPI_NV * miscNv = &(nvCmd->nv_object.misc.nv);
298298
TPM2B_NV_PUBLIC *publicInfo = &miscNv->public;
299+
TPM2B_NV_PUBLIC *existing_nv_public = NULL;
299300
TPM2B_DIGEST * authPolicy = &(miscNv->public.nvPublic.authPolicy);
300301
TPMS_POLICY * policy = &(context->policy.policy);
301302
TPMS_POLICY ** nvCmdPolicy = &nvCmd->nv_object.policy;
302303
ESYS_TR auth_session;
304+
bool nv_exists;
303305

304306
switch (context->state) {
305307
statecase(context->state, NV_CREATE_READ_PROFILE)
@@ -381,8 +383,11 @@ Fapi_CreateNv_Finish(
381383
fallthrough;
382384

383385
statecase(context->state, NV_CREATE_GET_INDEX)
384-
/* Check whether nv index was already defined */
385-
if (!nvCmd->public_templ.public.nvIndex) {
386+
if (nvCmd->public_templ.public.nvIndex) {
387+
/* Check nv index passed by user was already defined*/
388+
context->state = NV_CREATE_CHECK_EXISTING;
389+
return TSS2_FAPI_RC_TRY_AGAIN;
390+
} else {
386391
r = ifapi_get_nv_start_index(nvCmd->nvPath,
387392
&publicInfo->nvPublic.nvIndex);
388393
goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
@@ -396,13 +401,14 @@ Fapi_CreateNv_Finish(
396401
fallthrough;
397402

398403
statecase(context->state, NV_CREATE_FIND_INDEX)
399-
if (!nvCmd->public_templ.public.nvIndex) {
400-
/* Get nv index if not already defined. */
401-
r = ifapi_get_free_handle_finish(context, &publicInfo->nvPublic.nvIndex,
404+
/* Get nv index if not already defined. */
405+
r = ifapi_get_free_handle_finish(context, &publicInfo->nvPublic.nvIndex,
402406
nvCmd->maxNvIndex);
403-
return_try_again(r);
404-
goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
405-
}
407+
return_try_again(r);
408+
goto_if_error_reset_state(r, "FAPI get handle index.", error_cleanup);
409+
410+
fallthrough;
411+
statecase(context->state, NV_CREATE_INDEX)
406412

407413
/* Start a authorization session for the NV creation. */
408414
context->primary_state = PRIMARY_INIT;
@@ -418,11 +424,10 @@ Fapi_CreateNv_Finish(
418424
return_try_again(r);
419425
goto_if_error_reset_state(r, " FAPI create session", error_cleanup);
420426

421-
422427
fallthrough;
423428

424429
statecase(context->state, NV_CREATE_AUTHORIZE_HIERARCHY)
425-
/* Authorize with the storage hierarhcy / "owner" for NV creation. */
430+
/* Authorize with the storage hierarchy "owner" for NV creation. */
426431
r = ifapi_authorize_object(context, &nvCmd->auth_object, &auth_session);
427432
FAPI_SYNC(r, "Authorize hierarchy.", error_cleanup);
428433

@@ -443,8 +448,12 @@ Fapi_CreateNv_Finish(
443448

444449
goto_if_error_reset_state(r, "FAPI CreateWithTemplate_Finish", error_cleanup);
445450

446-
/* Store whether the NV index requires a password. */
447451
nvCmd->nv_object.public.handle = nvHandle;
452+
453+
fallthrough;
454+
455+
statecase(context->state, NV_CREATE_SERIALIZE)
456+
/* Store whether the NV index requires a password. */
448457
if (nvCmd->auth.size > 0)
449458
miscNv->with_auth = TPM2_YES;
450459
else
@@ -481,6 +490,60 @@ Fapi_CreateNv_Finish(
481490

482491
break;
483492

493+
statecase(context->state, NV_CREATE_CHECK_EXISTING)
494+
r = ifapi_check_existing_nv(context, publicInfo->nvPublic.nvIndex, &nv_exists,
495+
&nvCmd->nv_object.public.handle,
496+
&existing_nv_public);
497+
return_try_again(r);
498+
return_if_error_reset_state(r, "checking whether nv index exists failed");
499+
500+
if (nv_exists) {
501+
if (publicInfo->nvPublic.dataSize != existing_nv_public->nvPublic.dataSize) {
502+
LOG_WARNING("Data size from TPM will be used: %u",
503+
existing_nv_public->nvPublic.dataSize);
504+
}
505+
/* Check whether type is equal */
506+
if (!((existing_nv_public->nvPublic.attributes & TPMA_NV_TPM2_NT_MASK) ==
507+
(publicInfo->nvPublic.attributes & TPMA_NV_TPM2_NT_MASK))) {
508+
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
509+
"The existing NV object and the NV object defined "
510+
"have different types.",
511+
error_cleanup);
512+
}
513+
if (existing_nv_public->nvPublic.authPolicy.size) {
514+
if (existing_nv_public->nvPublic.attributes & TPMA_NV_POLICYWRITE &&
515+
existing_nv_public->nvPublic.attributes & TPMA_NV_POLICYREAD) {
516+
/* Check that the two policies are equal */
517+
if (existing_nv_public->nvPublic.authPolicy.size ==
518+
publicInfo->nvPublic.authPolicy.size &&
519+
memcmp(&existing_nv_public->nvPublic.authPolicy.buffer[0],
520+
&publicInfo->nvPublic.authPolicy.buffer[0],
521+
publicInfo->nvPublic.authPolicy.size) == 0) {
522+
context->state = NV_CREATE_SERIALIZE;
523+
} else {
524+
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
525+
"The two policies do not match.",
526+
error_cleanup);
527+
}
528+
} else if ((publicInfo->nvPublic.attributes & TPMA_NV_AUTHWRITE) &&
529+
(publicInfo->nvPublic.attributes & TPMA_NV_AUTHREAD)) {
530+
publicInfo->nvPublic.authPolicy.size = 0;
531+
LOG_WARNING("Policy defined for object will be ignored");
532+
context->state = NV_CREATE_SERIALIZE;
533+
} else {
534+
goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
535+
"Object with policy can't be used in FAPI.",
536+
error_cleanup);
537+
}
538+
} else {
539+
context->state = NV_CREATE_SERIALIZE;
540+
}
541+
*publicInfo = *existing_nv_public;
542+
} else {
543+
context->state = NV_CREATE_INDEX;
544+
}
545+
return TSS2_FAPI_RC_TRY_AGAIN;
546+
484547
statecasedefault(context->state);
485548
}
486549

@@ -498,6 +561,7 @@ Fapi_CreateNv_Finish(
498561
SAFE_FREE(miscNv->policyInstance);
499562
SAFE_FREE(nvCmd->nvPath);
500563
ifapi_session_clean(context);
564+
SAFE_FREE(existing_nv_public);
501565
LOG_TRACE("finished");
502566
return r;
503567
}

src/tss2-fapi/fapi_int.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ enum IFAPI_READ_NV_PUBLIC_STATE {
153153
READ_NV_PUBLIC_GET_PUBLIC
154154
};
155155

156+
/** The states for checking whether an nv index exits */
157+
enum IFAPI_CHECK_NV_STATE {
158+
CHECK_NV_INIT = 0,
159+
CHECK_NV_WAIT_FOR_GET_CAP,
160+
CHECK_NV_GET_ESYS_HANDLE,
161+
CHECK_NV_WAIT_FOR_READ_PUBLIC
162+
};
163+
164+
156165
#define IFAPI_MAX_CAP_INFO 17
157166

158167
typedef struct {
@@ -248,6 +257,8 @@ typedef struct {
248257
IFAPI_EVENT pcr_event; /**< Event to be added to log */
249258
TPML_DIGEST_VALUES digests; /**< Digest for the event data of an extend */
250259
bool skip_policy_computation; /**< switch whether policy needs to be computed */
260+
enum IFAPI_CHECK_NV_STATE nv_check; /**< state for checking existing nv indexes */
261+
TPMS_CAPABILITY_DATA *capability; /* TPM capability data to check nv index */
251262
} IFAPI_NV_Cmds;
252263

253264
/** The data structure holding internal state of Fapi_Initialize command.
@@ -975,6 +986,9 @@ enum FAPI_STATE {
975986
NV_CREATE_AUTH_SENT,
976987
NV_CREATE_WRITE,
977988
NV_CREATE_CALCULATE_POLICY,
989+
NV_CREATE_CHECK_EXISTING,
990+
NV_CREATE_INDEX,
991+
NV_CREATE_SERIALIZE,
978992

979993
NV_WRITE_READ,
980994
NV_WRITE_WRITE,

src/tss2-fapi/fapi_util.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5180,6 +5180,14 @@ ifapi_create_nv_objects(FAPI_CONTEXT *fapi_ctx, IFAPI_CREATE_NV *ctx)
51805180
return TSS2_FAPI_RC_TRY_AGAIN;
51815181
}
51825182

5183+
if (existing_nv_public->nvPublic.authPolicy.size > 0) {
5184+
/* NV objects with existing policy will not be automatically added. */
5185+
ctx->nv_cap_idx++;
5186+
SAFE_FREE(existing_nv_public);
5187+
ctx->state = CREATE_NV_CHECK_NV_INDEX;
5188+
return TSS2_FAPI_RC_TRY_AGAIN;
5189+
}
5190+
51835191
memset(&ctx->nv_object, 0, sizeof(IFAPI_OBJECT));
51845192
ctx->nv_object.objectType = IFAPI_NV_OBJ;
51855193
if (existing_nv_public->nvPublic.attributes & TPMA_NV_PLATFORMCREATE) {
@@ -5254,3 +5262,89 @@ ifapi_create_nv_objects(FAPI_CONTEXT *fapi_ctx, IFAPI_CREATE_NV *ctx)
52545262

52555263
return r;
52565264
}
5265+
5266+
/** Check whether an NV index exist on TPM and in keystore.
5267+
*
5268+
* It will be checked whether an NV index exists in the TPM.
5269+
* An error will be returned if the index already exists in
5270+
* the keystore.
5271+
*
5272+
* @param[in] context The FAPI_CONTEXT.
5273+
* @param[in] template The template which defines the key attributes and whether the
5274+
* key will be persistent.
5275+
* @param[out] The boolean which defines whether the index exists.
5276+
* @retval TSS2_RC_SUCCESS on success.
5277+
* @retval TSS2_FAPI_RC_BAD_VALUE if the index already exists.
5278+
* @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
5279+
* @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
5280+
* @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
5281+
* @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
5282+
* this function needs to be called again.
5283+
* @retval TSS2_FAPI_RC_IO_ERROR if an error occurred while accessing the
5284+
* object store.
5285+
* @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
5286+
* @retval TSS2_FAPI_RC_BAD_PATH if the path is used in inappropriate context
5287+
* or contains illegal characters.
5288+
* @retval TSS2_FAPI_RC_PATH_ALREADY_EXISTS if the object already exists in object store.
5289+
*/
5290+
TSS2_RC
5291+
ifapi_check_existing_nv(FAPI_CONTEXT *context, TPMI_RH_NV_INDEX nv_index, bool *nv_exists,
5292+
ESYS_TR *esys_nv_handle,
5293+
TPM2B_NV_PUBLIC **nvPublic)
5294+
{
5295+
TSS2_RC r;
5296+
*nv_exists = false;
5297+
TPMI_YES_NO moreData;
5298+
TPMS_CAPABILITY_DATA **capabilityData = &context->nv_cmd.capability;
5299+
5300+
switch (context->nv_cmd.nv_check) {
5301+
statecase(context->nv_cmd.nv_check, CHECK_NV_INIT);
5302+
*capabilityData = NULL;
5303+
r = Esys_GetCapability_Async(context->esys,
5304+
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_HANDLES,
5305+
nv_index, 1);
5306+
return_if_error(r, "Esys_GetCapability_Async");
5307+
fallthrough;
5308+
statecase(context->nv_cmd.nv_check, CHECK_NV_WAIT_FOR_GET_CAP);
5309+
r = Esys_GetCapability_Finish(context->esys, &moreData, capabilityData);
5310+
return_try_again(r);
5311+
return_if_error_reset_state(r, "GetCapablity_Finish");
5312+
if ((*capabilityData)->data.handles.count == 0 ||
5313+
(*capabilityData)->data.handles.handle[0] != nv_index) {
5314+
context->nv_cmd.nv_check = CHECK_NV_INIT;
5315+
SAFE_FREE(*capabilityData);
5316+
*nv_exists = false;
5317+
break;
5318+
}
5319+
SAFE_FREE(*capabilityData);
5320+
5321+
r = Esys_TR_FromTPMPublic_Async(context->esys, nv_index,
5322+
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
5323+
return_if_error(r, "Esys_TR_FromTPMPublic_Async");
5324+
5325+
fallthrough;
5326+
5327+
statecase(context->nv_cmd.nv_check, CHECK_NV_GET_ESYS_HANDLE);
5328+
r = Esys_TR_FromTPMPublic_Finish(context->esys, esys_nv_handle);
5329+
return_try_again(r);
5330+
5331+
return_if_error(r, "Esys_TR_FromTPMPublic_Finish");
5332+
5333+
/* Read public from the existing nv object */
5334+
r = Esys_NV_ReadPublic_Async(context->esys, *esys_nv_handle,
5335+
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE);
5336+
return_if_error(r, "Esys_NV_ReadPublic_Async");
5337+
fallthrough;
5338+
5339+
statecase(context->nv_cmd.nv_check, CHECK_NV_WAIT_FOR_READ_PUBLIC);
5340+
r = Esys_NV_ReadPublic_Finish(context->esys, nvPublic, NULL);
5341+
return_try_again(r);
5342+
return_if_error(r, "Error: nv read public");
5343+
*nv_exists = true;
5344+
break;
5345+
statecasedefault(context->cmd.Key_Create.state);
5346+
}
5347+
5348+
return TSS2_RC_SUCCESS;
5349+
5350+
}

src/tss2-fapi/fapi_util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,10 @@ ifapi_create_primary(FAPI_CONTEXT *context, IFAPI_KEY_TEMPLATE *template);
269269

270270
TSS2_RC
271271
ifapi_create_nv_objects(FAPI_CONTEXT *fapi_ctx, IFAPI_CREATE_NV *ctx);
272+
273+
TSS2_RC
274+
ifapi_check_existing_nv(FAPI_CONTEXT *context, TPMI_RH_NV_INDEX nv_index,
275+
bool *nv_exists,
276+
ESYS_TR *esys_nv_handle, TPM2B_NV_PUBLIC **nvPublic);
277+
272278
#endif /* FAPI_UTIL_H */

0 commit comments

Comments
 (0)