use std::net::{IpAddr,Ipv4Addr,Ipv6Addr};
use std::fmt;
use ikev2_transforms::*;
use ikev2_notify::NotifyType;
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct IkeExchangeType(pub u8);
impl IkeExchangeType {
pub const IKE_SA_INIT : IkeExchangeType = IkeExchangeType(34);
pub const IKE_AUTH : IkeExchangeType = IkeExchangeType(35);
pub const CREATE_CHILD_SA : IkeExchangeType = IkeExchangeType(36);
pub const INFORMATIONAL : IkeExchangeType = IkeExchangeType(37);
}
impl fmt::Debug for IkeExchangeType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
34 => f.write_str("IKE_SA_INIT"),
35 => f.write_str("IKE_AUTH"),
36 => f.write_str("CREATE_CHILD_SA"),
37 => f.write_str("INFORMATIONAL"),
n => f.debug_tuple("IkeExchangeType").field(&n).finish(),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ProtocolID(pub u8);
impl ProtocolID {
pub const IKE : ProtocolID = ProtocolID(1);
pub const AH : ProtocolID = ProtocolID(2);
pub const ESP : ProtocolID = ProtocolID(3);
}
impl fmt::Debug for ProtocolID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
1 => f.write_str("IKE"),
2 => f.write_str("AH"),
3 => f.write_str("ESP"),
n => f.debug_tuple("ProtocolID").field(&n).finish(),
}
}
}
pub const IKEV2_FLAG_INITIATOR : u8 = 0b1000;
pub const IKEV2_FLAG_VERSION : u8 = 0b10000;
pub const IKEV2_FLAG_RESPONSE : u8 = 0b100000;
#[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);
#[allow(non_upper_case_globals)]
impl IkePayloadType {
pub const NoNextPayload : IkePayloadType = IkePayloadType(0);
pub const SecurityAssociation : IkePayloadType = IkePayloadType(33);
pub const KeyExchange : IkePayloadType = IkePayloadType(34);
pub const IdentInitiator : IkePayloadType = IkePayloadType(35);
pub const IdentResponder : IkePayloadType = IkePayloadType(36);
pub const Certificate : IkePayloadType = IkePayloadType(37);
pub const CertificateRequest : IkePayloadType = IkePayloadType(38);
pub const Authentication : IkePayloadType = IkePayloadType(39);
pub const Nonce : IkePayloadType = IkePayloadType(40);
pub const Notify : IkePayloadType = IkePayloadType(41);
pub const Delete : IkePayloadType = IkePayloadType(42);
pub const VendorID : IkePayloadType = IkePayloadType(43);
pub const TrafficSelectorInitiator : IkePayloadType = IkePayloadType(44);
pub const TrafficSelectorResponder : IkePayloadType = IkePayloadType(45);
pub const EncryptedAndAuthenticated : IkePayloadType = IkePayloadType(46);
pub const Configuration : IkePayloadType = IkePayloadType(47);
pub const ExtensibleAuthentication : IkePayloadType = IkePayloadType(48);
}
impl fmt::Debug for IkePayloadType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
0 => f.write_str("NoNextPayload"),
33 => f.write_str("SecurityAssociation"),
34 => f.write_str("KeyExchange"),
35 => f.write_str("IdentInitiator"),
36 => f.write_str("IdentResponder"),
37 => f.write_str("Certificate"),
38 => f.write_str("CertificateRequest"),
39 => f.write_str("Authentication"),
40 => f.write_str("Nonce"),
41 => f.write_str("Notify"),
42 => f.write_str("Delete"),
43 => f.write_str("VendorID"),
44 => f.write_str("TrafficSelectorInitiator"),
45 => f.write_str("TrafficSelectorResponder"),
46 => f.write_str("EncryptedAndAuthenticated"),
47 => f.write_str("Configuration"),
48 => f.write_str("ExtensibleAuthentication"),
n => f.debug_tuple("IkePayloadType").field(&n).finish(),
}
}
}
#[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);
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)]
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)]
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 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>),
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>,
}