Skip to content

Commit

Permalink
wip: super clumsy fixes for no-std build
Browse files Browse the repository at this point in the history
Slapping `cfg` gates all over the place as a stopgap fix. Fixing
properly will require some reworking that will be done along other
required changes.
  • Loading branch information
cpu committed Mar 19, 2024
1 parent c0bd6e6 commit 9e8d367
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 24 deletions.
2 changes: 2 additions & 0 deletions rustls/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ impl ConfigBuilder<ClientConfig, WantsClientCert> {
#[cfg(feature = "tls12")]
require_ems: cfg!(feature = "fips"),
time_provider: self.state.time_provider,
#[cfg(feature = "std")]
grease_ech_hpke_provider: None,
#[cfg(feature = "std")]
ech_config: None,
}
}
Expand Down
20 changes: 18 additions & 2 deletions rustls/src/client/client_conn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloc::sync::Arc;
#[cfg(feature = "std")]
use alloc::vec;
use alloc::vec::Vec;
use core::marker::PhantomData;
Expand All @@ -10,18 +11,25 @@ use pki_types::{ServerName, UnixTime};
use super::handy::NoClientSessionStorage;
use super::hs;
use crate::builder::ConfigBuilder;
#[cfg(feature = "std")]
use crate::client::ech::EchState;
use crate::common_state::{CommonState, Protocol, Side};
use crate::conn::{ConnectionCore, UnbufferedConnectionCommon};
#[cfg(feature = "std")]
use crate::crypto::hpke::{HpkeProvider, HpkeSuite};
use crate::crypto::{CryptoProvider, SupportedKxGroup};
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error;
#[cfg(feature = "logging")]
use crate::log::trace;
#[cfg(feature = "std")]
use crate::msgs::codec::{Codec, Reader};
use crate::msgs::enums::{EchVersion, NamedGroup};
use crate::msgs::handshake::{ClientExtension, EchConfig as EchConfigMsg};
#[cfg(feature = "std")]
use crate::msgs::enums::EchVersion;
use crate::msgs::enums::NamedGroup;
use crate::msgs::handshake::ClientExtension;
#[cfg(feature = "std")]
use crate::msgs::handshake::EchConfig as EchConfigMsg;
use crate::msgs::persist;
use crate::suites::SupportedCipherSuite;
#[cfg(feature = "std")]
Expand Down Expand Up @@ -209,8 +217,10 @@ pub struct ClientConfig {

/// Provides the current system time
pub time_provider: Arc<dyn TimeProvider>,

/// When an HPKE provider is configured and no `ech_config` is provided, a GREASE
/// ECH extension will be offered when negotiating TLS 1.3.
#[cfg(feature = "std")]
pub grease_ech_hpke_provider: Option<&'static dyn HpkeProvider>,

/// Source of randomness and other crypto.
Expand All @@ -224,6 +234,7 @@ pub struct ClientConfig {
pub(super) verifier: Arc<dyn verify::ServerCertVerifier>,

/// How to offer Encrypted Client Hello (ECH). The default is to not offer ECH.
#[cfg(feature = "std")]
pub(super) ech_config: Option<EchConfig>,
}

Expand Down Expand Up @@ -344,6 +355,7 @@ impl ClientConfig {
///
/// If the client configuration has enabled TLS 1.2, this function will return an error. ECH
/// may only be used with TLS 1.3+.
#[cfg(feature = "std")]
pub fn enable_ech(&mut self, config: EchConfig) -> Result<(), Error> {
if self
.versions
Expand Down Expand Up @@ -418,7 +430,9 @@ impl Clone for ClientConfig {
#[cfg(feature = "tls12")]
require_ems: self.require_ems,
time_provider: Arc::clone(&self.time_provider),
#[cfg(feature = "std")]
grease_ech_hpke_provider: self.grease_ech_hpke_provider,
#[cfg(feature = "std")]
ech_config: self.ech_config.clone(),
}
}
Expand Down Expand Up @@ -510,6 +524,7 @@ pub enum Tls12Resumption {
///
/// Note: differs from the protocol-encoded EchConfig (`EchConfigMsg`).
#[derive(Clone, Debug)]
#[cfg(feature = "std")]
pub struct EchConfig {
/// The provider to use for HPKE operations.
pub(crate) hpke_provider: &'static dyn HpkeProvider,
Expand All @@ -521,6 +536,7 @@ pub struct EchConfig {
pub(crate) suite: HpkeSuite,
}

#[cfg(feature = "std")]
impl EchConfig {
/// Construct an EchConfig by selecting a ECH config from the provided bytes that is compatible
/// with the given HPKE provider.
Expand Down
1 change: 1 addition & 0 deletions rustls/src/client/ech.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use alloc::vec::Vec;
use pki_types::{DnsName, ServerName};
use subtle::ConstantTimeEq;

#[cfg(feature = "std")]
use crate::client::EchConfig;
use crate::crypto::hash::Hash;
use crate::crypto::hpke::{EncapsulatedSecret, HpkeProvider, HpkePublicKey, HpkeSealer, HpkeSuite};
Expand Down
35 changes: 27 additions & 8 deletions rustls/src/client/hs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::bs_debug;
use crate::check::inappropriate_handshake_message;
use crate::client::client_conn::ClientConnectionData;
use crate::client::common::ClientHelloDetails;
#[cfg(feature = "std")]
use crate::client::ech::EchState;
use crate::client::{tls13, ClientConfig};
use crate::common_state::{CommonState, State};
Expand Down Expand Up @@ -146,6 +147,7 @@ pub(super) fn start_handshake(
let random = Random::new(config.provider.secure_random)?;
let extension_order_seed = crate::rand::random_u16(config.provider.secure_random)?;

#[cfg(feature = "std")]
let ech_context = match config.ech_config.as_ref() {
Some(ech_config) => Some(EchState::new(
ech_config,
Expand Down Expand Up @@ -176,6 +178,7 @@ pub(super) fn start_handshake(
server_name,
},
cx,
#[cfg(feature = "std")]
ech_context,
)
}
Expand All @@ -186,6 +189,7 @@ struct ExpectServerHello {
early_key_schedule: Option<KeyScheduleEarly>,
offered_key_share: Option<Box<dyn ActiveKeyExchange>>,
suite: Option<SupportedCipherSuite>,
#[cfg(feature = "std")]
ech_context: Option<EchState>,
}

Expand Down Expand Up @@ -214,7 +218,7 @@ fn emit_client_hello_for_retry(
suite: Option<SupportedCipherSuite>,
mut input: ClientHelloInput,
cx: &mut ClientContext<'_>,
mut ech_context: Option<EchState>,
#[cfg(feature = "std")] mut ech_context: Option<EchState>,
) -> NextStateOrError<'static> {
let config = &input.config;
let support_tls12 = config.supports_version(ProtocolVersion::TLSv1_2) && !cx.common.is_quic();
Expand Down Expand Up @@ -266,12 +270,19 @@ fn emit_client_hello_for_retry(
// We only want to send the SNI extension if the server name contains a DNS name and SNI is
// enabled.
if let (ServerName::DnsName(dns), true) = (&input.server_name, config.enable_sni) {
// If we have an ECH context, then we need to use the ECH config's public name for the
// outer hello SNI, otherwise we use the server name from the client config.
exts.push(ClientExtension::make_sni(match ech_context.as_ref() {
Some(ech_context) => &ech_context.outer_name,
None => dns,
}));
#[cfg(feature = "std")]
{
// If we have an ECH context, then we need to use the ECH config's public name for the
// outer hello SNI, otherwise we use the server name from the client config.
exts.push(ClientExtension::make_sni(match ech_context.as_ref() {
Some(ech_context) => &ech_context.outer_name,
None => dns,
}));
}
#[cfg(not(feature = "std"))]
{
exts.push(ClientExtension::make_sni(dns));
}
}

if let Some(key_share) = &key_share {
Expand Down Expand Up @@ -335,6 +346,7 @@ fn emit_client_hello_for_retry(
// We don't do renegotiation at all, in fact.
cipher_suites.push(CipherSuite::TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

#[cfg_attr(not(feature = "std"), allow(unused_mut))]
let mut chp_payload = ClientHelloPayload {
client_version: ProtocolVersion::TLSv1_2,
random: input.random,
Expand All @@ -344,6 +356,7 @@ fn emit_client_hello_for_retry(
extensions: exts,
};

#[cfg(feature = "std")]
match (ech_context.as_mut(), config.grease_ech_hpke_provider) {
// ECH config, GREASE is irrelevant.
(Some(ech_context), _) => {
Expand Down Expand Up @@ -434,6 +447,7 @@ fn emit_client_hello_for_retry(
early_key_schedule,
offered_key_share: key_share,
suite,
#[cfg(feature = "std")]
ech_context,
};

Expand Down Expand Up @@ -730,7 +744,9 @@ impl State<ClientConnectionData> for ExpectServerHello {
// We always send a key share when TLS 1.3 is enabled.
self.offered_key_share.unwrap(),
self.input.sent_tls13_fake_ccs,
#[cfg(feature = "std")]
self.ech_context,
#[cfg(feature = "std")]
&m,
)
}
Expand Down Expand Up @@ -768,7 +784,7 @@ impl ExpectServerHelloOrHelloRetryRequest {
}

fn handle_hello_retry_request(
mut self,
#[cfg_attr(not(feature = "std"), allow(unused_mut))] mut self,
cx: &mut ClientContext<'_>,
m: Message,
) -> NextStateOrError<'static> {
Expand Down Expand Up @@ -893,6 +909,7 @@ impl ExpectServerHelloOrHelloRetryRequest {
cx.common.suite = Some(cs);

// If we offered ECH, we need to confirm that the server accepted it.
#[cfg(feature = "std")]
match (self.next.ech_context.as_ref(), cs.tls13()) {
(Some(_), None) => {
unreachable!("ECH context should only be set when TLS 1.3 was negotiated")
Expand All @@ -913,6 +930,7 @@ impl ExpectServerHelloOrHelloRetryRequest {

// If we offered ECH, we also need to update the separate transcript with the
// hello retry request message.
#[cfg(feature = "std")]
if let Some(ech_context) = self.next.ech_context.as_mut() {
ech_context.transcript_hrr_update(cs.hash_provider(), &m);
}
Expand Down Expand Up @@ -947,6 +965,7 @@ impl ExpectServerHelloOrHelloRetryRequest {
Some(cs),
self.next.input,
cx,
#[cfg(feature = "std")]
self.next.ech_context,
)
}
Expand Down
18 changes: 12 additions & 6 deletions rustls/src/client/tls13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use super::client_conn::ClientConnectionData;
use super::hs::ClientContext;
use crate::check::inappropriate_handshake_message;
use crate::client::common::{ClientAuthDetails, ClientHelloDetails, ServerCertDetails};
use crate::client::ech::EchState;
use crate::client::{ech, hs, ClientConfig, ClientSessionStore};
#[cfg(feature = "std")]
use crate::client::ech::{self, EchState};
use crate::client::{hs, ClientConfig, ClientSessionStore};
use crate::common_state::{CommonState, Protocol, Side, State};
use crate::conn::ConnectionRandoms;
use crate::crypto::ActiveKeyExchange;
Expand Down Expand Up @@ -65,15 +66,15 @@ pub(super) fn handle_server_hello(
server_hello: &ServerHelloPayload,
mut resuming_session: Option<persist::Tls13ClientSessionValue>,
server_name: ServerName<'static>,
mut randoms: ConnectionRandoms,
#[cfg_attr(not(feature = "std"), allow(unused_mut))] mut randoms: ConnectionRandoms,
suite: &'static Tls13CipherSuite,
mut transcript: HandshakeHash,
#[cfg_attr(not(feature = "std"), allow(unused_mut))] mut transcript: HandshakeHash,
early_key_schedule: Option<KeyScheduleEarly>,
hello: ClientHelloDetails,
our_key_share: Box<dyn ActiveKeyExchange>,
mut sent_tls13_fake_ccs: bool,
ech_context: Option<EchState>,
server_hello_msg: &Message,
#[cfg(feature = "std")] ech_context: Option<EchState>,
#[cfg(feature = "std")] server_hello_msg: &Message,
) -> hs::NextStateOrError<'static> {
validate_server_hello(cx.common, server_hello)?;

Expand Down Expand Up @@ -148,6 +149,7 @@ pub(super) fn handle_server_hello(

let shared_secret = our_key_share.complete(&their_key_share.payload.0)?;

#[cfg_attr(not(feature = "std"), allow(unused_mut))]
let mut key_schedule = key_schedule_pre_handshake.into_handshake(shared_secret);

// Remember what KX group the server liked for next time.
Expand All @@ -160,6 +162,7 @@ pub(super) fn handle_server_hello(
// the two halves will have different record layer protections. Disallow this.
cx.common.check_aligned_handshake()?;

#[cfg(feature = "std")]
let ech_status = match ech_context {
// ECH wasn't offered.
None => ech::Status::NotOffered,
Expand Down Expand Up @@ -205,6 +208,7 @@ pub(super) fn handle_server_hello(
transcript,
key_schedule,
hello,
#[cfg(feature = "std")]
ech_status,
}))
}
Expand Down Expand Up @@ -397,6 +401,7 @@ struct ExpectEncryptedExtensions {
transcript: HandshakeHash,
key_schedule: KeyScheduleHandshake,
hello: ClientHelloDetails,
#[cfg(feature = "std")]
ech_status: ech::Status,
}

Expand Down Expand Up @@ -425,6 +430,7 @@ impl State<ClientConnectionData> for ExpectEncryptedExtensions {
// this stage rather than in the ExpectServerHello state because we want to be able to
// include retry configs that may be present in the server's encrypted extensions. This
// also allows us to send the alert in encrypted form.
#[cfg(feature = "std")]
if matches!(self.ech_status, ech::Status::Rejected) {
return Err(ech::fatal_alert_required(
exts.server_ech_extension()
Expand Down
5 changes: 4 additions & 1 deletion rustls/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use core::fmt;
use std::time::SystemTimeError;

use crate::enums::{AlertDescription, ContentType, HandshakeType};
use crate::msgs::handshake::{EchConfig, KeyExchangeAlgorithm};
#[cfg(feature = "std")]
use crate::msgs::handshake::EchConfig;
use crate::msgs::handshake::KeyExchangeAlgorithm;
use crate::rand;

/// rustls reports protocol errors using this type.
Expand Down Expand Up @@ -275,6 +277,7 @@ pub enum PeerIncompatible {
Tls12NotOfferedOrEnabled,
Tls13RequiredForQuic,
UncompressedEcPointsRequired,
#[cfg(feature = "std")]
ServerRejectedEncryptedClientHello(Option<Vec<EchConfig>>),
}

Expand Down
13 changes: 8 additions & 5 deletions rustls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,9 +441,11 @@ pub mod internal {
pub mod handshake {
pub use crate::msgs::handshake::{
CertificateChain, ClientExtension, ClientHelloPayload, DistinguishedName,
EchConfig, EchConfigContents, HandshakeMessagePayload, HandshakePayload,
HpkeKeyConfig, HpkeSymmetricCipherSuite, KeyShareEntry, Random, SessionId,
HandshakeMessagePayload, HandshakePayload, HpkeKeyConfig, HpkeSymmetricCipherSuite,
KeyShareEntry, Random, SessionId,
};
#[cfg(feature = "std")]
pub use crate::msgs::handshake::{EchConfig, EchConfigContents};
}
pub mod message {
pub use crate::msgs::message::{
Expand Down Expand Up @@ -534,6 +536,7 @@ pub mod client {
pub(super) mod builder;
mod client_conn;
mod common;
#[cfg(feature = "std")]
mod ech;
pub(super) mod handy;
mod hs;
Expand All @@ -543,11 +546,11 @@ pub mod client {

pub use builder::WantsClientCert;
pub use client_conn::{
ClientConfig, ClientConnectionData, ClientSessionStore, EarlyDataError, EchConfig,
ResolvesClientCert, Resumption, Tls12Resumption, UnbufferedClientConnection,
ClientConfig, ClientConnectionData, ClientSessionStore, EarlyDataError, ResolvesClientCert,
Resumption, Tls12Resumption, UnbufferedClientConnection,
};
#[cfg(feature = "std")]
pub use client_conn::{ClientConnection, WriteEarlyData};
pub use client_conn::{ClientConnection, EchConfig, WriteEarlyData};
#[cfg(feature = "std")]
pub use handy::ClientSessionMemoryCache;

Expand Down
1 change: 1 addition & 0 deletions rustls/src/msgs/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl fmt::Debug for PayloadU16 {
pub struct PayloadU8(pub(crate) Vec<u8>);

impl PayloadU8 {
#[cfg(feature = "std")]
pub(crate) fn encode_slice(slice: &[u8], bytes: &mut Vec<u8>) {
(slice.len() as u8).encode(bytes);
bytes.extend_from_slice(slice);
Expand Down

0 comments on commit 9e8d367

Please sign in to comment.