Skip to content

Commit

Permalink
crypto: replace ring AEAD API
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ghedo committed Jan 10, 2025
1 parent b17904e commit 447970c
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 86 deletions.
141 changes: 124 additions & 17 deletions quiche/src/crypto/boringssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use super::*;
use std::mem::MaybeUninit;

use libc::c_int;
use libc::c_uint;
use libc::c_void;

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

#[derive(Clone)]
#[repr(C)]
struct AES_KEY {
rd_key: [u32; 4 * (14 + 1)],
rounds: c_int,
}

impl Algorithm {
fn get_evp_aead(self) -> *const EVP_AEAD {
match self {
Expand Down Expand Up @@ -126,29 +135,87 @@ impl Seal {
}
}

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

let ctx = unsafe {
let aead = alg.get_evp_aead();
ChaCha(Vec<u8>),
}

let rc = EVP_AEAD_CTX_init(
ctx.as_mut_ptr(),
aead,
key.as_ptr(),
alg.key_len(),
alg.tag_len(),
std::ptr::null_mut(),
);
impl HeaderProtectionKey {
pub fn new(alg: Algorithm, hp_key: Vec<u8>) -> Result<Self> {
match alg {
Algorithm::AES128_GCM => unsafe {
let mut aes_key = MaybeUninit::<AES_KEY>::uninit();

if rc != 1 {
return Err(Error::CryptoFail);
let rc = AES_set_encrypt_key(
(&hp_key).as_ptr(),
128,
aes_key.as_mut_ptr(),
);

if rc != 0 {
return Err(Error::CryptoFail);
}

let aes_key = aes_key.assume_init();
Ok(Self::Aes(aes_key))
},

Algorithm::AES256_GCM => unsafe {
let mut aes_key = MaybeUninit::<AES_KEY>::uninit();

let rc = AES_set_encrypt_key(
(&hp_key).as_ptr(),
256,
aes_key.as_mut_ptr(),
);

if rc != 0 {
return Err(Error::CryptoFail);
}

let aes_key = aes_key.assume_init();
Ok(Self::Aes(aes_key))
},

Algorithm::ChaCha20_Poly1305 => Ok(Self::ChaCha(hp_key)),
}
}

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

Ok(ctx)
match self {
Self::Aes(aes_key) => unsafe {
AES_ecb_encrypt(
sample.as_ptr(),
(&mut new_mask).as_mut_ptr(),
aes_key as _,
1,
);
},

Self::ChaCha(key) => unsafe {
const PLAINTEXT: &[u8; 5] = b"\x00\x00\x00\x00\x00";

let counter = u32::from_le_bytes([
sample[0], sample[1], sample[2], sample[3]
]);

CRYPTO_chacha_20(
(&mut new_mask).as_mut_ptr(),
PLAINTEXT.as_ptr(),
PLAINTEXT.len(),
(&key).as_ptr(),
(&sample[std::mem::size_of::<u32>()..]).as_ptr(),
counter,
);
},
}

Ok(new_mask)
}
}

pub(crate) struct PacketKey {
Expand Down Expand Up @@ -180,6 +247,31 @@ impl PacketKey {
}
}

fn make_aead_ctx(alg: Algorithm, key: &[u8]) -> Result<EVP_AEAD_CTX> {
let mut ctx = MaybeUninit::uninit();

let ctx = unsafe {
let aead = alg.get_evp_aead();

let rc = EVP_AEAD_CTX_init(
ctx.as_mut_ptr(),
aead,
key.as_ptr(),
alg.key_len(),
alg.tag_len(),
std::ptr::null_mut(),
);

if rc != 1 {
return Err(Error::CryptoFail);
}

ctx.assume_init()
};

Ok(ctx)
}

pub(crate) fn hkdf_extract(
alg: Algorithm, out: &mut [u8], secret: &[u8], salt: &[u8],
) -> Result<()> {
Expand Down Expand Up @@ -262,4 +354,19 @@ extern {
nonce_len: usize, inp: *const u8, in_len: usize, extra_in: *const u8,
extra_in_len: usize, ad: *const u8, ad_len: usize,
) -> c_int;

// AES
fn AES_set_encrypt_key(
key: *const u8, bits: c_uint, aeskey: *mut AES_KEY,
) -> c_int;

fn AES_ecb_encrypt(
inp: *const u8, out: *mut u8, key: *const AES_KEY, enc: c_int,
) -> c_void;

// ChaCha20
fn CRYPTO_chacha_20(
out: *mut u8, inp: *const u8, in_len: usize, key: *const u8,
nonce: *const u8, counter: u32,
) -> c_void;
}
49 changes: 6 additions & 43 deletions quiche/src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,9 @@ pub enum Algorithm {
ChaCha20_Poly1305,
}

// Note: some vendor-specific methods are implemented by each vendor's submodule
// (openssl-quictls / boringssl).
impl Algorithm {
// Note: some vendor-specific methods are implemented by each vendor's
// submodule (openssl-quictls / boringssl).
fn get_ring_hp(self) -> &'static aead::quic::Algorithm {
match self {
Algorithm::AES128_GCM => &aead::quic::AES_128,
Algorithm::AES256_GCM => &aead::quic::AES_256,
Algorithm::ChaCha20_Poly1305 => &aead::quic::CHACHA20,
}
}

fn get_evp_digest(self) -> *const EVP_MD {
match self {
Algorithm::AES128_GCM => unsafe { EVP_sha256() },
Expand Down Expand Up @@ -173,13 +165,7 @@ impl Open {
return Ok(<[u8; 5]>::default());
}

let mask = self
.header
.hpk
.new_mask(sample)
.map_err(|_| Error::CryptoFail)?;

Ok(mask)
self.header.new_mask(sample)
}

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

secret: next_secret,

header: HeaderProtectionKey::new(
self.alg,
self.header.hp_key.clone(),
)?,
header: self.header.clone(),

packet: next_packet_key,
})
Expand Down Expand Up @@ -264,13 +247,7 @@ impl Seal {
return Ok(<[u8; 5]>::default());
}

let mask = self
.header
.hpk
.new_mask(sample)
.map_err(|_| Error::CryptoFail)?;

Ok(mask)
self.header.new_mask(sample)
}

pub fn alg(&self) -> Algorithm {
Expand All @@ -288,29 +265,15 @@ impl Seal {

secret: next_secret,

header: HeaderProtectionKey::new(
self.alg,
self.header.hp_key.clone(),
)?,
header: self.header.clone(),

packet: next_packet_key,
})
}
}

pub struct HeaderProtectionKey {
hpk: aead::quic::HeaderProtectionKey,

hp_key: Vec<u8>,
}

impl HeaderProtectionKey {
pub fn new(alg: Algorithm, hp_key: Vec<u8>) -> Result<Self> {
aead::quic::HeaderProtectionKey::new(alg.get_ring_hp(), &hp_key)
.map(|hpk| Self { hpk, hp_key })
.map_err(|_| Error::CryptoFail)
}

pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
let key_len = aead.key_len();

Expand Down
Loading

0 comments on commit 447970c

Please sign in to comment.