@@ -421,3 +421,125 @@ mod test_nv_increment {
421
421
assert_eq ! ( first_value + 1 , second_value) ;
422
422
}
423
423
}
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