ipsec_parser/
ikev2_parser.rs

1use crate::error::IPsecError;
2use crate::ikev2::*;
3use crate::ikev2_notify::NotifyType;
4use crate::ikev2_transforms::*;
5use nom::bytes::streaming::take;
6use nom::combinator::{complete, cond, map, map_parser, verify};
7use nom::error::{make_error, ErrorKind};
8use nom::multi::{count, many1};
9use nom::number::streaming::{be_u16, be_u32, be_u64, be_u8};
10use nom::{Err, IResult, Needed};
11
12pub fn parse_ikev2_header(i: &[u8]) -> IResult<&[u8], IkeV2Header> {
13    if i.len() < 28 {
14        return Err(Err::Incomplete(Needed::new(28)));
15    }
16    let (i, init_spi) = be_u64(i)?;
17    let (i, resp_spi) = be_u64(i)?;
18    let (i, next_payload) = map(be_u8, IkePayloadType)(i)?;
19    let (i, vers) = be_u8(i)?;
20    let maj_ver = vers >> 4;
21    let min_ver = vers & 0b1111;
22    let (i, exch_type) = map(be_u8, IkeExchangeType)(i)?;
23    let (i, flags) = be_u8(i)?;
24    let (i, msg_id) = be_u32(i)?;
25    let (i, length) = be_u32(i)?;
26    let hdr = IkeV2Header {
27        init_spi,
28        resp_spi,
29        next_payload,
30        maj_ver,
31        min_ver,
32        exch_type,
33        flags,
34        msg_id,
35        length,
36    };
37    Ok((i, hdr))
38}
39
40#[inline]
41fn bits_split_1(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
42    let (i, b) = be_u8(i)?;
43    let b1 = b >> 7;
44    let b2_7 = b & 0b_0111_1111;
45    Ok((i, (b1, b2_7)))
46}
47
48pub fn parse_ikev2_payload_generic(i: &[u8]) -> IResult<&[u8], IkeV2GenericPayload> {
49    let (i, next_payload_type) = map(be_u8, IkePayloadType)(i)?;
50    let (i, b) = bits_split_1(i)?;
51    let (i, payload_length) = verify(be_u16, |&n| n >= 4)(i)?;
52    let (i, payload) = take(payload_length - 4)(i)?;
53    let hdr = IkeV2PayloadHeader {
54        next_payload_type,
55        critical: b.0 == 1,
56        reserved: b.1,
57        payload_length,
58    };
59    let payload = IkeV2GenericPayload { hdr, payload };
60    Ok((i, payload))
61}
62
63pub fn parse_ikev2_transform(i: &[u8]) -> IResult<&[u8], IkeV2RawTransform> {
64    let (i, last) = be_u8(i)?;
65    let (i, reserved1) = be_u8(i)?;
66    let (i, transform_length) = be_u16(i)?;
67    let (i, transform_type) = be_u8(i)?;
68    let (i, reserved2) = be_u8(i)?;
69    let (i, transform_id) = be_u16(i)?;
70    // we have to specify a callback here to force lazy evaluation,
71    // because the function arguments are evaluated *before* the test (causing underflow)
72    let (i, attributes) = cond(transform_length > 8, |d| take(transform_length - 8)(d))(i)?;
73    let transform = IkeV2RawTransform {
74        last,
75        reserved1,
76        transform_length,
77        transform_type: IkeTransformType(transform_type),
78        reserved2,
79        transform_id,
80        attributes,
81    };
82    Ok((i, transform))
83}
84
85pub fn parse_ikev2_proposal(i: &[u8]) -> IResult<&[u8], IkeV2Proposal> {
86    if i.len() < 8 {
87        return Err(Err::Incomplete(Needed::new(8)));
88    }
89    let (i, last) = be_u8(i)?;
90    let (i, reserved) = be_u8(i)?;
91    let (i, proposal_length) = be_u16(i)?;
92    let (i, proposal_num) = be_u8(i)?;
93    let (i, protocol_id) = map(be_u8, ProtocolID)(i)?;
94    let (i, spi_size) = be_u8(i)?;
95    let (i, num_transforms) = be_u8(i)?;
96    let (i, spi) = cond(spi_size > 0, take(spi_size))(i)?;
97    if proposal_length < (8u16 + spi_size as u16) {
98        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
99    }
100    let (i, transforms) = map_parser(
101        take(proposal_length - 8 - (spi_size as u16)),
102        count(parse_ikev2_transform, num_transforms as usize),
103    )(i)?;
104    let proposal = IkeV2Proposal {
105        last,
106        reserved,
107        proposal_length,
108        proposal_num,
109        protocol_id,
110        spi_size,
111        num_transforms,
112        spi,
113        transforms,
114    };
115    Ok((i, proposal))
116}
117
118pub fn parse_ikev2_payload_sa(i: &[u8], _length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
119    map(
120        many1(complete(parse_ikev2_proposal)),
121        IkeV2PayloadContent::SA,
122    )(i)
123}
124
125pub fn parse_ikev2_payload_kex(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
126    if length < 4 {
127        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
128    }
129    let (i, dh_group) = map(be_u16, IkeTransformDHType)(i)?;
130    let (i, reserved) = be_u16(i)?;
131    let (i, kex_data) = take(length - 4)(i)?;
132    let payload = KeyExchangePayload {
133        dh_group,
134        reserved,
135        kex_data,
136    };
137    Ok((i, IkeV2PayloadContent::KE(payload)))
138}
139
140pub fn parse_ikev2_payload_ident_init(
141    i: &[u8],
142    length: u16,
143) -> IResult<&[u8], IkeV2PayloadContent> {
144    if length < 4 {
145        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
146    }
147    let (i, id_type) = map(be_u8, IdentificationType)(i)?;
148    let (i, reserved1) = be_u8(i)?;
149    let (i, reserved2) = be_u16(i)?;
150    let (i, ident_data) = take(length - 4)(i)?;
151    let payload = IdentificationPayload {
152        id_type,
153        reserved1,
154        reserved2,
155        ident_data,
156    };
157    Ok((i, IkeV2PayloadContent::IDi(payload)))
158}
159
160pub fn parse_ikev2_payload_ident_resp(
161    i: &[u8],
162    length: u16,
163) -> IResult<&[u8], IkeV2PayloadContent> {
164    if length < 4 {
165        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
166    }
167    let (i, id_type) = map(be_u8, IdentificationType)(i)?;
168    let (i, reserved1) = be_u8(i)?;
169    let (i, reserved2) = be_u16(i)?;
170    let (i, ident_data) = take(length - 4)(i)?;
171    let payload = IdentificationPayload {
172        id_type,
173        reserved1,
174        reserved2,
175        ident_data,
176    };
177    Ok((i, IkeV2PayloadContent::IDr(payload)))
178}
179
180pub fn parse_ikev2_payload_certificate(
181    i: &[u8],
182    length: u16,
183) -> IResult<&[u8], IkeV2PayloadContent> {
184    if length < 1 {
185        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
186    }
187    let (i, cert_encoding) = map(be_u8, CertificateEncoding)(i)?;
188    let (i, cert_data) = take(length - 1)(i)?;
189    let payload = CertificatePayload {
190        cert_encoding,
191        cert_data,
192    };
193    Ok((i, IkeV2PayloadContent::Certificate(payload)))
194}
195
196pub fn parse_ikev2_payload_certificate_request(
197    i: &[u8],
198    length: u16,
199) -> IResult<&[u8], IkeV2PayloadContent> {
200    if length < 1 {
201        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
202    }
203    let (i, cert_encoding) = map(be_u8, CertificateEncoding)(i)?;
204    let (i, ca_data) = take(length - 1)(i)?;
205    let payload = CertificateRequestPayload {
206        cert_encoding,
207        ca_data,
208    };
209    Ok((i, IkeV2PayloadContent::CertificateRequest(payload)))
210}
211
212pub fn parse_ikev2_payload_authentication(
213    i: &[u8],
214    length: u16,
215) -> IResult<&[u8], IkeV2PayloadContent> {
216    if length < 4 {
217        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
218    }
219    let (i, auth_method) = map(be_u8, AuthenticationMethod)(i)?;
220    let (i, auth_data) = take(length - 4)(i)?;
221    let payload = AuthenticationPayload {
222        auth_method,
223        auth_data,
224    };
225    Ok((i, IkeV2PayloadContent::Authentication(payload)))
226}
227
228pub fn parse_ikev2_payload_nonce(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
229    let (i, nonce_data) = take(length)(i)?;
230    Ok((i, IkeV2PayloadContent::Nonce(NoncePayload { nonce_data })))
231}
232
233pub fn parse_ikev2_payload_notify(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
234    let (i, protocol_id) = map(be_u8, ProtocolID)(i)?;
235    let (i, spi_size) = be_u8(i)?;
236    let (i, notify_type) = map(be_u16, NotifyType)(i)?;
237    let (i, spi) = cond(spi_size > 0, take(spi_size))(i)?;
238    let (i, notify_data) = cond(
239        length > 8 + spi_size as u16,
240        // we have to specify a callback here to force lazy evaluation,
241        // because the function arguments are evaluated *before* the test (causing underflow)
242        |d| take(length - (8 + spi_size as u16))(d),
243    )(i)?;
244    let payload = NotifyPayload {
245        protocol_id,
246        spi_size,
247        notify_type,
248        spi,
249        notify_data,
250    };
251    Ok((i, IkeV2PayloadContent::Notify(payload)))
252}
253
254pub fn parse_ikev2_payload_vendor_id(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
255    if length < 8 {
256        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
257    }
258    let (i, vendor_id) = take(length - 8)(i)?;
259    Ok((
260        i,
261        IkeV2PayloadContent::VendorID(VendorIDPayload { vendor_id }),
262    ))
263}
264
265pub fn parse_ikev2_payload_delete(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
266    if length < 8 {
267        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
268    }
269    let (i, protocol_id) = map(be_u8, ProtocolID)(i)?;
270    let (i, spi_size) = be_u8(i)?;
271    let (i, num_spi) = be_u16(i)?;
272    let (i, spi) = take(length - 8)(i)?;
273    let payload = DeletePayload {
274        protocol_id,
275        spi_size,
276        num_spi,
277        spi,
278    };
279    Ok((i, IkeV2PayloadContent::Delete(payload)))
280}
281
282fn parse_ts_addr(i: &[u8], t: TSType) -> IResult<&[u8], &[u8]> {
283    match t {
284        TSType::IPv4AddrRange => take(4usize)(i),
285        TSType::IPv6AddrRange => take(16usize)(i),
286        _ => Err(nom::Err::Error(make_error(i, ErrorKind::Switch))),
287    }
288}
289
290fn parse_ikev2_ts(i: &[u8]) -> IResult<&[u8], TrafficSelector> {
291    let (i, ts_type) = map(be_u8, TSType)(i)?;
292    let (i, ip_proto_id) = be_u8(i)?;
293    let (i, sel_length) = be_u16(i)?;
294    let (i, start_port) = be_u16(i)?;
295    let (i, end_port) = be_u16(i)?;
296    let (i, start_addr) = parse_ts_addr(i, ts_type)?;
297    let (i, end_addr) = parse_ts_addr(i, ts_type)?;
298    let ts = TrafficSelector {
299        ts_type,
300        ip_proto_id,
301        sel_length,
302        start_port,
303        end_port,
304        start_addr,
305        end_addr,
306    };
307    Ok((i, ts))
308}
309
310pub fn parse_ikev2_payload_ts(i: &[u8], length: u16) -> IResult<&[u8], TrafficSelectorPayload> {
311    if length < 4 {
312        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
313    }
314    let (i, num_ts) = be_u8(i)?;
315    let (i, reserved) = take(3usize)(i)?;
316    let (i, ts) = map_parser(take(length - 4), many1(complete(parse_ikev2_ts)))(i)?;
317    let payload = TrafficSelectorPayload {
318        num_ts,
319        reserved,
320        ts,
321    };
322    Ok((i, payload))
323}
324
325pub fn parse_ikev2_payload_ts_init(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
326    map(
327        |d| parse_ikev2_payload_ts(d, length),
328        IkeV2PayloadContent::TSi,
329    )(i)
330}
331
332pub fn parse_ikev2_payload_ts_resp(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
333    map(
334        |d| parse_ikev2_payload_ts(d, length),
335        IkeV2PayloadContent::TSr,
336    )(i)
337}
338
339pub fn parse_ikev2_payload_encrypted(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
340    map(take(length), |d| {
341        IkeV2PayloadContent::Encrypted(EncryptedPayload(d))
342    })(i)
343}
344
345pub fn parse_ikev2_payload_unknown(i: &[u8], length: u16) -> IResult<&[u8], IkeV2PayloadContent> {
346    map(take(length), IkeV2PayloadContent::Unknown)(i)
347}
348
349#[rustfmt::skip]
350pub fn parse_ikev2_payload_with_type(
351    i: &[u8],
352    length: u16,
353    next_payload_type: IkePayloadType,
354) -> IResult<&[u8], IkeV2PayloadContent> {
355    let f = match next_payload_type {
356        // IkePayloadType::NoNextPayload       => parse_ikev2_payload_unknown, // XXX ?
357        IkePayloadType::SecurityAssociation       => parse_ikev2_payload_sa,
358        IkePayloadType::KeyExchange               => parse_ikev2_payload_kex,
359        IkePayloadType::IdentInitiator            => parse_ikev2_payload_ident_init,
360        IkePayloadType::IdentResponder            => parse_ikev2_payload_ident_resp,
361        IkePayloadType::Certificate               => parse_ikev2_payload_certificate,
362        IkePayloadType::CertificateRequest        => parse_ikev2_payload_certificate_request,
363        IkePayloadType::Authentication            => parse_ikev2_payload_authentication,
364        IkePayloadType::Nonce                     => parse_ikev2_payload_nonce,
365        IkePayloadType::Notify                    => parse_ikev2_payload_notify,
366        IkePayloadType::Delete                    => parse_ikev2_payload_delete,
367        IkePayloadType::VendorID                  => parse_ikev2_payload_vendor_id,
368        IkePayloadType::TrafficSelectorInitiator  => parse_ikev2_payload_ts_init,
369        IkePayloadType::TrafficSelectorResponder  => parse_ikev2_payload_ts_resp,
370        IkePayloadType::EncryptedAndAuthenticated => parse_ikev2_payload_encrypted,
371        // None                                               => parse_ikev2_payload_unknown,
372        _ => parse_ikev2_payload_unknown,
373        // _ => panic!("unknown type {}",next_payload_type),
374    };
375    map_parser(take(length),move |d| f(d, length))(i)
376}
377
378fn parse_ikev2_payload_list_fold<'a>(
379    res_v: Result<Vec<IkeV2Payload<'a>>, IPsecError>,
380    p: IkeV2GenericPayload<'a>,
381) -> Result<Vec<IkeV2Payload<'a>>, IPsecError> {
382    let mut v = res_v?;
383    // println!("parse_payload_list_fold: v.len={} p={:?}",v.len(),p);
384    debug_assert!(!v.is_empty());
385    let last_payload = v
386        .last()
387        .expect("parse_payload_list_fold: called with empty input");
388    let next_payload_type = last_payload.hdr.next_payload_type;
389    if p.hdr.payload_length < 4 {
390        return Err(IPsecError::PayloadTooSmall);
391    }
392    match parse_ikev2_payload_with_type(p.payload, p.hdr.payload_length - 4, next_payload_type) {
393        Ok((rem, p2)) => {
394            // let (rem, p2) = parse_ikev2_payload_with_type(p.payload, p.hdr.payload_length - 4, next_payload_type)?;
395            if !rem.is_empty() {
396                return Err(IPsecError::ExtraBytesInPayload); // XXX should this be only a warning?
397            }
398            let payload = IkeV2Payload {
399                hdr: p.hdr.clone(),
400                content: p2,
401            };
402            v.push(payload);
403            Ok(v)
404        }
405        Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(IPsecError::NomError(e.code)),
406        Err(nom::Err::Incomplete(_)) => Err(IPsecError::NomError(ErrorKind::Complete)),
407    }
408}
409
410pub fn parse_ikev2_payload_list(
411    i: &[u8],
412    initial_type: IkePayloadType,
413) -> IResult<&[u8], Result<Vec<IkeV2Payload>, IPsecError>> {
414    // XXX fold manually, because fold_many1 requires accumulator to have Clone, and we don't want
415    // XXX to implement that for IkeV2Payload
416    let mut acc = Ok(vec![IkeV2Payload {
417        hdr: IkeV2PayloadHeader {
418            next_payload_type: initial_type,
419            critical: false,
420            reserved: 0,
421            payload_length: 0,
422        },
423        content: IkeV2PayloadContent::Dummy,
424    }]);
425    #[allow(clippy::clone_double_ref)]
426    let mut i = i.clone();
427    loop {
428        if i.is_empty() {
429            break;
430        }
431
432        let (rem, p) = complete(parse_ikev2_payload_generic)(i)?;
433
434        acc = parse_ikev2_payload_list_fold(acc, p);
435
436        i = rem;
437    }
438    Ok((i, acc))
439    // XXX should we split_first() the vector and return all but the first element ?
440}
441
442/// Parse an IKEv2 message
443///
444/// Parse the IKEv2 header and payload list
445#[allow(clippy::type_complexity)]
446pub fn parse_ikev2_message(
447    i: &[u8],
448) -> IResult<&[u8], (IkeV2Header, Result<Vec<IkeV2Payload>, IPsecError>)> {
449    let (i, hdr) = parse_ikev2_header(i)?;
450    if hdr.length < 28 {
451        return Err(Err::Error(make_error(i, ErrorKind::Verify)));
452    }
453    let (i, msg) = map_parser(take(hdr.length - 28), |d| {
454        parse_ikev2_payload_list(d, hdr.next_payload)
455    })(i)?;
456    Ok((i, (hdr, msg)))
457}
458
459#[cfg(test)]
460mod tests {
461    use crate::ikev2_parser::*;
462
463    #[rustfmt::skip]
464static IKEV2_INIT_REQ: &[u8] = &[
465    0x01, 0xf8, 0xc3, 0xd4, 0xbb, 0x77, 0x3f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466    0x21, 0x20, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x22, 0x00, 0x00, 0x30,
467    0x00, 0x00, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x14,
468    0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x08,
469    0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1e, 0x28, 0x00, 0x00, 0x88,
470    0x00, 0x1e, 0x00, 0x00, 0x8f, 0xe6, 0xf3, 0x6e, 0x88, 0x7b, 0x18, 0x9b, 0x5e, 0xce, 0xf2, 0x56,
471    0xf9, 0x8d, 0x76, 0xaa, 0xcb, 0x07, 0xb3, 0xb9, 0x58, 0xee, 0x73, 0xea, 0x7b, 0x73, 0xb1, 0x04,
472    0x7e, 0xa4, 0x2a, 0x4e, 0x44, 0x1f, 0xb9, 0x3e, 0xf9, 0xa9, 0xab, 0x0c, 0x54, 0x5a, 0xa7, 0x46,
473    0x2e, 0x58, 0x3c, 0x06, 0xb2, 0xed, 0x91, 0x8d, 0x11, 0xca, 0x67, 0xdb, 0x21, 0x6b, 0xb8, 0xad,
474    0xbf, 0x57, 0x3f, 0xba, 0x5a, 0xa6, 0x7d, 0x49, 0x83, 0x4b, 0xa9, 0x93, 0x6f, 0x4c, 0xe9, 0x66,
475    0xcd, 0x57, 0x5c, 0xba, 0x07, 0x42, 0xfa, 0x0b, 0xe8, 0xb9, 0xd0, 0x25, 0xc4, 0xb9, 0xdf, 0x29,
476    0xd7, 0xe4, 0x6e, 0xd6, 0x54, 0x78, 0xaa, 0x95, 0x02, 0xbf, 0x25, 0x55, 0x71, 0xfa, 0x9e, 0xcb,
477    0x05, 0xea, 0x8f, 0x7b, 0x14, 0x0e, 0x1d, 0xdf, 0xb4, 0x03, 0x5f, 0x2d, 0x21, 0x66, 0x58, 0x6e,
478    0x42, 0x72, 0x32, 0x03, 0x29, 0x00, 0x00, 0x24, 0xe3, 0x3b, 0x52, 0xaa, 0x6f, 0x6d, 0x62, 0x87,
479    0x16, 0xd7, 0xab, 0xc6, 0x45, 0xa6, 0xcc, 0x97, 0x07, 0x43, 0x3d, 0x85, 0x83, 0xde, 0xab, 0x97,
480    0xdb, 0xbf, 0x08, 0xce, 0x0f, 0xad, 0x59, 0x71, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x04,
481    0xcc, 0xc0, 0x64, 0x5c, 0x1e, 0xeb, 0xc2, 0x1d, 0x09, 0x2b, 0xf0, 0x7f, 0xca, 0x34, 0xc3, 0xe6,
482    0x2b, 0x20, 0xec, 0x8f, 0x29, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x05, 0x15, 0x39, 0x75, 0x77,
483    0xf5, 0x54, 0x87, 0xa3, 0x8f, 0xd8, 0xaf, 0x70, 0xb0, 0x9c, 0x20, 0x9c, 0xff, 0x4a, 0x37, 0xd1,
484    0x29, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x2f, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
485    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x16
486];
487
488    #[test]
489    fn test_ikev2_init_req() {
490        let empty = &b""[..];
491        let bytes = &IKEV2_INIT_REQ[0..28];
492        let expected = Ok((
493            empty,
494            IkeV2Header {
495                init_spi: 0x01f8c3d4bb773f2f,
496                resp_spi: 0x0,
497                next_payload: IkePayloadType::SecurityAssociation,
498                maj_ver: 2,
499                min_ver: 0,
500                exch_type: IkeExchangeType::IKE_SA_INIT,
501                flags: 0x8,
502                msg_id: 0,
503                length: 328,
504            },
505        ));
506        let res = parse_ikev2_header(bytes);
507        assert_eq!(res, expected);
508    }
509
510    static IKEV2_INIT_RESP: &[u8] = include_bytes!("../assets/ike-sa-init-resp.bin");
511
512    #[test]
513    fn test_ikev2_init_resp() {
514        let bytes = IKEV2_INIT_RESP;
515        let (rem, ref hdr) = parse_ikev2_header(bytes).expect("parsing header failed");
516        let (rem2, res_p) =
517            parse_ikev2_payload_list(rem, hdr.next_payload).expect("parsing payload failed");
518        assert!(rem2.is_empty());
519        let p = res_p.expect("parsing payload failed");
520        // there are 5 items + dummy => 6
521        assert_eq!(p.len(), 6);
522        // first one is always dummy
523        assert_eq!(p[0].content, IkeV2PayloadContent::Dummy);
524    }
525
526    #[rustfmt::skip]
527static IKEV2_PAYLOAD_SA: &[u8] = &[
528    0x22, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x00, 0x03, 0x03, 0x00, 0x00, 0x0c,
529    0x01, 0x00, 0x00, 0x14, 0x80, 0x0e, 0x00, 0x80, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05,
530    0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x1e
531];
532
533    #[test]
534    fn test_ikev2_payload_sa() {
535        let bytes = IKEV2_PAYLOAD_SA;
536        let expected1 = IkeV2GenericPayload {
537            hdr: IkeV2PayloadHeader {
538                next_payload_type: IkePayloadType::KeyExchange,
539                critical: false,
540                reserved: 0,
541                payload_length: 40,
542            },
543            payload: &bytes[4..],
544        };
545        let (_, res) = parse_ikev2_payload_generic(bytes).expect("Failed to parse");
546        assert_eq!(res, expected1);
547        let attrs1 = &[0x80, 0x0e, 0x00, 0x80];
548        let expected2 = IkeV2PayloadContent::SA(vec![IkeV2Proposal {
549            last: 0,
550            reserved: 0,
551            proposal_length: 36,
552            proposal_num: 1,
553            protocol_id: ProtocolID::IKE,
554            spi_size: 0,
555            num_transforms: 3,
556            spi: None,
557            transforms: vec![
558                IkeV2RawTransform {
559                    last: 3,
560                    reserved1: 0,
561                    transform_length: 12,
562                    transform_type: IkeTransformType::EncryptionAlgorithm,
563                    reserved2: 0,
564                    transform_id: 20,
565                    attributes: Some(attrs1),
566                },
567                IkeV2RawTransform {
568                    last: 3,
569                    reserved1: 0,
570                    transform_length: 8,
571                    transform_type: IkeTransformType::PseudoRandomFunction,
572                    reserved2: 0,
573                    transform_id: 5,
574                    attributes: None,
575                },
576                IkeV2RawTransform {
577                    last: 0,
578                    reserved1: 0,
579                    transform_length: 8,
580                    transform_type: IkeTransformType::DiffieHellmanGroup,
581                    reserved2: 0,
582                    transform_id: 30,
583                    attributes: None,
584                },
585            ],
586        }]);
587
588        let (rem, res2) = parse_ikev2_payload_sa(res.payload, 0).expect("Failed to parse");
589        assert!(rem.is_empty());
590        assert_eq!(res2, expected2);
591    }
592
593    #[test]
594    fn test_ikev2_parse_payload_many() {
595        // let empty = &b""[..];
596        let bytes = &IKEV2_INIT_REQ[28..];
597        let res = parse_ikev2_payload_list(bytes, IkePayloadType::SecurityAssociation);
598        println!("{:?}", res);
599    }
600}