libsignal_protocol/crypto/
native.rs

1use aes::{Aes128, Aes192, Aes256};
2use aes_ctr::{
3    stream_cipher::{NewStreamCipher, SyncStreamCipher},
4    Aes128Ctr, Aes192Ctr, Aes256Ctr,
5};
6use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
7use hmac::{Hmac, Mac};
8use sha2::{Digest, Sha256, Sha512};
9
10use crate::{
11    crypto::{Crypto, Sha256Hmac, Sha512Digest, SignalCipherType},
12    errors::InternalError,
13};
14
15// FWI, PKCS5 padding is a subset of PKCS7
16type Aes128Cbc = Cbc<Aes128, Pkcs7>;
17type Aes192Cbc = Cbc<Aes192, Pkcs7>;
18type Aes256Cbc = Cbc<Aes256, Pkcs7>;
19
20// Create alias for HMAC-SHA256
21type HmacSha256 = Hmac<Sha256>;
22
23#[derive(Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
24pub enum Mode {
25    Encrypt,
26    Decrypt,
27}
28
29/// Cryptography routines using native Rust crates.
30#[derive(Debug, Copy, Clone, PartialEq)]
31pub struct DefaultCrypto;
32
33impl DefaultCrypto {
34    fn crypter(
35        self,
36        mode: Mode,
37        cipher: SignalCipherType,
38        key: &[u8],
39        iv: &[u8],
40        data: &[u8],
41    ) -> Result<Vec<u8>, InternalError> {
42        let result = match (cipher, key.len()) {
43            (SignalCipherType::AesCtrNoPadding, 16) => {
44                let mut buf = data.to_vec();
45                let mut c = Aes128Ctr::new_var(key, iv)
46                    .map_err(|_| InternalError::Unknown)?;
47                c.apply_keystream(&mut buf);
48                buf
49            },
50            (SignalCipherType::AesCtrNoPadding, 24) => {
51                let mut buf = data.to_vec();
52                let mut c = Aes192Ctr::new_var(key, iv)
53                    .map_err(|_| InternalError::Unknown)?;
54                c.apply_keystream(&mut buf);
55                buf
56            },
57            (SignalCipherType::AesCtrNoPadding, 32) => {
58                let mut buf = data.to_vec();
59                let mut c = Aes256Ctr::new_var(key, iv)
60                    .map_err(|_| InternalError::Unknown)?;
61                c.apply_keystream(&mut buf);
62                buf
63            },
64            (SignalCipherType::AesCbcPkcs5, 16) => {
65                let c = Aes128Cbc::new_var(&key, &iv)
66                    .map_err(|_| InternalError::Unknown)?;
67                match mode {
68                    Mode::Encrypt => c.encrypt_vec(data),
69                    Mode::Decrypt => c
70                        .decrypt_vec(data)
71                        .map_err(|_| InternalError::Unknown)?,
72                }
73            },
74            (SignalCipherType::AesCbcPkcs5, 24) => {
75                let c = Aes192Cbc::new_var(&key, &iv)
76                    .map_err(|_| InternalError::Unknown)?;
77                match mode {
78                    Mode::Encrypt => c.encrypt_vec(data),
79                    Mode::Decrypt => c
80                        .decrypt_vec(data)
81                        .map_err(|_| InternalError::Unknown)?,
82                }
83            },
84            (SignalCipherType::AesCbcPkcs5, 32) => {
85                let c = Aes256Cbc::new_var(&key, &iv)
86                    .map_err(|_| InternalError::Unknown)?;
87                match mode {
88                    Mode::Encrypt => c.encrypt_vec(data),
89                    Mode::Decrypt => c
90                        .decrypt_vec(data)
91                        .map_err(|_| InternalError::Unknown)?,
92                }
93            },
94            (cipher, size) => unreachable!(
95                "A combination of {:?} and {} doesn't make sense",
96                cipher, size
97            ),
98        };
99        Ok(result)
100    }
101}
102
103#[cfg(feature = "crypto-native")]
104impl Crypto for DefaultCrypto {
105    fn fill_random(&self, buffer: &mut [u8]) -> Result<(), InternalError> {
106        use rand::RngCore;
107        let mut rng = rand::thread_rng();
108        rng.fill_bytes(buffer);
109        Ok(())
110    }
111
112    fn hmac_sha256(
113        &self,
114        key: &[u8],
115    ) -> Result<Box<dyn Sha256Hmac>, InternalError> {
116        let mac =
117            HmacSha256::new_varkey(key).map_err(|_| InternalError::Unknown)?;
118        Ok(Box::new(mac))
119    }
120
121    fn sha512_digest(&self) -> Result<Box<dyn Sha512Digest>, InternalError> {
122        Ok(Box::new(Sha512::new()))
123    }
124
125    fn encrypt(
126        &self,
127        cipher: SignalCipherType,
128        key: &[u8],
129        iv: &[u8],
130        data: &[u8],
131    ) -> Result<Vec<u8>, InternalError> {
132        self.crypter(Mode::Encrypt, cipher, key, iv, data)
133    }
134
135    fn decrypt(
136        &self,
137        cipher: SignalCipherType,
138        key: &[u8],
139        iv: &[u8],
140        data: &[u8],
141    ) -> Result<Vec<u8>, InternalError> {
142        self.crypter(Mode::Decrypt, cipher, key, iv, data)
143    }
144}
145
146#[cfg(feature = "crypto-native")]
147impl Default for DefaultCrypto {
148    fn default() -> Self { Self }
149}
150
151#[cfg(feature = "crypto-native")]
152impl Sha512Digest for Sha512 {
153    fn update(&mut self, data: &[u8]) -> Result<(), InternalError> {
154        self.input(data);
155        Ok(())
156    }
157
158    fn finalize(&mut self) -> Result<Vec<u8>, InternalError> {
159        let result = self.result_reset();
160        Ok(result.to_vec())
161    }
162}
163
164#[cfg(feature = "crypto-native")]
165impl Sha256Hmac for HmacSha256 {
166    fn update(&mut self, data: &[u8]) -> Result<(), InternalError> {
167        self.input(data);
168        Ok(())
169    }
170
171    fn finalize(&mut self) -> Result<Vec<u8>, InternalError> {
172        let result = self.result_reset().code();
173        Ok(result.to_vec())
174    }
175}