netcode 0.2.2

Wrapper for netcode.io library
Documentation
use libsodium_sys;

use common::*;

pub const NETCODE_ENCRYPT_EXTA_BYTES: usize = libsodium_sys::crypto_aead_chacha20poly1305_ABYTES;

#[derive(Debug)]
pub enum EncryptError {
    InvalidPublicKeySize,
    BufferSizeMismatch,
    Failed
}

pub fn generate_key() -> [u8; NETCODE_KEY_BYTES] {
    let mut key: [u8; NETCODE_KEY_BYTES] = [0; NETCODE_KEY_BYTES];

    random_bytes(&mut key);

    key
}

pub fn random_bytes(out: &mut [u8]) {
    unsafe {
        libsodium_sys::randombytes_buf(out.as_mut_ptr(), out.len());
    }
}

pub fn encode(out: &mut [u8], data: &[u8], additional_data: &[u8], nonce: u64, key: &[u8; NETCODE_KEY_BYTES]) -> Result<usize, EncryptError> {
    if key.len() != NETCODE_KEY_BYTES {
        return Err(EncryptError::InvalidPublicKeySize)
    }

    if out.len() < data.len() + NETCODE_ENCRYPT_EXTA_BYTES {
        return Err(EncryptError::BufferSizeMismatch)
    }

    let (result, written) = unsafe {
        let mut written: u64 = out.len() as u64;
        let result = libsodium_sys::crypto_aead_chacha20poly1305_encrypt(
                out.as_mut_ptr(),
                &mut written,
                data.as_ptr(),
                data.len() as u64,
                additional_data.as_ptr(),
                additional_data.len() as u64,
                ::std::ptr::null(),
                ::std::mem::transmute(&nonce),
                key);

        (result, written)
    };

    match result {
        -1 => Err(EncryptError::Failed),
        _ => Ok(written as usize)
    }
}

pub fn decode(out: &mut [u8], data: &[u8], additional_data: &[u8], nonce: u64, key: &[u8; NETCODE_KEY_BYTES]) -> Result<usize, EncryptError> {
    if key.len() != NETCODE_KEY_BYTES {
        return Err(EncryptError::InvalidPublicKeySize)
    }

    if out.len() < data.len() - NETCODE_ENCRYPT_EXTA_BYTES {
        return Err(EncryptError::BufferSizeMismatch)
    }

    let (result, read) = unsafe {
        let mut read: u64 = out.len() as u64;
        let result = libsodium_sys::crypto_aead_chacha20poly1305_decrypt(
                out.as_mut_ptr(),
                &mut read,
                ::std::ptr::null_mut(),
                data.as_ptr(),
                data.len() as u64,
                additional_data.as_ptr(),
                additional_data.len() as u64,
                ::std::mem::transmute(&nonce),
                key);

        (result, read)
    };

    match result {
        -1 => Err(EncryptError::Failed),
        _ => Ok(read as usize)
    }
}