Skip to content

Commit 55cb0ef

Browse files
Merge pull request #22 from hyperfinitism/feature/add-full-sym-enc-types
feat(startauthsession): Add support full symmetric algorithm/bits/mode combinations
2 parents 67986ed + b028165 commit 55cb0ef

2 files changed

Lines changed: 205 additions & 11 deletions

File tree

src/cmd/startauthsession.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub struct StartAuthSessionCmd {
4242
#[arg(long = "audit-session", conflicts_with_all = ["policy_session", "hmac_session"])]
4343
pub audit_session: bool,
4444

45-
/// Symmetric algorithm for session encryption (aes128cfb, aes256cfb, xor, null)
45+
/// Symmetric algorithm for session encryption (e.g. aes-128-cfb, sm4-128-cfb, camellia-256-cbc, xor-sha256, null)
4646
#[arg(long = "symmetric", default_value = "aes128cfb", value_parser = parse::parse_symmetric_definition)]
4747
pub symmetric: SymmetricDefinition,
4848

src/parse.rs

Lines changed: 204 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use tss_esapi::attributes::NvIndexAttributesBuilder;
1616
use tss_esapi::handles::AuthHandle;
1717
use tss_esapi::interface_types::algorithm::{HashingAlgorithm, SymmetricMode};
1818
use tss_esapi::interface_types::ecc::EccCurve;
19+
use tss_esapi::interface_types::key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits};
1920
use tss_esapi::interface_types::reserved_handles::{Hierarchy, HierarchyAuth, Provision};
2021
use 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`.
492500
pub 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,87 @@ pub fn parse_tpm2_operation(s: &str) -> Result<u16, String> {
569679
)),
570680
}
571681
}
682+
683+
// ===========================================================================
684+
// Tests
685+
// ===========================================================================
686+
687+
#[test]
688+
fn symdef_aes_256_cbc() {
689+
let def = parse_symmetric_definition("aes-256-cbc").unwrap();
690+
assert!(matches!(
691+
def,
692+
SymmetricDefinition::Aes {
693+
key_bits: AesKeyBits::Aes256,
694+
mode: SymmetricMode::Cbc,
695+
}
696+
));
697+
}
698+
699+
#[test]
700+
fn symdef_camellia_192_ecb() {
701+
let def = parse_symmetric_definition("camellia-192-ecb").unwrap();
702+
assert!(matches!(
703+
def,
704+
SymmetricDefinition::Camellia {
705+
key_bits: CamelliaKeyBits::Camellia192,
706+
mode: SymmetricMode::Ecb,
707+
}
708+
));
709+
}
710+
711+
#[test]
712+
fn symdef_xor_sha1() {
713+
let def = parse_symmetric_definition("xor-sha1").unwrap();
714+
assert!(matches!(
715+
def,
716+
SymmetricDefinition::Xor {
717+
hashing_algorithm: HashingAlgorithm::Sha1,
718+
}
719+
));
720+
}
721+
722+
// Legacy shorthand forms
723+
#[test]
724+
fn symdef_aes128cfb() {
725+
let def = parse_symmetric_definition("aes128cfb").unwrap();
726+
assert!(matches!(def, SymmetricDefinition::AES_128_CFB));
727+
}
728+
729+
#[test]
730+
fn symdef_aes256cfb() {
731+
let def = parse_symmetric_definition("aes256cfb").unwrap();
732+
assert!(matches!(def, SymmetricDefinition::AES_256_CFB));
733+
}
734+
735+
#[test]
736+
fn symdef_xor() {
737+
let def = parse_symmetric_definition("xor").unwrap();
738+
assert!(matches!(
739+
def,
740+
SymmetricDefinition::Xor {
741+
hashing_algorithm: HashingAlgorithm::Sha256,
742+
}
743+
));
744+
}
745+
746+
// Error cases
747+
#[test]
748+
fn symdef_unknown_algo() {
749+
assert!(parse_symmetric_definition("foobar-128-cfb").is_err());
750+
}
751+
752+
#[test]
753+
fn symdef_aes_128_with_invalid_null_mode() {
754+
assert!(parse_symmetric_definition("aes-128-null").is_err());
755+
}
756+
757+
#[test]
758+
fn symdef_sm4_cbc_with_unavailable_192_bits() {
759+
assert!(parse_symmetric_definition("sm4-192-cbc").is_err());
760+
}
761+
762+
#[test]
763+
fn symdef_empty_string() {
764+
assert!(parse_symmetric_definition("").is_err());
765+
}

0 commit comments

Comments
 (0)