use crate::security::sdes::{Sdes, SdesConfig, SdesCryptoAttribute, SdesRole};
use crate::security::SecurityKeyExchange;
use crate::srtp::{SRTP_AES128_CM_SHA1_32, SRTP_AES128_CM_SHA1_80};
#[test]
fn test_sdes_crypto_attribute_parsing() {
let attr_str = "1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
let attr =
SdesCryptoAttribute::parse(attr_str).expect("Failed to parse valid crypto attribute");
assert_eq!(attr.tag, 1);
assert_eq!(attr.crypto_suite, "AES_CM_128_HMAC_SHA1_80");
assert_eq!(attr.key_method, "inline");
assert_eq!(attr.key_info, "PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR");
assert!(attr.session_params.is_empty());
let attr_str = "2 AES_CM_128_HMAC_SHA1_32 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR KDR=1;UNENCRYPTED_SRTP";
let attr =
SdesCryptoAttribute::parse(attr_str).expect("Failed to parse crypto attribute with params");
assert_eq!(attr.tag, 2);
assert_eq!(attr.crypto_suite, "AES_CM_128_HMAC_SHA1_32");
assert_eq!(attr.key_method, "inline");
assert_eq!(attr.key_info, "PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR");
assert_eq!(attr.session_params.len(), 2);
assert_eq!(attr.session_params[0], "KDR=1");
assert_eq!(attr.session_params[1], "UNENCRYPTED_SRTP");
let str_repr = attr.to_string();
assert_eq!(str_repr, "2 AES_CM_128_HMAC_SHA1_32 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR KDR=1;UNENCRYPTED_SRTP");
let invalid_attr = "1 AES_CM_128_HMAC_SHA1_80 inline";
let result = SdesCryptoAttribute::parse(invalid_attr);
assert!(result.is_err());
}
#[test]
fn test_sdes_offer_answer_exchange() {
let offerer_config = SdesConfig {
crypto_suites: vec![SRTP_AES128_CM_SHA1_80, SRTP_AES128_CM_SHA1_32],
offer_count: 2,
};
let mut offerer = Sdes::new(offerer_config, SdesRole::Offerer);
let answerer_config = SdesConfig {
crypto_suites: vec![SRTP_AES128_CM_SHA1_80, SRTP_AES128_CM_SHA1_32],
offer_count: 1,
};
let mut answerer = Sdes::new(answerer_config, SdesRole::Answerer);
offerer.init().expect("Failed to initialize offerer");
answerer.init().expect("Failed to initialize answerer");
let offer_result = offerer
.process_message(b"")
.expect("Failed to create offer");
assert!(offer_result.is_some());
let offer = offer_result.unwrap();
let offer_str = std::str::from_utf8(&offer).expect("Offer is not valid UTF-8");
println!("SDP Offer: {}", offer_str);
assert!(offer_str.contains("a=crypto:"));
assert!(offer_str.contains("AES_CM_128_HMAC_SHA1_80"));
let answer_result = answerer
.process_message(&offer)
.expect("Failed to process offer");
assert!(answer_result.is_some());
let answer = answer_result.unwrap();
let answer_str = std::str::from_utf8(&answer).expect("Answer is not valid UTF-8");
println!("SDP Answer: {}", answer_str);
assert!(answer_str.contains("a=crypto:"));
offerer
.process_message(&answer)
.expect("Failed to process answer");
assert!(offerer.is_complete());
assert!(answerer.is_complete());
assert!(offerer.get_srtp_key().is_some());
assert!(answerer.get_srtp_key().is_some());
assert_eq!(
offerer.get_srtp_key().unwrap().key(),
answerer.get_srtp_key().unwrap().key()
);
assert_eq!(
offerer.get_srtp_key().unwrap().salt(),
answerer.get_srtp_key().unwrap().salt()
);
}
#[test]
fn test_sdes_multiple_crypto_suites() {
let offerer_config = SdesConfig {
crypto_suites: vec![SRTP_AES128_CM_SHA1_80, SRTP_AES128_CM_SHA1_32],
offer_count: 2,
};
let mut offerer = Sdes::new(offerer_config, SdesRole::Offerer);
let answerer_config = SdesConfig {
crypto_suites: vec![SRTP_AES128_CM_SHA1_32, SRTP_AES128_CM_SHA1_80],
offer_count: 1,
};
let mut answerer = Sdes::new(answerer_config, SdesRole::Answerer);
offerer.init().expect("Failed to initialize offerer");
answerer.init().expect("Failed to initialize answerer");
let offer_result = offerer
.process_message(b"")
.expect("Failed to create offer");
assert!(offer_result.is_some());
let offer = offer_result.unwrap();
let offer_str = std::str::from_utf8(&offer).expect("Offer is not valid UTF-8");
assert!(offer_str.contains("AES_CM_128_HMAC_SHA1_80"));
assert!(offer_str.contains("AES_CM_128_HMAC_SHA1_32"));
let answer_result = answerer
.process_message(&offer)
.expect("Failed to process offer");
assert!(answer_result.is_some());
let answer = answer_result.unwrap();
let answer_str = std::str::from_utf8(&answer).expect("Answer is not valid UTF-8");
assert!(answer_str.contains("a=crypto:1"));
offerer
.process_message(&answer)
.expect("Failed to process answer");
assert!(offerer.is_complete());
assert!(answerer.is_complete());
assert_eq!(
offerer.get_srtp_suite().unwrap().tag_length,
answerer.get_srtp_suite().unwrap().tag_length
);
}
#[test]
fn test_sdes_error_handling() {
let answerer_config = SdesConfig::default();
let mut answerer = Sdes::new(answerer_config, SdesRole::Answerer);
let result = answerer.process_message(b"");
assert!(result.is_err());
let invalid_offer = b"a=crypto:1 INVALID_SUITE inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR";
let result = answerer.process_message(invalid_offer);
assert!(result.is_err());
}