net-wire 0.1.0

Allocation-free no_std wire views and codecs for network protocols.
Documentation
use net_wire::tls::{
    ClientHello, ClientHelloBuilder, ServerHelloBuilder, TlsBuildError, TlsCipherSuite,
    TlsCompressionMethod, TlsContentType, TlsExtensionBuilder, TlsExtensionType,
    TlsHandshakeBuilder, TlsHandshakeType, TlsProtocolVersion, TlsRecordBuilder,
};

fn built_client_from_local<'a>(buffer: &'a mut [u8]) -> ClientHello<'a> {
    let random = [0x11; 32];
    let extensions = [0, 43, 0, 3, 2, 3, 4];
    ClientHelloBuilder::new(
        buffer,
        TlsProtocolVersion::TLS12,
        &random,
        &[0x22],
        &[0x13, 0x01],
        &[0],
        Some(&extensions),
    )
    .build()
    .unwrap()
}

#[test]
fn builders_copy_inputs_and_fail_atomically() {
    let mut record_output = [0xaa; 9];
    let record = TlsRecordBuilder::new(
        &mut record_output,
        TlsContentType::HANDSHAKE,
        TlsProtocolVersion::TLS12,
        &[1, 2],
    )
    .build()
    .unwrap();
    assert_eq!(record.as_bytes(), &[22, 3, 3, 0, 2, 1, 2]);

    let mut handshake_output = [0xaa; 8];
    let handshake = TlsHandshakeBuilder::new(
        &mut handshake_output,
        TlsHandshakeType::CLIENT_HELLO,
        &[1, 2],
    )
    .build()
    .unwrap();
    assert_eq!(handshake, &[1, 0, 0, 2, 1, 2]);

    let mut extension_output = [0xaa; 9];
    let extension = TlsExtensionBuilder::new(
        &mut extension_output,
        TlsExtensionType::SUPPORTED_VERSIONS,
        &[2, 3, 4],
    )
    .build()
    .unwrap();
    assert_eq!(extension.data(), &[2, 3, 4]);
    assert_eq!(extension_output[..7], [0, 43, 0, 3, 2, 3, 4]);
    assert_eq!(extension_output[7..], [0xaa, 0xaa]);

    let mut client_output = [0xaa; 64];
    let client = built_client_from_local(&mut client_output);
    assert_eq!(client.random(), &[0x11; 32]);
    assert_eq!(client.session_id(), &[0x22]);
    assert!(client.offers_tls13());
    let represented = client.as_bytes().len();
    assert!(
        client_output[represented..]
            .iter()
            .all(|byte| *byte == 0xaa)
    );

    let mut server_output = [0xaa; 48];
    let random = [0x33; 32];
    let server = ServerHelloBuilder::new(
        &mut server_output,
        TlsProtocolVersion::TLS12,
        &random,
        &[0x44],
        TlsCipherSuite::TLS_AES_128_GCM_SHA256,
        TlsCompressionMethod::NULL,
        None,
    )
    .build()
    .unwrap();
    assert_eq!(server.session_id(), &[0x44]);
    assert_eq!(
        server.cipher_suite(),
        TlsCipherSuite::TLS_AES_128_GCM_SHA256
    );

    let mut short = [0xaa; 6];
    let before = short;
    assert_eq!(
        TlsRecordBuilder::new(
            &mut short,
            TlsContentType::HANDSHAKE,
            TlsProtocolVersion::TLS12,
            &[1, 2],
        )
        .build(),
        Err(TlsBuildError::BufferTooShort {
            required: 7,
            available: 6,
        })
    );
    assert_eq!(short, before);

    let mut short_handshake = [0xaa; 5];
    let before = short_handshake;
    assert_eq!(
        TlsHandshakeBuilder::new(
            &mut short_handshake,
            TlsHandshakeType::CLIENT_HELLO,
            &[1, 2],
        )
        .build(),
        Err(TlsBuildError::BufferTooShort {
            required: 6,
            available: 5,
        })
    );
    assert_eq!(short_handshake, before);

    let mut invalid = [0xaa; 64];
    let before = invalid;
    assert_eq!(
        ClientHelloBuilder::new(
            &mut invalid,
            TlsProtocolVersion::TLS12,
            &[0; 32],
            &[],
            &[0x13],
            &[0],
            None,
        )
        .build(),
        Err(TlsBuildError::InvalidValue)
    );
    assert_eq!(invalid, before);

    let mut malformed_extensions = [0xaa; 64];
    let before = malformed_extensions;
    assert_eq!(
        ClientHelloBuilder::new(
            &mut malformed_extensions,
            TlsProtocolVersion::TLS12,
            &[0; 32],
            &[],
            &[0x13, 0x01],
            &[0],
            Some(&[0, 43, 0]),
        )
        .build(),
        Err(TlsBuildError::InvalidValue)
    );
    assert_eq!(malformed_extensions, before);

    let oversized = vec![0u8; usize::from(u16::MAX) + 1];
    let mut untouched = [0xaa; 8];
    let before = untouched;
    assert_eq!(
        TlsExtensionBuilder::new(&mut untouched, TlsExtensionType::COOKIE, &oversized).build(),
        Err(TlsBuildError::LengthTooLarge)
    );
    assert_eq!(untouched, before);

    let compression_methods = [0u8; 256];
    let mut compression_output = [0xaa; 64];
    let before = compression_output;
    assert_eq!(
        ClientHelloBuilder::new(
            &mut compression_output,
            TlsProtocolVersion::TLS12,
            &[0; 32],
            &[],
            &[0x13, 0x01],
            &compression_methods,
            None,
        )
        .build(),
        Err(TlsBuildError::LengthTooLarge)
    );
    assert_eq!(compression_output, before);
}