noise_protocol/
traits.rs

1/// A trait for fixed size u8 array.
2
3// Inspired by ArrayVec and SmallVec, but no unsafe.
4
5// Use this trait so that we don't have to use [`Vec`] for some semi-fixed length buffers and
6// input/output types.
7pub trait U8Array: Sized {
8    /// Create a new array filled with all zeros.
9    fn new() -> Self;
10    /// Create a new array filled with a same value.
11    fn new_with(_: u8) -> Self;
12    /// Create a new array from a slice.
13    ///
14    /// # Panics
15    ///
16    /// The slice must be of the same length.
17    fn from_slice(_: &[u8]) -> Self;
18    /// Length of the array.
19    fn len() -> usize;
20    /// As slice.
21    fn as_slice(&self) -> &[u8];
22    /// As mutable slice.
23    fn as_mut(&mut self) -> &mut [u8];
24    // Cannot just impl [`Clone`], that will conflict with [u8; 32].
25    /// Clone.
26    fn clone(&self) -> Self {
27        Self::from_slice(self.as_slice())
28    }
29}
30
31macro_rules! impl_array {
32    ($len:expr) => {
33        impl U8Array for [u8; $len] {
34            fn new() -> Self {
35                [0u8; $len]
36            }
37            fn new_with(x: u8) -> Self {
38                [x; $len]
39            }
40            fn from_slice(data: &[u8]) -> Self {
41                let mut a = [0u8; $len];
42                a.copy_from_slice(data);
43                a
44            }
45            fn len() -> usize {
46                $len
47            }
48            fn as_slice(&self) -> &[u8] {
49                self
50            }
51            fn as_mut(&mut self) -> &mut [u8] {
52                self
53            }
54        }
55    };
56}
57
58impl_array!(32);
59impl_array!(64);
60impl_array!(128);
61
62/// A DH.
63pub trait DH {
64    /// Type of private key.
65    type Key: U8Array;
66    /// Type of pubkey key.
67    type Pubkey: U8Array;
68    /// Type of output.
69    type Output: U8Array;
70
71    /// Name of this DH function, e.g., “25519”.
72    fn name() -> &'static str;
73
74    /// Randomly generate a new private key.
75    fn genkey() -> Self::Key;
76
77    /// Calculate public key from a private key.
78    fn pubkey(_: &Self::Key) -> Self::Pubkey;
79
80    /// Perform DH key exchange.
81    fn dh(_: &Self::Key, _: &Self::Pubkey) -> Result<Self::Output, ()>;
82}
83
84/// An AEAD.
85pub trait Cipher {
86    /// Name of this cipher function.
87    fn name() -> &'static str;
88    /// Type of key.
89    type Key: U8Array;
90
91    /// Length of key.
92    fn key_len() -> usize {
93        Self::Key::len()
94    }
95
96    /// Length of auth tag.
97    ///
98    /// All ciphers specified in the spec has tag length 16.
99    fn tag_len() -> usize {
100        16
101    }
102
103    /// AEAD encryption.
104    ///
105    /// # Panics
106    ///
107    /// If `out.len() != plaintext.len() + Self::tag_len()`
108    fn encrypt(k: &Self::Key, nonce: u64, ad: &[u8], plaintext: &[u8], out: &mut [u8]);
109
110    /// AEAD encryption, but encrypt on one buffer.
111    /// return the length of ciphertext.
112    ///
113    /// # Panics
114    ///
115    /// If `in_out.len() < plaintext_len + Self::tag_len()`
116    fn encrypt_in_place(
117        k: &Self::Key,
118        nonce: u64,
119        ad: &[u8],
120        in_out: &mut [u8],
121        plaintext_len: usize,
122    ) -> usize;
123
124    /// AEAD decryption.
125    ///
126    /// # Panics
127    ///
128    /// If `out.len() != ciphertext.len() - Self::tag_len()`
129    fn decrypt(
130        k: &Self::Key,
131        nonce: u64,
132        ad: &[u8],
133        ciphertext: &[u8],
134        out: &mut [u8],
135    ) -> Result<(), ()>;
136
137    /// AEAD decryption, but decrypt on one buffer.
138    /// return the length of plaintext.
139    ///
140    /// # Panics
141    ///
142    /// If `in_out.len() < ciphertext_len` or `ciphertext_len < Self::tag_len()`
143    fn decrypt_in_place(
144        k: &Self::Key,
145        nonce: u64,
146        ad: &[u8],
147        in_out: &mut [u8],
148        ciphertext_len: usize,
149    ) -> Result<usize, ()>;
150
151    /// Rekey. Returns a new cipher key as a pseudorandom function of `k`.
152    fn rekey(k: &Self::Key) -> Self::Key {
153        // XXX: `k1` is not zeroed.
154        let mut k1 = [0u8; 48];
155        Self::encrypt(k, 0u64.wrapping_sub(1), &[], &[0; 32], &mut k1);
156        Self::Key::from_slice(&k1[..32])
157    }
158}
159
160/// A hash function.
161pub trait Hash: Default {
162    /// Name of the hash function.
163    fn name() -> &'static str;
164
165    /// Type of a block.
166    type Block: U8Array;
167    /// Type of output.
168    type Output: U8Array;
169
170    /// Length of block.
171    fn block_len() -> usize {
172        Self::Block::len()
173    }
174
175    /// Length of hash output, in number of bytes.
176    fn hash_len() -> usize {
177        Self::Output::len()
178    }
179
180    /// Reset state of hash context.
181    fn reset(&mut self) {
182        *self = Default::default();
183    }
184
185    /// Update hash context with some input.
186    fn input(&mut self, data: &[u8]);
187
188    /// Get hash result.
189    fn result(&mut self) -> Self::Output;
190
191    /// Calculate hash of some data.
192    fn hash(data: &[u8]) -> Self::Output {
193        let mut h: Self = Default::default();
194        h.input(data);
195        h.result()
196    }
197
198    /// Calculate HMAC-THIS-HASH, with some `key` and several messages.
199    fn hmac_many(key: &[u8], data: &[&[u8]]) -> Self::Output {
200        assert!(key.len() <= Self::block_len());
201
202        let mut ipad = Self::Block::new_with(0x36u8);
203        let mut opad = Self::Block::new_with(0x5cu8);
204
205        let ipad = ipad.as_mut();
206        let opad = opad.as_mut();
207
208        for (i, b) in key.iter().enumerate() {
209            ipad[i] ^= b;
210            opad[i] ^= b;
211        }
212
213        let mut hasher: Self = Default::default();
214        hasher.input(ipad);
215        for d in data {
216            hasher.input(d);
217        }
218        let inner_output = hasher.result();
219
220        hasher.reset();
221        hasher.input(opad);
222        hasher.input(inner_output.as_slice());
223        hasher.result()
224    }
225
226    /// Calculate HMAC-THIS-HASH, with some `key` and a message.
227    fn hmac(key: &[u8], data: &[u8]) -> Self::Output {
228        Self::hmac_many(key, &[data])
229    }
230
231    /// Calculate HKDF, as specified in the noise spec.
232    fn hkdf(chaining_key: &[u8], input_key_material: &[u8]) -> (Self::Output, Self::Output) {
233        let temp_key = Self::hmac(chaining_key, input_key_material);
234        let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
235        let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
236        (out1, out2)
237    }
238
239    /// Triple output HKDF.
240    fn hkdf3(
241        chaining_key: &[u8],
242        input_key_material: &[u8],
243    ) -> (Self::Output, Self::Output, Self::Output) {
244        let temp_key = Self::hmac(chaining_key, input_key_material);
245        let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
246        let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
247        let out3 = Self::hmac_many(temp_key.as_slice(), &[out2.as_slice(), &[3u8]]);
248        (out1, out2, out3)
249    }
250}