use crate::ikev2_notify::NotifyType;
use crate::ikev2_transforms::*;
use rusticata_macros::newtype_enum;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct IkeExchangeType(pub u8);
newtype_enum! {
impl debug IkeExchangeType {
IKE_SA_INIT = 34,
IKE_AUTH = 35,
CREATE_CHILD_SA = 36,
INFORMATIONAL = 37,
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ProtocolID(pub u8);
newtype_enum! {
impl debug ProtocolID {
IKE = 1,
AH = 2,
ESP = 3,
}
}
pub const IKEV2_FLAG_INITIATOR: u8 = 0b1000;
pub const IKEV2_FLAG_VERSION: u8 = 0b1_0000;
pub const IKEV2_FLAG_RESPONSE: u8 = 0b10_0000;
#[derive(Clone, Debug, PartialEq)]
pub struct IkeV2Header {
pub init_spi: u64,
pub resp_spi: u64,
pub next_payload: IkePayloadType,
pub maj_ver: u8,
pub min_ver: u8,
pub exch_type: IkeExchangeType,
pub flags: u8,
pub msg_id: u32,
pub length: u32,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct IkePayloadType(pub u8);
newtype_enum! {
impl debug IkePayloadType {
NoNextPayload = 0,
SecurityAssociation = 33,
KeyExchange = 34,
IdentInitiator = 35,
IdentResponder = 36,
Certificate = 37,
CertificateRequest = 38,
Authentication = 39,
Nonce = 40,
Notify = 41,
Delete = 42,
VendorID = 43,
TrafficSelectorInitiator = 44,
TrafficSelectorResponder = 45,
EncryptedAndAuthenticated = 46,
Configuration = 47,
ExtensibleAuthentication = 48,
}
}
#[derive(Debug, PartialEq)]
pub struct IkeV2GenericPayload<'a> {
pub hdr: IkeV2PayloadHeader,
pub payload: &'a [u8],
}
#[derive(Clone, Debug, PartialEq)]
pub struct IkeV2Proposal<'a> {
pub last: u8,
pub reserved: u8,
pub proposal_length: u16,
pub proposal_num: u8,
pub protocol_id: ProtocolID,
pub spi_size: u8,
pub num_transforms: u8,
pub spi: Option<&'a [u8]>,
pub transforms: Vec<IkeV2RawTransform<'a>>,
}
#[derive(Debug, PartialEq)]
pub struct KeyExchangePayload<'a> {
pub dh_group: IkeTransformDHType,
pub reserved: u16,
pub kex_data: &'a [u8],
}
#[derive(Debug, PartialEq)]
pub struct IdentificationPayload<'a> {
pub id_type: IdentificationType,
pub reserved1: u8,
pub reserved2: u16,
pub ident_data: &'a [u8],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct IdentificationType(pub u8);
#[rustfmt::skip]
impl IdentificationType {
pub const ID_IPV4_ADDR : IdentificationType = IdentificationType(1);
pub const ID_FQDN : IdentificationType = IdentificationType(2);
pub const ID_RFC822_ADDR : IdentificationType = IdentificationType(3);
pub const ID_IPV6_ADDR : IdentificationType = IdentificationType(5);
pub const ID_DER_ASN1_DN : IdentificationType = IdentificationType(9);
pub const ID_DER_ASN1_GN : IdentificationType = IdentificationType(10);
pub const ID_KEY_ID : IdentificationType = IdentificationType(11);
}
#[derive(Debug, PartialEq)]
pub struct CertificatePayload<'a> {
pub cert_encoding: CertificateEncoding,
pub cert_data: &'a [u8],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CertificateEncoding(pub u8);
#[allow(non_upper_case_globals)]
#[rustfmt::skip]
impl CertificateEncoding {
pub const Pkcs7_X509 : CertificateEncoding = CertificateEncoding(1);
pub const PgpCert : CertificateEncoding = CertificateEncoding(2);
pub const DnsKey : CertificateEncoding = CertificateEncoding(3);
pub const X509Sig : CertificateEncoding = CertificateEncoding(4);
pub const Kerberos : CertificateEncoding = CertificateEncoding(6);
pub const Crl : CertificateEncoding = CertificateEncoding(7);
pub const Arl : CertificateEncoding = CertificateEncoding(8);
pub const SpkiCert : CertificateEncoding = CertificateEncoding(9);
pub const X509CertAttr : CertificateEncoding = CertificateEncoding(10);
pub const OldRsaKey : CertificateEncoding = CertificateEncoding(11);
pub const X509Cert_HashUrl : CertificateEncoding = CertificateEncoding(12);
pub const X509Bundle_HashUrl : CertificateEncoding = CertificateEncoding(13);
pub const OCSPContent : CertificateEncoding = CertificateEncoding(14);
pub const RawPublicKey : CertificateEncoding = CertificateEncoding(15);
}
#[derive(Debug, PartialEq)]
pub struct CertificateRequestPayload<'a> {
pub cert_encoding: CertificateEncoding,
pub ca_data: &'a [u8],
}
#[derive(Debug, PartialEq)]
pub struct AuthenticationPayload<'a> {
pub auth_method: AuthenticationMethod,
pub auth_data: &'a [u8],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AuthenticationMethod(pub u8);
#[allow(non_upper_case_globals)]
#[rustfmt::skip]
impl AuthenticationMethod {
pub const RsaSig : AuthenticationMethod = AuthenticationMethod(1);
pub const SharedKeyMIC : AuthenticationMethod = AuthenticationMethod(2);
pub const DssSig : AuthenticationMethod = AuthenticationMethod(3);
pub const EcdsaSha256P256 : AuthenticationMethod = AuthenticationMethod(9);
pub const EcdsaSha384P384 : AuthenticationMethod = AuthenticationMethod(10);
pub const EcdsaSha512P512 : AuthenticationMethod = AuthenticationMethod(11);
pub const GenericPass : AuthenticationMethod = AuthenticationMethod(12);
pub const Null : AuthenticationMethod = AuthenticationMethod(13);
pub const DigitalSig : AuthenticationMethod = AuthenticationMethod(14);
pub fn is_unassigned(self) -> bool {
(self.0 >= 4 && self.0 <= 8) ||
(self.0 >= 15 && self.0 <= 200)
}
pub fn is_private_use(self) -> bool {
self.0 >= 201
}
}
#[derive(PartialEq)]
pub struct NoncePayload<'a> {
pub nonce_data: &'a [u8],
}
#[derive(PartialEq)]
pub struct NotifyPayload<'a> {
pub protocol_id: ProtocolID,
pub spi_size: u8,
pub notify_type: NotifyType,
pub spi: Option<&'a [u8]>,
pub notify_data: Option<&'a [u8]>,
}
#[derive(Debug, PartialEq)]
pub struct DeletePayload<'a> {
pub protocol_id: ProtocolID,
pub spi_size: u8,
pub num_spi: u16,
pub spi: &'a [u8],
}
#[derive(Debug, PartialEq)]
pub struct VendorIDPayload<'a> {
pub vendor_id: &'a [u8],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TSType(pub u8);
#[allow(non_upper_case_globals)]
impl TSType {
pub const IPv4AddrRange: TSType = TSType(7);
pub const IPv6AddrRange: TSType = TSType(8);
pub const FcAddrRange: TSType = TSType(9);
}
#[derive(Debug, PartialEq)]
pub struct TrafficSelector<'a> {
pub ts_type: TSType,
pub ip_proto_id: u8,
pub sel_length: u16,
pub start_port: u16,
pub end_port: u16,
pub start_addr: &'a [u8],
pub end_addr: &'a [u8],
}
fn ipv4_from_slice(b: &[u8]) -> Ipv4Addr {
Ipv4Addr::new(b[0], b[1], b[2], b[3])
}
fn ipv6_from_slice(b: &[u8]) -> Ipv6Addr {
Ipv6Addr::new(
(b[0] as u16) << 8 | (b[1] as u16),
(b[2] as u16) << 8 | (b[3] as u16),
(b[4] as u16) << 8 | (b[5] as u16),
(b[6] as u16) << 8 | (b[7] as u16),
(b[8] as u16) << 8 | (b[9] as u16),
(b[10] as u16) << 8 | (b[11] as u16),
(b[12] as u16) << 8 | (b[13] as u16),
(b[14] as u16) << 8 | (b[15] as u16),
)
}
impl<'a> TrafficSelector<'a> {
pub fn get_ts_type(&self) -> TSType {
self.ts_type
}
pub fn get_start_addr(&self) -> Option<IpAddr> {
match self.ts_type {
TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.start_addr))),
TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.start_addr))),
_ => None,
}
}
pub fn get_end_addr(&self) -> Option<IpAddr> {
match self.ts_type {
TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.end_addr))),
TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.end_addr))),
_ => None,
}
}
}
#[derive(Debug, PartialEq)]
pub struct TrafficSelectorPayload<'a> {
pub num_ts: u8,
pub reserved: &'a [u8], pub ts: Vec<TrafficSelector<'a>>,
}
#[derive(Debug, PartialEq)]
pub struct EncryptedPayload<'a>(pub &'a [u8]);
#[derive(Debug, PartialEq)]
pub enum IkeV2PayloadContent<'a> {
SA(Vec<IkeV2Proposal<'a>>),
KE(KeyExchangePayload<'a>),
IDi(IdentificationPayload<'a>),
IDr(IdentificationPayload<'a>),
Certificate(CertificatePayload<'a>),
CertificateRequest(CertificateRequestPayload<'a>),
Authentication(AuthenticationPayload<'a>),
Nonce(NoncePayload<'a>),
Notify(NotifyPayload<'a>),
Delete(DeletePayload<'a>),
VendorID(VendorIDPayload<'a>),
TSi(TrafficSelectorPayload<'a>),
TSr(TrafficSelectorPayload<'a>),
Encrypted(EncryptedPayload<'a>),
Unknown(&'a [u8]),
Dummy,
}
#[derive(Clone, Debug, PartialEq)]
pub struct IkeV2PayloadHeader {
pub next_payload_type: IkePayloadType,
pub critical: bool,
pub reserved: u8,
pub payload_length: u16,
}
#[derive(Debug, PartialEq)]
pub struct IkeV2Payload<'a> {
pub hdr: IkeV2PayloadHeader,
pub content: IkeV2PayloadContent<'a>,
}