Skip to main content

reqtls/boring/evp/
mod.rs

1use crate::boring::{CryptDecodeParam, HashType};
2mod curve;
3pub mod cipher;
4mod aead;
5
6use crate::boring::bindings::*;
7use crate::error::RlsResult;
8pub use aead::AeadCrypto;
9pub use cipher::Cipher;
10pub use curve::EvpCurve;
11
12use crate::boring::CryptEncodeParam;
13use crate::extend::Aead;
14use crate::hash::Hmac;
15use crate::RlsError;
16
17#[cfg_attr(feature = "export", repr(C))]
18#[allow(non_camel_case_types)]
19pub enum CipherType {
20    AES_128_CBC = 0,
21    AES_192_CBC = 1,
22    AES_256_CBC = 2,
23    AES_128_ECB = 3,
24    AES_192_ECB = 4,
25    AES_256_ECB = 5,
26    AES_128_CTR = 6,
27    AES_192_CTR = 7,
28    AES_256_CTR = 8,
29    AES_128_GCM = 9,
30    AES_192_GCM = 10,
31    AES_256_GCM = 11,
32    AES_128_OFB = 12,
33    AES_192_OFB = 13,
34    AES_256_OFB = 14,
35    DES_CBC = 15,
36    DES_ECB = 16,
37    RC4 = 17,
38}
39
40impl CipherType {
41    pub fn as_boring(&self) -> *const EVP_CIPHER {
42        match self {
43            CipherType::AES_128_CBC => unsafe { EVP_aes_128_cbc() }
44            CipherType::AES_192_CBC => unsafe { EVP_aes_192_cbc() }
45            CipherType::AES_256_CBC => unsafe { EVP_aes_256_cbc() }
46            CipherType::AES_128_ECB => unsafe { EVP_aes_128_ecb() }
47            CipherType::AES_192_ECB => unsafe { EVP_aes_192_ecb() }
48            CipherType::AES_256_ECB => unsafe { EVP_aes_256_ecb() }
49            CipherType::AES_128_CTR => unsafe { EVP_aes_128_ctr() }
50            CipherType::AES_192_CTR => unsafe { EVP_aes_192_ctr() }
51            CipherType::AES_256_CTR => unsafe { EVP_aes_256_ctr() }
52            CipherType::AES_128_GCM => unsafe { EVP_aes_128_gcm() }
53            CipherType::AES_192_GCM => unsafe { EVP_aes_192_gcm() }
54            CipherType::AES_256_GCM => unsafe { EVP_aes_256_gcm() }
55            CipherType::AES_128_OFB => unsafe { EVP_aes_128_ofb() }
56            CipherType::AES_192_OFB => unsafe { EVP_aes_192_ofb() }
57            CipherType::AES_256_OFB => unsafe { EVP_aes_256_ofb() }
58            CipherType::DES_CBC => unsafe { EVP_des_cbc() }
59            CipherType::DES_ECB => unsafe { EVP_des_ecb() }
60            CipherType::RC4 => unsafe { EVP_rc4() }
61        }
62    }
63}
64
65
66pub struct CipherCrypto {
67    mac_key: Vec<u8>,
68    key: Vec<u8>,
69    cipher: Cipher,
70    hash: HashType,
71}
72
73impl CipherCrypto {
74    pub fn new(aead: &Aead, key: Vec<u8>, mac: Vec<u8>, hash: HashType) -> RlsResult<CipherCrypto> {
75        let cipher = match aead {
76            Aead::AES_128_CBC_SHA => Cipher::aes_128_cbc(),
77            Aead::AES_256_CBC_SHA => Cipher::aes_256_cbc(),
78            _ => return Err("not suite, but in suite".into())
79        };
80        Ok(CipherCrypto {
81            mac_key: mac,
82            cipher,
83            key,
84            hash,
85        })
86    }
87
88    /// cbc加密块:
89    /// ```text
90    /// mac = HMAC_SHA1(mac_key, seq_num + record_type + version + len(明文) + plaintext) //20位
91    /// ciphertext = AES_CBC(key, iv, plaintext || mac || padding) //pcsk7
92    ///```
93    pub fn encrypt(&self, param: CryptEncodeParam) -> RlsResult<()> {
94        self.cipher.init_encrypt(self.key.as_ptr(), param.iv.as_ptr())?;
95        let mut hmac = Hmac::new(&self.mac_key, self.hash)?;
96        hmac.update(param.seq.to_be_bytes())?;
97        hmac.update(&param.buffer.head()[..3])?;
98        hmac.update((param.buffer.origin_payload().len() as u16).to_be_bytes())?;
99        hmac.update(param.buffer.origin_payload())?;
100        let mac = hmac.finalize()?;
101        let context = param.buffer.origin_payload().as_ptr();
102        let out = param.buffer.encrypted_buffer().as_mut_ptr();
103        let plain_len = self.cipher.encrypt_update(context, param.buffer.origin_payload().len(), out)?;
104        let out = unsafe { out.add(plain_len) };
105        let mac_len = self.cipher.encrypt_update(mac.as_ptr(), mac.len(), out)?;
106        let padding_len = 16 - (param.buffer.origin_payload().len() + mac.len() + 1) % 16;
107        let padding = vec![padding_len as u8; padding_len + 1];
108        let out = unsafe { out.add(mac_len) };
109        let padding_len = self.cipher.encrypt_update(padding.as_ptr(), padding.len(), out)?;
110        let out = unsafe { out.add(padding_len) };
111        let final_len = self.cipher.encrypt_finalize(out)?;
112        let len = plain_len + mac_len + padding_len + final_len;
113        param.buffer.set_encrypted_len(len);
114        Ok(())
115    }
116
117    pub fn decrypt(&self, param: CryptDecodeParam) -> RlsResult<usize> {
118        self.cipher.init_decrypt(self.key.as_ptr(), param.iv.as_ptr())?;
119        let context = param.buffer.encrypted_payload().as_ptr();
120        let out = param.buffer.decrypted_buffer().as_mut_ptr();
121        let out_len = self.cipher.decrypt_update(context, param.buffer.encrypted_payload().len(), out)?;
122        let out = unsafe { out.add(out_len) };
123        let final_len = self.cipher.decrypt_finalize(out)?;
124        let len = out_len + final_len;
125        let padding_len = param.buffer.decrypted_buffer()[len - 1] as usize;
126        let len = len - padding_len - 1;
127        let mut hmac = Hmac::new(&self.mac_key, self.hash)?;
128        hmac.update(param.seq.to_be_bytes())?;
129        hmac.update(&param.buffer.head()[..3])?;
130        hmac.update((len as u16 - 20).to_be_bytes())?;
131        hmac.update(&param.buffer.decrypted_buffer()[..len - 20])?;
132        let cmac = hmac.finalize()?;
133        let mac = &param.buffer.decrypted_buffer()[len - 20..len - 1];
134        let res = unsafe { CRYPTO_memcmp(cmac.as_ptr() as *const _, mac.as_ptr() as *const _, mac.len()) };
135        if res != 0 { return Err(RlsError::CipherMacError); }
136        Ok(len - 20)
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use crate::boring::evp::CipherCrypto;
143    use crate::boring::{CryptDecodeParam, CryptEncodeParam, HashType};
144    use crate::buffer::{RecordDecodeBuffer, RecordEncodeBuffer};
145    use crate::extend::Aead;
146    use crate::{base64, rand, Cipher, RecordType};
147
148    #[test]
149    fn test_cipher() {
150        let mut cipher = Cipher::aes_192_ctr();
151        cipher.set_secret_key("1234567812345678", Some("1234567812345678"));
152        let res = cipher.encrypt(b"foobar".to_vec()).unwrap();
153        println!("{}", base64::b64encode(&res).unwrap());
154
155        let res = cipher.decrypt(res).unwrap();
156        println!("{}", String::from_utf8(res).unwrap());
157    }
158
159    #[test]
160    fn test_cipher_cryptor() {
161        let aead = Aead::AES_128_CBC_SHA;
162        let key = rand::random::<[u8; 16]>().to_vec();
163        let iv = rand::random::<[u8; 16]>();
164        println!("{:?}", iv);
165        let mut buffer = [0; 1024];
166        // payload.extend(&[0; 20]);
167        let payload = [1, 2, 3, 4, 5, 61, 2, 3, 4, 5, 6, 7, 8, 9, 23, 23];
168        let mac_key = [12; 20];
169        let mut record_buffer = RecordEncodeBuffer::new(RecordType::HandShake, &mut buffer, &payload, &aead);
170        record_buffer.add_explicit_iv(&iv);
171
172        let crypto = CipherCrypto::new(&aead, key, mac_key.to_vec(), HashType::Sha1).unwrap();
173        crypto.encrypt(CryptEncodeParam {
174            nonce: &[0; 12],
175            iv: &iv,
176            aad: &[0; 13],
177            seq: &0,
178            buffer: &mut record_buffer,
179        }).unwrap();
180        let len = record_buffer.record_len();
181        println!("{}", len);
182        println!("{:?}", &buffer[..len + 10]);
183        println!("-----------------encrypted---------------------");
184        let mut decoded_buffer = vec![0; 1024];
185        let mut record_buffer = RecordDecodeBuffer::from_buffer(&buffer[..len], &mut decoded_buffer, &aead).unwrap();
186        let len = crypto.decrypt(CryptDecodeParam {
187            nonce: &[0; 12],
188            iv: &iv,
189            aad: &[0; 13],
190            seq: &0,
191            buffer: &mut record_buffer,
192        }).unwrap();
193        println!("{:?}", &decoded_buffer[..len]);
194    }
195}