Add ChaCha20 support to QUIC header protection
This requires the addition of a constructor for aead::nonce::Iv from an aead::block::Block. I agree to license my contributions to each file under the terms given at the top of each file I changed.
This commit is contained in:
parent
351ed16251
commit
016a5d54f8
@ -52,6 +52,23 @@ impl Key {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_mask(&self, sample: Block) -> [u8; 5] {
|
||||
let mut out: [u8; 5] = [0; 5];
|
||||
let iv = Iv::assume_unique_for_key(sample);
|
||||
|
||||
unsafe {
|
||||
self.encrypt(
|
||||
CounterOrIv::Iv(iv),
|
||||
out.as_ptr(),
|
||||
out.len(),
|
||||
out.as_mut_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
pub fn encrypt_overlapping(&self, counter: Counter, in_out: &mut [u8], in_prefix_len: usize) {
|
||||
// XXX: The x86 and at least one branch of the ARM assembly language
|
||||
// code doesn't allow overlapping input and output unless they are
|
||||
|
@ -131,6 +131,9 @@ where
|
||||
}
|
||||
|
||||
impl Iv {
|
||||
#[inline]
|
||||
pub fn assume_unique_for_key(a: Block) -> Self { Iv(a) }
|
||||
|
||||
#[inline]
|
||||
pub fn into_block_less_safe(self) -> Block { self.0 }
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! See draft-ietf-quic-tls.
|
||||
|
||||
use crate::{
|
||||
aead::{aes, block::Block},
|
||||
aead::{aes, block::Block, chacha},
|
||||
cpu, error,
|
||||
polyfill::convert::*,
|
||||
};
|
||||
@ -31,6 +31,7 @@ pub struct HeaderProtectionKey {
|
||||
#[allow(variant_size_differences)]
|
||||
enum KeyInner {
|
||||
Aes(aes::Key),
|
||||
ChaCha20(chacha::Key),
|
||||
}
|
||||
|
||||
impl HeaderProtectionKey {
|
||||
@ -83,6 +84,7 @@ derive_debug_via_self!(Algorithm, self.id);
|
||||
enum AlgorithmID {
|
||||
AES_128,
|
||||
AES_256,
|
||||
CHACHA20,
|
||||
}
|
||||
|
||||
impl PartialEq for Algorithm {
|
||||
@ -120,7 +122,30 @@ fn aes_init_256(key: &[u8]) -> Result<KeyInner, error::Unspecified> {
|
||||
fn aes_new_mask(key: &KeyInner, sample: Block) -> [u8; 5] {
|
||||
let aes_key = match key {
|
||||
KeyInner::Aes(key) => key,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
aes_key.new_mask(sample)
|
||||
}
|
||||
|
||||
/// ChaCha20.
|
||||
pub static CHACHA20: Algorithm = Algorithm {
|
||||
key_len: chacha::KEY_LEN,
|
||||
init: chacha20_init,
|
||||
new_mask: chacha20_new_mask,
|
||||
id: AlgorithmID::CHACHA20,
|
||||
};
|
||||
|
||||
fn chacha20_init(key: &[u8]) -> Result<KeyInner, error::Unspecified> {
|
||||
let chacha20_key: &[u8; chacha::KEY_LEN] = key.try_into_()?;
|
||||
Ok(KeyInner::ChaCha20(chacha::Key::from(chacha20_key)))
|
||||
}
|
||||
|
||||
fn chacha20_new_mask(key: &KeyInner, sample: Block) -> [u8; 5] {
|
||||
let chacha20_key = match key {
|
||||
KeyInner::ChaCha20(key) => key,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
chacha20_key.new_mask(sample)
|
||||
}
|
||||
|
3
tests/quic_chacha20_tests.txt
Normal file
3
tests/quic_chacha20_tests.txt
Normal file
@ -0,0 +1,3 @@
|
||||
KEY = 59bdff7a5bcdaacf319d99646c6273ad96687d2c74ace678f15a1c710675bb23
|
||||
SAMPLE = 215a7c1688b4ab7d830dcd052aef9f3c
|
||||
MASK = 6409a6196d
|
@ -39,6 +39,9 @@ fn quic_aes_128() { test_quic(&quic::AES_128, "tests/quic_aes_128_tests.txt"); }
|
||||
#[test]
|
||||
fn quic_aes_256() { test_quic(&quic::AES_256, "tests/quic_aes_256_tests.txt"); }
|
||||
|
||||
#[test]
|
||||
fn quic_chacha20() { test_quic(&quic::CHACHA20, "tests/quic_chacha20_tests.txt"); }
|
||||
|
||||
fn test_quic(alg: &'static quic::Algorithm, file_path: &str) {
|
||||
test_sample_len(alg);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user