@@ -16,6 +16,7 @@ use tss_esapi::attributes::NvIndexAttributesBuilder;
1616use tss_esapi:: handles:: AuthHandle ;
1717use tss_esapi:: interface_types:: algorithm:: { HashingAlgorithm , SymmetricMode } ;
1818use tss_esapi:: interface_types:: ecc:: EccCurve ;
19+ use tss_esapi:: interface_types:: key_bits:: { AesKeyBits , CamelliaKeyBits , Sm4KeyBits } ;
1920use tss_esapi:: interface_types:: reserved_handles:: { Hierarchy , HierarchyAuth , Provision } ;
2021use tss_esapi:: structures:: {
2122 Auth , Data , HashScheme , PcrSelectionList , PcrSelectionListBuilder , PcrSlot , SensitiveData ,
@@ -484,21 +485,130 @@ pub fn parse_ecc_curve(s: &str) -> Result<EccCurve, String> {
484485// Symmetric definition (for sessions)
485486// ---------------------------------------------------------------------------
486487
487- /// Parse a symmetric algorithm definition for session encryption .
488+ /// Parse a symmetric algorithm definition.
488489///
489- /// Accepted values: `aes128cfb`, `aes256cfb`, `xor`, `null`.
490+ /// Accepted formats:
491+ /// - `aes-{128,192,256}-{cfb,cbc,ecb,ofb,ctr}` — AES with key size and mode
492+ /// - `sm4-128-{cfb,cbc,ecb,ofb,ctr}` — SM4 with key size and mode
493+ /// - `camellia-{128,192,256}-{cfb,cbc,ecb,ofb,ctr}` — Camellia with key size and mode
494+ /// - `xor-{sha1,sha256,...}` — XOR with a hashing algorithm
495+ /// - `null` — no symmetric algorithm
496+ ///
497+ /// Legacy shorthand forms `aes128cfb` and `aes256cfb` are also accepted.
490498///
491499/// Intended for use as a clap `value_parser`.
492500pub fn parse_symmetric_definition ( s : & str ) -> Result < SymmetricDefinition , String > {
493- match s. to_lowercase ( ) . as_str ( ) {
494- "aes128cfb" | "aes-128-cfb" => Ok ( SymmetricDefinition :: AES_128_CFB ) ,
495- "aes256cfb" | "aes-256-cfb" => Ok ( SymmetricDefinition :: AES_256_CFB ) ,
496- "xor" => Ok ( SymmetricDefinition :: Xor {
497- hashing_algorithm : HashingAlgorithm :: Sha256 ,
498- } ) ,
499- "null" => Ok ( SymmetricDefinition :: Null ) ,
501+ let lower = s. to_lowercase ( ) ;
502+
503+ // Handle "null" first.
504+ if lower == "null" {
505+ return Ok ( SymmetricDefinition :: Null ) ;
506+ }
507+
508+ // Legacy shorthand aliases for backwards compatibility.
509+ match lower. as_str ( ) {
510+ "aes128cfb" => {
511+ return Ok ( SymmetricDefinition :: Aes {
512+ key_bits : AesKeyBits :: Aes128 ,
513+ mode : SymmetricMode :: Cfb ,
514+ } ) ;
515+ }
516+ "aes256cfb" => {
517+ return Ok ( SymmetricDefinition :: Aes {
518+ key_bits : AesKeyBits :: Aes256 ,
519+ mode : SymmetricMode :: Cfb ,
520+ } ) ;
521+ }
522+ "xor" => {
523+ return Ok ( SymmetricDefinition :: Xor {
524+ hashing_algorithm : HashingAlgorithm :: Sha256 ,
525+ } ) ;
526+ }
527+ _ => { }
528+ }
529+
530+ let parts: Vec < & str > = lower. split ( '-' ) . collect ( ) ;
531+
532+ match parts[ 0 ] {
533+ "aes" => {
534+ if parts. len ( ) != 3 {
535+ return Err ( format ! (
536+ "expected 'aes-<bits>-<mode>' (e.g. aes-128-cfb), got: '{s}'"
537+ ) ) ;
538+ }
539+ let key_bits = match parts[ 1 ] {
540+ "128" => AesKeyBits :: Aes128 ,
541+ "192" => AesKeyBits :: Aes192 ,
542+ "256" => AesKeyBits :: Aes256 ,
543+ _ => {
544+ return Err ( format ! (
545+ "unsupported AES key size: {} (expected 128, 192, or 256)" ,
546+ parts[ 1 ]
547+ ) ) ;
548+ }
549+ } ;
550+ let mode = parse_symmetric_mode ( parts[ 2 ] ) ?;
551+ if mode == SymmetricMode :: Null {
552+ return Err ( format ! ( "unsupported AES symmetric mode: {}" , parts[ 2 ] ) ) ;
553+ } ;
554+ Ok ( SymmetricDefinition :: Aes { key_bits, mode } )
555+ }
556+ "sm4" => {
557+ if parts. len ( ) != 3 {
558+ return Err ( format ! (
559+ "expected 'sm4-128-<mode>' (e.g. sm4-128-cfb), got: '{s}'"
560+ ) ) ;
561+ }
562+ let key_bits = match parts[ 1 ] {
563+ "128" => Sm4KeyBits :: Sm4_128 ,
564+ _ => {
565+ return Err ( format ! (
566+ "unsupported SM4 key size: {} (expected 128)" ,
567+ parts[ 1 ]
568+ ) ) ;
569+ }
570+ } ;
571+ let mode = parse_symmetric_mode ( parts[ 2 ] ) ?;
572+ if mode == SymmetricMode :: Null {
573+ return Err ( format ! ( "unsupported SM4 symmetric mode: {}" , parts[ 2 ] ) ) ;
574+ } ;
575+ Ok ( SymmetricDefinition :: Sm4 { key_bits, mode } )
576+ }
577+ "camellia" => {
578+ if parts. len ( ) != 3 {
579+ return Err ( format ! (
580+ "expected 'camellia-<bits>-<mode>' (e.g. camellia-128-cfb), got: '{s}'"
581+ ) ) ;
582+ }
583+ let key_bits = match parts[ 1 ] {
584+ "128" => CamelliaKeyBits :: Camellia128 ,
585+ "192" => CamelliaKeyBits :: Camellia192 ,
586+ "256" => CamelliaKeyBits :: Camellia256 ,
587+ _ => {
588+ return Err ( format ! (
589+ "unsupported Camellia key size: {} (expected 128, 192, or 256)" ,
590+ parts[ 1 ]
591+ ) ) ;
592+ }
593+ } ;
594+ let mode = parse_symmetric_mode ( parts[ 2 ] ) ?;
595+ if mode == SymmetricMode :: Null {
596+ return Err ( format ! ( "unsupported Camellia symmetric mode: {}" , parts[ 2 ] ) ) ;
597+ } ;
598+ Ok ( SymmetricDefinition :: Camellia { key_bits, mode } )
599+ }
600+ "xor" => {
601+ if parts. len ( ) != 2 {
602+ return Err ( format ! (
603+ "expected 'xor-<hash>' (e.g. xor-sha256), got: '{s}'"
604+ ) ) ;
605+ }
606+ let hashing_algorithm = parse_hashing_algorithm ( parts[ 1 ] ) ?;
607+ Ok ( SymmetricDefinition :: Xor { hashing_algorithm } )
608+ }
500609 _ => Err ( format ! (
501- "unsupported symmetric definition: {s} (supported: aes128cfb, aes256cfb, xor, null)"
610+ "unsupported symmetric algorithm: '{}'; expected aes, sm4, camellia, xor, or null" ,
611+ parts[ 0 ]
502612 ) ) ,
503613 }
504614}
@@ -569,3 +679,50 @@ pub fn parse_tpm2_operation(s: &str) -> Result<u16, String> {
569679 ) ) ,
570680 }
571681}
682+
683+ // ===========================================================================
684+ // Tests
685+ // ===========================================================================
686+
687+ #[ test]
688+ fn symdef_xor_sha384 ( ) {
689+ let def = parse_symmetric_definition ( "xor-sha384" ) . unwrap ( ) ;
690+ assert ! ( matches!(
691+ def,
692+ SymmetricDefinition :: Xor {
693+ hashing_algorithm: HashingAlgorithm :: Sha384 ,
694+ }
695+ ) ) ;
696+ }
697+
698+ #[ test]
699+ fn symdef_xor_sha1 ( ) {
700+ let def = parse_symmetric_definition ( "xor-sha1" ) . unwrap ( ) ;
701+ assert ! ( matches!(
702+ def,
703+ SymmetricDefinition :: Xor {
704+ hashing_algorithm: HashingAlgorithm :: Sha1 ,
705+ }
706+ ) ) ;
707+ }
708+
709+ #[ test]
710+ fn symdef_xor_missing_hash ( ) {
711+ assert ! ( parse_symmetric_definition( "xor" ) . is_err( ) ) ;
712+ }
713+
714+ // Error cases
715+ #[ test]
716+ fn symdef_unknown_algo ( ) {
717+ assert ! ( parse_symmetric_definition( "foobar-128-cfb" ) . is_err( ) ) ;
718+ }
719+
720+ #[ test]
721+ fn symdef_aes_with_null ( ) {
722+ assert ! ( parse_symmetric_definition( "aes-128-null" ) . is_err( ) ) ;
723+ }
724+
725+ #[ test]
726+ fn symdef_empty_string ( ) {
727+ assert ! ( parse_symmetric_definition( "" ) . is_err( ) ) ;
728+ }
0 commit comments