Skip to content

Commit

Permalink
CryptoSpace -> Epoch
Browse files Browse the repository at this point in the history
  • Loading branch information
larseggert committed Feb 11, 2025
1 parent 4c42992 commit 227c1bd
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 75 deletions.
5 changes: 2 additions & 3 deletions neqo-crypto/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

use enum_map::Enum;

use crate::{ssl, Error};
Expand All @@ -15,7 +13,7 @@ use crate::{ssl, Error};

pub type Alert = u8;

#[derive(Default, Debug, Enum, Clone, Copy, PartialEq, Eq)]
#[derive(Default, Debug, Enum, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Epoch {
// TLS doesn't really have an "initial" concept that maps to QUIC so directly,
// but this should be clear enough.
Expand Down Expand Up @@ -74,6 +72,7 @@ remap_enum! {
}
}

#[allow(dead_code)]
mod ciphers {
include!(concat!(env!("OUT_DIR"), "/nss_ciphers.rs"));
}
Expand Down
13 changes: 6 additions & 7 deletions neqo-transport/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
ConnectionId, ConnectionIdEntry, ConnectionIdGenerator, ConnectionIdManager,
ConnectionIdRef, ConnectionIdStore, LOCAL_ACTIVE_CID_LIMIT,
},
crypto::{Crypto, CryptoDxState, CryptoSpace},
crypto::{Crypto, CryptoDxState, Epoch},
ecn,
events::{ConnectionEvent, ConnectionEvents, OutgoingDatagramOutcome},
frame::{
Expand Down Expand Up @@ -1292,7 +1292,7 @@ impl Connection {
#[allow(clippy::needless_pass_by_value)] // To consume an owned datagram below.
fn save_datagram(
&mut self,
cspace: CryptoSpace,
cspace: Epoch,
d: Datagram<impl AsRef<[u8]>>,
remaining: usize,
now: Instant,
Expand Down Expand Up @@ -1673,7 +1673,7 @@ impl Connection {
// This was a valid-appearing Initial packet: maybe probe with
// a Handshake packet to keep the handshake moving.
self.received_untracked |=
self.role == Role::Client && cspace == CryptoSpace::Initial;
self.role == Role::Client && cspace == Epoch::Initial;
}
_ => (),
}
Expand Down Expand Up @@ -2060,7 +2060,7 @@ impl Connection {

fn build_packet_header(
path: &Path,
cspace: CryptoSpace,
cspace: Epoch,
encoder: Encoder,
tx: &CryptoDxState,
address_validation: &AddressValidationInfo,
Expand Down Expand Up @@ -2876,7 +2876,7 @@ impl Connection {
// server can rely on implicit acknowledgment.
self.discard_keys(PacketNumberSpace::Initial, now);
}
self.saved_datagrams.make_available(CryptoSpace::Handshake);
self.saved_datagrams.make_available(Epoch::Handshake);
}
}

Expand Down Expand Up @@ -3245,8 +3245,7 @@ impl Connection {
self.process_tps(now)?;
self.set_state(State::Connected, now);
self.create_resumption_token(now);
self.saved_datagrams
.make_available(CryptoSpace::ApplicationData);
self.saved_datagrams.make_available(Epoch::ApplicationData);
self.stats.borrow_mut().resumed = self
.crypto
.tls
Expand Down
20 changes: 10 additions & 10 deletions neqo-transport/src/connection/saved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{mem, time::Instant};

use neqo_common::{qdebug, qinfo, Datagram};

use crate::crypto::CryptoSpace;
use crate::crypto::Epoch;

/// The number of datagrams that are saved during the handshake when
/// keys to decrypt them are not yet available.
Expand All @@ -25,19 +25,19 @@ pub struct SavedDatagram {
pub struct SavedDatagrams {
handshake: Vec<SavedDatagram>,
application_data: Vec<SavedDatagram>,
available: Option<CryptoSpace>,
available: Option<Epoch>,
}

impl SavedDatagrams {
fn store(&mut self, cspace: CryptoSpace) -> &mut Vec<SavedDatagram> {
fn store(&mut self, cspace: Epoch) -> &mut Vec<SavedDatagram> {
match cspace {
CryptoSpace::Handshake => &mut self.handshake,
CryptoSpace::ApplicationData => &mut self.application_data,
Epoch::Handshake => &mut self.handshake,
Epoch::ApplicationData => &mut self.application_data,
_ => panic!("unexpected space"),
}
}

pub fn save(&mut self, cspace: CryptoSpace, d: Datagram, t: Instant) {
pub fn save(&mut self, cspace: Epoch, d: Datagram, t: Instant) {
let store = self.store(cspace);

if store.len() < MAX_SAVED_DATAGRAMS {
Expand All @@ -48,15 +48,15 @@ impl SavedDatagrams {
}
}

pub fn make_available(&mut self, cspace: CryptoSpace) {
debug_assert_ne!(cspace, CryptoSpace::ZeroRtt);
debug_assert_ne!(cspace, CryptoSpace::Initial);
pub fn make_available(&mut self, cspace: Epoch) {
debug_assert_ne!(cspace, Epoch::ZeroRtt);
debug_assert_ne!(cspace, Epoch::Initial);
if !self.store(cspace).is_empty() {
self.available = Some(cspace);
}
}

pub const fn available(&self) -> Option<CryptoSpace> {
pub const fn available(&self) -> Option<Epoch> {
self.available
}

Expand Down
81 changes: 37 additions & 44 deletions neqo-transport/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ use std::{
};

use neqo_common::{hex, hex_snip_middle, qdebug, qinfo, qtrace, Encoder, Role};
pub use neqo_crypto::Epoch;
use neqo_crypto::{
hkdf, hp::HpKey, Aead, Agent, AntiReplay, Cipher, Epoch, Error as CryptoError, HandshakeState,
hkdf, hp::HpKey, Aead, Agent, AntiReplay, Cipher, Error as CryptoError, HandshakeState,
PrivateKey, PublicKey, Record, RecordList, ResumptionToken, SymKey, ZeroRttChecker,
TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_CT_HANDSHAKE,
TLS_GRP_EC_SECP256R1, TLS_GRP_EC_SECP384R1, TLS_GRP_EC_SECP521R1, TLS_GRP_EC_X25519,
Expand Down Expand Up @@ -792,14 +793,6 @@ impl CryptoDxAppData {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum CryptoSpace {
Initial,
ZeroRtt,
Handshake,
ApplicationData,
}

/// All of the keying material needed for a connection.
///
/// Note that the methods on this struct take a version but those are only ever
Expand Down Expand Up @@ -827,19 +820,19 @@ impl CryptoStates {
&mut self,
version: Version,
space: PacketNumberSpace,
) -> Option<(CryptoSpace, &mut CryptoDxState)> {
) -> Option<(Epoch, &mut CryptoDxState)> {
match space {
PacketNumberSpace::Initial => self
.tx_mut(version, CryptoSpace::Initial)
.map(|dx| (CryptoSpace::Initial, dx)),
.tx_mut(version, Epoch::Initial)
.map(|dx| (Epoch::Initial, dx)),
PacketNumberSpace::Handshake => self
.tx_mut(version, CryptoSpace::Handshake)
.map(|dx| (CryptoSpace::Handshake, dx)),
.tx_mut(version, Epoch::Handshake)
.map(|dx| (Epoch::Handshake, dx)),
PacketNumberSpace::ApplicationData => {
if let Some(app) = self.app_write.as_mut() {
Some((CryptoSpace::ApplicationData, &mut app.dx))
Some((Epoch::ApplicationData, &mut app.dx))
} else {
self.zero_rtt.as_mut().map(|dx| (CryptoSpace::ZeroRtt, dx))
self.zero_rtt.as_mut().map(|dx| (Epoch::ZeroRtt, dx))
}
}
}
Expand All @@ -848,54 +841,54 @@ impl CryptoStates {
pub fn tx_mut<'a>(
&'a mut self,
version: Version,
cspace: CryptoSpace,
cspace: Epoch,
) -> Option<&'a mut CryptoDxState> {
let tx = |k: Option<&'a mut CryptoState>| k.map(|dx| &mut dx.tx);
match cspace {
CryptoSpace::Initial => tx(self.initials.get_mut(&version)),
CryptoSpace::ZeroRtt => self
Epoch::Initial => tx(self.initials.get_mut(&version)),
Epoch::ZeroRtt => self
.zero_rtt
.as_mut()
.filter(|z| z.direction == CryptoDxDirection::Write),
CryptoSpace::Handshake => tx(self.handshake.as_mut()),
CryptoSpace::ApplicationData => self.app_write.as_mut().map(|app| &mut app.dx),
Epoch::Handshake => tx(self.handshake.as_mut()),
Epoch::ApplicationData => self.app_write.as_mut().map(|app| &mut app.dx),
}
}

pub fn tx<'a>(&'a self, version: Version, cspace: CryptoSpace) -> Option<&'a CryptoDxState> {
pub fn tx<'a>(&'a self, version: Version, cspace: Epoch) -> Option<&'a CryptoDxState> {
let tx = |k: Option<&'a CryptoState>| k.map(|dx| &dx.tx);
match cspace {
CryptoSpace::Initial => tx(self.initials.get(&version)),
CryptoSpace::ZeroRtt => self
Epoch::Initial => tx(self.initials.get(&version)),
Epoch::ZeroRtt => self
.zero_rtt
.as_ref()
.filter(|z| z.direction == CryptoDxDirection::Write),
CryptoSpace::Handshake => tx(self.handshake.as_ref()),
CryptoSpace::ApplicationData => self.app_write.as_ref().map(|app| &app.dx),
Epoch::Handshake => tx(self.handshake.as_ref()),
Epoch::ApplicationData => self.app_write.as_ref().map(|app| &app.dx),
}
}

pub fn select_tx(
&self,
version: Version,
space: PacketNumberSpace,
) -> Option<(CryptoSpace, &CryptoDxState)> {
) -> Option<(Epoch, &CryptoDxState)> {
match space {
PacketNumberSpace::Initial => self
.tx(version, CryptoSpace::Initial)
.map(|dx| (CryptoSpace::Initial, dx)),
.tx(version, Epoch::Initial)
.map(|dx| (Epoch::Initial, dx)),
PacketNumberSpace::Handshake => self
.tx(version, CryptoSpace::Handshake)
.map(|dx| (CryptoSpace::Handshake, dx)),
.tx(version, Epoch::Handshake)
.map(|dx| (Epoch::Handshake, dx)),
PacketNumberSpace::ApplicationData => self.app_write.as_ref().map_or_else(
|| self.zero_rtt.as_ref().map(|dx| (CryptoSpace::ZeroRtt, dx)),
|app| Some((CryptoSpace::ApplicationData, &app.dx)),
|| self.zero_rtt.as_ref().map(|dx| (Epoch::ZeroRtt, dx)),
|app| Some((Epoch::ApplicationData, &app.dx)),
),
}
}

pub fn rx_hp(&mut self, version: Version, cspace: CryptoSpace) -> Option<&mut CryptoDxState> {
if cspace == CryptoSpace::ApplicationData {
pub fn rx_hp(&mut self, version: Version, cspace: Epoch) -> Option<&mut CryptoDxState> {
if cspace == Epoch::ApplicationData {
self.app_read.as_mut().map(|ar| &mut ar.dx)
} else {
self.rx(version, cspace, false)
Expand All @@ -905,18 +898,18 @@ impl CryptoStates {
pub fn rx<'a>(
&'a mut self,
version: Version,
cspace: CryptoSpace,
cspace: Epoch,
key_phase: bool,
) -> Option<&'a mut CryptoDxState> {
let rx = |x: Option<&'a mut CryptoState>| x.map(|dx| &mut dx.rx);
match cspace {
CryptoSpace::Initial => rx(self.initials.get_mut(&version)),
CryptoSpace::ZeroRtt => self
Epoch::Initial => rx(self.initials.get_mut(&version)),
Epoch::ZeroRtt => self
.zero_rtt
.as_mut()
.filter(|z| z.direction == CryptoDxDirection::Read),
CryptoSpace::Handshake => rx(self.handshake.as_mut()),
CryptoSpace::ApplicationData => {
Epoch::Handshake => rx(self.handshake.as_mut()),
Epoch::ApplicationData => {
let f = |a: Option<&'a mut CryptoDxAppData>| {
a.filter(|ar| ar.dx.key_phase() == key_phase)
};
Expand All @@ -936,11 +929,11 @@ impl CryptoStates {
/// is possible to attribute 0-RTT packets to an existing connection if there
/// is a multi-packet Initial, that is an unusual circumstance, so we
/// don't do caching for that in those places that call this function.
pub fn rx_pending(&self, space: CryptoSpace) -> bool {
pub fn rx_pending(&self, space: Epoch) -> bool {
match space {
CryptoSpace::Initial | CryptoSpace::ZeroRtt => false,
CryptoSpace::Handshake => self.handshake.is_none() && !self.initials.is_empty(),
CryptoSpace::ApplicationData => self.app_read.is_none(),
Epoch::Initial | Epoch::ZeroRtt => false,
Epoch::Handshake => self.handshake.is_none() && !self.initials.is_empty(),
Epoch::ApplicationData => self.app_read.is_none(),
}
}

Expand Down
4 changes: 2 additions & 2 deletions neqo-transport/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ pub enum Error {
InvalidResumptionToken,
InvalidRetry,
InvalidStreamId,
KeysDiscarded(crypto::CryptoSpace),
KeysDiscarded(crypto::Epoch),
/// Packet protection keys are exhausted.
/// Also used when too many key updates have happened.
KeysExhausted,
/// Packet protection keys aren't available yet for the identified space.
KeysPending(crypto::CryptoSpace),
KeysPending(crypto::Epoch),
/// An attempt to update keys can be blocked if
/// a packet sent with the current keys hasn't been acknowledged.
KeyUpdateBlocked,
Expand Down
18 changes: 9 additions & 9 deletions neqo-transport/src/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use neqo_crypto::random;

use crate::{
cid::{ConnectionId, ConnectionIdDecoder, ConnectionIdRef, MAX_CONNECTION_ID_LEN},
crypto::{CryptoDxState, CryptoSpace, CryptoStates},
crypto::{CryptoDxState, CryptoStates, Epoch},
frame::FRAME_TYPE_PADDING,
recovery::SendProfile,
version::{Version, WireVersion},
Expand Down Expand Up @@ -89,7 +89,7 @@ impl PacketType {
}

#[allow(clippy::fallible_impl_from)]
impl From<PacketType> for CryptoSpace {
impl From<PacketType> for Epoch {
fn from(v: PacketType) -> Self {
match v {
PacketType::Initial => Self::Initial,
Expand All @@ -101,13 +101,13 @@ impl From<PacketType> for CryptoSpace {
}
}

impl From<CryptoSpace> for PacketType {
fn from(cs: CryptoSpace) -> Self {
impl From<Epoch> for PacketType {
fn from(cs: Epoch) -> Self {
match cs {
CryptoSpace::Initial => Self::Initial,
CryptoSpace::ZeroRtt => Self::ZeroRtt,
CryptoSpace::Handshake => Self::Handshake,
CryptoSpace::ApplicationData => Self::Short,
Epoch::Initial => Self::Initial,
Epoch::ZeroRtt => Self::ZeroRtt,
Epoch::Handshake => Self::Handshake,
Epoch::ApplicationData => Self::Short,
}
}
}
Expand Down Expand Up @@ -864,7 +864,7 @@ impl<'a> PublicPacket<'a> {
crypto: &mut CryptoStates,
release_at: Instant,
) -> Res<DecryptedPacket> {
let cspace: CryptoSpace = self.packet_type.into();
let cspace: Epoch = self.packet_type.into();
// When we don't have a version, the crypto code doesn't need a version
// for lookup, so use the default, but fix it up if decryption succeeds.
let version = self.version().unwrap_or_default();
Expand Down

0 comments on commit 227c1bd

Please sign in to comment.