libFenrir/src/enc/sym.rs

168 lines
4.0 KiB
Rust
Raw Normal View History

//! Symmetric cypher stuff
use ::zeroize::Zeroize;
/// Secret, used for keys.
/// Grants that on drop() we will zero out memory
#[derive(Zeroize)]
#[zeroize(drop)]
#[allow(missing_debug_implementations)]
pub struct Secret {
secret: [u8; 32],
}
impl Secret {
/// return a reference to the secret
pub fn as_ref(&self) -> &[u8; 32] {
&self.secret
}
}
impl From<::x25519_dalek::SharedSecret> for Secret {
fn from(shared_secret: ::x25519_dalek::SharedSecret) -> Self {
Self {
secret: shared_secret.to_bytes(),
}
}
}
/// List of possible Ciphers
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
#[repr(u8)]
pub enum CipherKind {
/// Chaha20_Poly1305
Chacha20Poly1305 = 0,
}
impl CipherKind {
/// required length of the nonce
pub fn nonce_len(&self) -> usize {
::ring::aead::CHACHA20_POLY1305.nonce_len()
}
/// required length of the key
pub fn key_len(&self) -> usize {
::ring::aead::CHACHA20_POLY1305.key_len()
}
/// Length of the authentication tag
pub fn tag_len(&self) -> usize {
::ring::aead::CHACHA20_POLY1305.tag_len()
}
}
/// actual ciphers
#[derive(Debug)]
pub enum Cipher {
/// Cipher Chaha20_Poly1305
Chacha20Poly1305(Chacha20Poly1305),
}
impl Cipher {
/// Build a new Cipher
pub fn new(kind: CipherKind, secret: Secret) -> Self {
match kind {
CipherKind::Chacha20Poly1305 => {
Self::Chacha20Poly1305(Chacha20Poly1305::new(secret))
}
}
}
}
/// Chacha20Poly1305 cipher
#[derive(Debug)]
pub struct Chacha20Poly1305 {
cipher: ::ring::aead::OpeningKey<Nonce>,
}
impl Chacha20Poly1305 {
/// Initialize the cipher with the given nonce
pub fn with_nonce(key: Secret, nonce: Nonce) -> Self {
let unbound_key = ::ring::aead::UnboundKey::new(
&::ring::aead::CHACHA20_POLY1305,
key.as_ref(),
)
.unwrap();
use ::ring::aead::BoundKey;
Self {
cipher: ::ring::aead::OpeningKey::<Nonce>::new(unbound_key, nonce),
}
}
/// Initialize a new ChachaPoly20 cipher with a random nonce
pub fn new(key: Secret) -> Self {
Self::with_nonce(key, Nonce::new())
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
#[allow(missing_debug_implementations)]
struct NonceNum {
high: u32,
low: u64,
}
/// Nonce with sequence for chach20_apoly1305
#[repr(C)]
pub union Nonce {
num: NonceNum,
// ring::aead::Nonce does not implement 'Copy'
// even though it's just [u8;12]
raw: ::core::mem::ManuallyDrop<::ring::aead::Nonce>,
easy_from: [u8; 12],
}
impl ::core::fmt::Debug for Nonce {
fn fmt(
&self,
f: &mut core::fmt::Formatter<'_>,
) -> Result<(), ::std::fmt::Error> {
// use the Debug from NonceNum
#[allow(unsafe_code)]
unsafe {
core::fmt::Debug::fmt(&self.num, f)
}
}
}
impl Nonce {
// FIXME: nonces should be random!
/// Generate a new random Nonce
pub fn new() -> Self {
#[allow(unsafe_code)]
unsafe {
Self {
num: NonceNum { high: 42, low: 69 },
}
}
}
/// Create Nonce from array
pub fn from_slice(raw: [u8; 12]) -> Self {
#[allow(unsafe_code)]
unsafe {
Self { easy_from: raw }
}
}
}
impl Clone for Nonce {
fn clone(&self) -> Self {
#[allow(unsafe_code)]
unsafe {
Self { num: self.num }
}
}
}
impl ::ring::aead::NonceSequence for Nonce {
fn advance(
&mut self,
) -> Result<::ring::aead::Nonce, ::ring::error::Unspecified> {
#[allow(unsafe_code)]
unsafe {
let old_low = self.num.low;
self.num.low = self.num.low + 1;
if self.num.low < old_low {
self.num.high = self.num.high;
}
Ok(::core::mem::ManuallyDrop::take(&mut self.raw))
}
}
}