diff options
Diffstat (limited to 'src/crypto.rs')
-rw-r--r-- | src/crypto.rs | 242 |
1 files changed, 176 insertions, 66 deletions
diff --git a/src/crypto.rs b/src/crypto.rs index 079961f..b873757 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -38,7 +38,7 @@ use crate::Result; use crate::packet; #[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Level { Initial = 0, ZeroRTT = 1, @@ -49,18 +49,16 @@ pub enum Level { impl Level { pub fn from_epoch(e: packet::Epoch) -> Level { match e { - packet::EPOCH_INITIAL => Level::Initial, + packet::Epoch::Initial => Level::Initial, - packet::EPOCH_HANDSHAKE => Level::Handshake, + packet::Epoch::Handshake => Level::Handshake, - packet::EPOCH_APPLICATION => Level::OneRTT, - - _ => unreachable!(), + packet::Epoch::Application => Level::OneRTT, } } } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Algorithm { #[allow(non_camel_case_types)] AES128_GCM, @@ -131,45 +129,38 @@ impl Algorithm { pub struct Open { alg: Algorithm, - ctx: EVP_AEAD_CTX, + secret: Vec<u8>, - hp_key: aead::quic::HeaderProtectionKey, + header: HeaderProtectionKey, - nonce: Vec<u8>, + packet: PacketKey, } impl Open { pub fn new( - alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], + alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8], ) -> Result<Open> { Ok(Open { alg, - ctx: make_aead_ctx(alg, key)?, + secret: Vec::from(secret), - hp_key: aead::quic::HeaderProtectionKey::new( - alg.get_ring_hp(), - hp_key, - ) - .map_err(|_| Error::CryptoFail)?, + header: HeaderProtectionKey::new(alg, hp_key)?, - nonce: Vec::from(iv), + packet: PacketKey::new(alg, key, iv)?, }) } pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open> { - let key_len = aead.key_len(); - let nonce_len = aead.nonce_len(); + Ok(Open { + alg: aead, - let mut key = vec![0; key_len]; - let mut iv = vec![0; nonce_len]; - let mut pn_key = vec![0; key_len]; + secret: Vec::from(secret), - derive_pkt_key(aead, secret, &mut key)?; - derive_pkt_iv(aead, secret, &mut iv)?; - derive_hdr_key(aead, secret, &mut pn_key)?; + header: HeaderProtectionKey::from_secret(aead, secret)?, - Open::new(aead, &key, &iv, &pn_key) + packet: PacketKey::from_secret(aead, secret)?, + }) } pub fn open_with_u64_counter( @@ -188,11 +179,11 @@ impl Open { let max_out_len = out_len; - let nonce = make_nonce(&self.nonce, counter); + let nonce = make_nonce(&self.packet.nonce, counter); let rc = unsafe { EVP_AEAD_CTX_open( - &self.ctx, // ctx + &self.packet.ctx, // ctx buf.as_mut_ptr(), // out &mut out_len, // out_len max_out_len, // max_out_len @@ -218,7 +209,8 @@ impl Open { } let mask = self - .hp_key + .header + .hpk .new_mask(sample) .map_err(|_| Error::CryptoFail)?; @@ -228,50 +220,59 @@ impl Open { pub fn alg(&self) -> Algorithm { self.alg } + + pub fn derive_next_packet_key(&self) -> Result<Open> { + let next_secret = derive_next_secret(self.alg, &self.secret)?; + + let next_packet_key = PacketKey::from_secret(self.alg, &next_secret)?; + + Ok(Open { + alg: self.alg, + + secret: next_secret, + + header: HeaderProtectionKey::new(self.alg, &self.header.hp_key)?, + + packet: next_packet_key, + }) + } } pub struct Seal { alg: Algorithm, - ctx: EVP_AEAD_CTX, + secret: Vec<u8>, - hp_key: aead::quic::HeaderProtectionKey, + header: HeaderProtectionKey, - nonce: Vec<u8>, + packet: PacketKey, } impl Seal { pub fn new( - alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], + alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8], ) -> Result<Seal> { Ok(Seal { alg, - ctx: make_aead_ctx(alg, key)?, + secret: Vec::from(secret), - hp_key: aead::quic::HeaderProtectionKey::new( - alg.get_ring_hp(), - hp_key, - ) - .map_err(|_| Error::CryptoFail)?, + header: HeaderProtectionKey::new(alg, hp_key)?, - nonce: Vec::from(iv), + packet: PacketKey::new(alg, key, iv)?, }) } pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> { - let key_len = aead.key_len(); - let nonce_len = aead.nonce_len(); + Ok(Seal { + alg: aead, - let mut key = vec![0; key_len]; - let mut iv = vec![0; nonce_len]; - let mut pn_key = vec![0; key_len]; + secret: Vec::from(secret), - derive_pkt_key(aead, secret, &mut key)?; - derive_pkt_iv(aead, secret, &mut iv)?; - derive_hdr_key(aead, secret, &mut pn_key)?; + header: HeaderProtectionKey::from_secret(aead, secret)?, - Seal::new(aead, &key, &iv, &pn_key) + packet: PacketKey::from_secret(aead, secret)?, + }) } pub fn seal_with_u64_counter( @@ -302,11 +303,11 @@ impl Seal { return Err(Error::CryptoFail); } - let nonce = make_nonce(&self.nonce, counter); + let nonce = make_nonce(&self.packet.nonce, counter); let rc = unsafe { EVP_AEAD_CTX_seal_scatter( - &self.ctx, // ctx + &self.packet.ctx, // ctx buf.as_mut_ptr(), // out buf[in_len..].as_mut_ptr(), // out_tag &mut out_tag_len, // out_tag_len @@ -335,7 +336,8 @@ impl Seal { } let mask = self - .hp_key + .header + .hpk .new_mask(sample) .map_err(|_| Error::CryptoFail)?; @@ -345,12 +347,85 @@ impl Seal { pub fn alg(&self) -> Algorithm { self.alg } + + pub fn derive_next_packet_key(&self) -> Result<Seal> { + let next_secret = derive_next_secret(self.alg, &self.secret)?; + + let next_packet_key = PacketKey::from_secret(self.alg, &next_secret)?; + + Ok(Seal { + alg: self.alg, + + secret: next_secret, + + header: HeaderProtectionKey::new(self.alg, &self.header.hp_key)?, + + packet: next_packet_key, + }) + } +} + +pub struct HeaderProtectionKey { + hpk: aead::quic::HeaderProtectionKey, + + hp_key: Vec<u8>, +} + +impl HeaderProtectionKey { + pub fn new(alg: Algorithm, hp_key: &[u8]) -> Result<Self> { + aead::quic::HeaderProtectionKey::new(alg.get_ring_hp(), hp_key) + .map(|hpk| Self { + hpk, + hp_key: Vec::from(hp_key), + }) + .map_err(|_| Error::CryptoFail) + } + + pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> { + let key_len = aead.key_len(); + + let mut hp_key = vec![0; key_len]; + + derive_hdr_key(aead, secret, &mut hp_key)?; + + Self::new(aead, &hp_key) + } +} + +pub struct PacketKey { + ctx: EVP_AEAD_CTX, + + nonce: Vec<u8>, +} + +impl PacketKey { + pub fn new(alg: Algorithm, key: &[u8], iv: &[u8]) -> Result<Self> { + Ok(Self { + ctx: make_aead_ctx(alg, key)?, + + nonce: Vec::from(iv), + }) + } + + pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> { + let key_len = aead.key_len(); + let nonce_len = aead.nonce_len(); + + let mut key = vec![0; key_len]; + let mut iv = vec![0; nonce_len]; + + derive_pkt_key(aead, secret, &mut key)?; + derive_pkt_iv(aead, secret, &mut iv)?; + + Self::new(aead, &key, &iv) + } } pub fn derive_initial_key_material( cid: &[u8], version: u32, is_server: bool, ) -> Result<(Open, Seal)> { - let mut secret = [0; 32]; + let mut client_secret = [0; 32]; + let mut server_secret = [0; 32]; let aead = Algorithm::AES128_GCM; @@ -364,30 +439,54 @@ pub fn derive_initial_key_material( let mut client_iv = vec![0; nonce_len]; let mut client_hp_key = vec![0; key_len]; - derive_client_initial_secret(&initial_secret, &mut secret)?; - derive_pkt_key(aead, &secret, &mut client_key)?; - derive_pkt_iv(aead, &secret, &mut client_iv)?; - derive_hdr_key(aead, &secret, &mut client_hp_key)?; + derive_client_initial_secret(&initial_secret, &mut client_secret)?; + derive_pkt_key(aead, &client_secret, &mut client_key)?; + derive_pkt_iv(aead, &client_secret, &mut client_iv)?; + derive_hdr_key(aead, &client_secret, &mut client_hp_key)?; // Server. let mut server_key = vec![0; key_len]; let mut server_iv = vec![0; nonce_len]; let mut server_hp_key = vec![0; key_len]; - derive_server_initial_secret(&initial_secret, &mut secret)?; - derive_pkt_key(aead, &secret, &mut server_key)?; - derive_pkt_iv(aead, &secret, &mut server_iv)?; - derive_hdr_key(aead, &secret, &mut server_hp_key)?; + derive_server_initial_secret(&initial_secret, &mut server_secret)?; + derive_pkt_key(aead, &server_secret, &mut server_key)?; + derive_pkt_iv(aead, &server_secret, &mut server_iv)?; + derive_hdr_key(aead, &server_secret, &mut server_hp_key)?; let (open, seal) = if is_server { ( - Open::new(aead, &client_key, &client_iv, &client_hp_key)?, - Seal::new(aead, &server_key, &server_iv, &server_hp_key)?, + Open::new( + aead, + &client_key, + &client_iv, + &client_hp_key, + &client_secret, + )?, + Seal::new( + aead, + &server_key, + &server_iv, + &server_hp_key, + &server_secret, + )?, ) } else { ( - Open::new(aead, &server_key, &server_iv, &server_hp_key)?, - Seal::new(aead, &client_key, &client_iv, &client_hp_key)?, + Open::new( + aead, + &server_key, + &server_iv, + &server_hp_key, + &server_secret, + )?, + Seal::new( + aead, + &client_key, + &client_iv, + &client_hp_key, + &client_secret, + )?, ) }; @@ -433,6 +532,17 @@ fn derive_server_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()> { hkdf_expand_label(prk, LABEL, out) } +fn derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>> { + const LABEL: &[u8] = b"quic ku"; + + let mut next_secret = vec![0; secret.len()]; + + let secret_prk = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret); + hkdf_expand_label(&secret_prk, LABEL, &mut next_secret)?; + + Ok(next_secret) +} + pub fn derive_hdr_key( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()> { |