diff --git a/.clippy.toml b/.clippy.toml index 4e779c6..69feff2 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -msrv = "1.83.0" +msrv = "1.86.0" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 744b836..fbec33f 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -23,7 +23,7 @@ jobs: - nss - rust-hpke rust: - - 1.83.0 # MSRV + - 1.86.0 # MSRV - stable steps: diff --git a/Cargo.toml b/Cargo.toml index c98afeb..40a019c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,6 @@ keywords = ["ohttp", "http", "bhttp", "ietf"] categories = ["network-programming", "web-programming", "security"] readme = "README.md" version = "0.7.2" -edition = "2021" +edition = "2024" license = "MIT OR Apache-2.0" -rust-version = "1.83.0" +rust-version = "1.86.0" diff --git a/bhttp/src/lib.rs b/bhttp/src/lib.rs index caa6b37..9f5c4ca 100644 --- a/bhttp/src/lib.rs +++ b/bhttp/src/lib.rs @@ -19,8 +19,8 @@ pub mod stream; pub use err::Error; use err::Res; #[cfg(feature = "http")] -use parse::{downcase, is_ows, read_line, split_at, COLON, SEMICOLON, SLASH, SP}; -use parse::{index_of, trim_ows, COMMA}; +use parse::{COLON, SEMICOLON, SLASH, SP, downcase, is_ows, read_line, split_at}; +use parse::{COMMA, index_of, trim_ows}; use rw::{read_varint, read_vec, write_len, write_varint, write_vec}; #[cfg(feature = "http")] @@ -452,11 +452,7 @@ impl ControlData { #[must_use] pub fn path(&self) -> Option<&[u8]> { if let Self::Request { path, .. } = self { - if path.is_empty() { - None - } else { - Some(path) - } + if path.is_empty() { None } else { Some(path) } } else { None } diff --git a/bhttp/src/rw.rs b/bhttp/src/rw.rs index 0520356..9cd9532 100644 --- a/bhttp/src/rw.rs +++ b/bhttp/src/rw.rs @@ -1,8 +1,8 @@ use std::{borrow::BorrowMut, convert::TryFrom, io}; use crate::{ - err::{Error, Res}, ReadSeek, + err::{Error, Res}, }; #[allow(clippy::cast_possible_truncation)] @@ -98,7 +98,7 @@ mod test { use std::io::Cursor; use super::{read_varint, write_varint}; - use crate::{rw::read_vec, Error}; + use crate::{Error, rw::read_vec}; #[test] fn basics() { diff --git a/bhttp/src/stream/int.rs b/bhttp/src/stream/int.rs index 3a000b6..5aab868 100644 --- a/bhttp/src/stream/int.rs +++ b/bhttp/src/stream/int.rs @@ -1,6 +1,6 @@ use std::{ future::Future, - pin::{pin, Pin}, + pin::{Pin, pin}, task::{Context, Poll}, }; @@ -82,7 +82,7 @@ impl Future for ReadVarint { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.as_mut(); - if let Self::First(ref mut src) = this.get_mut() { + if let Self::First(src) = this.get_mut() { let mut buf = [0; 1]; let src_ref = src.as_mut().unwrap(); if let Poll::Ready(res) = pin!(src_ref).poll_read(cx, &mut buf[..]) { diff --git a/bhttp/src/stream/mod.rs b/bhttp/src/stream/mod.rs index bfba2c1..9cbfb2b 100644 --- a/bhttp/src/stream/mod.rs +++ b/bhttp/src/stream/mod.rs @@ -5,16 +5,16 @@ use std::{ cmp::min, io::{Cursor, Error as IoError, Result as IoResult}, mem, - pin::{pin, Pin}, + pin::{Pin, pin}, task::{Context, Poll}, }; -use futures::{stream::unfold, AsyncRead, Stream, TryStreamExt}; +use futures::{AsyncRead, Stream, TryStreamExt, stream::unfold}; use crate::{ + COOKIE, ControlData, Error, Field, FieldSection, Header, InformationalResponse, Message, Mode, err::Res, stream::{int::read_varint, vec::read_vec}, - ControlData, Error, Field, FieldSection, Header, InformationalResponse, Message, Mode, COOKIE, }; mod int; mod vec; @@ -414,7 +414,7 @@ mod test { use futures::TryStreamExt; use sync_async::{Dribble, SyncRead, SyncResolve, SyncTryCollect}; - use crate::{stream::AsyncReadMessage, Error, Message}; + use crate::{Error, Message, stream::AsyncReadMessage}; // Example from Section 5.1 of RFC 9292. const REQUEST1: &[u8] = &[ diff --git a/bhttp/src/stream/vec.rs b/bhttp/src/stream/vec.rs index 7289be9..38d832a 100644 --- a/bhttp/src/stream/vec.rs +++ b/bhttp/src/stream/vec.rs @@ -1,13 +1,13 @@ use std::{ future::Future, mem, - pin::{pin, Pin}, + pin::{Pin, pin}, task::{Context, Poll}, }; -use futures::{io::AsyncRead, FutureExt}; +use futures::{FutureExt, io::AsyncRead}; -use super::int::{read_varint, ReadVarint}; +use super::int::{ReadVarint, read_varint}; use crate::{Error, Res}; /// A reader for a varint-length-prefixed buffer. @@ -32,7 +32,7 @@ impl ReadVec { /// if this is called after the length is read. pub fn limit(&mut self, limit: u64) { usize::try_from(limit).expect("cannot set a limit larger than usize::MAX"); - if let Self::ReadLen { ref mut cap, .. } = self { + if let Self::ReadLen { cap, .. } = self { *cap = limit; } else { panic!("cannot set a limit once the size has been read"); @@ -122,7 +122,7 @@ mod test { use futures::AsyncRead; use sync_async::SyncResolve; - use crate::{rw::write_varint as sync_write_varint, stream::vec::read_vec, Error}; + use crate::{Error, rw::write_varint as sync_write_varint, stream::vec::read_vec}; const FILL_VALUE: u8 = 90; diff --git a/ohttp-client-cli/src/main.rs b/ohttp-client-cli/src/main.rs index 37a948d..2cb6e24 100644 --- a/ohttp-client-cli/src/main.rs +++ b/ohttp-client-cli/src/main.rs @@ -3,7 +3,7 @@ use std::io::{self, BufRead, Write}; use bhttp::{Message, Mode}; -use ohttp::{init, ClientRequest}; +use ohttp::{ClientRequest, init}; fn main() { init(); diff --git a/ohttp-server/src/main.rs b/ohttp-server/src/main.rs index 41f0cc8..edd30a1 100644 --- a/ohttp-server/src/main.rs +++ b/ohttp-server/src/main.rs @@ -9,8 +9,8 @@ use std::{ use bhttp::{Message, Mode, StatusCode}; use ohttp::{ - hpke::{Aead, Kdf, Kem}, KeyConfig, Server as OhttpServer, SymmetricSuite, + hpke::{Aead, Kdf, Kem}, }; use structopt::StructOpt; use warp::Filter; diff --git a/ohttp/Cargo.toml b/ohttp/Cargo.toml index 80d8b2b..7e2f920 100644 --- a/ohttp/Cargo.toml +++ b/ohttp/Cargo.toml @@ -25,19 +25,19 @@ stream = ["dep:futures", "dep:pin-project"] unsafe-print-secrets = [] [dependencies] -aead = {version = "0.5", optional = true, features = ["std"]} -aes-gcm = {version = "0.10", optional = true} +aead = {version = "0.6", optional = true, features = ["alloc"]} +aes-gcm = {version = "0.11", optional = true} byteorder = "1.4" -chacha20poly1305 = {version = "0.10", optional = true} +chacha20poly1305 = {version = "0.11", optional = true} futures = {version = "0.3", optional = true} hex = "0.4" -hkdf = {version = "0.12", optional = true} -hpke = {version = "0.13", optional = true, default-features = false, features = ["std", "x25519", "p256"]} +hkdf = {version = "0.13", optional = true} +hpke = {version = "0.14", optional = true, default-features = false, features = ["getrandom", "x25519", "nistp", "mlkem", "aes", "chacha"]} log = {version = "0.4", default-features = false} pin-project = {version = "1.1", optional = true} -rand = {version = "0.9", optional = true} +rand = {version = "0.10", optional = true} regex = {version = "~1.11", optional = true} -sha2 = {version = "0.10", optional = true} +sha2 = {version = "0.11", optional = true} thiserror = "2" [build-dependencies] diff --git a/ohttp/build.rs b/ohttp/build.rs index f904101..12a3026 100644 --- a/ohttp/build.rs +++ b/ohttp/build.rs @@ -54,8 +54,7 @@ mod nss { } fn is_debug() -> bool { - env::var("DEBUG") - .is_ok_and(|d| d.parse::().unwrap_or(false)) + env::var("DEBUG").is_ok_and(|d| d.parse::().unwrap_or(false)) } // bindgen needs access to libclang. @@ -84,8 +83,12 @@ mod nss { }; let libclang_dir = mozbuild_root.join("clang").join("lib"); if libclang_dir.is_dir() { - env::set_var("LIBCLANG_PATH", libclang_dir.to_str().unwrap()); - println!("rustc-env:LIBCLANG_PATH={}", libclang_dir.to_str().unwrap()); + let libclang_dir = libclang_dir.to_str().unwrap(); + unsafe { + // SAFETY: this is a single-threaded program + env::set_var("LIBCLANG_PATH", libclang_dir); + } + println!("rustc-env:LIBCLANG_PATH={libclang_dir}"); } else { println!("warning: LIBCLANG_PATH isn't set; maybe run ./mach bootstrap with gecko"); } @@ -271,16 +274,13 @@ mod nss { builder = builder.clang_arg("-v"); builder = builder.clang_arg("-DNO_NSPR_10_SUPPORT"); - if env::consts::OS == "windows" { - builder = builder.clang_arg("-DWIN"); - } else if env::consts::OS == "macos" { - builder = builder.clang_arg("-DDARWIN"); - } else if env::consts::OS == "linux" { - builder = builder.clang_arg("-DLINUX"); - } else if env::consts::OS == "android" { - builder = builder.clang_arg("-DLINUX"); - builder = builder.clang_arg("-DANDROID"); - } + builder = match env::consts::OS { + "windows" => builder.clang_arg("-DWIN"), + "macos" => builder.clang_arg("-DDARWIN"), + "linux" => builder.clang_arg("-DLINUX"), + "android" => builder.clang_arg("-DLINUX").clang_arg("-DANDROID"), + _ => builder, + }; if bindings.cplusplus { builder = builder.clang_args(&["-x", "c++", "-std=c++11"]); } @@ -399,8 +399,8 @@ mod nss { #[cfg(any(feature = "gecko", feature = "app-svc"))] fn setup_for_gecko() -> Vec { use mozbuild::{ - config::{BINDGEN_SYSTEM_FLAGS, NSPR_CFLAGS, NSS_CFLAGS}, TOPOBJDIR, + config::{BINDGEN_SYSTEM_FLAGS, NSPR_CFLAGS, NSS_CFLAGS}, }; let fold_libs = mozbuild::config::MOZ_FOLD_LIBS; @@ -489,7 +489,9 @@ mod nss { "NSS_DIR path (obtained via `env`) does not exist: {}", nss_dir.display() ); - panic!("It looks like NSS is not built. Please run `libs/verify-[platform]-environment.sh` in application-services first!"); + panic!( + "It looks like NSS is not built. Please run `libs/verify-[platform]-environment.sh` in application-services first!" + ); } let lib_dir = nss_dir.join("lib"); diff --git a/ohttp/src/config.rs b/ohttp/src/config.rs index df1ea3d..7a20dd1 100644 --- a/ohttp/src/config.rs +++ b/ohttp/src/config.rs @@ -7,17 +7,17 @@ use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt}; #[cfg(feature = "nss")] use crate::nss::{ - hpke::{generate_key_pair, Config as HpkeConfig, HpkeR}, PrivateKey, PublicKey, + hpke::{Config as HpkeConfig, HpkeR, generate_key_pair}, }; #[cfg(feature = "rust-hpke")] use crate::rh::hpke::{ - derive_key_pair, generate_key_pair, Config as HpkeConfig, HpkeR, PrivateKey, PublicKey, + Config as HpkeConfig, HpkeR, PrivateKey, PublicKey, derive_key_pair, generate_key_pair, }; use crate::{ + KeyId, err::{Error, Res}, hpke::{Aead as AeadId, Kdf, Kem}, - KeyId, }; /// A tuple of KDF and AEAD identifiers. @@ -286,8 +286,9 @@ mod test { use std::iter::zip; use crate::{ + Error, KeyConfig, KeyId, SymmetricSuite, hpke::{Aead, Kdf, Kem}, - init, Error, KeyConfig, KeyId, SymmetricSuite, + init, }; const KEY_ID: KeyId = 1; diff --git a/ohttp/src/crypto.rs b/ohttp/src/crypto.rs index a22b74e..12af0aa 100644 --- a/ohttp/src/crypto.rs +++ b/ohttp/src/crypto.rs @@ -1,4 +1,4 @@ -use crate::{err::Res, AeadId}; +use crate::{AeadId, err::Res}; pub trait Decrypt { fn open(&mut self, aad: &[u8], ct: &[u8]) -> Res>; diff --git a/ohttp/src/err.rs b/ohttp/src/err.rs index ec7741e..88051e2 100644 --- a/ohttp/src/err.rs +++ b/ohttp/src/err.rs @@ -49,4 +49,11 @@ impl From for Error { } } +// If this happens, it's a programming error in this crate. +impl From for Error { + fn from(_v: std::array::TryFromSliceError) -> Self { + Self::Internal + } +} + pub type Res = Result; diff --git a/ohttp/src/hpke.rs b/ohttp/src/hpke.rs index fe557d3..6571fab 100644 --- a/ohttp/src/hpke.rs +++ b/ohttp/src/hpke.rs @@ -31,8 +31,9 @@ macro_rules! convert_enum { convert_enum! { pub enum Kem { - P256Sha256 = 16, // DHKEM(P-256, HKDF-SHA256) = 0x0010 X25519Sha256 = 32, // DHKEM(X25519, HKDF-SHA256) = 0x0020 + P256Sha256 = 16, // DHKEM(P-256, HKDF-SHA256) = 0x0010 + XWing = 0x647a, // X-Wing (MLKEM768-X25519) = 0x647a } } @@ -40,16 +41,18 @@ impl Kem { #[must_use] pub fn n_enc(self) -> usize { match self { - Kem::P256Sha256 => 65, - Kem::X25519Sha256 => 32, + Self::X25519Sha256 => 32, + Self::P256Sha256 => 65, + Self::XWing => 1120, } } #[must_use] pub fn n_pk(self) -> usize { match self { - Kem::P256Sha256 => 65, - Kem::X25519Sha256 => 32, + Self::X25519Sha256 => 32, + Self::P256Sha256 => 65, + Self::XWing => 1216, } } } diff --git a/ohttp/src/lib.rs b/ohttp/src/lib.rs index 7ff7d96..6dd6e55 100644 --- a/ohttp/src/lib.rs +++ b/ohttp/src/lib.rs @@ -33,10 +33,11 @@ use log::trace; #[cfg(feature = "nss")] use crate::nss::{ + PublicKey, SymKey, aead::{Aead, Mode, NONCE_LEN}, hkdf::{Hkdf, KeyMechanism}, hpke::{Config as HpkeConfig, Exporter, HpkeR, HpkeS}, - random, PublicKey, SymKey, + random, }; #[cfg(feature = "stream")] use crate::stream::{ClientRequest as StreamClient, ServerRequest as ServerRequestStream}; @@ -49,10 +50,10 @@ use crate::{err::Res, hpke::Aead as AeadId}; use crate::{ rand::random, rh::{ + SymKey, aead::{Aead, Mode, NONCE_LEN}, hkdf::{Hkdf, KeyMechanism}, hpke::{Config as HpkeConfig, Exporter, HpkeR, HpkeS, PublicKey}, - SymKey, }, }; @@ -329,10 +330,10 @@ mod test { use log::trace; use crate::{ + ClientRequest, Error, KeyConfig, KeyId, Server, config::SymmetricSuite, err::Res, hpke::{Aead, Kdf, Kem}, - ClientRequest, Error, KeyConfig, KeyId, Server, }; pub const KEY_ID: KeyId = 1; @@ -408,6 +409,32 @@ mod test { assert_eq!(&response[..], RESPONSE); } + #[test] + fn request_response_xwing() { + init(); + + // X-Wing HPKE is only available with the rust-hpke backend. + if !super::HpkeConfig::new(Kem::XWing, Kdf::HkdfSha256, Aead::Aes128Gcm).supported() { + return; + } + + let server_config = KeyConfig::new(KEY_ID, Kem::XWing, Vec::from(SYMMETRIC)).unwrap(); + let server = Server::new(server_config).unwrap(); + let encoded_config = server.config().encode().unwrap(); + trace!("X-Wing Config: {}", hex::encode(&encoded_config)); + + let client = ClientRequest::from_encoded_config(&encoded_config).unwrap(); + let (enc_request, client_response) = client.encapsulate(REQUEST).unwrap(); + trace!("X-Wing Encapsulated Request: {}", hex::encode(&enc_request)); + + let (request, server_response) = server.decapsulate(&enc_request).unwrap(); + assert_eq!(&request[..], REQUEST); + + let enc_response = server_response.encapsulate(RESPONSE).unwrap(); + let response = client_response.decapsulate(&enc_response).unwrap(); + assert_eq!(&response[..], RESPONSE); + } + #[test] fn two_requests() { init(); diff --git a/ohttp/src/nss/aead.rs b/ohttp/src/nss/aead.rs index 4735547..e5f6c34 100644 --- a/ohttp/src/nss/aead.rs +++ b/ohttp/src/nss/aead.rs @@ -9,12 +9,12 @@ use log::trace; use super::{ err::secstatus_to_res, p11::{ + Item, SymKey, sys::{ - self, PK11Context, PK11_AEADOp, PK11_CreateContextBySymKey, PRBool, CKA_DECRYPT, + self, CK_ATTRIBUTE_TYPE, CK_GENERATOR_FUNCTION, CK_MECHANISM_TYPE, CKA_DECRYPT, CKA_ENCRYPT, CKA_NSS_MESSAGE, CKG_GENERATE_COUNTER_XOR, CKG_NO_GENERATE, CKM_AES_GCM, - CKM_CHACHA20_POLY1305, CK_ATTRIBUTE_TYPE, CK_GENERATOR_FUNCTION, CK_MECHANISM_TYPE, + CKM_CHACHA20_POLY1305, PK11_AEADOp, PK11_CreateContextBySymKey, PK11Context, PRBool, }, - Item, SymKey, }, }; use crate::{ @@ -43,7 +43,9 @@ where } unsafe fn destroy_aead_context(ctx: *mut PK11Context) { - sys::PK11_DestroyContext(ctx, PRBool::from(true)); + unsafe { + sys::PK11_DestroyContext(ctx, PRBool::from(true)); + } } scoped_ptr!(Context, PK11Context, destroy_aead_context); @@ -229,7 +231,7 @@ impl Encrypt for Aead { mod test { use super::{ super::{super::hpke::Aead as AeadId, init}, - Aead, Mode, SequenceNumber, NONCE_LEN, + Aead, Mode, NONCE_LEN, SequenceNumber, }; use crate::crypto::{Decrypt, Encrypt}; diff --git a/ohttp/src/nss/err.rs b/ohttp/src/nss/err.rs index 133d179..92d53e8 100644 --- a/ohttp/src/nss/err.rs +++ b/ohttp/src/nss/err.rs @@ -89,8 +89,8 @@ pub fn secstatus_to_res(rv: SECStatus) -> Res<()> { #[cfg(test)] mod tests { use super::{ - super::{init, SECFailure, SECSuccess}, - secstatus_to_res, PRErrorCode, PR_SetError, + super::{SECFailure, SECSuccess, init}, + PR_SetError, PRErrorCode, secstatus_to_res, }; fn set_error_code(code: PRErrorCode) { diff --git a/ohttp/src/nss/hkdf.rs b/ohttp/src/nss/hkdf.rs index 7796d0e..92e0d49 100644 --- a/ohttp/src/nss/hkdf.rs +++ b/ohttp/src/nss/hkdf.rs @@ -5,12 +5,12 @@ use log::trace; use super::{ super::hpke::{Aead, Kdf}, p11::{ + ParamItem, SymKey, sys::{ - self, CKA_DERIVE, CKF_HKDF_SALT_DATA, CKF_HKDF_SALT_NULL, CKM_AES_GCM, - CKM_CHACHA20_POLY1305, CKM_HKDF_DATA, CKM_HKDF_DERIVE, CKM_SHA256, CK_BBOOL, - CK_HKDF_PARAMS, CK_INVALID_HANDLE, CK_MECHANISM_TYPE, CK_OBJECT_HANDLE, CK_ULONG, + self, CK_BBOOL, CK_HKDF_PARAMS, CK_INVALID_HANDLE, CK_MECHANISM_TYPE, CK_OBJECT_HANDLE, + CK_ULONG, CKA_DERIVE, CKF_HKDF_SALT_DATA, CKF_HKDF_SALT_NULL, CKM_AES_GCM, + CKM_CHACHA20_POLY1305, CKM_HKDF_DATA, CKM_HKDF_DERIVE, CKM_SHA256, }, - ParamItem, SymKey, }, }; use crate::err::Res; diff --git a/ohttp/src/nss/hpke.rs b/ohttp/src/nss/hpke.rs index 856bb9f..45d2d67 100644 --- a/ohttp/src/nss/hpke.rs +++ b/ohttp/src/nss/hpke.rs @@ -10,8 +10,8 @@ pub use sys::{HpkeAeadId as AeadId, HpkeKdfId as KdfId, HpkeKemId as KemId}; use super::{ super::hpke::{Aead, Kdf, Kem}, - err::{sec::SEC_ERROR_INVALID_ARGS, secstatus_to_res, Error}, - p11::{sys, Item, PrivateKey, PublicKey, Slot, SymKey}, + err::{Error, sec::SEC_ERROR_INVALID_ARGS, secstatus_to_res}, + p11::{Item, PrivateKey, PublicKey, Slot, SymKey, sys}, }; use crate::{ crypto::{Decrypt, Encrypt}, @@ -70,7 +70,9 @@ pub trait Exporter { } unsafe fn destroy_hpke_context(cx: *mut sys::HpkeContext) { - sys::PK11_HPKE_DestroyContext(cx, sys::PRBool::from(true)); + unsafe { + sys::PK11_HPKE_DestroyContext(cx, sys::PRBool::from(true)); + } } scoped_ptr!(HpkeContext, sys::HpkeContext, destroy_hpke_context); @@ -324,7 +326,7 @@ pub fn generate_key_pair(kem: Kem) -> Res<(PrivateKey, PublicKey)> { #[cfg(test)] mod test { - use super::{generate_key_pair, Config, HpkeContext, HpkeR, HpkeS}; + use super::{Config, HpkeContext, HpkeR, HpkeS, generate_key_pair}; use crate::{ crypto::{Decrypt, Encrypt}, hpke::Aead, diff --git a/ohttp/src/nss/mod.rs b/ohttp/src/nss/mod.rs index 91dc44e..6b85006 100644 --- a/ohttp/src/nss/mod.rs +++ b/ohttp/src/nss/mod.rs @@ -9,10 +9,10 @@ pub mod hpke; use std::{ptr::null, sync::OnceLock}; -use err::secstatus_to_res; pub use err::Error; +use err::secstatus_to_res; -pub use self::p11::{random, PrivateKey, PublicKey, SymKey}; +pub use self::p11::{PrivateKey, PublicKey, SymKey, random}; #[allow(clippy::pedantic, non_upper_case_globals, clippy::upper_case_acronyms)] mod nss_init { diff --git a/ohttp/src/nss/p11.rs b/ohttp/src/nss/p11.rs index bbdbfdd..f383966 100644 --- a/ohttp/src/nss/p11.rs +++ b/ohttp/src/nss/p11.rs @@ -14,7 +14,7 @@ use std::{ use crate::{ err::{Error, Res}, - nss::err::{secstatus_to_res, Error as NssError}, + nss::err::{Error as NssError, secstatus_to_res}, }; #[allow( @@ -31,11 +31,11 @@ pub mod sys { } use sys::{ - PK11ObjectType, PK11SlotInfo, PK11SymKey, PK11_ExtractKeyValue, PK11_FreeSlot, PK11_FreeSymKey, + CK_ATTRIBUTE_TYPE, CKA_VALUE, PK11_ExtractKeyValue, PK11_FreeSlot, PK11_FreeSymKey, PK11_GenerateRandom, PK11_GetInternalSlot, PK11_GetKeyData, PK11_ReadRawAttribute, - PK11_ReferenceSymKey, PRBool, SECITEM_FreeItem, SECItem, SECItemType, SECKEYPrivateKey, - SECKEYPublicKey, SECKEY_DestroyPrivateKey, SECKEY_DestroyPublicKey, CKA_VALUE, - CK_ATTRIBUTE_TYPE, + PK11_ReferenceSymKey, PK11ObjectType, PK11SlotInfo, PK11SymKey, PRBool, SECITEM_FreeItem, + SECItem, SECItemType, SECKEY_DestroyPrivateKey, SECKEY_DestroyPublicKey, SECKEYPrivateKey, + SECKEYPublicKey, }; macro_rules! scoped_ptr { @@ -249,7 +249,9 @@ impl<'a, T: Sized + 'a> ParamItem<'a, T> { } unsafe fn destroy_secitem(item: *mut SECItem) { - SECITEM_FreeItem(item, PRBool::from(true)); + unsafe { + SECITEM_FreeItem(item, PRBool::from(true)); + } } scoped_ptr!(Item, SECItem, destroy_secitem, noptr); @@ -271,10 +273,10 @@ impl Item { /// # Safety /// This dereferences two pointers. It doesn't get much less safe. pub(crate) unsafe fn into_vec(self) -> Vec { - let b = self.ptr.as_ref().unwrap(); + let b = unsafe { self.ptr.as_ref() }.unwrap(); // Sanity check the type, as some types don't count bytes in `Item::len`. assert_eq!(b.type_, SECItemType::siBuffer); - let slc = std::slice::from_raw_parts(b.data, usize::try_from(b.len).unwrap()); + let slc = unsafe { std::slice::from_raw_parts(b.data, usize::try_from(b.len).unwrap()) }; Vec::from(slc) } } diff --git a/ohttp/src/rand.rs b/ohttp/src/rand.rs index 1d0fed0..4c58e72 100644 --- a/ohttp/src/rand.rs +++ b/ohttp/src/rand.rs @@ -4,7 +4,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ::rand::{rng, RngCore}; +use ::rand::{Rng as _, rng}; #[must_use] pub fn random(size: usize) -> Vec { diff --git a/ohttp/src/rh/aead.rs b/ohttp/src/rh/aead.rs index 62b6bbb..2a9e484 100644 --- a/ohttp/src/rh/aead.rs +++ b/ohttp/src/rh/aead.rs @@ -1,8 +1,8 @@ use std::convert::TryFrom; -use aead::{AeadMut, Key, KeyInit, Nonce, Payload}; -use aes_gcm::{Aes128Gcm, Aes256Gcm}; -use chacha20poly1305::ChaCha20Poly1305; +use ::aead::{Aead as _, Key, KeyInit, Nonce, Payload}; +use ::aes_gcm::{Aes128Gcm, Aes256Gcm}; +use ::chacha20poly1305::ChaCha20Poly1305; use super::SymKey; use crate::{ @@ -34,20 +34,20 @@ enum AeadEngine { impl AeadEngine { fn encrypt(&mut self, nonce: &[u8], pt: Payload) -> Res> { let tag = match self { - Self::Aes128Gcm(e) => e.encrypt(Nonce::::from_slice(nonce), pt)?, - Self::Aes256Gcm(e) => e.encrypt(Nonce::::from_slice(nonce), pt)?, + Self::Aes128Gcm(e) => e.encrypt(&Nonce::::try_from(nonce)?, pt)?, + Self::Aes256Gcm(e) => e.encrypt(&Nonce::::try_from(nonce)?, pt)?, Self::ChaCha20Poly1305(e) => { - e.encrypt(Nonce::::from_slice(nonce), pt)? + e.encrypt(&Nonce::::try_from(nonce)?, pt)? } }; Ok(tag) } fn decrypt(&mut self, nonce: &[u8], pt: Payload) -> Res> { let tag = match self { - Self::Aes128Gcm(e) => e.decrypt(Nonce::::from_slice(nonce), pt)?, - Self::Aes256Gcm(e) => e.decrypt(Nonce::::from_slice(nonce), pt)?, + Self::Aes128Gcm(e) => e.decrypt(&Nonce::::try_from(nonce)?, pt)?, + Self::Aes256Gcm(e) => e.decrypt(&Nonce::::try_from(nonce)?, pt)?, Self::ChaCha20Poly1305(e) => { - e.decrypt(Nonce::::from_slice(nonce), pt)? + e.decrypt(&Nonce::::try_from(nonce)?, pt)? } }; Ok(tag) @@ -74,14 +74,18 @@ impl Aead { ) -> Res { let aead = match algorithm { AeadId::Aes128Gcm => AeadEngine::Aes128Gcm(Box::new(Aes128Gcm::new( - Key::::from_slice(key.as_ref()), + &Key::::try_from(key.as_ref())?, ))), AeadId::Aes256Gcm => AeadEngine::Aes256Gcm(Box::new(Aes256Gcm::new( - Key::::from_slice(key.as_ref()), + &Key::::try_from(key.as_ref())?, ))), - AeadId::ChaCha20Poly1305 => AeadEngine::ChaCha20Poly1305(Box::new( - ChaCha20Poly1305::new(Key::::from_slice(key.as_ref())), - )), + AeadId::ChaCha20Poly1305 => { + AeadEngine::ChaCha20Poly1305(Box::new(ChaCha20Poly1305::new(&Key::< + ChaCha20Poly1305, + >::try_from( + key.as_ref() + )?))) + } }; Ok(Self { mode, @@ -145,9 +149,10 @@ impl Encrypt for Aead { mod test { use super::SequenceNumber; use crate::{ + Aead, Mode, NONCE_LEN, crypto::{Decrypt, Encrypt}, hpke::Aead as AeadId, - init, Aead, Mode, NONCE_LEN, + init, }; /// Check that the first invocation of encryption matches expected values. diff --git a/ohttp/src/rh/hpke.rs b/ohttp/src/rh/hpke.rs index 61220d7..20f10a2 100644 --- a/ohttp/src/rh/hpke.rs +++ b/ohttp/src/rh/hpke.rs @@ -1,20 +1,22 @@ use std::ops::Deref; use ::hpke as rust_hpke; -use ::rand::rng; +use ::hpke::inout::InOutBuf; +use hpke::kem::DhP256HkdfSha256; use log::trace; use rust_hpke::{ + Deserializable, OpModeR, OpModeS, Serializable, aead::{AeadCtxR, AeadCtxS, AeadTag, AesGcm128, ChaCha20Poly1305}, kdf::HkdfSha256, - kem::{DhP256HkdfSha256, Kem as KemTrait, X25519HkdfSha256}, - setup_receiver, setup_sender, Deserializable, OpModeR, OpModeS, Serializable, + kem::{Kem as KemTrait, X25519HkdfSha256, XWing}, + setup_receiver, setup_sender, }; use super::SymKey; use crate::{ + Error, Res, crypto::{Decrypt, Encrypt}, hpke::{Aead, Kdf, Kem}, - Error, Res, }; /// Configuration for `Hpke`. @@ -43,7 +45,7 @@ impl Config { } pub fn supported(self) -> bool { - matches!(self.kem, Kem::X25519Sha256 | Kem::P256Sha256) + matches!(self.kem, Kem::X25519Sha256 | Kem::P256Sha256 | Kem::XWing) && self.kdf == Kdf::HkdfSha256 && matches!(self.aead, Aead::Aes128Gcm | Aead::ChaCha20Poly1305) } @@ -64,6 +66,7 @@ impl Default for Config { pub enum PublicKey { X25519(::PublicKey), P256(::PublicKey), + XWing(::PublicKey), } impl PublicKey { @@ -72,6 +75,7 @@ impl PublicKey { Ok(match self { Self::X25519(k) => Vec::from(k.to_bytes().as_slice()), Self::P256(k) => Vec::from(k.to_bytes().as_slice()), + Self::XWing(k) => Vec::from(k.to_bytes().as_slice()), }) } } @@ -91,6 +95,7 @@ impl std::fmt::Debug for PublicKey { pub enum PrivateKey { X25519(::PrivateKey), P256(::PrivateKey), + XWing(::PrivateKey), } impl PrivateKey { @@ -99,6 +104,7 @@ impl PrivateKey { Ok(match self { Self::X25519(k) => Vec::from(k.to_bytes().as_slice()), Self::P256(k) => Vec::from(k.to_bytes().as_slice()), + Self::XWing(k) => Vec::from(k.to_bytes().as_slice()), }) } } @@ -121,49 +127,72 @@ enum SenderContextX25519HkdfSha256HkdfSha256 { ChaCha20Poly1305(Box>), } -enum SenderContextX25519HkdfSha256 { - HkdfSha256(SenderContextX25519HkdfSha256HkdfSha256), -} - enum SenderContextP256HkdfSha256HkdfSha256 { AesGcm128(Box>), ChaCha20Poly1305(Box>), } +enum SenderContextXWingHkdfSha256HkdfSha256 { + AesGcm128(Box>), + ChaCha20Poly1305(Box>), +} + +enum SenderContextX25519HkdfSha256 { + HkdfSha256(SenderContextX25519HkdfSha256HkdfSha256), +} + enum SenderContextP256HkdfSha256 { HkdfSha256(SenderContextP256HkdfSha256HkdfSha256), } +enum SenderContextXWingHkdfSha256 { + HkdfSha256(SenderContextXWingHkdfSha256HkdfSha256), +} + enum SenderContext { X25519HkdfSha256(SenderContextX25519HkdfSha256), P256HkdfSha256(SenderContextP256HkdfSha256), + XWingHkdfSha256(SenderContextXWingHkdfSha256), } impl SenderContext { fn seal(&mut self, plaintext: &mut [u8], aad: &[u8]) -> Res> { + let buf = InOutBuf::from(plaintext); Ok(match self { Self::X25519HkdfSha256(SenderContextX25519HkdfSha256::HkdfSha256( SenderContextX25519HkdfSha256HkdfSha256::AesGcm128(context), )) => { - let tag = context.seal_in_place_detached(plaintext, aad)?; + let tag = context.seal_inout_detached(buf, aad)?; Vec::from(tag.to_bytes().as_slice()) } Self::X25519HkdfSha256(SenderContextX25519HkdfSha256::HkdfSha256( SenderContextX25519HkdfSha256HkdfSha256::ChaCha20Poly1305(context), )) => { - let tag = context.seal_in_place_detached(plaintext, aad)?; + let tag = context.seal_inout_detached(buf, aad)?; Vec::from(tag.to_bytes().as_slice()) } Self::P256HkdfSha256(SenderContextP256HkdfSha256::HkdfSha256( SenderContextP256HkdfSha256HkdfSha256::AesGcm128(context), )) => { - let tag = context.seal_in_place_detached(plaintext, aad)?; + let tag = context.seal_inout_detached(buf, aad)?; Vec::from(tag.to_bytes().as_slice()) } Self::P256HkdfSha256(SenderContextP256HkdfSha256::HkdfSha256( SenderContextP256HkdfSha256HkdfSha256::ChaCha20Poly1305(context), )) => { - let tag = context.seal_in_place_detached(plaintext, aad)?; + let tag = context.seal_inout_detached(buf, aad)?; + Vec::from(tag.to_bytes().as_slice()) + } + Self::XWingHkdfSha256(SenderContextXWingHkdfSha256::HkdfSha256( + SenderContextXWingHkdfSha256HkdfSha256::AesGcm128(context), + )) => { + let tag = context.seal_inout_detached(buf, aad)?; + Vec::from(tag.to_bytes().as_slice()) + } + Self::XWingHkdfSha256(SenderContextXWingHkdfSha256::HkdfSha256( + SenderContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305(context), + )) => { + let tag = context.seal_inout_detached(buf, aad)?; Vec::from(tag.to_bytes().as_slice()) } }) @@ -191,6 +220,16 @@ impl SenderContext { )) => { context.export(info, out_buf)?; } + Self::XWingHkdfSha256(SenderContextXWingHkdfSha256::HkdfSha256( + SenderContextXWingHkdfSha256HkdfSha256::AesGcm128(context), + )) => { + context.export(info, out_buf)?; + } + Self::XWingHkdfSha256(SenderContextXWingHkdfSha256::HkdfSha256( + SenderContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305(context), + )) => { + context.export(info, out_buf)?; + } } Ok(()) } @@ -210,11 +249,9 @@ pub struct HpkeS { impl HpkeS { /// Create a new context that uses the KEM mode for sending. pub fn new(config: Config, pk_r: &PublicKey, info: &[u8]) -> Res { - let mut csprng = rng(); - macro_rules! dispatch_hpkes_new { { - ($c:expr, $pk:expr, $csprng:expr): [$( $(#[$meta:meta])* { + ($c:expr, $pk:expr): [$( $(#[$meta:meta])* { $kemid:path => $kem:path, $kdfid:path => $kdf:path, $aeadid:path => $aead:path, @@ -232,11 +269,10 @@ impl HpkeS { }, $pke(pk_r), ) => { - let (enc, context) = setup_sender::<$aead, $kdf, $kem, _>( + let (enc, context) = setup_sender::<$aead, $kdf, $kem>( &OpModeS::Base, pk_r, info, - $csprng, )?; ( $ctxt1($ctxt2($ctxt3(Box::new(context)))), @@ -249,7 +285,7 @@ impl HpkeS { }; } - let (context, enc) = dispatch_hpkes_new! { (config, pk_r, &mut csprng): [ + let (context, enc) = dispatch_hpkes_new! { (config, pk_r): [ { Kem::X25519Sha256 => X25519HkdfSha256, Kdf::HkdfSha256 => HkdfSha256, @@ -286,6 +322,24 @@ impl HpkeS { SenderContextP256HkdfSha256::HkdfSha256, SenderContextP256HkdfSha256HkdfSha256::ChaCha20Poly1305, }, + { + Kem::XWing => XWing, + Kdf::HkdfSha256 => HkdfSha256, + Aead::Aes128Gcm => AesGcm128, + PublicKey::XWing, + SenderContext::XWingHkdfSha256, + SenderContextXWingHkdfSha256::HkdfSha256, + SenderContextXWingHkdfSha256HkdfSha256::AesGcm128, + }, + { + Kem::XWing => XWing, + Kdf::HkdfSha256 => HkdfSha256, + Aead::ChaCha20Poly1305 => ChaCha20Poly1305, + PublicKey::XWing, + SenderContext::XWingHkdfSha256, + SenderContextXWingHkdfSha256::HkdfSha256, + SenderContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305, + }, ]}; Ok(Self { @@ -339,22 +393,32 @@ enum ReceiverContextX25519HkdfSha256HkdfSha256 { ChaCha20Poly1305(Box>), } -enum ReceiverContextX25519HkdfSha256 { - HkdfSha256(ReceiverContextX25519HkdfSha256HkdfSha256), -} - enum ReceiverContextP256HkdfSha256HkdfSha256 { AesGcm128(Box>), ChaCha20Poly1305(Box>), } +enum ReceiverContextXWingHkdfSha256HkdfSha256 { + AesGcm128(Box>), + ChaCha20Poly1305(Box>), +} + +enum ReceiverContextX25519HkdfSha256 { + HkdfSha256(ReceiverContextX25519HkdfSha256HkdfSha256), +} + enum ReceiverContextP256HkdfSha256 { HkdfSha256(ReceiverContextP256HkdfSha256HkdfSha256), } +enum ReceiverContextXWingHkdfSha256 { + HkdfSha256(ReceiverContextXWingHkdfSha256HkdfSha256), +} + enum ReceiverContext { X25519HkdfSha256(ReceiverContextX25519HkdfSha256), P256HkdfSha256(ReceiverContextP256HkdfSha256), + XWingHkdfSha256(ReceiverContextXWingHkdfSha256), } impl ReceiverContext { @@ -368,9 +432,10 @@ impl ReceiverContext { } let (ct, tag_slice) = ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); let tag = AeadTag::::from_bytes(tag_slice)?; - context.open_in_place_detached(ct, aad, &tag)?; - ct + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() } Self::X25519HkdfSha256(ReceiverContextX25519HkdfSha256::HkdfSha256( ReceiverContextX25519HkdfSha256HkdfSha256::ChaCha20Poly1305(context), @@ -380,9 +445,10 @@ impl ReceiverContext { } let (ct, tag_slice) = ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); let tag = AeadTag::::from_bytes(tag_slice)?; - context.open_in_place_detached(ct, aad, &tag)?; - ct + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() } Self::P256HkdfSha256(ReceiverContextP256HkdfSha256::HkdfSha256( ReceiverContextP256HkdfSha256HkdfSha256::AesGcm128(context), @@ -392,9 +458,10 @@ impl ReceiverContext { } let (ct, tag_slice) = ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); let tag = AeadTag::::from_bytes(tag_slice)?; - context.open_in_place_detached(ct, aad, &tag)?; - ct + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() } Self::P256HkdfSha256(ReceiverContextP256HkdfSha256::HkdfSha256( ReceiverContextP256HkdfSha256HkdfSha256::ChaCha20Poly1305(context), @@ -404,9 +471,36 @@ impl ReceiverContext { } let (ct, tag_slice) = ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); let tag = AeadTag::::from_bytes(tag_slice)?; - context.open_in_place_detached(ct, aad, &tag)?; - ct + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() + } + Self::XWingHkdfSha256(ReceiverContextXWingHkdfSha256::HkdfSha256( + ReceiverContextXWingHkdfSha256HkdfSha256::AesGcm128(context), + )) => { + if ciphertext.len() < AeadTag::::size() { + return Err(Error::Truncated); + } + let (ct, tag_slice) = + ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); + let tag = AeadTag::::from_bytes(tag_slice)?; + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() + } + Self::XWingHkdfSha256(ReceiverContextXWingHkdfSha256::HkdfSha256( + ReceiverContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305(context), + )) => { + if ciphertext.len() < AeadTag::::size() { + return Err(Error::Truncated); + } + let (ct, tag_slice) = + ciphertext.split_at_mut(ciphertext.len() - AeadTag::::size()); + let mut ct = InOutBuf::from(ct); + let tag = AeadTag::::from_bytes(tag_slice)?; + context.open_inout_detached(ct.reborrow(), aad, &tag)?; + ct.into_out() } }) } @@ -433,6 +527,16 @@ impl ReceiverContext { )) => { context.export(info, out_buf)?; } + Self::XWingHkdfSha256(ReceiverContextXWingHkdfSha256::HkdfSha256( + ReceiverContextXWingHkdfSha256HkdfSha256::AesGcm128(context), + )) => { + context.export(info, out_buf)?; + } + Self::XWingHkdfSha256(ReceiverContextXWingHkdfSha256::HkdfSha256( + ReceiverContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305(context), + )) => { + context.export(info, out_buf)?; + } } Ok(()) } @@ -525,6 +629,24 @@ impl HpkeR { ReceiverContextP256HkdfSha256::HkdfSha256, ReceiverContextP256HkdfSha256HkdfSha256::ChaCha20Poly1305, }, + { + Kem::XWing => XWing, + Kdf::HkdfSha256 => HkdfSha256, + Aead::Aes128Gcm => AesGcm128, + PrivateKey::XWing, + ReceiverContext::XWingHkdfSha256, + ReceiverContextXWingHkdfSha256::HkdfSha256, + ReceiverContextXWingHkdfSha256HkdfSha256::AesGcm128, + }, + { + Kem::XWing => XWing, + Kdf::HkdfSha256 => HkdfSha256, + Aead::ChaCha20Poly1305 => ChaCha20Poly1305, + PrivateKey::XWing, + ReceiverContext::XWingHkdfSha256, + ReceiverContextXWingHkdfSha256::HkdfSha256, + ReceiverContextXWingHkdfSha256HkdfSha256::ChaCha20Poly1305, + }, ]}; Ok(Self { context, config }) @@ -542,6 +664,7 @@ impl HpkeR { Kem::P256Sha256 => { PublicKey::P256(::PublicKey::from_bytes(k)?) } + Kem::XWing => PublicKey::XWing(::PublicKey::from_bytes(k)?), }) } } @@ -577,16 +700,19 @@ impl Deref for HpkeR { /// Generate a key pair for the identified KEM. #[allow(clippy::unnecessary_wraps)] pub fn generate_key_pair(kem: Kem) -> Res<(PrivateKey, PublicKey)> { - let mut csprng = rng(); let (sk, pk) = match kem { Kem::X25519Sha256 => { - let (sk, pk) = X25519HkdfSha256::gen_keypair(&mut csprng); + let (sk, pk) = X25519HkdfSha256::gen_keypair(); (PrivateKey::X25519(sk), PublicKey::X25519(pk)) } Kem::P256Sha256 => { - let (sk, pk) = DhP256HkdfSha256::gen_keypair(&mut csprng); + let (sk, pk) = DhP256HkdfSha256::gen_keypair(); (PrivateKey::P256(sk), PublicKey::P256(pk)) } + Kem::XWing => { + let (sk, pk) = XWing::gen_keypair(); + (PrivateKey::XWing(sk), PublicKey::XWing(pk)) + } }; trace!("Generated key pair: sk={sk:?} pk={pk:?}"); Ok((sk, pk)) @@ -603,6 +729,10 @@ pub fn derive_key_pair(kem: Kem, ikm: &[u8]) -> Res<(PrivateKey, PublicKey)> { let (sk, pk) = DhP256HkdfSha256::derive_keypair(ikm); (PrivateKey::P256(sk), PublicKey::P256(pk)) } + Kem::XWing => { + let (sk, pk) = XWing::derive_keypair(ikm); + (PrivateKey::XWing(sk), PublicKey::XWing(pk)) + } }; trace!("Derived key pair: sk={sk:?} pk={pk:?}"); Ok((sk, pk)) @@ -610,7 +740,7 @@ pub fn derive_key_pair(kem: Kem, ikm: &[u8]) -> Res<(PrivateKey, PublicKey)> { #[cfg(test)] mod test { - use super::{generate_key_pair, Config, HpkeR, HpkeS}; + use super::{Config, HpkeR, HpkeS, generate_key_pair}; use crate::{ crypto::{Decrypt, Encrypt}, hpke::{Aead, Kem}, @@ -673,4 +803,14 @@ mod test { fn seal_open_chacha_p256() { seal_open(Aead::ChaCha20Poly1305, Kem::P256Sha256); } + + #[test] + fn seal_open_gcm_xwing() { + seal_open(Aead::Aes128Gcm, Kem::XWing); + } + + #[test] + fn seal_open_chacha_xwing() { + seal_open(Aead::ChaCha20Poly1305, Kem::XWing); + } } diff --git a/ohttp/src/stream.rs b/ohttp/src/stream.rs index 0c402ac..41cd2ad 100644 --- a/ohttp/src/stream.rs +++ b/ohttp/src/stream.rs @@ -12,12 +12,12 @@ use futures::{AsyncRead, AsyncWrite}; use pin_project::pin_project; use crate::{ - build_info, + Aead, Error, HpkeConfig, HpkeR, HpkeS, KeyConfig, KeyId, Mode, PublicKey, REQUEST_HEADER_LEN, + SymKey, build_info, crypto::{Decrypt, Encrypt}, entropy, err::Res, - export_secret, make_aead, random, Aead, Error, HpkeConfig, HpkeR, HpkeS, KeyConfig, KeyId, - Mode, PublicKey, SymKey, REQUEST_HEADER_LEN, + export_secret, make_aead, random, }; /// The info string for a chunked request. @@ -824,8 +824,8 @@ mod test { use sync_async::{Dribble, Pipe, SplitAt, Stutter, SyncRead, SyncResolve, Unadapt}; use crate::{ - test::{init, make_config, REQUEST, RESPONSE}, ClientRequest, Server, + test::{REQUEST, RESPONSE, init, make_config}, }; #[test] diff --git a/sync-async/src/lib.rs b/sync-async/src/lib.rs index f4a9826..09dc0ce 100644 --- a/sync-async/src/lib.rs +++ b/sync-async/src/lib.rs @@ -2,13 +2,13 @@ use std::{ cmp::min, future::Future, io::Result as IoResult, - pin::{pin, Pin}, + pin::{Pin, pin}, task::{Context, Poll}, }; use futures::{ - io::{ReadHalf, WriteHalf}, AsyncRead, AsyncReadExt, AsyncWrite, TryStream, TryStreamExt, + io::{ReadHalf, WriteHalf}, }; use pin_project::pin_project;