webrtc_dtls/crypto/
crypto_cbc.rs

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
11use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
12use p256::elliptic_curve::subtle::ConstantTimeEq;
13use rand::Rng;
14use std::io::Cursor;
15use std::ops::Not;
16
17use super::padding::DtlsPadding;
18use crate::content::*;
19use crate::error::*;
20use crate::prf::*;
21use crate::record_layer::record_layer_header::*;
22type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
23type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
24
25// State needed to handle encrypted input/output
26#[derive(Clone)]
27pub struct CryptoCbc {
28    local_key: Vec<u8>,
29    remote_key: Vec<u8>,
30    write_mac: Vec<u8>,
31    read_mac: Vec<u8>,
32}
33
34impl CryptoCbc {
35    const BLOCK_SIZE: usize = 16;
36    const MAC_SIZE: usize = 20;
37
38    pub fn new(
39        local_key: &[u8],
40        local_mac: &[u8],
41        remote_key: &[u8],
42        remote_mac: &[u8],
43    ) -> Result<Self> {
44        Ok(CryptoCbc {
45            local_key: local_key.to_vec(),
46            write_mac: local_mac.to_vec(),
47
48            remote_key: remote_key.to_vec(),
49            read_mac: remote_mac.to_vec(),
50        })
51    }
52
53    pub fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
54        let mut payload = raw[RECORD_LAYER_HEADER_SIZE..].to_vec();
55        let raw = &raw[..RECORD_LAYER_HEADER_SIZE];
56
57        // Generate + Append MAC
58        let h = pkt_rlh;
59
60        let mac = prf_mac(
61            h.epoch,
62            h.sequence_number,
63            h.content_type,
64            h.protocol_version,
65            &payload,
66            &self.write_mac,
67        )?;
68        payload.extend_from_slice(&mac);
69
70        let mut iv: Vec<u8> = vec![0; Self::BLOCK_SIZE];
71        rand::thread_rng().fill(iv.as_mut_slice());
72
73        let write_cbc = Aes256CbcEnc::new_from_slices(&self.local_key, &iv)?;
74        let encrypted = write_cbc.encrypt_padded_vec_mut::<DtlsPadding>(&payload);
75
76        // Prepend unencrypte header with encrypted payload
77        let mut r = vec![];
78        r.extend_from_slice(raw);
79        r.extend_from_slice(&iv);
80        r.extend_from_slice(&encrypted);
81
82        let r_len = (r.len() - RECORD_LAYER_HEADER_SIZE) as u16;
83        r[RECORD_LAYER_HEADER_SIZE - 2..RECORD_LAYER_HEADER_SIZE]
84            .copy_from_slice(&r_len.to_be_bytes());
85
86        Ok(r)
87    }
88
89    pub fn decrypt(&self, r: &[u8]) -> Result<Vec<u8>> {
90        let mut reader = Cursor::new(r);
91        let h = RecordLayerHeader::unmarshal(&mut reader)?;
92        if h.content_type == ContentType::ChangeCipherSpec {
93            // Nothing to encrypt with ChangeCipherSpec
94            return Ok(r.to_vec());
95        }
96
97        let body = &r[RECORD_LAYER_HEADER_SIZE..];
98        let iv = &body[0..Self::BLOCK_SIZE];
99        let body = &body[Self::BLOCK_SIZE..];
100        //TODO: add body.len() check
101
102        let read_cbc = Aes256CbcDec::new_from_slices(&self.remote_key, iv)?;
103
104        let decrypted = read_cbc
105            .decrypt_padded_vec_mut::<DtlsPadding>(body)
106            .map_err(|_| Error::ErrInvalidPacketLength)?;
107
108        let recv_mac = &decrypted[decrypted.len() - Self::MAC_SIZE..];
109        let decrypted = &decrypted[0..decrypted.len() - Self::MAC_SIZE];
110        let mac = prf_mac(
111            h.epoch,
112            h.sequence_number,
113            h.content_type,
114            h.protocol_version,
115            decrypted,
116            &self.read_mac,
117        )?;
118
119        if recv_mac.ct_eq(&mac).not().into() {
120            return Err(Error::ErrInvalidMac);
121        }
122
123        let mut d = Vec::with_capacity(RECORD_LAYER_HEADER_SIZE + decrypted.len());
124        d.extend_from_slice(&r[..RECORD_LAYER_HEADER_SIZE]);
125        d.extend_from_slice(decrypted);
126
127        Ok(d)
128    }
129}