webrtc_dtls/crypto/
crypto_gcm.rs1use std::io::Cursor;
10
11use aes_gcm::aead::generic_array::GenericArray;
12use aes_gcm::aead::AeadInPlace;
13use aes_gcm::{Aes128Gcm, KeyInit};
14use rand::Rng;
15
16use super::*;
17use crate::content::*;
18use crate::error::*;
19use crate::record_layer::record_layer_header::*; const CRYPTO_GCM_TAG_LENGTH: usize = 16;
22const CRYPTO_GCM_NONCE_LENGTH: usize = 12;
23
24#[derive(Clone)]
26pub struct CryptoGcm {
27 local_gcm: Aes128Gcm,
28 remote_gcm: Aes128Gcm,
29 local_write_iv: Vec<u8>,
30 remote_write_iv: Vec<u8>,
31}
32
33impl CryptoGcm {
34 pub fn new(
35 local_key: &[u8],
36 local_write_iv: &[u8],
37 remote_key: &[u8],
38 remote_write_iv: &[u8],
39 ) -> Self {
40 let key = GenericArray::from_slice(local_key);
41 let local_gcm = Aes128Gcm::new(key);
42
43 let key = GenericArray::from_slice(remote_key);
44 let remote_gcm = Aes128Gcm::new(key);
45
46 CryptoGcm {
47 local_gcm,
48 local_write_iv: local_write_iv.to_vec(),
49 remote_gcm,
50 remote_write_iv: remote_write_iv.to_vec(),
51 }
52 }
53
54 pub fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
55 let payload = &raw[RECORD_LAYER_HEADER_SIZE..];
56 let raw = &raw[..RECORD_LAYER_HEADER_SIZE];
57
58 let mut nonce = vec![0u8; CRYPTO_GCM_NONCE_LENGTH];
59 nonce[..4].copy_from_slice(&self.local_write_iv[..4]);
60 rand::thread_rng().fill(&mut nonce[4..]);
61 let nonce = GenericArray::from_slice(&nonce);
62
63 let additional_data = generate_aead_additional_data(pkt_rlh, payload.len());
64
65 let mut buffer: Vec<u8> = Vec::new();
66 buffer.extend_from_slice(payload);
67
68 self.local_gcm
69 .encrypt_in_place(nonce, &additional_data, &mut buffer)
70 .map_err(|e| Error::Other(e.to_string()))?;
71
72 let mut r = Vec::with_capacity(raw.len() + nonce.len() + buffer.len());
73 r.extend_from_slice(raw);
74 r.extend_from_slice(&nonce[4..]);
75 r.extend_from_slice(&buffer);
76
77 let r_len = (r.len() - RECORD_LAYER_HEADER_SIZE) as u16;
79 r[RECORD_LAYER_HEADER_SIZE - 2..RECORD_LAYER_HEADER_SIZE]
80 .copy_from_slice(&r_len.to_be_bytes());
81
82 Ok(r)
83 }
84
85 pub fn decrypt(&self, r: &[u8]) -> Result<Vec<u8>> {
86 let mut reader = Cursor::new(r);
87 let h = RecordLayerHeader::unmarshal(&mut reader)?;
88 if h.content_type == ContentType::ChangeCipherSpec {
89 return Ok(r.to_vec());
91 }
92
93 if r.len() <= (RECORD_LAYER_HEADER_SIZE + 8) {
94 return Err(Error::ErrNotEnoughRoomForNonce);
95 }
96
97 let mut nonce = vec![];
98 nonce.extend_from_slice(&self.remote_write_iv[..4]);
99 nonce.extend_from_slice(&r[RECORD_LAYER_HEADER_SIZE..RECORD_LAYER_HEADER_SIZE + 8]);
100 let nonce = GenericArray::from_slice(&nonce);
101
102 let out = &r[RECORD_LAYER_HEADER_SIZE + 8..];
103
104 let additional_data = generate_aead_additional_data(&h, out.len() - CRYPTO_GCM_TAG_LENGTH);
105
106 let mut buffer: Vec<u8> = Vec::new();
107 buffer.extend_from_slice(out);
108
109 self.remote_gcm
110 .decrypt_in_place(nonce, &additional_data, &mut buffer)
111 .map_err(|e| Error::Other(e.to_string()))?;
112
113 let mut d = Vec::with_capacity(RECORD_LAYER_HEADER_SIZE + buffer.len());
114 d.extend_from_slice(&r[..RECORD_LAYER_HEADER_SIZE]);
115 d.extend_from_slice(&buffer);
116
117 Ok(d)
118 }
119}