snow/
types.rs

1//! The traits for cryptographic implementations that can be used by Noise.
2
3use crate::{
4    constants::{CIPHERKEYLEN, MAXBLOCKLEN, MAXHASHLEN, TAGLEN},
5    Error,
6};
7use rand_core::{CryptoRng, RngCore};
8
9/// CSPRNG operations
10pub trait Random: CryptoRng + RngCore + Send + Sync {}
11
12/// Diffie-Hellman operations
13pub trait Dh: Send + Sync {
14    /// The string that the Noise spec defines for the primitive
15    fn name(&self) -> &'static str;
16
17    /// The length in bytes of a public key for this primitive
18    fn pub_len(&self) -> usize;
19
20    /// The length in bytes of a private key for this primitive
21    fn priv_len(&self) -> usize;
22
23    /// Set the private key
24    fn set(&mut self, privkey: &[u8]);
25
26    /// Generate a new private key
27    fn generate(&mut self, rng: &mut dyn Random);
28
29    /// Get the public key
30    fn pubkey(&self) -> &[u8];
31
32    /// Get the private key
33    fn privkey(&self) -> &[u8];
34
35    /// Calculate a Diffie-Hellman exchange.
36    fn dh(&self, pubkey: &[u8], out: &mut [u8]) -> Result<(), Error>;
37}
38
39/// Cipher operations
40pub trait Cipher: Send + Sync {
41    /// The string that the Noise spec defines for the primitive
42    fn name(&self) -> &'static str;
43
44    /// Set the key
45    fn set(&mut self, key: &[u8]);
46
47    /// Encrypt (with associated data) a given plaintext.
48    fn encrypt(&self, nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) -> usize;
49
50    /// Decrypt (with associated data) a given ciphertext.
51    fn decrypt(
52        &self,
53        nonce: u64,
54        authtext: &[u8],
55        ciphertext: &[u8],
56        out: &mut [u8],
57    ) -> Result<usize, Error>;
58
59    /// Rekey according to Section 4.2 of the Noise Specification, with a default
60    /// implementation guaranteed to be secure for all ciphers.
61    fn rekey(&mut self) {
62        let mut ciphertext = [0; CIPHERKEYLEN + TAGLEN];
63        let ciphertext_len = self.encrypt(u64::MAX, &[], &[0; CIPHERKEYLEN], &mut ciphertext);
64        assert_eq!(ciphertext_len, ciphertext.len());
65        self.set(&ciphertext[..CIPHERKEYLEN]);
66    }
67}
68
69/// Hashing operations
70pub trait Hash: Send + Sync {
71    /// The string that the Noise spec defines for the primitive
72    fn name(&self) -> &'static str;
73
74    /// The block length for the primitive
75    fn block_len(&self) -> usize;
76
77    /// The final hash digest length for the primitive
78    fn hash_len(&self) -> usize;
79
80    /// Reset the internal state
81    fn reset(&mut self);
82
83    /// Provide input to the internal state
84    fn input(&mut self, data: &[u8]);
85
86    /// Get the resulting hash
87    fn result(&mut self, out: &mut [u8]);
88
89    /// Calculate HMAC, as specified in the Noise spec.
90    ///
91    /// NOTE: This method clobbers the existing internal state
92    fn hmac(&mut self, key: &[u8], data: &[u8], out: &mut [u8]) {
93        assert!(key.len() <= self.block_len());
94        let block_len = self.block_len();
95        let hash_len = self.hash_len();
96        let mut ipad = [0x36u8; MAXBLOCKLEN];
97        let mut opad = [0x5cu8; MAXBLOCKLEN];
98        for count in 0..key.len() {
99            ipad[count] ^= key[count];
100            opad[count] ^= key[count];
101        }
102        self.reset();
103        self.input(&ipad[..block_len]);
104        self.input(data);
105        let mut inner_output = [0u8; MAXHASHLEN];
106        self.result(&mut inner_output);
107        self.reset();
108        self.input(&opad[..block_len]);
109        self.input(&inner_output[..hash_len]);
110        self.result(out);
111    }
112
113    /// Derive keys as specified in the Noise spec.
114    ///
115    /// NOTE: This method clobbers the existing internal state
116    fn hkdf(
117        &mut self,
118        chaining_key: &[u8],
119        input_key_material: &[u8],
120        outputs: usize,
121        out1: &mut [u8],
122        out2: &mut [u8],
123        out3: &mut [u8],
124    ) {
125        let hash_len = self.hash_len();
126        let mut temp_key = [0u8; MAXHASHLEN];
127        self.hmac(chaining_key, input_key_material, &mut temp_key);
128        self.hmac(&temp_key, &[1u8], out1);
129        if outputs == 1 {
130            return;
131        }
132
133        let mut in2 = [0u8; MAXHASHLEN + 1];
134        copy_slices!(out1[0..hash_len], &mut in2);
135        in2[hash_len] = 2;
136        self.hmac(&temp_key, &in2[..=hash_len], out2);
137        if outputs == 2 {
138            return;
139        }
140
141        let mut in3 = [0u8; MAXHASHLEN + 1];
142        copy_slices!(out2[0..hash_len], &mut in3);
143        in3[hash_len] = 3;
144        self.hmac(&temp_key, &in3[..=hash_len], out3);
145    }
146}
147
148/// Kem operations.
149#[cfg(feature = "hfs")]
150pub trait Kem: Send + Sync {
151    /// The string that the Noise spec defines for the primitive.
152    fn name(&self) -> &'static str;
153
154    /// The length in bytes of a public key for this primitive.
155    fn pub_len(&self) -> usize;
156
157    /// The length in bytes the Kem cipherthext for this primitive.
158    fn ciphertext_len(&self) -> usize;
159
160    /// Shared secret length in bytes that this Kem encapsulates.
161    fn shared_secret_len(&self) -> usize;
162
163    /// Generate a new private key.
164    fn generate(&mut self, rng: &mut dyn Random);
165
166    /// Get the public key
167    fn pubkey(&self) -> &[u8];
168
169    /// Generate a shared secret and encapsulate it using this Kem.
170    #[must_use]
171    fn encapsulate(
172        &self,
173        pubkey: &[u8],
174        shared_secret_out: &mut [u8],
175        ciphertext_out: &mut [u8],
176    ) -> Result<(usize, usize), ()>;
177
178    /// Decapsulate a ciphertext producing a shared secret.
179    #[must_use]
180    fn decapsulate(&self, ciphertext: &[u8], shared_secret_out: &mut [u8]) -> Result<usize, ()>;
181}