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