@@ -22,12 +22,16 @@ use sha2::{Digest as Sha2Digest, Sha256, Sha384, Sha512};
2222
2323/// A type implementing RustCrypto-based hash/digest owned traits.
2424/// Compatible with Hubris digest server requirements
25- pub struct RustCryptoController {
26- // No state needed - each operation creates its own context
27- }
25+ /// `RustCrypto`-based cryptographic controller
26+ ///
27+ /// Provides software-based cryptographic operations using the `RustCrypto`
28+ /// ecosystem for Hubris and other embedded environments.
29+ pub struct RustCryptoController { }
2830
2931impl RustCryptoController {
30- pub fn new ( ) -> Self {
32+ /// Creates a new `RustCrypto` controller instance
33+ #[ must_use]
34+ pub const fn new ( ) -> Self {
3135 Self { }
3236 }
3337}
@@ -534,11 +538,12 @@ impl HubrisDigestDevice for RustCryptoController {
534538}
535539
536540#[ cfg( test) ]
541+ #[ allow( clippy:: unwrap_used) ]
537542mod tests {
538543 use super :: * ;
544+ use heapless:: Vec ;
539545
540546 #[ test]
541- #[ allow( clippy:: unwrap_used) ]
542547 fn test_digest_operations ( ) {
543548 // Test SHA-256
544549 let controller = RustCryptoController :: new ( ) ;
@@ -677,4 +682,256 @@ mod tests {
677682 assert ! ( result. is_err( ) ) ;
678683 assert_eq ! ( result. unwrap_err( ) , CryptoError :: InvalidKeyLength ) ;
679684 }
685+
686+ #[ test]
687+ fn test_hubris_digest_integration ( ) {
688+ use openprot_platform_traits_hubris:: { HubrisDigestDevice , HubrisDigestOneShot } ;
689+
690+ let controller = RustCryptoController :: new ( ) ;
691+
692+ // Test SHA-256 one-shot operation
693+ let data = b"Hello, Hubris!" ;
694+ let result = controller. digest_sha256_oneshot ( data) ;
695+ assert ! ( result. is_ok( ) ) ;
696+ let digest = result. unwrap ( ) ;
697+ assert_eq ! ( digest. value. len( ) , 8 ) ; // 8 u32 words = 32 bytes
698+
699+ // Test digest context initialization
700+ let controller = RustCryptoController :: new ( ) ;
701+ let ctx_result = controller. init_digest_sha256 ( ) ;
702+ assert ! ( ctx_result. is_ok( ) ) ;
703+ }
704+
705+ #[ test]
706+ fn test_hubris_hmac_integration ( ) {
707+ use openprot_platform_traits_hubris:: { HubrisDigestDevice , HubrisDigestOneShot } ;
708+
709+ let controller = RustCryptoController :: new ( ) ;
710+ let key_data = b"test_key_123456789012345678901234" ; // 32 bytes
711+
712+ // Test HMAC-SHA256 one-shot operation
713+ let data = b"Hello, Hubris HMAC!" ;
714+ let result = controller. hmac_sha256_oneshot ( key_data, data) ;
715+ assert ! ( result. is_ok( ) ) ;
716+ let mac = result. unwrap ( ) ;
717+ assert_eq ! ( mac. len( ) , 32 ) ; // SHA-256 output is 32 bytes
718+
719+ // Test HMAC context initialization
720+ let controller = RustCryptoController :: new ( ) ;
721+ let key = SecureOwnedKey :: new ( key_data) . unwrap ( ) ;
722+ let ctx_result = controller. init_hmac_sha256 ( key) ;
723+ assert ! ( ctx_result. is_ok( ) ) ;
724+ }
725+
726+ #[ test]
727+ fn test_hubris_key_creation ( ) {
728+ use openprot_platform_traits_hubris:: HubrisDigestDevice ;
729+
730+ // Test key creation with valid sizes
731+ let small_key = b"small" ;
732+ let result = RustCryptoController :: create_hmac_key ( small_key) ;
733+ assert ! ( result. is_ok( ) ) ;
734+
735+ // Test with maximum key size using heapless::Vec for realistic embedded testing
736+ let mut max_key: Vec < u8 , 256 > = Vec :: new ( ) ; // heapless::Vec with capacity 256
737+ max_key
738+ . resize ( RustCryptoController :: MAX_KEY_SIZE , 0 )
739+ . unwrap ( ) ;
740+ let result = RustCryptoController :: create_hmac_key ( & max_key) ;
741+ assert ! ( result. is_ok( ) ) ;
742+
743+ // Test key creation with oversized key
744+ let mut oversized_key: Vec < u8 , 256 > = Vec :: new ( ) ;
745+ oversized_key
746+ . resize ( RustCryptoController :: MAX_KEY_SIZE + 1 , 0 )
747+ . unwrap ( ) ;
748+ let result = RustCryptoController :: create_hmac_key ( & oversized_key) ;
749+ assert ! ( result. is_err( ) ) ;
750+ }
751+
752+ #[ test]
753+ fn test_hubris_error_mapping ( ) {
754+ use openprot_platform_traits_hubris:: { HubrisCryptoError , HubrisDigestDevice } ;
755+
756+ // Test error mapping for oversized keys using heapless::Vec
757+ let mut oversized_key: Vec < u8 , 256 > = Vec :: new ( ) ;
758+ oversized_key
759+ . resize ( RustCryptoController :: MAX_KEY_SIZE + 1 , 0 )
760+ . unwrap ( ) ;
761+ let result = RustCryptoController :: create_hmac_key ( & oversized_key) ;
762+ assert_eq ! ( result. unwrap_err( ) , HubrisCryptoError :: InvalidKeyLength ) ;
763+ }
764+
765+ #[ test]
766+ fn test_hubris_sha256_correctness ( ) {
767+ use openprot_platform_traits_hubris:: HubrisDigestOneShot ;
768+
769+ let controller = RustCryptoController :: new ( ) ;
770+
771+ // Test with known SHA-256 test vector
772+ // Input: "abc"
773+ // Expected SHA-256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
774+ let data = b"abc" ;
775+ let result = controller. digest_sha256_oneshot ( data) . unwrap ( ) ;
776+
777+ // Use the proper as_bytes() method for comparison
778+ let digest_bytes = result. as_bytes ( ) ;
779+
780+ let expected = [
781+ 0xba , 0x78 , 0x16 , 0xbf , 0x8f , 0x01 , 0xcf , 0xea , 0x41 , 0x41 , 0x40 , 0xde , 0x5d , 0xae ,
782+ 0x22 , 0x23 , 0xb0 , 0x03 , 0x61 , 0xa3 , 0x96 , 0x17 , 0x7a , 0x9c , 0xb4 , 0x10 , 0xff , 0x61 ,
783+ 0xf2 , 0x00 , 0x15 , 0xad ,
784+ ] ;
785+
786+ assert_eq ! (
787+ digest_bytes, expected,
788+ "SHA-256 digest does not match expected test vector"
789+ ) ;
790+ }
791+
792+ #[ test]
793+ fn test_hubris_hmac_sha256_correctness ( ) {
794+ use openprot_platform_traits_hubris:: HubrisDigestOneShot ;
795+
796+ let controller = RustCryptoController :: new ( ) ;
797+
798+ // Test with known HMAC-SHA256 test vector from RFC 4231
799+ // Key: "key" (0x6b6579)
800+ // Data: "The quick brown fox jumps over the lazy dog"
801+ // Expected: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
802+ let key = b"key" ;
803+ let data = b"The quick brown fox jumps over the lazy dog" ;
804+
805+ let result = controller. hmac_sha256_oneshot ( key, data) . unwrap ( ) ;
806+
807+ let expected = [
808+ 0xf7 , 0xbc , 0x83 , 0xf4 , 0x30 , 0x53 , 0x84 , 0x24 , 0xb1 , 0x32 , 0x98 , 0xe6 , 0xaa , 0x6f ,
809+ 0xb1 , 0x43 , 0xef , 0x4d , 0x59 , 0xa1 , 0x49 , 0x46 , 0x17 , 0x59 , 0x97 , 0x47 , 0x9d , 0xbc ,
810+ 0x2d , 0x1a , 0x3c , 0xd8 ,
811+ ] ;
812+
813+ assert_eq ! (
814+ result, expected,
815+ "HMAC-SHA256 does not match expected test vector"
816+ ) ;
817+ }
818+
819+ #[ test]
820+ fn test_hubris_digest_context_operations ( ) {
821+ use openprot_hal_blocking:: digest:: owned:: DigestOp ;
822+ use openprot_platform_traits_hubris:: HubrisDigestDevice ;
823+
824+ let controller = RustCryptoController :: new ( ) ;
825+
826+ // Test incremental hashing with known result
827+ // Hash "abc" in parts: "a" + "bc"
828+ let ctx = controller. init_digest_sha256 ( ) . unwrap ( ) ;
829+ let ctx = ctx. update ( b"a" ) . unwrap ( ) ;
830+ let ctx = ctx. update ( b"bc" ) . unwrap ( ) ;
831+ let ( result, _controller) = ctx. finalize ( ) . unwrap ( ) ;
832+
833+ // Should match the same result as hashing "abc" at once
834+ let digest_bytes = result. as_bytes ( ) ;
835+
836+ let expected = [
837+ 0xba , 0x78 , 0x16 , 0xbf , 0x8f , 0x01 , 0xcf , 0xea , 0x41 , 0x41 , 0x40 , 0xde , 0x5d , 0xae ,
838+ 0x22 , 0x23 , 0xb0 , 0x03 , 0x61 , 0xa3 , 0x96 , 0x17 , 0x7a , 0x9c , 0xb4 , 0x10 , 0xff , 0x61 ,
839+ 0xf2 , 0x00 , 0x15 , 0xad ,
840+ ] ;
841+
842+ assert_eq ! (
843+ digest_bytes, expected,
844+ "Incremental SHA-256 digest does not match expected result"
845+ ) ;
846+ }
847+
848+ #[ test]
849+ fn test_hubris_hmac_context_operations ( ) {
850+ use openprot_hal_blocking:: mac:: owned:: MacOp ;
851+ use openprot_platform_traits_hubris:: HubrisDigestDevice ;
852+
853+ let controller = RustCryptoController :: new ( ) ;
854+ let key_data = b"key" ;
855+ let key = SecureOwnedKey :: new ( key_data) . unwrap ( ) ;
856+
857+ // Test incremental HMAC with known result
858+ // HMAC "The quick brown fox jumps over the lazy dog" in parts
859+ let ctx = controller. init_hmac_sha256 ( key) . unwrap ( ) ;
860+ let ctx = ctx. update ( b"The quick brown fox " ) . unwrap ( ) ;
861+ let ctx = ctx. update ( b"jumps over the lazy dog" ) . unwrap ( ) ;
862+ let ( result, _controller) = ctx. finalize ( ) . unwrap ( ) ;
863+
864+ let expected = [
865+ 0xf7 , 0xbc , 0x83 , 0xf4 , 0x30 , 0x53 , 0x84 , 0x24 , 0xb1 , 0x32 , 0x98 , 0xe6 , 0xaa , 0x6f ,
866+ 0xb1 , 0x43 , 0xef , 0x4d , 0x59 , 0xa1 , 0x49 , 0x46 , 0x17 , 0x59 , 0x97 , 0x47 , 0x9d , 0xbc ,
867+ 0x2d , 0x1a , 0x3c , 0xd8 ,
868+ ] ;
869+
870+ assert_eq ! (
871+ result, expected,
872+ "Incremental HMAC-SHA256 does not match expected result"
873+ ) ;
874+ }
875+
876+ #[ test]
877+ fn test_hubris_comprehensive_crypto_demo ( ) {
878+ use openprot_hal_blocking:: digest:: owned:: DigestOp ;
879+ use openprot_hal_blocking:: mac:: owned:: MacOp ;
880+ use openprot_platform_traits_hubris:: { HubrisDigestDevice , HubrisDigestOneShot } ;
881+
882+ // Test 1: SHA-256 One-shot
883+ let controller = RustCryptoController :: new ( ) ;
884+ let message = b"Hello, Hubris crypto world!" ;
885+ let digest = controller. digest_sha256_oneshot ( message) . unwrap ( ) ;
886+ assert_eq ! ( digest. as_bytes( ) . len( ) , 32 ) ; // SHA-256 produces 32 bytes
887+
888+ // Test 2: Incremental SHA-256
889+ let controller = RustCryptoController :: new ( ) ;
890+ let ctx = controller. init_digest_sha256 ( ) . unwrap ( ) ;
891+ let ctx = ctx. update ( b"Hello, " ) . unwrap ( ) ;
892+ let ctx = ctx. update ( b"Hubris crypto " ) . unwrap ( ) ;
893+ let ctx = ctx. update ( b"world!" ) . unwrap ( ) ;
894+ let ( digest_inc, _controller_recovered) = ctx. finalize ( ) . unwrap ( ) ;
895+ assert_eq ! ( digest. as_bytes( ) , digest_inc. as_bytes( ) ) ;
896+
897+ // Test 3: HMAC-SHA256 One-shot
898+ let controller = RustCryptoController :: new ( ) ;
899+ let key_data = b"secure_key_for_hubris_testing_123" ;
900+ let hmac = controller. hmac_sha256_oneshot ( key_data, message) . unwrap ( ) ;
901+ assert_eq ! ( hmac. len( ) , 32 ) ; // HMAC-SHA256 produces 32 bytes
902+
903+ // Test 4: Incremental HMAC-SHA256
904+ let controller = RustCryptoController :: new ( ) ;
905+ let key = SecureOwnedKey :: new ( key_data) . unwrap ( ) ;
906+ let ctx = controller. init_hmac_sha256 ( key) . unwrap ( ) ;
907+ let ctx = ctx. update ( b"Hello, " ) . unwrap ( ) ;
908+ let ctx = ctx. update ( b"Hubris crypto " ) . unwrap ( ) ;
909+ let ctx = ctx. update ( b"world!" ) . unwrap ( ) ;
910+ let ( hmac_inc, _controller_recovered) = ctx. finalize ( ) . unwrap ( ) ;
911+ assert_eq ! ( hmac, hmac_inc) ;
912+
913+ // Test 5: Key Management with heapless::Vec (embedded-friendly)
914+ let mut dynamic_key: Vec < u8 , 64 > = Vec :: new ( ) ;
915+ dynamic_key
916+ . extend_from_slice ( b"dynamic_embedded_key" )
917+ . unwrap ( ) ;
918+ let key_result = RustCryptoController :: create_hmac_key ( & dynamic_key) ;
919+ assert ! ( key_result. is_ok( ) ) ;
920+
921+ // Test 6: Error handling with oversized keys
922+ let mut oversized_key: Vec < u8 , 256 > = Vec :: new ( ) ;
923+ oversized_key
924+ . resize ( RustCryptoController :: MAX_KEY_SIZE + 1 , 0 )
925+ . unwrap ( ) ;
926+ let error_result = RustCryptoController :: create_hmac_key ( & oversized_key) ;
927+ assert ! ( error_result. is_err( ) ) ;
928+
929+ // All operations completed successfully - demonstrates that:
930+ // ✅ RustCrypto backend is fully functional
931+ // ✅ Hubris platform traits properly implemented
932+ // ✅ Memory-safe operations in no_std environment
933+ // ✅ Cryptographically correct results verified
934+ // ✅ heapless::Vec integration working
935+ // ✅ Controller recovery after operations working
936+ }
680937}
0 commit comments