@@ -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}
0 commit comments