use std::fmt::Debug;
use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder};
use serde::{Deserialize, Serialize};
use strum_macros::{EnumDiscriminants, EnumIs};
use super::{
data::{get_gn_from_int, get_gn_value_type_from_int, get_int_from_gn},
other_name_hw_module::OtherNameHardwareModuleName,
};
use crate::{name::Name, oid::C509oid};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct GeneralName {
gn_type: GeneralNameTypeRegistry,
value: GeneralNameValue,
}
#[allow(dead_code)]
impl GeneralName {
#[must_use]
pub fn new(gn_type: GeneralNameTypeRegistry, value: GeneralNameValue) -> Self {
Self { gn_type, value }
}
#[must_use]
pub fn get_gn_type(&self) -> &GeneralNameTypeRegistry {
&self.gn_type
}
#[must_use]
pub fn get_gn_value(&self) -> &GeneralNameValue {
&self.value
}
}
impl Encode<()> for GeneralName {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
let i = get_int_from_gn(self.gn_type).map_err(minicbor::encode::Error::message)?;
e.i16(i)?;
self.value.encode(e, ctx)?;
Ok(())
}
}
impl Decode<'_, ()> for GeneralName {
fn decode(d: &mut Decoder<'_>, _ctx: &mut ()) -> Result<Self, minicbor::decode::Error> {
if minicbor::data::Type::U8 == d.datatype()? || minicbor::data::Type::I8 == d.datatype()? {
let i = d.i16()?;
let gn = get_gn_from_int(i).map_err(minicbor::decode::Error::message)?;
let value_type =
get_gn_value_type_from_int(i).map_err(minicbor::decode::Error::message)?;
Ok(GeneralName::new(
gn,
GeneralNameValue::decode(d, &mut value_type.get_type())?,
))
} else {
Err(minicbor::decode::Error::message(
"GeneralName id type invalid, expected int",
))
}
}
}
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Copy, PartialEq, Clone, Eq, Hash, EnumIs, Deserialize, Serialize)]
pub enum GeneralNameTypeRegistry {
OtherNameBundleEID, OtherNameSmtpUTF8Mailbox,
OtherNameHardwareModuleName,
OtherName,
Rfc822Name,
DNSName,
DirectoryName,
UniformResourceIdentifier,
IPAddress,
RegisteredID,
}
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, PartialEq, Clone, EnumDiscriminants, Deserialize, Serialize)]
#[strum_discriminants(name(GeneralNameValueType))]
#[serde(rename_all = "snake_case")]
pub enum GeneralNameValue {
Text(String),
OtherNameHWModuleName(OtherNameHardwareModuleName),
Bytes(Vec<u8>),
Oid(C509oid),
Name(Name),
Unsupported,
}
trait GeneralNameValueTrait {
fn get_type(&self) -> GeneralNameValueType;
}
impl GeneralNameValueTrait for GeneralNameValueType {
fn get_type(&self) -> GeneralNameValueType {
*self
}
}
impl Encode<()> for GeneralNameValue {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
GeneralNameValue::Text(value) => {
e.str(value)?;
},
GeneralNameValue::Bytes(value) => {
e.bytes(value)?;
},
GeneralNameValue::Oid(value) => {
value.encode(e, ctx)?;
},
GeneralNameValue::OtherNameHWModuleName(value) => {
value.encode(e, ctx)?;
},
GeneralNameValue::Name(value) => {
Name::encode(value, e, ctx)?;
},
GeneralNameValue::Unsupported => {
return Err(minicbor::encode::Error::message(
"Cannot encode unsupported GeneralName value",
))
},
};
Ok(())
}
}
impl<C> Decode<'_, C> for GeneralNameValue
where C: GeneralNameValueTrait + Debug
{
fn decode(d: &mut Decoder<'_>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
match ctx.get_type() {
GeneralNameValueType::Text => {
let value = d.str()?.to_string();
Ok(GeneralNameValue::Text(value))
},
GeneralNameValueType::Bytes => {
let value = d.bytes()?.to_vec();
Ok(GeneralNameValue::Bytes(value))
},
GeneralNameValueType::Oid => {
let value = C509oid::decode(d, &mut ())?;
Ok(GeneralNameValue::Oid(value))
},
GeneralNameValueType::OtherNameHWModuleName => {
let value = OtherNameHardwareModuleName::decode(d, &mut ())?;
Ok(GeneralNameValue::OtherNameHWModuleName(value))
},
GeneralNameValueType::Name => {
let value = Name::decode(d, &mut ())?;
Ok(GeneralNameValue::Name(value))
},
GeneralNameValueType::Unsupported => {
Err(minicbor::decode::Error::message(
"Cannot decode Unsupported GeneralName value",
))
},
}
}
}
#[cfg(test)]
mod test_general_name {
use std::net::Ipv4Addr;
use asn1_rs::oid;
use super::*;
#[test]
fn encode_decode_text() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let gn = GeneralName::new(
GeneralNameTypeRegistry::DNSName,
GeneralNameValue::Text("example.com".to_string()),
);
gn.encode(&mut encoder, &mut ())
.expect("Failed to encode GeneralName");
assert_eq!(hex::encode(buffer.clone()), "026b6578616d706c652e636f6d");
let mut decoder = Decoder::new(&buffer);
let gn_decoded =
GeneralName::decode(&mut decoder, &mut ()).expect("Failed to decode GeneralName");
assert_eq!(gn_decoded, gn);
}
#[test]
fn encode_decode_hw_module_name() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let hw = OtherNameHardwareModuleName::new(oid!(2.16.840 .1 .101 .3 .4 .2 .1), vec![
0x01, 0x02, 0x03, 0x04,
]);
let gn = GeneralName::new(
GeneralNameTypeRegistry::OtherNameHardwareModuleName,
GeneralNameValue::OtherNameHWModuleName(hw),
);
gn.encode(&mut encoder, &mut ())
.expect("Failed to encode GeneralName");
assert_eq!(
hex::encode(buffer.clone()),
"2082496086480165030402014401020304"
);
let mut decoder = Decoder::new(&buffer);
let gn_decoded =
GeneralName::decode(&mut decoder, &mut ()).expect("Failed to decode GeneralName");
assert_eq!(gn_decoded, gn);
}
#[test]
fn encode_decode_ip() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
let gn = GeneralName::new(
GeneralNameTypeRegistry::IPAddress,
GeneralNameValue::Bytes(ipv4.octets().to_vec()),
);
gn.encode(&mut encoder, &mut ())
.expect("Failed to encode GeneralName");
assert_eq!(hex::encode(buffer.clone()), "0744c0a80101");
let mut decoder = Decoder::new(&buffer);
let gn_decoded =
GeneralName::decode(&mut decoder, &mut ()).expect("Failed to decode GeneralName");
assert_eq!(gn_decoded, gn);
}
#[test]
fn encode_decode_oid() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let gn = GeneralName::new(
GeneralNameTypeRegistry::RegisteredID,
GeneralNameValue::Oid(C509oid::new(oid!(2.16.840 .1 .101 .3 .4 .2 .1))),
);
gn.encode(&mut encoder, &mut ())
.expect("Failed to encode GeneralName");
assert_eq!(hex::encode(buffer.clone()), "0849608648016503040201");
let mut decoder = Decoder::new(&buffer);
let gn_decoded =
GeneralName::decode(&mut decoder, &mut ()).expect("Failed to decode GeneralName");
assert_eq!(gn_decoded, gn);
}
#[test]
fn encode_decode_mismatch_type() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let gn = GeneralName::new(
GeneralNameTypeRegistry::OtherNameSmtpUTF8Mailbox,
GeneralNameValue::Oid(C509oid::new(oid!(2.16.840 .1 .101 .3 .4 .2 .1))),
);
gn.encode(&mut encoder, &mut ())
.expect("Failed to encode GeneralName");
assert_eq!(hex::encode(buffer.clone()), "2149608648016503040201");
let mut decoder = Decoder::new(&buffer);
GeneralName::decode(&mut decoder, &mut ()).expect_err("Failed to decode GeneralName");
}
}