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:
Alessandro Ghedini 2019-01-05 03:11:44 +00:00 committed by Brian Smith
parent 351ed16251
commit 016a5d54f8
5 changed files with 52 additions and 1 deletions

View File

@ -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) { 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 // XXX: The x86 and at least one branch of the ARM assembly language
// code doesn't allow overlapping input and output unless they are // code doesn't allow overlapping input and output unless they are

View File

@ -131,6 +131,9 @@ where
} }
impl Iv { impl Iv {
#[inline]
pub fn assume_unique_for_key(a: Block) -> Self { Iv(a) }
#[inline] #[inline]
pub fn into_block_less_safe(self) -> Block { self.0 } pub fn into_block_less_safe(self) -> Block { self.0 }
} }

View File

@ -17,7 +17,7 @@
//! See draft-ietf-quic-tls. //! See draft-ietf-quic-tls.
use crate::{ use crate::{
aead::{aes, block::Block}, aead::{aes, block::Block, chacha},
cpu, error, cpu, error,
polyfill::convert::*, polyfill::convert::*,
}; };
@ -31,6 +31,7 @@ pub struct HeaderProtectionKey {
#[allow(variant_size_differences)] #[allow(variant_size_differences)]
enum KeyInner { enum KeyInner {
Aes(aes::Key), Aes(aes::Key),
ChaCha20(chacha::Key),
} }
impl HeaderProtectionKey { impl HeaderProtectionKey {
@ -83,6 +84,7 @@ derive_debug_via_self!(Algorithm, self.id);
enum AlgorithmID { enum AlgorithmID {
AES_128, AES_128,
AES_256, AES_256,
CHACHA20,
} }
impl PartialEq for Algorithm { 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] { fn aes_new_mask(key: &KeyInner, sample: Block) -> [u8; 5] {
let aes_key = match key { let aes_key = match key {
KeyInner::Aes(key) => key, KeyInner::Aes(key) => key,
_ => unreachable!(),
}; };
aes_key.new_mask(sample) 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)
}

View File

@ -0,0 +1,3 @@
KEY = 59bdff7a5bcdaacf319d99646c6273ad96687d2c74ace678f15a1c710675bb23
SAMPLE = 215a7c1688b4ab7d830dcd052aef9f3c
MASK = 6409a6196d

View File

@ -39,6 +39,9 @@ fn quic_aes_128() { test_quic(&quic::AES_128, "tests/quic_aes_128_tests.txt"); }
#[test] #[test]
fn quic_aes_256() { test_quic(&quic::AES_256, "tests/quic_aes_256_tests.txt"); } 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) { fn test_quic(alg: &'static quic::Algorithm, file_path: &str) {
test_sample_len(alg); test_sample_len(alg);