@@ -421,3 +421,125 @@ mod test_nv_increment {
421421 assert_eq ! ( first_value + 1 , second_value) ;
422422 }
423423}
424+
425+ mod test_nv_extend {
426+ use crate :: common:: create_ctx_with_session;
427+ use tss_esapi:: {
428+ attributes:: NvIndexAttributesBuilder ,
429+ constants:: nv_index_type:: NvIndexType ,
430+ handles:: NvIndexTpmHandle ,
431+ interface_types:: {
432+ algorithm:: HashingAlgorithm ,
433+ reserved_handles:: { NvAuth , Provision } ,
434+ } ,
435+ structures:: { MaxNvBuffer , NvPublicBuilder } ,
436+ } ;
437+
438+ #[ test]
439+ fn test_nv_extend ( ) {
440+ let mut context = create_ctx_with_session ( ) ;
441+ let nv_index = NvIndexTpmHandle :: new ( 0x01500029 ) . unwrap ( ) ;
442+
443+ // Create owner nv public.
444+ let owner_nv_index_attributes = NvIndexAttributesBuilder :: new ( )
445+ . with_owner_write ( true )
446+ . with_owner_read ( true )
447+ . with_orderly ( true )
448+ . with_nv_index_type ( NvIndexType :: Extend )
449+ . build ( )
450+ . expect ( "Failed to create owner nv index attributes" ) ;
451+
452+ let owner_nv_public = NvPublicBuilder :: new ( )
453+ . with_nv_index ( nv_index)
454+ . with_index_name_algorithm ( HashingAlgorithm :: Sha256 )
455+ . with_index_attributes ( owner_nv_index_attributes)
456+ . with_data_area_size ( 32 )
457+ . build ( )
458+ . expect ( "Failed to build NvPublic for owner" ) ;
459+
460+ let owner_nv_index_handle = context
461+ . nv_define_space ( Provision :: Owner , None , owner_nv_public)
462+ . expect ( "Call to nv_define_space failed" ) ;
463+
464+ // Attempt to read an un-"written"/uninitialized NV index that is defined as extend type
465+ let nv_read_result = context. nv_read ( NvAuth :: Owner , owner_nv_index_handle, 32 , 0 ) ;
466+ assert ! ( nv_read_result. is_err( ) ) ;
467+
468+ // Extend NV index with data
469+ let data = MaxNvBuffer :: try_from ( vec ! [ 0x0 ] ) . unwrap ( ) ;
470+ context
471+ . nv_extend ( NvAuth :: Owner , owner_nv_index_handle, data)
472+ . expect ( "Failed to extend NV index" ) ;
473+
474+ // Validate the new state of the index, which was extended by the data
475+ let nv_read_result = context. nv_read ( NvAuth :: Owner , owner_nv_index_handle, 32 , 0 ) ;
476+ let read_data = nv_read_result. expect ( "Call to nv_read failed" ) ;
477+
478+ // Expected value is sha256([0; 32] + [0; 1])
479+ assert_eq ! (
480+ [
481+ 0x7f , 0x9c , 0x9e , 0x31 , 0xac , 0x82 , 0x56 , 0xca , 0x2f , 0x25 , 0x85 , 0x83 , 0xdf , 0x26 ,
482+ 0x2d , 0xbc , 0x7d , 0x6f , 0x68 , 0xf2 , 0xa0 , 0x30 , 0x43 , 0xd5 , 0xc9 , 0x9a , 0x4a , 0xe5 ,
483+ 0xa7 , 0x39 , 0x6c , 0xe9
484+ ] ,
485+ read_data. as_ref( )
486+ ) ;
487+
488+ // Clean up defined NV index
489+ context
490+ . nv_undefine_space ( Provision :: Owner , owner_nv_index_handle)
491+ . expect ( "Call to nv_undefine_space failed" ) ;
492+
493+ // Create platform nv public that is cleared on TPM reset/shutdown
494+ let platform_nv_index_attributes = NvIndexAttributesBuilder :: new ( )
495+ . with_pp_write ( true )
496+ . with_pp_read ( true )
497+ . with_orderly ( true )
498+ . with_platform_create ( true )
499+ . with_nv_index_type ( NvIndexType :: Extend )
500+ . with_clear_stclear ( true )
501+ . build ( )
502+ . expect ( "Failed to create owner nv index attributes" ) ;
503+
504+ let platform_nv_public = NvPublicBuilder :: new ( )
505+ . with_nv_index ( nv_index)
506+ . with_index_name_algorithm ( HashingAlgorithm :: Sha256 )
507+ . with_index_attributes ( platform_nv_index_attributes)
508+ . with_data_area_size ( 32 )
509+ . build ( )
510+ . expect ( "Failed to build NvPublic for owner" ) ;
511+
512+ let platform_nv_index_handle = context
513+ . nv_define_space ( Provision :: Platform , None , platform_nv_public)
514+ . expect ( "Call to nv_define_space failed" ) ;
515+
516+ // Attempt to read an un-"written"/uninitialized NV index that is defined as extend type
517+ let nv_read_result = context. nv_read ( NvAuth :: Platform , platform_nv_index_handle, 32 , 0 ) ;
518+ assert ! ( nv_read_result. is_err( ) ) ;
519+
520+ // Extend NV index with data
521+ let data = MaxNvBuffer :: try_from ( vec ! [ 0x0 ] ) . unwrap ( ) ;
522+ context
523+ . nv_extend ( NvAuth :: Platform , platform_nv_index_handle, data)
524+ . expect ( "Failed to extend NV index" ) ;
525+
526+ // Validate the new state of the index, which was extended by the data
527+ let nv_read_result = context. nv_read ( NvAuth :: Platform , platform_nv_index_handle, 32 , 0 ) ;
528+ let read_data = nv_read_result. expect ( "Call to nv_read failed" ) ;
529+
530+ // Expected value is sha256([0; 32] + [0; 1])
531+ assert_eq ! (
532+ [
533+ 0x7f , 0x9c , 0x9e , 0x31 , 0xac , 0x82 , 0x56 , 0xca , 0x2f , 0x25 , 0x85 , 0x83 , 0xdf , 0x26 ,
534+ 0x2d , 0xbc , 0x7d , 0x6f , 0x68 , 0xf2 , 0xa0 , 0x30 , 0x43 , 0xd5 , 0xc9 , 0x9a , 0x4a , 0xe5 ,
535+ 0xa7 , 0x39 , 0x6c , 0xe9
536+ ] ,
537+ read_data. as_ref( )
538+ ) ;
539+
540+ // Clean up defined NV index
541+ context
542+ . nv_undefine_space ( Provision :: Platform , platform_nv_index_handle)
543+ . expect ( "Call to nv_undefine_space failed" ) ;
544+ }
545+ }
0 commit comments