Skip to content

Commit decf66a

Browse files
committed
crypto: replace ring AEAD API
This is currently only used for generating header protection masks, which, again, doesn't seem like something worth pulling a whole dependency for. This may or may not fall under FIPS scope.
1 parent b17904e commit decf66a

File tree

3 files changed

+251
-87
lines changed

3 files changed

+251
-87
lines changed

quiche/src/crypto/boringssl.rs

+124-17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use super::*;
33
use std::mem::MaybeUninit;
44

55
use libc::c_int;
6+
use libc::c_uint;
7+
use libc::c_void;
68

79
// NOTE: This structure is copied from <openssl/aead.h> in order to be able to
810
// statically allocate it. While it is not often modified upstream, it needs to
@@ -15,6 +17,13 @@ struct EVP_AEAD_CTX {
1517
tag_len: u8,
1618
}
1719

20+
#[derive(Clone)]
21+
#[repr(C)]
22+
pub(crate) struct AES_KEY {
23+
rd_key: [u32; 4 * (14 + 1)],
24+
rounds: c_int,
25+
}
26+
1827
impl Algorithm {
1928
fn get_evp_aead(self) -> *const EVP_AEAD {
2029
match self {
@@ -126,29 +135,87 @@ impl Seal {
126135
}
127136
}
128137

129-
fn make_aead_ctx(alg: Algorithm, key: &[u8]) -> Result<EVP_AEAD_CTX> {
130-
let mut ctx = MaybeUninit::uninit();
138+
#[derive(Clone)]
139+
pub(crate) enum HeaderProtectionKey {
140+
Aes(AES_KEY),
131141

132-
let ctx = unsafe {
133-
let aead = alg.get_evp_aead();
142+
ChaCha(Vec<u8>),
143+
}
134144

135-
let rc = EVP_AEAD_CTX_init(
136-
ctx.as_mut_ptr(),
137-
aead,
138-
key.as_ptr(),
139-
alg.key_len(),
140-
alg.tag_len(),
141-
std::ptr::null_mut(),
142-
);
145+
impl HeaderProtectionKey {
146+
pub fn new(alg: Algorithm, hp_key: Vec<u8>) -> Result<Self> {
147+
match alg {
148+
Algorithm::AES128_GCM => unsafe {
149+
let mut aes_key = MaybeUninit::<AES_KEY>::uninit();
143150

144-
if rc != 1 {
145-
return Err(Error::CryptoFail);
151+
let rc = AES_set_encrypt_key(
152+
(&hp_key).as_ptr(),
153+
128,
154+
aes_key.as_mut_ptr(),
155+
);
156+
157+
if rc != 0 {
158+
return Err(Error::CryptoFail);
159+
}
160+
161+
let aes_key = aes_key.assume_init();
162+
Ok(Self::Aes(aes_key))
163+
},
164+
165+
Algorithm::AES256_GCM => unsafe {
166+
let mut aes_key = MaybeUninit::<AES_KEY>::uninit();
167+
168+
let rc = AES_set_encrypt_key(
169+
(&hp_key).as_ptr(),
170+
256,
171+
aes_key.as_mut_ptr(),
172+
);
173+
174+
if rc != 0 {
175+
return Err(Error::CryptoFail);
176+
}
177+
178+
let aes_key = aes_key.assume_init();
179+
Ok(Self::Aes(aes_key))
180+
},
181+
182+
Algorithm::ChaCha20_Poly1305 => Ok(Self::ChaCha(hp_key)),
146183
}
184+
}
147185

148-
ctx.assume_init()
149-
};
186+
pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
187+
let mut new_mask = [0_u8; 5];
150188

151-
Ok(ctx)
189+
match self {
190+
Self::Aes(aes_key) => unsafe {
191+
AES_ecb_encrypt(
192+
sample.as_ptr(),
193+
(&mut new_mask).as_mut_ptr(),
194+
aes_key as _,
195+
1,
196+
);
197+
},
198+
199+
Self::ChaCha(key) => unsafe {
200+
const PLAINTEXT: &[u8; 5] = b"\x00\x00\x00\x00\x00";
201+
202+
let counter = u32::from_le_bytes([
203+
sample[0], sample[1], sample[2], sample[3],
204+
]);
205+
206+
CRYPTO_chacha_20(
207+
(&mut new_mask).as_mut_ptr(),
208+
PLAINTEXT.as_ptr(),
209+
PLAINTEXT.len(),
210+
(&key).as_ptr(),
211+
(&sample[std::mem::size_of::<u32>()..]).as_ptr(),
212+
counter,
213+
);
214+
},
215+
}
216+
217+
Ok(new_mask)
218+
}
152219
}
153220

154221
pub(crate) struct PacketKey {
@@ -180,6 +247,31 @@ impl PacketKey {
180247
}
181248
}
182249

250+
fn make_aead_ctx(alg: Algorithm, key: &[u8]) -> Result<EVP_AEAD_CTX> {
251+
let mut ctx = MaybeUninit::uninit();
252+
253+
let ctx = unsafe {
254+
let aead = alg.get_evp_aead();
255+
256+
let rc = EVP_AEAD_CTX_init(
257+
ctx.as_mut_ptr(),
258+
aead,
259+
key.as_ptr(),
260+
alg.key_len(),
261+
alg.tag_len(),
262+
std::ptr::null_mut(),
263+
);
264+
265+
if rc != 1 {
266+
return Err(Error::CryptoFail);
267+
}
268+
269+
ctx.assume_init()
270+
};
271+
272+
Ok(ctx)
273+
}
274+
183275
pub(crate) fn hkdf_extract(
184276
alg: Algorithm, out: &mut [u8], secret: &[u8], salt: &[u8],
185277
) -> Result<()> {
@@ -262,4 +354,19 @@ extern {
262354
nonce_len: usize, inp: *const u8, in_len: usize, extra_in: *const u8,
263355
extra_in_len: usize, ad: *const u8, ad_len: usize,
264356
) -> c_int;
357+
358+
// AES
359+
fn AES_set_encrypt_key(
360+
key: *const u8, bits: c_uint, aeskey: *mut AES_KEY,
361+
) -> c_int;
362+
363+
fn AES_ecb_encrypt(
364+
inp: *const u8, out: *mut u8, key: *const AES_KEY, enc: c_int,
365+
) -> c_void;
366+
367+
// ChaCha20
368+
fn CRYPTO_chacha_20(
369+
out: *mut u8, inp: *const u8, in_len: usize, key: *const u8,
370+
nonce: *const u8, counter: u32,
371+
) -> c_void;
265372
}

quiche/src/crypto/mod.rs

+6-44
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,9 @@ pub enum Algorithm {
6666
ChaCha20_Poly1305,
6767
}
6868

69+
// Note: some vendor-specific methods are implemented by each vendor's submodule
70+
// (openssl-quictls / boringssl).
6971
impl Algorithm {
70-
// Note: some vendor-specific methods are implemented by each vendor's
71-
// submodule (openssl-quictls / boringssl).
72-
fn get_ring_hp(self) -> &'static aead::quic::Algorithm {
73-
match self {
74-
Algorithm::AES128_GCM => &aead::quic::AES_128,
75-
Algorithm::AES256_GCM => &aead::quic::AES_256,
76-
Algorithm::ChaCha20_Poly1305 => &aead::quic::CHACHA20,
77-
}
78-
}
79-
8072
fn get_evp_digest(self) -> *const EVP_MD {
8173
match self {
8274
Algorithm::AES128_GCM => unsafe { EVP_sha256() },
@@ -173,13 +165,7 @@ impl Open {
173165
return Ok(<[u8; 5]>::default());
174166
}
175167

176-
let mask = self
177-
.header
178-
.hpk
179-
.new_mask(sample)
180-
.map_err(|_| Error::CryptoFail)?;
181-
182-
Ok(mask)
168+
self.header.new_mask(sample)
183169
}
184170

185171
pub fn alg(&self) -> Algorithm {
@@ -197,10 +183,7 @@ impl Open {
197183

198184
secret: next_secret,
199185

200-
header: HeaderProtectionKey::new(
201-
self.alg,
202-
self.header.hp_key.clone(),
203-
)?,
186+
header: self.header.clone(),
204187

205188
packet: next_packet_key,
206189
})
@@ -264,13 +247,7 @@ impl Seal {
264247
return Ok(<[u8; 5]>::default());
265248
}
266249

267-
let mask = self
268-
.header
269-
.hpk
270-
.new_mask(sample)
271-
.map_err(|_| Error::CryptoFail)?;
272-
273-
Ok(mask)
250+
self.header.new_mask(sample)
274251
}
275252

276253
pub fn alg(&self) -> Algorithm {
@@ -288,29 +265,14 @@ impl Seal {
288265

289266
secret: next_secret,
290267

291-
header: HeaderProtectionKey::new(
292-
self.alg,
293-
self.header.hp_key.clone(),
294-
)?,
268+
header: self.header.clone(),
295269

296270
packet: next_packet_key,
297271
})
298272
}
299273
}
300274

301-
pub struct HeaderProtectionKey {
302-
hpk: aead::quic::HeaderProtectionKey,
303-
304-
hp_key: Vec<u8>,
305-
}
306-
307275
impl HeaderProtectionKey {
308-
pub fn new(alg: Algorithm, hp_key: Vec<u8>) -> Result<Self> {
309-
aead::quic::HeaderProtectionKey::new(alg.get_ring_hp(), &hp_key)
310-
.map(|hpk| Self { hpk, hp_key })
311-
.map_err(|_| Error::CryptoFail)
312-
}
313-
314276
pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
315277
let key_len = aead.key_len();
316278

0 commit comments

Comments
 (0)