2023-02-16 18:11:45 +00:00
|
|
|
//! Symmetric cypher stuff
|
|
|
|
|
2023-02-17 13:59:02 +00:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 18:11:45 +00:00
|
|
|
#[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,
|
2023-02-17 13:59:02 +00:00
|
|
|
// ring::aead::Nonce does not implement 'Copy'
|
|
|
|
// even though it's just [u8;12]
|
2023-02-16 18:11:45 +00:00
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|