@@ -361,6 +361,78 @@ mod tests {
361361 assert ! ( context_info. flush_context( ) . is_ok( ) ) ;
362362 } // test_attestation_request
363363
364+ #[ tokio:: test]
365+ async fn test_filler_from_hardware_get_attestation_request ( ) {
366+ let _mutex = testing:: lock_tests ( ) . await ;
367+ let context_info_result = context_info:: ContextInfo :: new_from_str (
368+ context_info:: AlgorithmConfigurationString {
369+ tpm_encryption_alg : "rsa" . to_string ( ) ,
370+ tpm_hash_alg : "sha256" . to_string ( ) ,
371+ tpm_signing_alg : "rsassa" . to_string ( ) ,
372+ agent_data_path : "" . to_string ( ) ,
373+ disabled_signing_algorithms : vec ! [ ] ,
374+ } ,
375+ ) ;
376+
377+ let mut context_info = match context_info_result {
378+ Ok ( ctx) => ctx,
379+ Err ( e) => {
380+ println ! ( "Skipping test_filler_from_hardware_get_attestation_request: TPM not available or failed to init: {e:?}" ) ;
381+ return ;
382+ }
383+ } ;
384+
385+ let mut filler = FillerFromHardware :: new ( & mut context_info) ;
386+
387+ let request = filler. get_attestation_request ( ) ;
388+
389+ assert_eq ! ( request. data. type_, "attestation" ) ;
390+ let attributes = request. data . attributes ;
391+ assert_eq ! (
392+ attributes. evidence_supported. len( ) ,
393+ 3 ,
394+ "Should contain tpm_quote, uefi_log, and ima_log evidence"
395+ ) ;
396+
397+ let tpm_quote_evidence = attributes. evidence_supported . iter ( ) . find ( |e| {
398+ matches ! ( e, structures:: EvidenceSupported :: Certification { evidence_type, .. } if evidence_type == "tpm_quote" )
399+ } ) . expect ( "tpm_quote evidence not found" ) ;
400+
401+ if let structures:: EvidenceSupported :: Certification {
402+ capabilities,
403+ ..
404+ } = tpm_quote_evidence
405+ {
406+ assert ! (
407+ !capabilities. hash_algorithms. is_empty( ) ,
408+ "Hash algorithms should be populated from TPM"
409+ ) ;
410+ assert ! (
411+ !capabilities. signature_schemes. is_empty( ) ,
412+ "Signature schemes should be populated from TPM"
413+ ) ;
414+ assert ! (
415+ capabilities. available_subjects. sha256. is_some( ) ,
416+ "SHA256 PCR banks should be populated"
417+ ) ;
418+ assert ! (
419+ !capabilities. certification_keys. is_empty( ) ,
420+ "AK certification key should be present"
421+ ) ;
422+ } else {
423+ panic ! ( "Expected Certification evidence for tpm_quote" ) ;
424+ }
425+
426+ let _ = attributes. evidence_supported . iter ( ) . find ( |e| {
427+ matches ! ( e, structures:: EvidenceSupported :: EvidenceLog { evidence_type, .. } if evidence_type == "ima_log" )
428+ } ) . expect ( "ima_log evidence not found" ) ;
429+
430+ let _ = attributes. evidence_supported . iter ( ) . find ( |e| {
431+ matches ! ( e, structures:: EvidenceSupported :: EvidenceLog { evidence_type, .. } if evidence_type == "uefi_log" )
432+ } ) . expect ( "uefi_log evidence not found" ) ;
433+ assert ! ( context_info. flush_context( ) . is_ok( ) ) ;
434+ }
435+
364436 #[ tokio:: test]
365437 async fn test_session_request ( ) {
366438 use keylime:: context_info;
@@ -482,4 +554,178 @@ mod tests {
482554 . await ;
483555 assert ! ( context_info. flush_context( ) . is_ok( ) ) ;
484556 }
557+
558+ #[ tokio:: test]
559+ async fn test_get_filler_request_with_tpm ( ) {
560+ let _mutex = testing:: lock_tests ( ) . await ;
561+ let context_info_result = context_info:: ContextInfo :: new_from_str (
562+ context_info:: AlgorithmConfigurationString {
563+ tpm_encryption_alg : "rsa" . to_string ( ) ,
564+ tpm_hash_alg : "sha256" . to_string ( ) ,
565+ tpm_signing_alg : "rsassa" . to_string ( ) ,
566+ agent_data_path : "" . to_string ( ) ,
567+ disabled_signing_algorithms : vec ! [ ] ,
568+ } ,
569+ ) ;
570+
571+ if let Ok ( mut ctx) = context_info_result {
572+ {
573+ let mut filler = get_filler_request ( Some ( & mut ctx) ) ;
574+ // To check the type, we can't directly compare types of Box<dyn Trait>.
575+ // A simple way is to check the output of a method.
576+ let req = filler. get_session_request ( ) ;
577+ // FillerFromHardware returns a specific agent_id
578+ assert_eq ! ( req. data. attributes. agent_id, "example-agent" ) ;
579+ }
580+ assert ! ( ctx. clone( ) . flush_context( ) . is_ok( ) ) ;
581+ }
582+ }
583+
584+ #[ tokio:: test]
585+ async fn test_get_filler_request_without_tpm ( ) {
586+ let mut filler = get_filler_request ( None ) ;
587+ // TestingFiller returns an empty auth_supported vector
588+ let req = filler. get_session_request ( ) ;
589+ assert ! ( req. data. attributes. auth_supported. is_empty( ) ) ;
590+ }
591+
592+ #[ tokio:: test]
593+ async fn test_testing_filler_methods ( ) {
594+ let mut filler = TestingFiller :: new ( ) ;
595+
596+ // Test get_attestation_request
597+ let attestation_req = filler. get_attestation_request ( ) ;
598+ assert_eq ! ( attestation_req. data. type_, "attestation" ) ;
599+ assert ! ( attestation_req
600+ . data
601+ . attributes
602+ . evidence_supported
603+ . is_empty( ) ) ;
604+
605+ // Test get_session_request
606+ let session_req = filler. get_session_request ( ) ;
607+ assert_eq ! ( session_req. data. data_type, "session" ) ;
608+ assert ! ( session_req. data. attributes. auth_supported. is_empty( ) ) ;
609+
610+ // Test get_evidence_handling_request
611+ let dummy_response = crate :: attestation:: ResponseInformation {
612+ status_code : reqwest:: StatusCode :: OK ,
613+ headers : reqwest:: header:: HeaderMap :: new ( ) ,
614+ body : "{}" . to_string ( ) ,
615+ } ;
616+ let dummy_config = crate :: attestation:: NegotiationConfig {
617+ avoid_tpm : true ,
618+ url : "" ,
619+ timeout : 0 ,
620+ ca_certificate : "" ,
621+ client_certificate : "" ,
622+ key : "" ,
623+ insecure : None ,
624+ ima_log_path : None ,
625+ uefi_log_path : None ,
626+ max_retries : 0 ,
627+ initial_delay_ms : 0 ,
628+ max_delay_ms : None ,
629+ verifier_url : "" ,
630+ } ;
631+ let evidence_req = filler
632+ . get_evidence_handling_request ( & dummy_response, & dummy_config)
633+ . await ;
634+ assert_eq ! ( evidence_req. data. data_type, "error" ) ;
635+ assert ! ( evidence_req. data. attributes. evidence_collected. is_empty( ) ) ;
636+ }
637+
638+ #[ tokio:: test]
639+ async fn test_filler_from_hardware_new_with_uefi_error ( ) {
640+ let _mutex = testing:: lock_tests ( ) . await ;
641+ let context_info_result = context_info:: ContextInfo :: new_from_str (
642+ context_info:: AlgorithmConfigurationString {
643+ tpm_encryption_alg : "rsa" . to_string ( ) ,
644+ tpm_hash_alg : "sha256" . to_string ( ) ,
645+ tpm_signing_alg : "rsassa" . to_string ( ) ,
646+ agent_data_path : "" . to_string ( ) ,
647+ disabled_signing_algorithms : vec ! [ ] ,
648+ } ,
649+ ) ;
650+
651+ if let Ok ( mut ctx) = context_info_result {
652+ // Temporarily override config to point to a non-existent path
653+ let original_path =
654+ std:: env:: var ( "KEYLIME_CONFIG_PATH" ) . unwrap_or_default ( ) ;
655+ std:: env:: set_var (
656+ "KEYLIME_CONFIG_PATH" ,
657+ "test-data/non-existent-config.conf" ,
658+ ) ;
659+
660+ // Create a temporary config file with an invalid path for measuredboot_ml_path
661+ let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
662+ let config_path = temp_dir. path ( ) . join ( "keylime.conf" ) ;
663+ let mut file = std:: fs:: File :: create ( & config_path) . unwrap ( ) ;
664+ use std:: io:: Write ;
665+ writeln ! ( file, "[agent]" ) . unwrap ( ) ;
666+ writeln ! (
667+ file,
668+ "measuredboot_ml_path = /path/to/non/existent/log"
669+ )
670+ . unwrap ( ) ;
671+ std:: env:: set_var ( "KEYLIME_CONFIG_PATH" , config_path) ;
672+
673+ let filler = FillerFromHardware :: new ( & mut ctx) ;
674+ assert ! ( filler. uefi_log_handler. is_none( ) ) ;
675+
676+ // Restore original config path
677+ std:: env:: set_var ( "KEYLIME_CONFIG_PATH" , original_path) ;
678+ assert ! ( ctx. flush_context( ) . is_ok( ) ) ;
679+ }
680+ }
681+
682+ #[ tokio:: test]
683+ async fn test_get_evidence_handling_request_final_with_parsing_error ( ) {
684+ let _mutex = testing:: lock_tests ( ) . await ;
685+ let context_info_result = context_info:: ContextInfo :: new_from_str (
686+ context_info:: AlgorithmConfigurationString {
687+ tpm_encryption_alg : "rsa" . to_string ( ) ,
688+ tpm_hash_alg : "sha256" . to_string ( ) ,
689+ tpm_signing_alg : "rsassa" . to_string ( ) ,
690+ agent_data_path : "" . to_string ( ) ,
691+ disabled_signing_algorithms : vec ! [ ] ,
692+ } ,
693+ ) ;
694+
695+ if let Ok ( mut ctx) = context_info_result {
696+ let mut filler = FillerFromHardware :: new ( & mut ctx) ;
697+ let malformed_response =
698+ crate :: attestation:: ResponseInformation {
699+ status_code : reqwest:: StatusCode :: CREATED ,
700+ headers : reqwest:: header:: HeaderMap :: new ( ) ,
701+ body : "this is not valid json" . to_string ( ) ,
702+ } ;
703+ let dummy_config = crate :: attestation:: NegotiationConfig {
704+ avoid_tpm : true ,
705+ url : "" ,
706+ timeout : 0 ,
707+ ca_certificate : "" ,
708+ client_certificate : "" ,
709+ key : "" ,
710+ insecure : None ,
711+ ima_log_path : None ,
712+ uefi_log_path : None ,
713+ max_retries : 0 ,
714+ initial_delay_ms : 0 ,
715+ max_delay_ms : None ,
716+ verifier_url : "" ,
717+ } ;
718+
719+ let result = filler
720+ . get_evidence_handling_request_final (
721+ & malformed_response,
722+ & dummy_config,
723+ )
724+ . await ;
725+
726+ assert_eq ! ( result. data. data_type, "error" ) ;
727+ assert ! ( result. data. attributes. evidence_collected. is_empty( ) ) ;
728+ assert ! ( ctx. flush_context( ) . is_ok( ) ) ;
729+ }
730+ }
485731}
0 commit comments