xref: /webrtc/dtls/src/crypto/crypto_cbc.rs (revision ffe74184)
1 // AES-CBC (Cipher Block Chaining)
2 // First historic block cipher for AES.
3 // CBC mode is insecure and must not be used. It’s been progressively deprecated and
4 // removed from SSL libraries.
5 // Introduced with TLS 1.0 year 2002. Superseded by GCM in TLS 1.2 year 2008.
6 // Removed in TLS 1.3 year 2018.
7 // RFC 3268 year 2002 https://tools.ietf.org/html/rfc3268
8 
9 // https://github.com/RustCrypto/block-ciphers
10 
11 use std::io::Cursor;
12 use std::ops::Not;
13 
14 use crate::content::*;
15 use crate::error::*;
16 use crate::prf::*;
17 use crate::record_layer::record_layer_header::*;
18 
19 use aes::Aes256;
20 use block_modes::BlockModeError;
21 use block_modes::{BlockMode, Cbc};
22 use rand::Rng;
23 use subtle::ConstantTimeEq;
24 
25 use super::padding::DtlsPadding;
26 type Aes256Cbc = Cbc<Aes256, DtlsPadding>;
27 
28 // State needed to handle encrypted input/output
29 #[derive(Clone)]
30 pub struct CryptoCbc {
31     local_key: Vec<u8>,
32     remote_key: Vec<u8>,
33     write_mac: Vec<u8>,
34     read_mac: Vec<u8>,
35 }
36 
37 impl CryptoCbc {
38     const BLOCK_SIZE: usize = 16;
39     const MAC_SIZE: usize = 20;
40 
new( local_key: &[u8], local_mac: &[u8], remote_key: &[u8], remote_mac: &[u8], ) -> Result<Self>41     pub fn new(
42         local_key: &[u8],
43         local_mac: &[u8],
44         remote_key: &[u8],
45         remote_mac: &[u8],
46     ) -> Result<Self> {
47         Ok(CryptoCbc {
48             local_key: local_key.to_vec(),
49             write_mac: local_mac.to_vec(),
50 
51             remote_key: remote_key.to_vec(),
52             read_mac: remote_mac.to_vec(),
53         })
54     }
55 
encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>56     pub fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
57         let mut payload = raw[RECORD_LAYER_HEADER_SIZE..].to_vec();
58         let raw = &raw[..RECORD_LAYER_HEADER_SIZE];
59 
60         // Generate + Append MAC
61         let h = pkt_rlh;
62 
63         let mac = prf_mac(
64             h.epoch,
65             h.sequence_number,
66             h.content_type,
67             h.protocol_version,
68             &payload,
69             &self.write_mac,
70         )?;
71         payload.extend_from_slice(&mac);
72 
73         let mut iv: Vec<u8> = vec![0; Self::BLOCK_SIZE];
74         rand::thread_rng().fill(iv.as_mut_slice());
75 
76         let write_cbc = Aes256Cbc::new_var(&self.local_key, &iv)?;
77         let encrypted = write_cbc.encrypt_vec(&payload);
78 
79         // Prepend unencrypte header with encrypted payload
80         let mut r = vec![];
81         r.extend_from_slice(raw);
82         r.extend_from_slice(&iv);
83         r.extend_from_slice(&encrypted);
84 
85         let r_len = (r.len() - RECORD_LAYER_HEADER_SIZE) as u16;
86         r[RECORD_LAYER_HEADER_SIZE - 2..RECORD_LAYER_HEADER_SIZE]
87             .copy_from_slice(&r_len.to_be_bytes());
88 
89         Ok(r)
90     }
91 
decrypt(&self, r: &[u8]) -> Result<Vec<u8>>92     pub fn decrypt(&self, r: &[u8]) -> Result<Vec<u8>> {
93         let mut reader = Cursor::new(r);
94         let h = RecordLayerHeader::unmarshal(&mut reader)?;
95         if h.content_type == ContentType::ChangeCipherSpec {
96             // Nothing to encrypt with ChangeCipherSpec
97             return Ok(r.to_vec());
98         }
99 
100         let body = &r[RECORD_LAYER_HEADER_SIZE..];
101         let iv = &body[0..Self::BLOCK_SIZE];
102         let body = &body[Self::BLOCK_SIZE..];
103         //TODO: add body.len() check
104 
105         let read_cbc = Aes256Cbc::new_var(&self.remote_key, iv)?;
106 
107         let decrypted = read_cbc.decrypt_vec(body)?;
108 
109         let recv_mac = &decrypted[decrypted.len() - Self::MAC_SIZE..];
110         let decrypted = &decrypted[0..decrypted.len() - Self::MAC_SIZE];
111         let mac = prf_mac(
112             h.epoch,
113             h.sequence_number,
114             h.content_type,
115             h.protocol_version,
116             decrypted,
117             &self.read_mac,
118         )?;
119 
120         if recv_mac.ct_eq(&mac).not().into() {
121             return Err(BlockModeError.into());
122         }
123 
124         let mut d = Vec::with_capacity(RECORD_LAYER_HEADER_SIZE + decrypted.len());
125         d.extend_from_slice(&r[..RECORD_LAYER_HEADER_SIZE]);
126         d.extend_from_slice(decrypted);
127 
128         Ok(d)
129     }
130 }
131