wlan_common/security/
wep.rsuse fidl_fuchsia_wlan_common_security as fidl_security;
use thiserror::Error;
use crate::security::SecurityError;
pub const WEP40_KEY_BYTES: usize = 5;
pub const WEP104_KEY_BYTES: usize = 13;
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
#[non_exhaustive]
pub enum WepError {
#[error("invalid WEP key size: {0} bytes")]
Size(usize),
#[error("invalid WEP key encoding")]
Encoding,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WepKey {
Wep40([u8; WEP40_KEY_BYTES]),
Wep104([u8; WEP104_KEY_BYTES]),
}
impl WepKey {
pub fn parse(bytes: impl AsRef<[u8]>) -> Result<Self, WepError> {
const WEP40_HEX_ENCODING_BYTES: usize = WEP40_KEY_BYTES * 2;
const WEP104_HEX_ENCODING_BYTES: usize = WEP104_KEY_BYTES * 2;
let bytes = bytes.as_ref();
match bytes.len() {
WEP40_HEX_ENCODING_BYTES | WEP104_HEX_ENCODING_BYTES => {
let bytes = hex::decode(bytes).map_err(|_| WepError::Encoding)?;
Ok(match bytes.len() {
WEP40_KEY_BYTES => WepKey::Wep40(bytes.try_into().unwrap()),
WEP104_KEY_BYTES => WepKey::Wep104(bytes.try_into().unwrap()),
_ => unreachable!(),
})
}
_ => WepKey::try_from_literal_bytes(bytes),
}
}
pub(crate) fn try_from_literal_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, WepError> {
let bytes = bytes.as_ref();
let n = bytes.len();
match n {
WEP40_KEY_BYTES => Ok(WepKey::Wep40(bytes.try_into().unwrap())),
WEP104_KEY_BYTES => Ok(WepKey::Wep104(bytes.try_into().unwrap())),
_ => Err(WepError::Size(n)),
}
}
}
impl AsRef<[u8]> for WepKey {
fn as_ref(&self) -> &[u8] {
match self {
WepKey::Wep40(ref bytes) => bytes,
WepKey::Wep104(ref bytes) => bytes,
}
}
}
impl From<[u8; WEP40_KEY_BYTES]> for WepKey {
fn from(bytes: [u8; WEP40_KEY_BYTES]) -> Self {
WepKey::Wep40(bytes)
}
}
impl From<[u8; WEP104_KEY_BYTES]> for WepKey {
fn from(bytes: [u8; WEP104_KEY_BYTES]) -> Self {
WepKey::Wep104(bytes)
}
}
impl From<WepKey> for Vec<u8> {
fn from(key: WepKey) -> Self {
match key {
WepKey::Wep40(bytes) => bytes.into(),
WepKey::Wep104(bytes) => bytes.into(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WepAuthenticator {
pub key: WepKey,
}
impl From<WepAuthenticator> for fidl_security::Protocol {
fn from(_: WepAuthenticator) -> Self {
fidl_security::Protocol::Wep
}
}
impl From<WepAuthenticator> for fidl_security::WepCredentials {
fn from(authenticator: WepAuthenticator) -> Self {
let key = authenticator.key.into();
fidl_security::WepCredentials { key }
}
}
impl TryFrom<fidl_security::WepCredentials> for WepAuthenticator {
type Error = SecurityError;
fn try_from(credentials: fidl_security::WepCredentials) -> Result<Self, Self::Error> {
let key = WepKey::try_from_literal_bytes(credentials.key)?;
Ok(WepAuthenticator { key })
}
}
#[cfg(test)]
mod tests {
use test_case::test_case;
use crate::security::wep::{WepError, WepKey, WEP104_KEY_BYTES};
#[test_case([0xFF; 5] => Ok(WepKey::Wep40([0xFF; 5])))]
#[test_case("wep40" => Ok(WepKey::Wep40([b'w', b'e', b'p', b'4', b'0'])))]
#[test_case("abcdef0000" => Ok(WepKey::Wep40([0xAB, 0xCD, 0xEF, 0, 0])))]
#[test_case("FFFFFF0000" => Ok(WepKey::Wep40([0xFF, 0xFF, 0xFF, 0, 0])))]
#[test_case("aaaAAA0000" => Ok(WepKey::Wep40([0xAA, 0xAA, 0xAA, 0, 0])))]
#[test_case("authenticates" => Ok(WepKey::Wep104([
b'a', b'u', b't', b'h', b'e', b'n', b't', b'i', b'c', b'a', b't', b'e', b's',
])))]
#[test_case("ffffffffffffffffffffffffff" => Ok(WepKey::Wep104([0xFF; WEP104_KEY_BYTES])))]
#[test_case("abcdef" => Err(WepError::Size(6)))]
#[test_case("abcdefZZZZ" => Err(WepError::Encoding))]
fn parse_wep_key(bytes: impl AsRef<[u8]>) -> Result<WepKey, WepError> {
WepKey::parse(bytes)
}
}