use self::aead::Counter;
use std::io;
use std::io::Write;
pub use self::aead::{Aad, Algorithm, Key, Nonce};
pub use self::error::Invalid;
mod aead;
mod error;
#[cfg(feature = "ring")]
pub mod ring;
pub const MAX_BUF_SIZE: usize = (1 << 24) - 1;
pub const BUF_SIZE: usize = 1 << 14;
pub trait Close: private::Private {
fn close(self) -> io::Result<()>;
}
mod private {
pub trait Private {}
}
pub struct EncWriter<A: Algorithm, W: Write> {
inner: W,
algorithm: A,
buffer: Vec<u8>,
buf_size: usize,
nonce: Counter<A>,
aad: [u8; 16 + 1],
errored: bool,
closed: bool,
panicked: bool,
}
impl<A: Algorithm, W: Write> EncWriter<A, W> {
pub fn new(inner: W, key: &Key<A>, nonce: Nonce<A>, aad: Aad) -> Self {
Self::with_buffer_size(inner, key, nonce, aad, BUF_SIZE).unwrap()
}
pub fn with_buffer_size(
inner: W,
key: &Key<A>,
nonce: Nonce<A>,
aad: Aad,
buf_size: usize,
) -> Result<Self, Invalid> {
if buf_size == 0 || buf_size > MAX_BUF_SIZE {
return Err(Invalid::BufSize);
}
let algorithm = A::new(key.as_ref());
let mut nonce = Counter::zero(nonce);
let mut associated_data = [0; 1 + 16];
algorithm
.seal_in_place(
&nonce.next().unwrap(),
aad.as_ref(),
&mut associated_data[1..],
)
.unwrap();
Ok(EncWriter {
inner: inner,
algorithm: A::new(key.as_ref()),
buffer: Vec::with_capacity(buf_size + A::TAG_LEN),
buf_size: buf_size,
nonce: nonce,
aad: associated_data,
errored: false,
closed: false,
panicked: false,
})
}
fn close_internal(&mut self) -> io::Result<()> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
self.closed = true;
self.aad[0] = 0x80;
self.write_buffer().and_then(|()| self.inner.flush())
}
fn write_buffer(&mut self) -> io::Result<()> {
self.buffer.resize(self.buffer.len() + A::TAG_LEN, 0);
let ciphertext = self.algorithm.seal_in_place(
&self.nonce.next()?,
&self.aad,
self.buffer.as_mut_slice(),
)?;
self.panicked = true;
let r = self.inner.write_all(ciphertext);
self.panicked = false;
self.buffer.clear();
r
}
}
impl<A: Algorithm, W: Write> Write for EncWriter<A, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
let r: io::Result<usize> = {
let n = buf.len();
let remaining = self.buf_size - self.buffer.len();
if buf.len() <= remaining {
return self.buffer.write_all(buf).and(Ok(n));
}
self.buffer.extend_from_slice(&buf[..remaining]);
self.write_buffer()?;
let buf = &buf[remaining..];
let chunks = buf.chunks(self.buf_size);
chunks
.clone()
.take(chunks.len() - 1) .try_for_each(|chunk| {
self.buffer.extend_from_slice(chunk);
self.write_buffer()
})?;
self.buffer.extend_from_slice(chunks.last().unwrap()); Ok(n)
};
self.errored = r.is_err();
r
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.write(buf).and(Ok(()))
}
fn flush(&mut self) -> io::Result<()> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
self.panicked = true;
let r = self.inner.flush();
self.panicked = false;
self.errored = r.is_err();
r
}
}
impl<A: Algorithm, W: Write> private::Private for EncWriter<A, W> {}
impl<A: Algorithm, W: Write> Close for EncWriter<A, W> {
fn close(mut self) -> io::Result<()> {
self.close_internal()
}
}
impl<A1: Algorithm, A2: Algorithm, W: Write> EncWriter<A1, DecWriter<A2, W>> {
pub fn close(mut self) -> io::Result<()> {
self.close_internal()
.and_then(|()| self.inner.close_internal())
}
}
impl<A: Algorithm, W: Write> Drop for EncWriter<A, W> {
fn drop(&mut self) {
if !self.panicked && !self.closed {
let _r = self.close_internal();
}
}
}
pub struct DecWriter<A: Algorithm, W: Write> {
inner: W,
algorithm: A,
buffer: Vec<u8>,
buf_size: usize,
nonce: Counter<A>,
aad: [u8; 16 + 1],
errored: bool,
closed: bool,
panicked: bool,
}
impl<A: Algorithm, W: Write> DecWriter<A, W> {
pub fn new(inner: W, key: &Key<A>, nonce: Nonce<A>, aad: Aad) -> Self {
Self::with_buffer_size(inner, key, nonce, aad, BUF_SIZE).unwrap()
}
pub fn with_buffer_size(
inner: W,
key: &Key<A>,
nonce: Nonce<A>,
aad: Aad,
buf_size: usize,
) -> Result<Self, Invalid> {
if buf_size == 0 || buf_size > MAX_BUF_SIZE {
return Err(Invalid::BufSize);
}
let algorithm = A::new(key.as_ref());
let mut nonce = Counter::zero(nonce);
let mut associated_data = [0; 1 + 16];
algorithm
.seal_in_place(
&nonce.next().unwrap(),
aad.as_ref(),
&mut associated_data[1..],
)
.unwrap();
Ok(DecWriter {
inner: inner,
algorithm: A::new(key.as_ref()),
buffer: Vec::with_capacity(buf_size + A::TAG_LEN),
buf_size: buf_size,
nonce: nonce,
aad: associated_data,
errored: false,
closed: false,
panicked: false,
})
}
fn close_internal(&mut self) -> io::Result<()> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
self.closed = true;
self.aad[0] = 0x80; self.write_buffer().and_then(|()| self.inner.flush())
}
fn write_buffer(&mut self) -> io::Result<()> {
let plaintext = self.algorithm.open_in_place(
&self.nonce.next()?,
&self.aad,
self.buffer.as_mut_slice(),
)?;
self.panicked = true;
let r = self.inner.write_all(plaintext);
self.panicked = false;
self.buffer.clear();
r
}
}
impl<A: Algorithm, W: Write> Write for DecWriter<A, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
let r: io::Result<usize> = {
let n = buf.len();
let remaining = self.buf_size + A::TAG_LEN - self.buffer.len();
if buf.len() <= remaining {
return self.buffer.write_all(buf).and(Ok(n));
}
self.buffer.extend_from_slice(&buf[..remaining]);
self.write_buffer()?;
let buf = &buf[remaining..];
let chunks = buf.chunks(self.buf_size + A::TAG_LEN);
chunks
.clone()
.take(chunks.len() - 1) .try_for_each(|chunk| {
self.buffer.extend_from_slice(chunk);
self.write_buffer()
})?;
self.buffer.extend_from_slice(chunks.last().unwrap()); Ok(n)
};
self.errored = r.is_err();
r
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.write(buf).and(Ok(()))
}
fn flush(&mut self) -> io::Result<()> {
if self.errored {
return Err(io::Error::from(io::ErrorKind::Other));
}
self.panicked = true;
let r = self.inner.flush();
self.panicked = false;
self.errored = r.is_err();
r
}
}
impl<A: Algorithm, W: Write> private::Private for DecWriter<A, W> {}
impl<A: Algorithm, W: Write> Close for DecWriter<A, W> {
fn close(mut self) -> io::Result<()> {
self.close_internal()
}
}
impl<A1: Algorithm, A2: Algorithm, W: Write> DecWriter<A1, EncWriter<A2, W>> {
pub fn close(mut self) -> io::Result<()> {
self.close_internal()
.and_then(|()| self.inner.close_internal())
}
}
impl<A: Algorithm, W: Write> Drop for DecWriter<A, W> {
fn drop(&mut self) {
if !self.panicked && !self.closed {
let _r = self.close_internal();
}
}
}
#[cfg(test)]
mod tests {
use super::ring::AES_256_GCM;
use super::*;
#[test]
fn test_it2() {
let key: Key<ring::AES_256_GCM> = Key::new([0; AES_256_GCM::KEY_LEN]);
let nonce = Nonce::new([0; Nonce::<AES_256_GCM>::SIZE]);
let aad = Aad::from("Some authenticated but not encrypted data".as_bytes());
let plaintext = "".as_bytes();
let mut ciphertext: Vec<u8> = Vec::default(); let mut writer = EncWriter::new(&mut ciphertext, &key, nonce, aad);
writer.write_all(plaintext).unwrap();
writer.close().unwrap();
println!("{:?}", ciphertext);
}
}