diff --git a/Cargo.toml b/Cargo.toml index 7a59b71..2848f8a 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ repository = "https://github.com/franziskuskiefer/hpke-rs" [dependencies] log = "0.4" -serde_json = { version = "1.0", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } tls_codec = { version = "0.4.0", features = ["derive"], optional = true } zeroize = { version = "1.5", features = ["zeroize_derive"] } @@ -19,9 +18,10 @@ hpke-rs-crypto = { version = "0.1.3", path = "./traits" } [features] default = [] -serialization = ["serde", "serde_json", "tls_codec", "tls_codec/serde"] +std = [] +serialization = ["serde", "tls_codec", "tls_codec/serde", "std"] hazmat = [] -hpke-test = [] +hpke-test = ["std"] hpke-test-prng = [] # ⚠️ Enable testing PRNG - DO NOT USE [dev-dependencies] diff --git a/benches/bench.rs b/benches/bench.rs index 9e73efd..1518129 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -49,7 +49,7 @@ fn benchmark(c: &mut Criterion) { if Crypto::supports_kem(kem_mode).is_err() { continue; } - let hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); let label = format!("{} {}", Crypto::name(), hpke); let kp = hpke.generate_key_pair().unwrap(); let enc = kp.public_key().as_slice(); @@ -83,7 +83,7 @@ fn benchmark(c: &mut Criterion) { let mut group = c.benchmark_group(format!("{}", label)); group.bench_function("Setup Sender", |b| { b.iter(|| { - let hpke = + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); hpke.setup_sender( &pk_rm, @@ -114,7 +114,7 @@ fn benchmark(c: &mut Criterion) { group.bench_function(&format!("Seal {}({})", AEAD_PAYLOAD, AEAD_AAD), |b| { b.iter_batched( || { - let hpke = + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); let (_enc, context) = hpke .setup_sender( @@ -140,7 +140,7 @@ fn benchmark(c: &mut Criterion) { group.bench_function(&format!("Open {}({})", AEAD_PAYLOAD, AEAD_AAD), |b| { b.iter_batched( || { - let hpke = + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); let (enc, mut sender_context) = hpke .setup_sender( @@ -190,7 +190,7 @@ fn benchmark(c: &mut Criterion) { OsRng.fill_bytes(&mut ptxt); (hpke, aad, ptxt) }, - |(hpke, aad, ptxt)| { + |(mut hpke, aad, ptxt)| { let _ctxt = hpke .seal( &pk_rm, @@ -212,7 +212,7 @@ fn benchmark(c: &mut Criterion) { |b| { b.iter_batched( || { - let hpke = Hpke::::new( + let mut hpke = Hpke::::new( hpke_mode, kem_mode, kdf_mode, aead_mode, ); let (enc, mut sender_context) = hpke diff --git a/benches/manual_benches.rs b/benches/manual_benches.rs index b31e37a..cf759b2 100644 --- a/benches/manual_benches.rs +++ b/benches/manual_benches.rs @@ -56,7 +56,7 @@ fn benchmark() { if Crypto::supports_kem(kem_mode).is_err() { continue; } - let hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); let label = format!( "{} {} {} {} {}", Crypto::name(), @@ -98,7 +98,8 @@ fn benchmark() { let start = Instant::now(); for _ in 0..ITERATIONS { - let hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); + let mut hpke = + Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); let _sender = hpke .setup_sender( &pk_rm, diff --git a/fuzz/fuzz_targets/base.rs b/fuzz/fuzz_targets/base.rs index 1688f95..32e1cfc 100644 --- a/fuzz/fuzz_targets/base.rs +++ b/fuzz/fuzz_targets/base.rs @@ -5,7 +5,7 @@ use hpke_rs::prelude::*; use hpke_rs_crypto::types::*; fuzz_target!(|data: &[u8]| { - let hpke = Hpke::::new( + let mut hpke = Hpke::::new( HpkeMode::Base, KemAlgorithm::DhKemP256, KdfAlgorithm::HkdfSha256, diff --git a/src/dh_kem.rs b/src/dh_kem.rs index 043fe56..dfdaab5 100755 --- a/src/dh_kem.rs +++ b/src/dh_kem.rs @@ -1,5 +1,7 @@ //! DH KEM as described in §4.1. DH-Based KEM. +use alloc::{string::ToString, vec::Vec}; + use hpke_rs_crypto::{error::Error, types::KemAlgorithm, HpkeCrypto}; use crate::util::*; diff --git a/src/kdf.rs b/src/kdf.rs index 6e097c3..d273070 100755 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use hpke_rs_crypto::{error::Error, types::KdfAlgorithm, HpkeCrypto}; use crate::util::concat; diff --git a/src/kem.rs b/src/kem.rs index 1d148a6..a3b332e 100755 --- a/src/kem.rs +++ b/src/kem.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + use hpke_rs_crypto::{error::Error, types::KemAlgorithm, HpkeCrypto}; use crate::dh_kem; diff --git a/src/lib.rs b/src/lib.rs index 2ecc24d..6517298 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,18 @@ unused_extern_crates, unused_qualifications )] +#![cfg_attr(not(test), no_std)] -use std::sync::RwLock; +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +use alloc::{ + format, + string::{String, ToString}, + vec, + vec::Vec, +}; #[cfg(feature = "hpke-test-prng")] use hpke_rs_crypto::HpkeTestRng; @@ -79,15 +89,13 @@ pub enum HpkeError { /// Unable to collect enough randomness. InsufficientRandomness, - - /// A concurrency issue with an [`RwLock`]. - LockPoisoned, } +#[cfg(feature = "std")] impl std::error::Error for HpkeError {} -impl std::fmt::Display for HpkeError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for HpkeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "HPKE Error: {:?}", self) } } @@ -159,8 +167,8 @@ pub enum Mode { AuthPsk = 0x03, } -impl std::fmt::Display for Mode { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Display for Mode { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "{:?}", self) } } @@ -202,8 +210,8 @@ pub struct Context { } #[cfg(feature = "hazmat")] -impl std::fmt::Debug for Context { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Debug for Context { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "Context {{\n key: {:?}\n nonce: {:?}\n exporter_secret: {:?}\n seq no: {:?}\n}}", @@ -213,8 +221,8 @@ impl std::fmt::Debug for Context { } #[cfg(not(feature = "hazmat"))] -impl std::fmt::Debug for Context { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Debug for Context { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "Context {{\n key: {:?}\n nonce: {:?}\n exporter_secret: {:?}\n seq no: {:?}\n}}", @@ -331,7 +339,7 @@ pub struct Hpke { kem_id: KemAlgorithm, kdf_id: KdfAlgorithm, aead_id: AeadAlgorithm, - prng: RwLock, + prng: Crypto::HpkePrng, } impl Clone for Hpke { @@ -341,13 +349,13 @@ impl Clone for Hpke { kem_id: self.kem_id, kdf_id: self.kdf_id, aead_id: self.aead_id, - prng: RwLock::new(Crypto::prng()), + prng: Crypto::prng(), } } } -impl std::fmt::Display for Hpke { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Display for Hpke { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!( f, "{}_{}_{}_{}", @@ -372,7 +380,7 @@ impl Hpke { kem_id, kdf_id, aead_id, - prng: RwLock::new(Crypto::prng()), + prng: Crypto::prng(), } } @@ -391,7 +399,7 @@ impl Hpke { /// The encapsulated secret is returned together with the context. /// If the secret key is missing in an authenticated mode, an error is returned. pub fn setup_sender( - &self, + &mut self, pk_r: &HpkePublicKey, info: &[u8], psk: Option<&[u8]>, @@ -478,7 +486,7 @@ impl Hpke { /// Returns the encapsulated secret and the ciphertext, or an error. #[allow(clippy::too_many_arguments)] pub fn seal( - &self, + &mut self, pk_r: &HpkePublicKey, info: &[u8], aad: &[u8], @@ -534,7 +542,7 @@ impl Hpke { /// exporter context and length. #[allow(clippy::too_many_arguments)] pub fn send_export( - &self, + &mut self, pk_r: &HpkePublicKey, info: &[u8], psk: Option<&[u8]>, @@ -674,9 +682,8 @@ impl Hpke { /// This is equivalent to `derive_key_pair(random_vector(sk.len()))` /// /// Returns an `HpkeKeyPair`. - pub fn generate_key_pair(&self) -> Result { - let mut prng = self.prng.write().map_err(|_| HpkeError::LockPoisoned)?; - let (sk, pk) = kem::key_gen::(self.kem_id, &mut prng)?; + pub fn generate_key_pair(&mut self) -> Result { + let (sk, pk) = kem::key_gen::(self.kem_id, &mut self.prng)?; Ok(HpkeKeyPair::new(sk, pk)) } @@ -690,8 +697,8 @@ impl Hpke { } #[inline] - pub(crate) fn random(&self, len: usize) -> Result, HpkeError> { - let mut prng = self.prng.write().map_err(|_| HpkeError::LockPoisoned)?; + pub(crate) fn random(&mut self, len: usize) -> Result, HpkeError> { + let prng = &mut self.prng; let mut out = vec![0u8; len]; #[cfg(feature = "hpke-test-prng")] @@ -794,8 +801,8 @@ impl PartialEq for HpkePrivateKey { } #[cfg(not(feature = "hazmat"))] -impl std::fmt::Debug for HpkePrivateKey { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +impl core::fmt::Debug for HpkePrivateKey { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { f.debug_struct("HpkePrivateKey") .field("value", &"***") .finish() @@ -803,8 +810,8 @@ impl std::fmt::Debug for HpkePrivateKey { } #[cfg(feature = "hazmat")] -impl std::fmt::Debug for HpkePrivateKey { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { +impl core::fmt::Debug for HpkePrivateKey { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { f.debug_struct("HpkePrivateKey") .field("value", &self.value) .finish() @@ -891,14 +898,15 @@ impl tls_codec::Deserialize for &HpkePublicKey { /// Test util module. Should be moved really. #[cfg(feature = "hpke-test")] pub mod test_util { + use alloc::{format, string::String, vec, vec::Vec}; + use crate::HpkeError; use hpke_rs_crypto::{HpkeCrypto, HpkeTestRng}; impl super::Hpke { /// Set PRNG state for testing. - pub fn seed(&self, seed: &[u8]) -> Result<(), HpkeError> { - let mut prng = self.prng.write().map_err(|_| HpkeError::LockPoisoned)?; - prng.seed(seed); + pub fn seed(&mut self, seed: &[u8]) -> Result<(), HpkeError> { + self.prng.seed(seed); Ok(()) } } diff --git a/src/prelude.rs b/src/prelude.rs index e0bebf3..ab310a1 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -2,4 +2,4 @@ //! Include this to get access to all the public functions of HPKE. pub use super::{Mode as HpkeMode, *}; -pub use std::convert::TryFrom; +pub use core::convert::TryFrom; diff --git a/src/util.rs b/src/util.rs index d9d954b..5302272 100755 --- a/src/util.rs +++ b/src/util.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + #[inline] pub(crate) fn concat(values: &[&[u8]]) -> Vec { values.join(&[][..]) diff --git a/tests/test_hpke.rs b/tests/test_hpke.rs index dfd1376..03e8b99 100644 --- a/tests/test_hpke.rs +++ b/tests/test_hpke.rs @@ -43,7 +43,7 @@ macro_rules! generate_test_case { ($name:ident, $hpke_mode:expr, $kem_mode:expr, $kdf_mode:expr, $aead_mode:expr, $provider:ident) => { #[test] fn $name() { - let hpke = Hpke::<$provider>::new($hpke_mode, $kem_mode, $kdf_mode, $aead_mode); + let mut hpke = Hpke::<$provider>::new($hpke_mode, $kem_mode, $kdf_mode, $aead_mode); println!("Self test {}", hpke); // Self test seal and open with random keys. diff --git a/tests/test_hpke_kat.rs b/tests/test_hpke_kat.rs index 553ee1e..8a736be 100755 --- a/tests/test_hpke_kat.rs +++ b/tests/test_hpke_kat.rs @@ -181,7 +181,7 @@ fn kat(tests: Vec) { #[cfg(feature = "hpke-test-prng")] { log::trace!("Testing with known ikmE ..."); - let hpke_sender = Hpke::::new(mode, kem_id, kdf_id, aead_id); + let mut hpke_sender = Hpke::::new(mode, kem_id, kdf_id, aead_id); // This only works when seeding the PRNG with ikmE. hpke_sender.seed(&ikm_e).expect("Error injecting ikm_e"); let (enc, _sender_context_kat) = hpke_sender @@ -298,7 +298,7 @@ fn test_serialization() { for &kem_mode in &[0x10u16, 0x20] { let kem_mode = KemAlgorithm::try_from(kem_mode).unwrap(); - let hpke = + let mut hpke = Hpke::::new(hpke_mode, kem_mode, kdf_mode, aead_mode); // JSON: Public, Private, KeyPair