Skip to content

Commit 2a911a9

Browse files
author
Andreas Auernhammer
committed
restructure crate types
This commit completely redefines the API of the `sio` crate. The core type is `Algorithm` which now uses associated constants for the key, nonce and tag length. Using ass. constants the compiler can guarantee a lot of invariants, like: - The key passed to `Algorithm::new` has always the correct length. (Therefore we can return `Self` instead of a Result) - The nonce passed to `seal_in_place` / `open_in_place` has always the correct length. - It's actually not possible to implement `Algorithm` for an AEAD with a nonce size < 4 and use it with `sio`. Doing so causes the compiler to complain that `Nonce::<Algorithm>::SIZE` will overflow (usize becomes negative). Further, it's not possible to pass a wrong key or nonce to an enc/dec reader/writer. However, this commit only contains the basic structure. A lot of things are still missing. In particular: - docs and examples!!! - the enc/dec reader implementations - proper cargo.toml configuration (production/dev builds a.s.o) - tests and benchmarks.
1 parent fa1a64e commit 2a911a9

File tree

5 files changed

+511
-147
lines changed

5 files changed

+511
-147
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ edition = "2018"
77
description = "Secure IO"
88
license = "MIT"
99

10+
[features]
11+
default = ["ring"]
12+
1013
[dependencies]
14+
ring = { version = "0.14.6", optional = true }

src/aead.rs

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,105 @@
1+
use super::error::{Exceeded, Invalid, NotAuthentic};
2+
use std::marker::PhantomData;
3+
14
pub trait Algorithm {
2-
fn nonce_len(&self) -> usize;
5+
const KEY_LEN: usize;
6+
const NONCE_LEN: usize;
7+
const TAG_LEN: usize;
8+
9+
fn new(key: &[u8; 32]) -> Self;
10+
11+
fn seal_in_place<'a>(
12+
&self,
13+
nonce: &[u8; 12],
14+
aad: &[u8],
15+
in_out: &'a mut [u8],
16+
) -> Result<&'a [u8], Invalid>;
17+
18+
fn open_in_place<'a>(
19+
&self,
20+
nonce: &[u8; 12],
21+
aad: &[u8],
22+
in_out: &'a mut [u8],
23+
) -> Result<&'a [u8], NotAuthentic>;
24+
}
25+
26+
pub struct Key<A: Algorithm>([u8; 32], PhantomData<A>);
27+
28+
impl<A: Algorithm> Key<A> {
29+
pub const SIZE: usize = A::KEY_LEN;
30+
31+
pub fn new(bytes: [u8; 32]) -> Self {
32+
Key(bytes, PhantomData)
33+
}
34+
}
35+
36+
impl<A: Algorithm> AsRef<[u8; 32]> for Key<A> {
37+
fn as_ref(&self) -> &[u8; 32] {
38+
&self.0
39+
}
40+
}
41+
42+
pub struct Nonce<A: Algorithm>([u8; 8], PhantomData<A>);
43+
44+
impl<A: Algorithm> Nonce<A> {
45+
pub const SIZE: usize = A::NONCE_LEN - 4;
46+
47+
pub fn new(bytes: [u8; 8]) -> Self {
48+
Nonce(bytes, PhantomData)
49+
}
50+
}
51+
52+
impl<A: Algorithm> AsRef<[u8; 8]> for Nonce<A> {
53+
fn as_ref(&self) -> &[u8; 8] {
54+
&self.0
55+
}
56+
}
57+
58+
#[repr(transparent)]
59+
pub struct Aad<'a>(&'a [u8]);
60+
61+
impl<'a> Aad<'a> {
62+
#[inline]
63+
pub const fn from(aad: &'a [u8]) -> Self {
64+
Aad(aad)
65+
}
66+
}
67+
68+
impl Aad<'static> {
69+
#[inline]
70+
pub fn empty() -> Self {
71+
Self::from(&[])
72+
}
73+
}
74+
75+
impl<'a> AsRef<[u8]> for Aad<'a> {
76+
fn as_ref(&self) -> &[u8] {
77+
&self.0
78+
}
79+
}
80+
81+
pub(crate) struct Counter<A: Algorithm> {
82+
nonce: [u8; 8],
83+
seq_num: u32,
84+
phantom_data: PhantomData<A>,
85+
}
86+
87+
impl<A: Algorithm> Counter<A> {
88+
pub fn zero(nonce: Nonce<A>) -> Self {
89+
Counter {
90+
nonce: nonce.0,
91+
seq_num: 0,
92+
phantom_data: PhantomData,
93+
}
94+
}
95+
96+
pub fn next(&mut self) -> Result<[u8; 12], Exceeded> {
97+
let seq_num = self.seq_num.checked_add(1).ok_or(Exceeded)?;
398

4-
fn tag_len(&self) -> usize;
99+
let mut nonce = [0; 12];
100+
&nonce[..8].copy_from_slice(self.nonce.as_ref());
101+
nonce[8..].copy_from_slice(self.seq_num.to_le_bytes().as_ref());
102+
self.seq_num = seq_num;
103+
Ok(nonce)
104+
}
5105
}

src/error.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use std::error::Error;
2+
use std::{fmt, io};
3+
4+
#[derive(Clone, Copy, Debug, PartialEq)]
5+
pub struct NotAuthentic;
6+
7+
impl NotAuthentic {
8+
const fn description() -> &'static str {
9+
"not authentic"
10+
}
11+
}
12+
13+
impl Error for NotAuthentic {
14+
fn description(&self) -> &str {
15+
Self::description()
16+
}
17+
}
18+
19+
impl fmt::Display for NotAuthentic {
20+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21+
write!(f, "{}", Self::description())
22+
}
23+
}
24+
25+
impl From<NotAuthentic> for io::Error {
26+
fn from(_: NotAuthentic) -> Self {
27+
io::Error::new(io::ErrorKind::InvalidData, NotAuthentic)
28+
}
29+
}
30+
31+
#[derive(Clone, Copy, Debug, PartialEq)]
32+
pub struct Exceeded;
33+
34+
impl Exceeded {
35+
const fn description() -> &'static str {
36+
"data limit exceeded"
37+
}
38+
}
39+
40+
impl Error for Exceeded {
41+
fn description(&self) -> &str {
42+
Self::description()
43+
}
44+
}
45+
46+
impl fmt::Display for Exceeded {
47+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48+
write!(f, "{}", Self::description())
49+
}
50+
}
51+
52+
impl From<Exceeded> for io::Error {
53+
fn from(_: Exceeded) -> Self {
54+
io::Error::new(io::ErrorKind::InvalidData, Exceeded)
55+
}
56+
}
57+
58+
#[derive(Clone, Copy, Debug, PartialEq)]
59+
pub enum Invalid {
60+
Key,
61+
Nonce,
62+
BufSize,
63+
}
64+
65+
impl Error for Invalid {
66+
fn description(&self) -> &str {
67+
match self {
68+
Invalid::Key => "sio::Invalid::Key",
69+
Invalid::Nonce => "sio::Invalid::Nonce",
70+
Invalid::BufSize => "sio::Invalid::BufSize",
71+
}
72+
}
73+
}
74+
75+
impl fmt::Display for Invalid {
76+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77+
write!(f, "{}", self.description())
78+
}
79+
}
80+
81+
impl From<Invalid> for io::Error {
82+
fn from(e: Invalid) -> Self {
83+
io::Error::new(io::ErrorKind::Other, e)
84+
}
85+
}

0 commit comments

Comments
 (0)