foctet-core 0.2.0

Foctet Core protocol: framing, handshake, traffic keys, replay protection
Documentation
use foctet_core::{
    Direction, Frame, FrameHeader, TrafficKeys, decrypt_frame, encrypt_frame,
    frame::{PROFILE_X25519_HKDF_XCHACHA20POLY1305, flags},
    payload::{Tlv, decode_tlvs, encode_tlvs, tlv_type},
};
use proptest::prelude::*;

proptest! {
    #![proptest_config(ProptestConfig::with_cases(64))]

    #[test]
    fn frame_parser_never_panics_on_random_input(data in proptest::collection::vec(any::<u8>(), 0..8192)) {
        let _ = Frame::from_bytes(&data);
    }

    #[test]
    fn frame_roundtrip_holds_for_generated_header(
        stream_id in any::<u32>(),
        seq in any::<u64>(),
        ct in proptest::collection::vec(any::<u8>(), 0..2048),
    ) {
        let header = FrameHeader::new(flags::ACK_REQUIRED, PROFILE_X25519_HKDF_XCHACHA20POLY1305, 7, stream_id, seq, ct.len() as u32);
        let mut bytes = Vec::with_capacity(22 + ct.len());
        bytes.extend_from_slice(&header.encode());
        bytes.extend_from_slice(&ct);

        let parsed = Frame::from_bytes(&bytes).expect("frame parse");
        prop_assert_eq!(parsed.header, header);
        prop_assert_eq!(parsed.ciphertext, ct);
    }

    #[test]
    fn encrypt_decrypt_roundtrip_holds(
        stream_id in any::<u32>(),
        seq in any::<u64>(),
        payload in proptest::collection::vec(any::<u8>(), 0..1024),
    ) {
        let keys = TrafficKeys { key_id: 3, c2s: [0x11; 32], s2c: [0x22; 32] };
        let frame = encrypt_frame(&keys, Direction::C2S, 0, stream_id, seq, &payload).expect("encrypt");
        let plain = decrypt_frame(&keys, Direction::C2S, &frame).expect("decrypt");
        prop_assert_eq!(plain, payload);
    }

    #[test]
    fn tlv_parser_never_panics_and_roundtrips(
        a in proptest::collection::vec(any::<u8>(), 0..128),
        b in proptest::collection::vec(any::<u8>(), 0..128),
    ) {
        let tlvs = vec![
            Tlv::application_data(&a).expect("tlv app"),
            Tlv::new(tlv_type::ACK_HINT, b.clone()).expect("tlv ack"),
        ];
        let enc = encode_tlvs(&tlvs).expect("encode tlv");
        let dec = decode_tlvs(&enc).expect("decode tlv");
        prop_assert_eq!(dec, tlvs);

        let _ = decode_tlvs(&a);
    }
}