1 use crate::ikev2_notify::NotifyType;
2 use crate::ikev2_transforms::*;
3 use std::fmt;
4 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5 
6 /// Payload exchange type: SA, Auth, CreateChildSA, etc.
7 #[derive(Copy, Clone, PartialEq, Eq)]
8 pub struct IkeExchangeType(pub u8);
9 
10 #[rustfmt::skip]
11 impl IkeExchangeType {
12     pub const IKE_SA_INIT     : IkeExchangeType = IkeExchangeType(34);
13     pub const IKE_AUTH        : IkeExchangeType = IkeExchangeType(35);
14     pub const CREATE_CHILD_SA : IkeExchangeType = IkeExchangeType(36);
15     pub const INFORMATIONAL   : IkeExchangeType = IkeExchangeType(37);
16 }
17 
18 impl fmt::Debug for IkeExchangeType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result19     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20         match self.0 {
21             34 => f.write_str("IKE_SA_INIT"),
22             35 => f.write_str("IKE_AUTH"),
23             36 => f.write_str("CREATE_CHILD_SA"),
24             37 => f.write_str("INFORMATIONAL"),
25             n => f.debug_tuple("IkeExchangeType").field(&n).finish(),
26         }
27     }
28 }
29 
30 /// Protocol type: IKE, AH or ESP
31 ///
32 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.1
33 #[derive(Clone, Copy, PartialEq, Eq)]
34 pub struct ProtocolID(pub u8);
35 
36 #[rustfmt::skip]
37 impl ProtocolID {
38     pub const IKE : ProtocolID = ProtocolID(1);
39     pub const AH  : ProtocolID = ProtocolID(2);
40     pub const ESP : ProtocolID = ProtocolID(3);
41 }
42 
43 impl fmt::Debug for ProtocolID {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result44     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45         match self.0 {
46             1 => f.write_str("IKE"),
47             2 => f.write_str("AH"),
48             3 => f.write_str("ESP"),
49             n => f.debug_tuple("ProtocolID").field(&n).finish(),
50         }
51     }
52 }
53 
54 pub const IKEV2_FLAG_INITIATOR: u8 = 0b1000;
55 pub const IKEV2_FLAG_VERSION: u8 = 0b10000;
56 pub const IKEV2_FLAG_RESPONSE: u8 = 0b100000;
57 
58 /// The IKE Header
59 ///
60 /// IKE messages use UDP ports 500 and/or 4500, with one IKE message per
61 /// UDP datagram.  Information from the beginning of the packet through
62 /// the UDP header is largely ignored except that the IP addresses and
63 /// UDP ports from the headers are reversed and used for return packets.
64 /// When sent on UDP port 500, IKE messages begin immediately following
65 /// the UDP header.  When sent on UDP port 4500, IKE messages have
66 /// prepended four octets of zeros.  These four octets of zeros are not
67 /// part of the IKE message and are not included in any of the length
68 /// fields or checksums defined by IKE.  Each IKE message begins with the
69 /// IKE header, denoted HDR in this document.  Following the header are
70 /// one or more IKE payloads each identified by a Next Payload field in
71 /// the preceding payload.  Payloads are identified in the order in which
72 /// they appear in an IKE message by looking in the Next Payload field in
73 /// the IKE header, and subsequently according to the Next Payload field
74 /// in the IKE payload itself until a Next Payload field of zero
75 /// indicates that no payloads follow.  If a payload of type "Encrypted"
76 /// is found, that payload is decrypted and its contents parsed as
77 /// additional payloads.  An Encrypted payload MUST be the last payload
78 /// in a packet and an Encrypted payload MUST NOT contain another
79 /// Encrypted payload.
80 ///
81 /// The responder's SPI in the header identifies an instance of an IKE
82 /// Security Association.  It is therefore possible for a single instance
83 /// of IKE to multiplex distinct sessions with multiple peers, including
84 /// multiple sessions per peer.
85 ///
86 /// All multi-octet fields representing integers are laid out in big
87 /// endian order (also known as "most significant byte first", or
88 /// "network byte order").
89 ///
90 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.1
91 #[derive(Clone, Debug, PartialEq)]
92 pub struct IkeV2Header {
93     pub init_spi: u64,
94     pub resp_spi: u64,
95     pub next_payload: IkePayloadType,
96     pub maj_ver: u8,
97     pub min_ver: u8,
98     pub exch_type: IkeExchangeType,
99     pub flags: u8,
100     pub msg_id: u32,
101     pub length: u32,
102 }
103 
104 /// Payload type
105 #[derive(Clone, Copy, PartialEq, Eq)]
106 pub struct IkePayloadType(pub u8);
107 
108 #[allow(non_upper_case_globals)]
109 #[rustfmt::skip]
110 impl IkePayloadType {
111     pub const NoNextPayload             : IkePayloadType = IkePayloadType(0);
112     pub const SecurityAssociation       : IkePayloadType = IkePayloadType(33);
113     pub const KeyExchange               : IkePayloadType = IkePayloadType(34);
114     pub const IdentInitiator            : IkePayloadType = IkePayloadType(35);
115     pub const IdentResponder            : IkePayloadType = IkePayloadType(36);
116     pub const Certificate               : IkePayloadType = IkePayloadType(37);
117     pub const CertificateRequest        : IkePayloadType = IkePayloadType(38);
118     pub const Authentication            : IkePayloadType = IkePayloadType(39);
119     pub const Nonce                     : IkePayloadType = IkePayloadType(40);
120     pub const Notify                    : IkePayloadType = IkePayloadType(41);
121     pub const Delete                    : IkePayloadType = IkePayloadType(42);
122     pub const VendorID                  : IkePayloadType = IkePayloadType(43);
123     pub const TrafficSelectorInitiator  : IkePayloadType = IkePayloadType(44);
124     pub const TrafficSelectorResponder  : IkePayloadType = IkePayloadType(45);
125     pub const EncryptedAndAuthenticated : IkePayloadType = IkePayloadType(46);
126     pub const Configuration             : IkePayloadType = IkePayloadType(47);
127     pub const ExtensibleAuthentication  : IkePayloadType = IkePayloadType(48);
128 }
129 
130 impl fmt::Debug for IkePayloadType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result131     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132         match self.0 {
133             0 => f.write_str("NoNextPayload"),
134             33 => f.write_str("SecurityAssociation"),
135             34 => f.write_str("KeyExchange"),
136             35 => f.write_str("IdentInitiator"),
137             36 => f.write_str("IdentResponder"),
138             37 => f.write_str("Certificate"),
139             38 => f.write_str("CertificateRequest"),
140             39 => f.write_str("Authentication"),
141             40 => f.write_str("Nonce"),
142             41 => f.write_str("Notify"),
143             42 => f.write_str("Delete"),
144             43 => f.write_str("VendorID"),
145             44 => f.write_str("TrafficSelectorInitiator"),
146             45 => f.write_str("TrafficSelectorResponder"),
147             46 => f.write_str("EncryptedAndAuthenticated"),
148             47 => f.write_str("Configuration"),
149             48 => f.write_str("ExtensibleAuthentication"),
150             n => f.debug_tuple("IkePayloadType").field(&n).finish(),
151         }
152     }
153 }
154 
155 /// Generic (unparsed payload)
156 ///
157 /// Defined in [RFC7296]
158 #[derive(Debug, PartialEq)]
159 pub struct IkeV2GenericPayload<'a> {
160     pub hdr: IkeV2PayloadHeader,
161     pub payload: &'a [u8],
162 }
163 
164 /// Ciphersuite Proposal
165 ///
166 /// The Proposal structure contains within it a Proposal Num and an IPsec
167 /// protocol ID.  Each structure MUST have a proposal number one (1)
168 /// greater than the previous structure.  The first Proposal in the
169 /// initiator's SA payload MUST have a Proposal Num of one (1).  One
170 /// reason to use multiple proposals is to propose both standard crypto
171 /// ciphers and combined-mode ciphers.  Combined-mode ciphers include
172 /// both integrity and encryption in a single encryption algorithm, and
173 /// MUST either offer no integrity algorithm or a single integrity
174 /// algorithm of "NONE", with no integrity algorithm being the
175 /// RECOMMENDED method.  If an initiator wants to propose both combined-
176 /// mode ciphers and normal ciphers, it must include two proposals: one
177 /// will have all the combined-mode ciphers, and the other will have all
178 /// the normal ciphers with the integrity algorithms.  For example, one
179 /// such proposal would have two proposal structures.  Proposal 1 is ESP
180 /// with AES-128, AES-192, and AES-256 bits in Cipher Block Chaining
181 /// (CBC) mode, with either HMAC-SHA1-96 or XCBC-96 as the integrity
182 /// algorithm; Proposal 2 is AES-128 or AES-256 in GCM mode with an
183 /// 8-octet Integrity Check Value (ICV).  Both proposals allow but do not
184 /// require the use of ESNs (Extended Sequence Numbers).  This can be
185 /// illustrated as:
186 ///
187 /// ```ignore
188 /// SA Payload
189 ///    |
190 ///    +--- Proposal #1 ( Proto ID = ESP(3), SPI size = 4,
191 ///    |     |            7 transforms,      SPI = 0x052357bb )
192 ///    |     |
193 ///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
194 ///    |     |     +-- Attribute ( Key Length = 128 )
195 ///    |     |
196 ///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
197 ///    |     |     +-- Attribute ( Key Length = 192 )
198 ///    |     |
199 ///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
200 ///    |     |     +-- Attribute ( Key Length = 256 )
201 ///    |     |
202 ///    |     +-- Transform INTEG ( Name = AUTH_HMAC_SHA1_96 )
203 ///    |     +-- Transform INTEG ( Name = AUTH_AES_XCBC_96 )
204 ///    |     +-- Transform ESN ( Name = ESNs )
205 ///    |     +-- Transform ESN ( Name = No ESNs )
206 ///    |
207 ///    +--- Proposal #2 ( Proto ID = ESP(3), SPI size = 4,
208 ///          |            4 transforms,      SPI = 0x35a1d6f2 )
209 ///          |
210 ///          +-- Transform ENCR ( Name = AES-GCM with a 8 octet ICV )
211 ///          |     +-- Attribute ( Key Length = 128 )
212 ///          |
213 ///          +-- Transform ENCR ( Name = AES-GCM with a 8 octet ICV )
214 ///          |     +-- Attribute ( Key Length = 256 )
215 ///          |
216 ///          +-- Transform ESN ( Name = ESNs )
217 ///          +-- Transform ESN ( Name = No ESNs )
218 /// ```
219 ///
220 /// Each Proposal/Protocol structure is followed by one or more transform
221 /// structures.  The number of different transforms is generally
222 /// determined by the Protocol.  AH generally has two transforms:
223 /// Extended Sequence Numbers (ESNs) and an integrity check algorithm.
224 /// ESP generally has three: ESN, an encryption algorithm, and an
225 /// integrity check algorithm.  IKE generally has four transforms: a
226 /// Diffie-Hellman group, an integrity check algorithm, a PRF algorithm,
227 /// and an encryption algorithm.  For each Protocol, the set of
228 /// permissible transforms is assigned Transform ID numbers, which appear
229 /// in the header of each transform.
230 ///
231 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.1
232 #[derive(Clone, Debug, PartialEq)]
233 pub struct IkeV2Proposal<'a> {
234     pub last: u8,
235     pub reserved: u8,
236     pub proposal_length: u16,
237     pub proposal_num: u8,
238     pub protocol_id: ProtocolID,
239     pub spi_size: u8,
240     pub num_transforms: u8,
241     pub spi: Option<&'a [u8]>,
242     pub transforms: Vec<IkeV2RawTransform<'a>>,
243 }
244 
245 /// Key Exchange Payload
246 ///
247 /// The Key Exchange payload, denoted KE in this document, is used to
248 /// exchange Diffie-Hellman public numbers as part of a Diffie-Hellman
249 /// key exchange.  The Key Exchange payload consists of the IKE generic
250 /// payload header followed by the Diffie-Hellman public value itself.
251 ///
252 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.4
253 #[derive(Debug, PartialEq)]
254 pub struct KeyExchangePayload<'a> {
255     pub dh_group: IkeTransformDHType,
256     pub reserved: u16,
257     pub kex_data: &'a [u8],
258 }
259 
260 /// Identification Payloads
261 ///
262 /// The Identification payloads, denoted IDi and IDr in this document,
263 /// allow peers to assert an identity to one another.  This identity may
264 /// be used for policy lookup, but does not necessarily have to match
265 /// anything in the CERT payload; both fields may be used by an
266 /// implementation to perform access control decisions.  When using the
267 /// ID_IPV4_ADDR/ID_IPV6_ADDR identity types in IDi/IDr payloads, IKEv2
268 /// does not require this address to match the address in the IP header
269 /// of IKEv2 packets, or anything in the TSi/TSr payloads.  The contents
270 /// of IDi/IDr are used purely to fetch the policy and authentication
271 /// data related to the other party.
272 ///
273 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.5
274 #[derive(Debug, PartialEq)]
275 pub struct IdentificationPayload<'a> {
276     pub id_type: IdentificationType,
277     pub reserved1: u8,
278     pub reserved2: u16,
279     pub ident_data: &'a [u8],
280 }
281 
282 /// Type of Identification
283 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
284 pub struct IdentificationType(pub u8);
285 
286 #[rustfmt::skip]
287 impl IdentificationType {
288     /// A single four (4) octet IPv4 address.
289     pub const ID_IPV4_ADDR   : IdentificationType = IdentificationType(1);
290     /// A fully-qualified domain name string.  An example of an ID_FQDN
291     /// is "example.com".  The string MUST NOT contain any terminators
292     /// (e.g., NULL, CR, etc.).  All characters in the ID_FQDN are ASCII;
293     /// for an "internationalized domain name", the syntax is as defined
294     /// in [IDNA], for example "xn--tmonesimerkki-bfbb.example.net".
295     pub const ID_FQDN        : IdentificationType = IdentificationType(2);
296     /// A fully-qualified RFC 822 email address string.  An example of a
297     /// ID_RFC822_ADDR is "jsmith@example.com".  The string MUST NOT
298     /// contain any terminators.  Because of [EAI], implementations would
299     /// be wise to treat this field as UTF-8 encoded text, not as
300     /// pure ASCII.
301     pub const ID_RFC822_ADDR : IdentificationType = IdentificationType(3);
302     /// A single sixteen (16) octet IPv6 address.
303     pub const ID_IPV6_ADDR   : IdentificationType = IdentificationType(5);
304     /// The binary Distinguished Encoding Rules (DER) encoding of an ASN.1 X.500 Distinguished
305     /// Name.
306     pub const ID_DER_ASN1_DN : IdentificationType = IdentificationType(9);
307     /// The binary DER encoding of an ASN.1 X.509 GeneralName.
308     pub const ID_DER_ASN1_GN : IdentificationType = IdentificationType(10);
309     /// An opaque octet stream that may be used to pass vendor-specific information necessary to do
310     /// certain proprietary types of identification.
311     pub const ID_KEY_ID      : IdentificationType = IdentificationType(11);
312 }
313 
314 /// Certificate Payload
315 ///
316 /// The Certificate payload, denoted CERT in this document, provides a
317 /// means to transport certificates or other authentication-related
318 /// information via IKE.  Certificate payloads SHOULD be included in an
319 /// exchange if certificates are available to the sender.  The Hash and
320 /// URL formats of the Certificate payloads should be used in case the
321 /// peer has indicated an ability to retrieve this information from
322 /// elsewhere using an HTTP_CERT_LOOKUP_SUPPORTED Notify payload.  Note
323 /// that the term "Certificate payload" is somewhat misleading, because
324 /// not all authentication mechanisms use certificates and data other
325 /// than certificates may be passed in this payload.
326 ///
327 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.6
328 #[derive(Debug, PartialEq)]
329 pub struct CertificatePayload<'a> {
330     pub cert_encoding: CertificateEncoding,
331     pub cert_data: &'a [u8],
332 }
333 
334 /// Certificate Encoding
335 ///
336 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.6
337 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
338 pub struct CertificateEncoding(pub u8);
339 
340 #[allow(non_upper_case_globals)]
341 #[rustfmt::skip]
342 impl CertificateEncoding {
343     /// PKCS #7 wrapped X.509 certificate
344     pub const Pkcs7_X509                  : CertificateEncoding = CertificateEncoding(1);
345     /// PGP Certificate
346     pub const PgpCert                     : CertificateEncoding = CertificateEncoding(2);
347     /// DNS Signed Key
348     pub const DnsKey                      : CertificateEncoding = CertificateEncoding(3);
349     /// X.509 Certificate - Signature
350     pub const X509Sig                     : CertificateEncoding = CertificateEncoding(4);
351     /// Kerberos Token
352     pub const Kerberos                    : CertificateEncoding = CertificateEncoding(6);
353     /// Certificate Revocation List (CRL)
354     pub const Crl                         : CertificateEncoding = CertificateEncoding(7);
355     /// Authority Revocation List (ARL)
356     pub const Arl                         : CertificateEncoding = CertificateEncoding(8);
357     /// SPKI Certificate
358     pub const SpkiCert                    : CertificateEncoding = CertificateEncoding(9);
359     /// X.509 Certificate - Attribute
360     pub const X509CertAttr                : CertificateEncoding = CertificateEncoding(10);
361     /// Deprecated (was Raw RSA Key)
362     pub const OldRsaKey                   : CertificateEncoding = CertificateEncoding(11);
363     /// Hash and URL of X.509 certificate
364     pub const X509Cert_HashUrl            : CertificateEncoding = CertificateEncoding(12);
365     /// Hash and URL of X.509 bundle
366     pub const X509Bundle_HashUrl          : CertificateEncoding = CertificateEncoding(13);
367     /// OCSP Content ([RFC4806](https://tools.ietf.org/html/rfc4806))
368     pub const OCSPContent                 : CertificateEncoding = CertificateEncoding(14);
369     /// Raw Public Key ([RFC7670](https://tools.ietf.org/html/rfc7670))
370     pub const RawPublicKey                : CertificateEncoding = CertificateEncoding(15);
371 }
372 
373 /// Certificate Request Payload
374 ///
375 /// The Certificate Request payload, denoted CERTREQ in this document,
376 /// provides a means to request preferred certificates via IKE and can
377 /// appear in the IKE_INIT_SA response and/or the IKE_AUTH request.
378 /// Certificate Request payloads MAY be included in an exchange when the
379 /// sender needs to get the certificate of the receiver.
380 ///
381 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.7
382 #[derive(Debug, PartialEq)]
383 pub struct CertificateRequestPayload<'a> {
384     pub cert_encoding: CertificateEncoding,
385     pub ca_data: &'a [u8],
386 }
387 
388 /// Authentication Payload
389 ///
390 /// The Authentication payload, denoted AUTH in this document, contains
391 /// data used for authentication purposes.
392 ///
393 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.8
394 #[derive(Debug, PartialEq)]
395 pub struct AuthenticationPayload<'a> {
396     pub auth_method: AuthenticationMethod,
397     pub auth_data: &'a [u8],
398 }
399 
400 /// Method of authentication used.
401 ///
402 /// See also [IKEV2IANA](https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml) for the latest values.
403 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
404 pub struct AuthenticationMethod(pub u8);
405 
406 #[allow(non_upper_case_globals)]
407 #[rustfmt::skip]
408 impl AuthenticationMethod {
409     /// RSA Digital Signature
410     pub const RsaSig          : AuthenticationMethod = AuthenticationMethod(1);
411     /// Shared Key Message Integrity Code
412     pub const SharedKeyMIC    : AuthenticationMethod = AuthenticationMethod(2);
413     /// DSS Digital Signature
414     pub const DssSig          : AuthenticationMethod = AuthenticationMethod(3);
415     /// ECDSA with SHA-256 on the P-256 curve
416     pub const EcdsaSha256P256 : AuthenticationMethod = AuthenticationMethod(9);
417     /// ECDSA with SHA-384 on the P-384 curve
418     pub const EcdsaSha384P384 : AuthenticationMethod = AuthenticationMethod(10);
419     /// ECDSA with SHA-512 on the P-512 curve
420     pub const EcdsaSha512P512 : AuthenticationMethod = AuthenticationMethod(11);
421     /// Generic Secure Password Authentication Method
422     pub const GenericPass     : AuthenticationMethod = AuthenticationMethod(12);
423     /// NULL Authentication
424     pub const Null            : AuthenticationMethod = AuthenticationMethod(13);
425     /// Digital Signature
426     pub const DigitalSig      : AuthenticationMethod = AuthenticationMethod(14);
427 
428     /// Test if value is in unassigned range
is_unassigned(&self) -> bool429     pub fn is_unassigned(&self) -> bool {
430         (self.0 >= 4 && self.0 <= 8) ||
431         (self.0 >= 15 && self.0 <= 200)
432     }
433 
434     /// Test if value is in private use range
is_private_use(&self) -> bool435     pub fn is_private_use(&self) -> bool {
436         self.0 >= 201
437     }
438 }
439 
440 /// Nonce Payload
441 ///
442 /// The Nonce payload, denoted as Ni and Nr in this document for the
443 /// initiator's and responder's nonce, respectively, contains random data used to guarantee
444 /// liveness during an exchange and protect against replay attacks.
445 ///
446 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.9
447 #[derive(PartialEq)]
448 pub struct NoncePayload<'a> {
449     pub nonce_data: &'a [u8],
450 }
451 
452 /// Notify Payload
453 ///
454 /// The Notify payload, denoted N in this document, is used to transmit informational data, such as
455 /// error conditions and state transitions, to an IKE peer.  A Notify payload may appear in a
456 /// response message (usually specifying why a request was rejected), in an INFORMATIONAL exchange
457 /// (to report an error not in an IKE request), or in any other message to indicate sender
458 /// capabilities or to modify the meaning of the request.
459 ///
460 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.10
461 #[derive(PartialEq)]
462 pub struct NotifyPayload<'a> {
463     pub protocol_id: ProtocolID,
464     pub spi_size: u8,
465     pub notify_type: NotifyType,
466     pub spi: Option<&'a [u8]>,
467     pub notify_data: Option<&'a [u8]>,
468 }
469 
470 /// Delete Payload
471 ///
472 /// The Delete payload, denoted D in this document, contains a
473 /// protocol-specific Security Association identifier that the sender has
474 /// removed from its Security Association database and is, therefore, no
475 /// longer valid.  Figure 17 shows the format of the Delete payload.  It
476 /// is possible to send multiple SPIs in a Delete payload; however, each
477 /// SPI MUST be for the same protocol.  Mixing of protocol identifiers
478 /// MUST NOT be performed in the Delete payload.  It is permitted,
479 /// however, to include multiple Delete payloads in a single
480 /// INFORMATIONAL exchange where each Delete payload lists SPIs for a
481 /// different protocol.
482 ///
483 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.11
484 #[derive(Debug, PartialEq)]
485 pub struct DeletePayload<'a> {
486     pub protocol_id: ProtocolID,
487     pub spi_size: u8,
488     pub num_spi: u16,
489     pub spi: &'a [u8],
490 }
491 
492 /// Vendor ID Payload
493 ///
494 /// The Vendor ID payload, denoted V in this document, contains a vendor-
495 /// defined constant.  The constant is used by vendors to identify and
496 /// recognize remote instances of their implementations.  This mechanism
497 /// allows a vendor to experiment with new features while maintaining
498 /// backward compatibility.
499 ///
500 /// A Vendor ID payload MAY announce that the sender is capable of
501 /// accepting certain extensions to the protocol, or it MAY simply
502 /// identify the implementation as an aid in debugging.  A Vendor ID
503 /// payload MUST NOT change the interpretation of any information defined
504 /// in this specification (i.e., the critical bit MUST be set to 0).
505 /// Multiple Vendor ID payloads MAY be sent.  An implementation is not
506 /// required to send any Vendor ID payload at all.
507 ///
508 /// A Vendor ID payload may be sent as part of any message.  Reception of
509 /// a familiar Vendor ID payload allows an implementation to make use of
510 /// private use numbers described throughout this document, such as
511 /// private payloads, private exchanges, private notifications, etc.
512 /// Unfamiliar Vendor IDs MUST be ignored.
513 ///
514 /// Writers of documents who wish to extend this protocol MUST define a
515 /// Vendor ID payload to announce the ability to implement the extension
516 /// in the document.  It is expected that documents that gain acceptance
517 /// and are standardized will be given "magic numbers" out of the Future
518 /// Use range by IANA, and the requirement to use a Vendor ID will go
519 /// away.
520 ///
521 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.12
522 #[derive(Debug, PartialEq)]
523 pub struct VendorIDPayload<'a> {
524     pub vendor_id: &'a [u8],
525 }
526 
527 /// Type of Traffic Selector
528 ///
529 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13.1
530 ///
531 /// See also [IKEV2IANA](https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml) for the latest values.
532 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
533 pub struct TSType(pub u8);
534 
535 #[allow(non_upper_case_globals)]
536 impl TSType {
537     /// A range of IPv4 addresses
538     pub const IPv4AddrRange: TSType = TSType(7);
539     /// A range of IPv6 addresses
540     pub const IPv6AddrRange: TSType = TSType(8);
541     /// Fibre Channel Traffic Selectors ([RFC4595](https://tools.ietf.org/html/rfc4595))
542     pub const FcAddrRange: TSType = TSType(9);
543 }
544 
545 /// Traffic Selector
546 ///
547 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13.1
548 #[derive(Debug, PartialEq)]
549 pub struct TrafficSelector<'a> {
550     pub ts_type: TSType,
551     pub ip_proto_id: u8,
552     pub sel_length: u16,
553     pub start_port: u16,
554     pub end_port: u16,
555     pub start_addr: &'a [u8],
556     pub end_addr: &'a [u8],
557 }
558 
ipv4_from_slice(b: &[u8]) -> Ipv4Addr559 fn ipv4_from_slice(b: &[u8]) -> Ipv4Addr {
560     Ipv4Addr::new(b[0], b[1], b[2], b[3])
561 }
562 
ipv6_from_slice(b: &[u8]) -> Ipv6Addr563 fn ipv6_from_slice(b: &[u8]) -> Ipv6Addr {
564     Ipv6Addr::new(
565         (b[0] as u16) << 8 | (b[1] as u16),
566         (b[2] as u16) << 8 | (b[3] as u16),
567         (b[4] as u16) << 8 | (b[5] as u16),
568         (b[6] as u16) << 8 | (b[7] as u16),
569         (b[8] as u16) << 8 | (b[9] as u16),
570         (b[10] as u16) << 8 | (b[11] as u16),
571         (b[12] as u16) << 8 | (b[13] as u16),
572         (b[14] as u16) << 8 | (b[15] as u16),
573     )
574 }
575 
576 impl<'a> TrafficSelector<'a> {
get_ts_type(&self) -> TSType577     pub fn get_ts_type(&self) -> TSType {
578         self.ts_type
579     }
580 
get_start_addr(&self) -> Option<IpAddr>581     pub fn get_start_addr(&self) -> Option<IpAddr> {
582         match self.ts_type {
583             TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.start_addr))),
584             TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.start_addr))),
585             _ => None,
586         }
587     }
588 
get_end_addr(&self) -> Option<IpAddr>589     pub fn get_end_addr(&self) -> Option<IpAddr> {
590         match self.ts_type {
591             TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.end_addr))),
592             TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.end_addr))),
593             _ => None,
594         }
595     }
596 }
597 
598 /// Traffic Selector Payload
599 ///
600 /// The Traffic Selector payload, denoted TS in this document, allows
601 /// peers to identify packet flows for processing by IPsec security
602 /// services.  The Traffic Selector payload consists of the IKE generic
603 /// payload header followed by individual Traffic Selectors.
604 ///
605 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13
606 #[derive(Debug, PartialEq)]
607 pub struct TrafficSelectorPayload<'a> {
608     pub num_ts: u8,
609     pub reserved: &'a [u8], // 3 bytes
610     pub ts: Vec<TrafficSelector<'a>>,
611 }
612 
613 /// IKE Message Payload Content
614 ///
615 /// The content of an IKE message is one of the defined payloads.
616 ///
617 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2
618 #[derive(Debug, PartialEq)]
619 pub enum IkeV2PayloadContent<'a> {
620     SA(Vec<IkeV2Proposal<'a>>),
621     KE(KeyExchangePayload<'a>),
622     IDi(IdentificationPayload<'a>),
623     IDr(IdentificationPayload<'a>),
624     Certificate(CertificatePayload<'a>),
625     CertificateRequest(CertificateRequestPayload<'a>),
626     Authentication(AuthenticationPayload<'a>),
627     Nonce(NoncePayload<'a>),
628     Notify(NotifyPayload<'a>),
629     Delete(DeletePayload<'a>),
630     VendorID(VendorIDPayload<'a>),
631     TSi(TrafficSelectorPayload<'a>),
632     TSr(TrafficSelectorPayload<'a>),
633 
634     Unknown(&'a [u8]),
635 
636     Dummy,
637 }
638 
639 /// Generic Payload Header
640 ///
641 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2
642 #[derive(Clone, Debug, PartialEq)]
643 pub struct IkeV2PayloadHeader {
644     pub next_payload_type: IkePayloadType,
645     pub critical: bool,
646     pub reserved: u8,
647     pub payload_length: u16,
648 }
649 
650 /// IKE Message Payload
651 ///
652 /// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3
653 #[derive(Debug, PartialEq)]
654 pub struct IkeV2Payload<'a> {
655     pub hdr: IkeV2PayloadHeader,
656     pub content: IkeV2PayloadContent<'a>,
657 }
658