diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 678e957..02edf9b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -145,15 +145,20 @@ jobs: target: # for wasm - wasm32-unknown-unknown + # for any no_std target + - thumbv6m-none-eabi backend_feature: - u64_backend - u32_backend - p256,u64_backend + frontend_feature: + - slow-hash + - serialize steps: - uses: actions/checkout@v2 - uses: hecrj/setup-rust-action@v1 - run: rustup target add ${{ matrix.target }} - - run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }} + - run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.frontend_feature }} --features ${{ matrix.backend_feature }} benches: name: cargo bench compilation diff --git a/Cargo.toml b/Cargo.toml index 47dfe2d..24e7d0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ authors = ["Kevin Lewi ", "François Garillot "] license = "MIT" edition = "2018" readme = "README.md" +resolver = "2" [features] default = ["u64_backend", "serialize"] @@ -17,32 +18,33 @@ p256 = ["num-bigint", "num-integer", "num-traits", "once_cell", "p256_"] bench = [] u64_backend = ["curve25519-dalek/u64_backend"] u32_backend = ["curve25519-dalek/u32_backend"] -std = ["curve25519-dalek/std"] +std = ["curve25519-dalek/std", "getrandom", "rand/std", "rand/std_rng", "num-bigint/std", "num-integer/std", "num-traits/std"] serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"] [dependencies] -argon2 = { version = "0.2", optional = true } -base64 = { version = "0.13", optional = true } +argon2 = { version = "0.2", default-features = false, optional = true } +base64 = { version = "0.13", default-features = false, features = ["alloc"], optional = true } constant_time_eq = "0.1" curve25519-dalek = { version = "3", default-features = false } digest = "0.9" -displaydoc = "0.2" +displaydoc = { version = "0.2", default-features = false } generic-array = "0.14" -generic-bytes = { version = "0.1" } -getrandom = { version = "0.2", features = ["js"] } +getrandom = { version = "0.2", optional = true } hkdf = "0.11" hmac = "0.11" -num-bigint = { version = "0.4", optional = true } -num-integer = { version = "0.1", optional = true } -num-traits = { version = "0.2", optional = true } -once_cell = { version = "1", optional = true } -p256_ = { package = "p256", version = "0.9", optional = true } +num-bigint = { version = "0.4", default-features = false, optional = true } +num-integer = { version = "0.1", default-features = false, optional = true } +num-traits = { version = "0.2", default-features = false, optional = true } +once_cell = { version = "1", default-features = false, optional = true } +p256_ = { package = "p256", version = "0.9", default-features = false, features = ["arithmetic", "zeroize"], optional = true } rand = { version = "0.8", default-features = false } -serde = { version = "1", features = ["derive"], optional = true } +serde = { version = "1", default-features = false, features = ["alloc", "derive"], optional = true } subtle = { version = "2.3", default-features = false } -thiserror = "1" zeroize = { version = "1", features = ["zeroize_derive"] } +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = ["js"], optional = true } + [dev-dependencies] base64 = "0.13" bincode = "1" @@ -50,6 +52,7 @@ chacha20poly1305 = "0.8" criterion = "0.3" hex = "0.4" lazy_static = "1" +opaque-ke = { path = "", default-features = false, features = ["std"] } serde_json = "1" sha2 = "0.9" proptest = "1" diff --git a/src/envelope.rs b/src/envelope.rs index b8e4211..42e058f 100644 --- a/src/envelope.rs +++ b/src/envelope.rs @@ -8,7 +8,7 @@ use crate::{ errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError}, group::Group, hash::Hash, - keypair::{KeyPair, PrivateKey, PublicKey}, + keypair::{KeyPair, PublicKey}, opaque::{bytestrings_from_identifiers, Identifiers}, }; use alloc::vec; @@ -16,7 +16,6 @@ use alloc::vec::Vec; use core::convert::TryFrom; use digest::Digest; use generic_array::{typenum::Unsigned, GenericArray}; -use generic_bytes::SizedBytes; use hkdf::Hkdf; use hmac::{Hmac, Mac, NewMac}; use rand::{CryptoRng, RngCore}; @@ -35,7 +34,7 @@ fn build_inner_envelope_internal( nonce: &[u8], ) -> Result, ProtocolError> { let h = Hkdf::::new(None, random_pwd); - let mut keypair_seed = vec![0u8; as SizedBytes>::Len::to_usize()]; + let mut keypair_seed = vec![0u8; ::ScalarLen::USIZE]; h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed) .map_err(|_| InternalPakeError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( @@ -53,7 +52,7 @@ fn recover_keys_internal( nonce: &[u8], ) -> Result, ProtocolError> { let h = Hkdf::::new(None, random_pwd); - let mut keypair_seed = vec![0u8; as SizedBytes>::Len::to_usize()]; + let mut keypair_seed = vec![0u8; ::ScalarLen::USIZE]; h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed) .map_err(|_| InternalPakeError::HkdfError)?; let client_static_keypair = KeyPair::::from_private_key_slice( @@ -153,15 +152,15 @@ type SealResult = ( impl Envelope { fn hmac_key_size() -> usize { - ::OutputSize::to_usize() + ::OutputSize::USIZE } fn export_key_size() -> usize { - ::OutputSize::to_usize() + ::OutputSize::USIZE } pub(crate) fn len() -> usize { - ::OutputSize::to_usize() + NONCE_LEN + ::OutputSize::USIZE + NONCE_LEN } pub(crate) fn serialize(&self) -> Vec { @@ -201,7 +200,7 @@ impl Envelope { nonce: vec![0u8; NONCE_LEN], hmac: GenericArray::clone_from_slice(&vec![ 0u8; - ::OutputSize::to_usize() + ::OutputSize::USIZE ]), } } diff --git a/src/errors.rs b/src/errors.rs index 9fbc2aa..98329c7 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -296,24 +296,6 @@ impl ProtocolError { } } -impl From for InternalPakeError { - fn from(_: generic_bytes::TryFromSizedBytesError) -> Self { - InternalPakeError::InvalidByteSequence - } -} - -impl From for PakeError { - fn from(e: generic_bytes::TryFromSizedBytesError) -> Self { - PakeError::CryptoError(e.into()) - } -} - -impl From for ProtocolError { - fn from(e: generic_bytes::TryFromSizedBytesError) -> Self { - PakeError::CryptoError(e.into()).into() - } -} - pub(crate) mod utils { use super::*; diff --git a/src/group/expand.rs b/src/group/expand.rs index c67ad36..45f5681 100644 --- a/src/group/expand.rs +++ b/src/group/expand.rs @@ -31,8 +31,8 @@ pub fn expand_message_xmd( dst: &[u8], len_in_bytes: usize, ) -> Result, ProtocolError> { - let b_in_bytes = ::OutputSize::to_usize(); - let r_in_bytes = ::BlockSize::to_usize(); + let b_in_bytes = ::OutputSize::USIZE; + let r_in_bytes = ::BlockSize::USIZE; let ell = div_ceil(len_in_bytes, b_in_bytes); if ell > 255 { diff --git a/src/group/p256.rs b/src/group/p256.rs index a3abe0f..839813f 100644 --- a/src/group/p256.rs +++ b/src/group/p256.rs @@ -18,7 +18,7 @@ use generic_array::{ArrayLength, GenericArray}; use num_bigint::{BigInt, Sign}; use num_integer::Integer; use num_traits::{One, ToPrimitive}; -use once_cell::sync::Lazy; +use once_cell::unsync::Lazy; use p256_::elliptic_curve::group::prime::PrimeCurveAffine; use p256_::elliptic_curve::group::GroupEncoding; use p256_::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint}; @@ -27,50 +27,41 @@ use p256_::elliptic_curve::Field; use p256_::{AffinePoint, EncodedPoint, ProjectivePoint}; use rand::{CryptoRng, RngCore}; -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2 -// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1` -const P: Lazy = Lazy::new(|| { - BigInt::from_str( - "115792089210356248762697446949407573530086143415290314195533631308867097853951", - ) - .unwrap() -}); -// `A: -3` -const A: Lazy = Lazy::new(|| BigInt::from(-3)); -// `B: 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b` -const B: Lazy = Lazy::new(|| { - BigInt::parse_bytes( - b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - 16, - ) - .unwrap() -}); // `L: 48` pub const L: usize = 48; -// `Z: -10` -const Z: Lazy = Lazy::new(|| BigInt::from(-10)); -// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0] -// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369` -pub const N: Lazy = Lazy::new(|| { - BigInt::from_str( - "115792089210356248762697446949407573529996955224135760342422259061068512044369", - ) - .unwrap() -}); -#[cfg(feature = "p256")] impl Group for ProjectivePoint { const SUITE_ID: usize = 0x0003; // Implements the `hash_to_curve()` function from // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3 fn map_to_curve(msg: &[u8], dst: &[u8]) -> Result { + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2 + // `p: 2^256 - 2^224 + 2^192 + 2^96 - 1` + const P: Lazy = Lazy::new(|| { + BigInt::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853951", + ) + .unwrap() + }); + // `A: -3` + const A: Lazy = Lazy::new(|| BigInt::from(-3)); + // `B: 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b` + const B: Lazy = Lazy::new(|| { + BigInt::parse_bytes( + b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + 16, + ) + .unwrap() + }); + // `Z: -10` + const Z: Lazy = Lazy::new(|| BigInt::from(-10)); + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3 // `hash_to_curve` calls `hash_to_field` with a `count` of `2` // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3 // `hash_to_field` calls `expand_message` with a `len_in_bytes` of `count * L` - let uniform_bytes = - super::expand::expand_message_xmd::(msg, dst, 2 * crate::group::p256::L)?; + let uniform_bytes = super::expand::expand_message_xmd::(msg, dst, 2 * L)?; // map to curve let (q0x, q0y) = map_to_curve_simple_swu(&uniform_bytes[..L], &A, &B, &P, &Z); @@ -93,12 +84,20 @@ impl Group for ProjectivePoint { // Implements the `HashToScalar()` function from // https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.3 fn hash_to_scalar(input: &[u8], dst: &[u8]) -> Result { + // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0] + // P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369` + const N: once_cell::unsync::Lazy = once_cell::unsync::Lazy::new(|| { + BigInt::from_str( + "115792089210356248762697446949407573529996955224135760342422259061068512044369", + ) + .unwrap() + }); + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3 // `HashToScalar` is `hash_to_field` - let uniform_bytes = - super::expand::expand_message_xmd::(input, dst, crate::group::p256::L)?; + let uniform_bytes = super::expand::expand_message_xmd::(input, dst, L)?; let mut bytes = BigInt::from_bytes_be(Sign::Plus, &uniform_bytes) - .mod_floor(&crate::group::p256::N) + .mod_floor(&N) .to_bytes_be() .1; bytes.resize(32, 0); @@ -410,6 +409,22 @@ mod tests { #[test] fn map_to_curve_simple_swu() { + const P: Lazy = Lazy::new(|| { + BigInt::from_str( + "115792089210356248762697446949407573530086143415290314195533631308867097853951", + ) + .unwrap() + }); + const A: Lazy = Lazy::new(|| BigInt::from(-3)); + const B: Lazy = Lazy::new(|| { + BigInt::parse_bytes( + b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + 16, + ) + .unwrap() + }); + const Z: Lazy = Lazy::new(|| BigInt::from(-10)); + // Test vectors taken from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-J.1.1 let test_vectors = alloc::vec![ Params { diff --git a/src/key_exchange/tripledh.rs b/src/key_exchange/tripledh.rs index e0225a4..cc29f17 100644 --- a/src/key_exchange/tripledh.rs +++ b/src/key_exchange/tripledh.rs @@ -15,7 +15,7 @@ use crate::{ key_exchange::traits::{ FromBytes, GenerateKe2Result, GenerateKe3Result, KeyExchange, ToBytes, ToBytesWithPointers, }, - keypair::{KeyPair, PrivateKey, PublicKey, SecretKey, SizedBytesExt}, + keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}, serialization::serialize, }; use alloc::vec; @@ -26,7 +26,6 @@ use generic_array::{ typenum::{Unsigned, U32}, ArrayLength, GenericArray, }; -use generic_bytes::SizedBytes; use hkdf::Hkdf; use hmac::{Hmac, Mac, NewMac}; use rand::{CryptoRng, RngCore}; @@ -214,9 +213,7 @@ impl KeyExchange for TripleDH { } fn ke2_message_size() -> usize { - NonceLen::to_usize() - + ::ElemLen::to_usize() - + <::OutputSize as Unsigned>::to_usize() + NonceLen::USIZE + ::ElemLen::USIZE + ::OutputSize::USIZE } } @@ -260,9 +257,9 @@ pub struct Ke1Message { impl FromBytes for Ke1State { fn from_bytes(bytes: &[u8]) -> Result { - let key_len = ::ElemLen::to_usize(); + let key_len = ::ElemLen::USIZE; - let nonce_len = NonceLen::to_usize(); + let nonce_len = NonceLen::USIZE; let checked_bytes = check_slice_size_atleast(bytes, key_len + nonce_len, "ke1_state")?; Ok(Self { @@ -283,11 +280,8 @@ impl ToBytesWithPointers for Ke1State { #[cfg(test)] fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> { vec![ - ( - self.client_e_sk.as_ptr(), - as SizedBytes>::Len::to_usize(), - ), - (self.client_nonce.as_ptr(), NonceLen::to_usize()), + (self.client_e_sk.as_ptr(), G::ScalarLen::USIZE), + (self.client_nonce.as_ptr(), NonceLen::USIZE), ] } } @@ -300,10 +294,10 @@ impl ToBytes for Ke1Message { impl FromBytes for Ke1Message { fn from_bytes(ke1_message_bytes: &[u8]) -> Result { - let nonce_len = NonceLen::to_usize(); + let nonce_len = NonceLen::USIZE; let checked_nonce = check_slice_size( ke1_message_bytes, - nonce_len + ::ElemLen::to_usize(), + nonce_len + ::ElemLen::USIZE, "ke1_message nonce", )?; @@ -351,9 +345,9 @@ impl> ToBytesWithPointers for Ke2State { #[cfg(test)] fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> { vec![ - (self.km3.as_ptr(), HashLen::to_usize()), - (self.hashed_transcript.as_ptr(), HashLen::to_usize()), - (self.session_key.as_ptr(), HashLen::to_usize()), + (self.km3.as_ptr(), HashLen::USIZE), + (self.hashed_transcript.as_ptr(), HashLen::USIZE), + (self.session_key.as_ptr(), HashLen::USIZE), ] } } @@ -370,7 +364,7 @@ pub struct Ke2Message> { impl> FromBytes for Ke2State { fn from_bytes(input: &[u8]) -> Result { - let hash_len = HashLen::to_usize(); + let hash_len = HashLen::USIZE; let checked_bytes = check_slice_size(input, 3 * hash_len, "ke2_state")?; Ok(Self { @@ -397,8 +391,8 @@ impl> Ke2Message { impl> FromBytes for Ke2Message { fn from_bytes(input: &[u8]) -> Result { - let key_len = ::ElemLen::to_usize(); - let nonce_len = NonceLen::to_usize(); + let key_len = ::ElemLen::USIZE; + let nonce_len = NonceLen::USIZE; let checked_nonce = check_slice_size_atleast(input, nonce_len, "ke2_message nonce")?; let unchecked_server_e_pk = check_slice_size_atleast( @@ -408,7 +402,7 @@ impl> FromBytes for Ke2Message { )?; let checked_mac = check_slice_size( &unchecked_server_e_pk[key_len..], - HashLen::to_usize(), + HashLen::USIZE, "ke1_message mac", )?; @@ -468,7 +462,7 @@ impl> ToBytes for Ke3Message { impl> FromBytes for Ke3Message { fn from_bytes(bytes: &[u8]) -> Result { - let checked_bytes = check_slice_size(bytes, HashLen::to_usize(), "ke3_message")?; + let checked_bytes = check_slice_size(bytes, HashLen::USIZE, "ke3_message")?; Ok(Self { mac: GenericArray::clone_from_slice(checked_bytes), @@ -513,14 +507,14 @@ fn derive_3dh_keys>( &handshake_secret, STR_SERVER_MAC, b"", - ::OutputSize::to_usize(), + ::OutputSize::USIZE, ) .map_err(ProtocolError::into_custom)?; let km3 = hkdf_expand_label::( &handshake_secret, STR_CLIENT_MAC, b"", - ::OutputSize::to_usize(), + ::OutputSize::USIZE, ) .map_err(ProtocolError::into_custom)?; @@ -577,13 +571,13 @@ fn derive_secrets( hkdf, label, hashed_derivation_transcript, - ::OutputSize::to_usize(), + ::OutputSize::USIZE, ) } -// Generate a random nonce up to NonceLen::to_usize() bytes. +// Generate a random nonce up to NonceLen::USIZE bytes. fn generate_nonce(rng: &mut R) -> GenericArray { - let mut nonce_bytes = vec![0u8; NonceLen::to_usize()]; + let mut nonce_bytes = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut nonce_bytes); GenericArray::clone_from_slice(&nonce_bytes) } diff --git a/src/keypair.rs b/src/keypair.rs index f298e1e..4e61fdf 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -9,32 +9,14 @@ use crate::errors::{InternalPakeError, ProtocolError}; use crate::group::Group; -use alloc::borrow::ToOwned; use alloc::vec::Vec; use core::fmt::Debug; use core::ops::Deref; -#[cfg(test)] use generic_array::typenum::Unsigned; use generic_array::{ArrayLength, GenericArray}; -use generic_bytes::{SizedBytes, TryFromSizedBytesError}; -#[cfg(all(test, feature = "std"))] -use proptest::prelude::*; -#[cfg(all(test, feature = "std"))] -use rand::{rngs::StdRng, SeedableRng}; use rand::{CryptoRng, RngCore}; use zeroize::Zeroize; -/// Convenience extension trait of SizedBytes -pub trait SizedBytesExt: SizedBytes { - /// Convert from bytes - fn from_bytes(bytes: &[u8]) -> Result { - ::from_arr(GenericArray::from_slice(bytes)) - } -} - -// blanket implementation -impl SizedBytesExt for T where T: SizedBytes {} - /// A Keypair trait with public-private verification #[cfg_attr( feature = "serialize", @@ -142,17 +124,20 @@ impl KeyPair { #[cfg(test)] pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> { alloc::vec![ - (self.pk.as_ptr(), G::ElemLen::to_usize()), - (self.sk.as_ptr(), G::ScalarLen::to_usize()), + (self.pk.as_ptr(), G::ElemLen::USIZE), + (self.sk.as_ptr(), G::ScalarLen::USIZE), ] } } -#[cfg(all(test, feature = "std"))] +#[cfg(test)] impl KeyPair { /// Test-only strategy returning a proptest Strategy based on /// generate_random - fn uniform_keypair_strategy() -> BoxedStrategy { + fn uniform_keypair_strategy() -> proptest::prelude::BoxedStrategy { + use proptest::prelude::*; + use rand::{rngs::StdRng, SeedableRng}; + // The no_shrink is because keypairs should be fixed -- shrinking would cause a different // keypair to be generated, which appears to not be very useful. any::<[u8; 32]>() @@ -223,13 +208,9 @@ impl> Deref for Key { // Don't make it implement SizedBytes so that it's not constructible outside of this module. impl> Key { - fn to_arr(&self) -> GenericArray { - GenericArray::clone_from_slice(&self.0[..]) - } - - #[allow(clippy::unnecessary_wraps)] - fn from_arr(key_bytes: &GenericArray) -> Result { - Ok(Key(key_bytes.to_owned())) + /// Convert to bytes + pub fn to_arr(&self) -> GenericArray { + self.0.clone() } } @@ -268,15 +249,19 @@ impl Deref for PrivateKey { } } -impl SizedBytes for PrivateKey { - type Len = G::ScalarLen; - - fn to_arr(&self) -> GenericArray { - self.0.to_arr() +impl PrivateKey { + /// Convert from bytes + pub fn from_arr(key_bytes: GenericArray) -> Self { + PrivateKey(Key(key_bytes)) } - fn from_arr(key_bytes: &GenericArray) -> Result { - Ok(PrivateKey(Key::from_arr(key_bytes)?)) + /// Convert from slice + pub fn from_bytes(key_bytes: &[u8]) -> Result { + if key_bytes.len() == G::ScalarLen::USIZE { + Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone())) + } else { + Err(InternalPakeError::InvalidByteSequence) + } } } @@ -359,15 +344,19 @@ impl Deref for PublicKey { } } -impl SizedBytes for PublicKey { - type Len = G::ElemLen; - - fn to_arr(&self) -> GenericArray { - self.0.to_arr() +impl PublicKey { + /// Convert from bytes + pub fn from_arr(key_bytes: GenericArray) -> Self { + Self(Key(key_bytes)) } - fn from_arr(key_bytes: &GenericArray) -> Result { - Ok(PublicKey(Key::from_arr(key_bytes)?)) + /// Convert from slice + pub fn from_bytes(key_bytes: &[u8]) -> Result { + if key_bytes.len() == G::ElemLen::USIZE { + Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone())) + } else { + Err(InternalPakeError::InvalidByteSequence) + } } } @@ -378,11 +367,12 @@ mod tests { use core::slice::from_raw_parts; use curve25519_dalek::ristretto::RistrettoPoint; use generic_array::typenum::Unsigned; + use proptest::prelude::*; use rand::rngs::OsRng; #[test] fn test_zeroize_key() -> Result<(), ProtocolError> { - let key_len = ::ElemLen::to_usize(); + let key_len = ::ElemLen::USIZE; let mut key = Key::<::ElemLen>(GenericArray::clone_from_slice( &alloc::vec![ 1u8; @@ -415,7 +405,6 @@ mod tests { Ok(()) } - #[cfg(feature = "std")] proptest! { #[test] fn test_ristretto_check(kp in KeyPair::::uniform_keypair_strategy()) { @@ -505,7 +494,7 @@ mod tests { let sk = RistrettoPoint::random_nonzero_scalar(&mut OsRng); let sk_bytes = RistrettoPoint::scalar_as_bytes(sk); - let sk = RemoteKey(PrivateKey::from_arr(&sk_bytes).unwrap()); + let sk = RemoteKey(PrivateKey::from_arr(sk_bytes)); let keypair = KeyPair::from_private_key(sk).unwrap(); let server_setup = ServerSetup::::new_with_key(&mut OsRng, keypair); diff --git a/src/lib.rs b/src/lib.rs index 99ae69d..ece3473 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -748,7 +748,6 @@ //! ``` //! # use curve25519_dalek::ristretto::RistrettoPoint; //! # use generic_array::{GenericArray, typenum::U32}; -//! # use generic_bytes::SizedBytes; //! # use opaque_ke::{CipherSuite, errors::{InternalPakeError}, keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}, ServerSetup}; //! # use rand::rngs::OsRng; //! # use zeroize::Zeroize; @@ -781,8 +780,7 @@ //! fn public_key( //! &self //! ) -> Result, InternalPakeError> { -//! let pk = YourRemoteKey::public_key(self).map_err(InternalPakeError::Custom)?; -//! PublicKey::from_arr(&pk).map_err(InternalPakeError::from) +//! YourRemoteKey::public_key(self).map(PublicKey::from_arr).map_err(InternalPakeError::Custom) //! } //! //! fn serialize(&self) -> Vec { @@ -796,7 +794,7 @@ //! } //! } //! -//! # let remote_key = YourRemoteKey(PrivateKey::from_arr(&GenericArray::default()).unwrap()); +//! # let remote_key = YourRemoteKey(PrivateKey::from_arr(GenericArray::default())); //! let keypair = KeyPair::from_private_key(remote_key).unwrap(); //! let server_setup = ServerSetup::::new_with_key(&mut OsRng, keypair); //! ``` diff --git a/src/messages.rs b/src/messages.rs index 382195e..32f87e1 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -14,13 +14,12 @@ use crate::{ }, group::Group, key_exchange::traits::{FromBytes, KeyExchange, ToBytes}, - keypair::{KeyPair, PublicKey, SecretKey, SizedBytesExt}, + keypair::{KeyPair, PublicKey, SecretKey}, opaque::ServerSetup, }; use alloc::vec::Vec; use digest::Digest; use generic_array::{typenum::Unsigned, GenericArray}; -use generic_bytes::SizedBytes; use rand::{CryptoRng, RngCore}; // Messages @@ -57,7 +56,7 @@ impl RegistrationRequest { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let elem_len = ::ElemLen::to_usize(); + let elem_len = ::ElemLen::USIZE; let checked_slice = check_slice_size(input, elem_len, "first_message_bytes")?; // Check that the message is actually containing an element of the // correct subgroup @@ -107,8 +106,8 @@ impl RegistrationResponse { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let elem_len = ::ElemLen::to_usize(); - let key_len = as SizedBytes>::Len::to_usize(); + let elem_len = ::ElemLen::USIZE; + let key_len = ::ElemLen::USIZE; let checked_slice = check_slice_size(input, elem_len + key_len, "registration_response_bytes")?; @@ -177,8 +176,8 @@ impl RegistrationUpload { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let key_len = as SizedBytes>::Len::to_usize(); - let hash_len = ::OutputSize::to_usize(); + let key_len = ::ElemLen::USIZE; + let hash_len = ::OutputSize::USIZE; let checked_slice = check_slice_size_atleast(input, key_len + hash_len, "registration_upload_bytes")?; let envelope = Envelope::::deserialize(&checked_slice[key_len + hash_len..])?; @@ -198,7 +197,7 @@ impl RegistrationUpload { rng: &mut R, server_setup: &ServerSetup, ) -> Self { - let mut masking_key = alloc::vec![0u8; ::OutputSize::to_usize()]; + let mut masking_key = alloc::vec![0u8; ::OutputSize::USIZE]; rng.fill_bytes(&mut masking_key); Self { @@ -245,7 +244,7 @@ impl CredentialRequest { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let elem_len = ::ElemLen::to_usize(); + let elem_len = ::ElemLen::USIZE; let checked_slice = check_slice_size_atleast(input, elem_len, "login_first_message_bytes")?; @@ -327,8 +326,8 @@ impl CredentialResponse { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let elem_len = ::ElemLen::to_usize(); - let key_len = as SizedBytes>::Len::to_usize(); + let elem_len = ::ElemLen::USIZE; + let key_len = ::ElemLen::USIZE; let nonce_len: usize = 32; let envelope_len = Envelope::::len(); let masked_response_len = key_len + envelope_len; diff --git a/src/opaque.rs b/src/opaque.rs index b3475a6..bc1da3b 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -24,7 +24,6 @@ use alloc::vec::Vec; use core::marker::PhantomData; use digest::Digest; use generic_array::{typenum::Unsigned, GenericArray}; -use generic_bytes::SizedBytes; use hkdf::Hkdf; use rand::{CryptoRng, RngCore}; use zeroize::Zeroize; @@ -69,7 +68,7 @@ impl> ServerSetup { rng: &mut R, keypair: KeyPair, ) -> Self { - let mut seed = vec![0u8; ::OutputSize::to_usize()]; + let mut seed = vec![0u8; ::OutputSize::USIZE]; rng.fill_bytes(&mut seed); Self { @@ -91,8 +90,8 @@ impl> ServerSetup { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result> { - let seed_len = ::OutputSize::to_usize(); - let key_len = as SizedBytes>::Len::to_usize(); + let seed_len = ::OutputSize::USIZE; + let key_len = ::ScalarLen::USIZE; let checked_slice = check_slice_size(input, seed_len + key_len + key_len, "server_setup")?; Ok(Self { @@ -149,8 +148,8 @@ impl ClientRegistration { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let elem_len = ::ElemLen::to_usize(); - let scalar_len = ::ScalarLen::to_usize(); + let elem_len = ::ElemLen::USIZE; + let scalar_len = ::ScalarLen::USIZE; let min_expected_len = elem_len + scalar_len; let checked_slice = (if input.len() <= min_expected_len { Err(InternalPakeError::SizeError { @@ -332,7 +331,7 @@ impl ClientRegistration { #[cfg_attr(not(test), allow(unused_variables))] let (randomized_pwd, h) = Hkdf::::extract(None, &password_derived_key); - let mut masking_key = vec![0u8; ::OutputSize::to_usize()]; + let mut masking_key = vec![0u8; ::OutputSize::USIZE]; h.expand(STR_MASKING_KEY, &mut masking_key) .map_err(|_| InternalPakeError::HkdfError)?; @@ -490,7 +489,7 @@ impl ClientLogin { /// Deserialization from bytes pub fn deserialize(input: &[u8]) -> Result { - let scalar_len = ::ScalarLen::to_usize(); + let scalar_len = ::ScalarLen::USIZE; let checked_slice = (if input.len() <= scalar_len { Err(InternalPakeError::SizeError { name: "client_login_bytes", @@ -664,7 +663,7 @@ impl ClientLogin { )?; let h = Hkdf::::new(None, &password_derived_key); - let mut masking_key = vec![0u8; ::OutputSize::to_usize()]; + let mut masking_key = vec![0u8; ::OutputSize::USIZE]; h.expand(STR_MASKING_KEY, &mut masking_key) .map_err(|_| InternalPakeError::HkdfError)?; @@ -1029,7 +1028,7 @@ fn oprf_key_from_seed( oprf_seed: &GenericArray, credential_identifier: &[u8], ) -> Result { - let mut ikm = vec![0u8; as SizedBytes>::Len::to_usize()]; + let mut ikm = vec![0u8; G::ScalarLen::USIZE]; Hkdf::::from_prk(oprf_seed) .map_err(|_| InternalPakeError::HkdfError)? .expand(&[credential_identifier, STR_OPRF_KEY].concat(), &mut ikm) @@ -1043,8 +1042,7 @@ fn mask_response( server_s_pk: &PublicKey, envelope: &Envelope, ) -> Result, ProtocolError> { - let mut xor_pad = - vec![0u8; as SizedBytes>::Len::to_usize() + Envelope::::len()]; + let mut xor_pad = vec![0u8; ::ElemLen::USIZE + Envelope::::len()]; Hkdf::::from_prk(masking_key) .map_err(|_| InternalPakeError::HkdfError)? .expand( @@ -1067,8 +1065,7 @@ fn unmask_response( masking_nonce: &[u8], masked_response: &[u8], ) -> Result<(PublicKey, Envelope), ProtocolError> { - let mut xor_pad = - vec![0u8; as SizedBytes>::Len::to_usize() + Envelope::::len()]; + let mut xor_pad = vec![0u8; ::ElemLen::USIZE + Envelope::::len()]; Hkdf::::from_prk(masking_key) .map_err(|_| InternalPakeError::HkdfError)? .expand( @@ -1081,9 +1078,8 @@ fn unmask_response( .zip(masked_response.iter()) .map(|(&x1, &x2)| x1 ^ x2) .collect(); - let key_len = as SizedBytes>::Len::to_usize(); - let unchecked_server_s_pk = - PublicKey::from_arr(&GenericArray::clone_from_slice(&plaintext[..key_len]))?; + let key_len = ::ElemLen::USIZE; + let unchecked_server_s_pk = PublicKey::from_bytes(&plaintext[..key_len])?; let envelope = Envelope::deserialize(&plaintext[key_len..])?; // Ensure that public key is valid diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index eb50553..357ad67 100644 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -12,7 +12,7 @@ use crate::{ traits::{FromBytes, KeyExchange, ToBytes}, tripledh::{NonceLen, TripleDH}, }, - keypair::{KeyPair, PublicKey}, + keypair::KeyPair, serialization::{i2osp, os2ip, serialize}, *, }; @@ -23,7 +23,6 @@ use alloc::vec::Vec; use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; use generic_array::typenum::Unsigned; -use generic_bytes::SizedBytes; use proptest::{collection::vec, prelude::*}; use rand::{rngs::OsRng, RngCore}; @@ -79,8 +78,8 @@ fn server_registration_roundtrip() { // Construct a mock envelope let mut mock_envelope_bytes = Vec::new(); - mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::to_usize()]); // empty nonce - // mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key + mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::USIZE]); // empty nonce + // mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key mock_envelope_bytes.extend_from_slice(&[0; MAC_SIZE]); // length-MAC_SIZE hmac let mock_client_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); @@ -157,7 +156,7 @@ fn registration_upload_roundtrip() { let mut nonce = [0u8; 32]; rng.fill_bytes(&mut nonce); - let mut masking_key = vec![0u8; ::OutputSize::to_usize()]; + let mut masking_key = vec![0u8; ::OutputSize::USIZE]; rng.fill_bytes(&mut masking_key); let (envelope, _, _) = @@ -182,7 +181,7 @@ fn credential_request_roundtrip() { let alpha_bytes = alpha.to_arr().to_vec(); let client_e_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); - let mut client_nonce = vec![0u8; NonceLen::to_usize()]; + let mut client_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let ke1m: Vec = [&client_nonce[..], &client_e_kp.public()].concat(); @@ -217,17 +216,14 @@ fn credential_response_roundtrip() { let mut masking_nonce = vec![0u8; 32]; rng.fill_bytes(&mut masking_nonce); - let mut masked_response = vec![ - 0u8; - as SizedBytes>::Len::to_usize() - + Envelope::::len() - ]; + let mut masked_response = + vec![0u8; ::ElemLen::USIZE + Envelope::::len()]; rng.fill_bytes(&mut masked_response); let server_e_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); let mut mac = [0u8; MAC_SIZE]; rng.fill_bytes(&mut mac); - let mut server_nonce = vec![0u8; NonceLen::to_usize()]; + let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let ke2m: Vec = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat(); @@ -280,7 +276,7 @@ fn client_login_roundtrip() { let sc = ::random_nonzero_scalar(&mut rng); let client_e_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); - let mut client_nonce = vec![0u8; NonceLen::to_usize()]; + let mut client_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let serialized_credential_request = b"serialized credential_request".to_vec(); @@ -304,7 +300,7 @@ fn ke1_message_roundtrip() { let mut rng = OsRng; let client_e_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); - let mut client_nonce = vec![0u8; NonceLen::to_usize()]; + let mut client_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let ke1m: Vec = [&client_nonce[..], &client_e_kp.public()].concat(); @@ -323,7 +319,7 @@ fn ke2_message_roundtrip() { let server_e_kp = KeyPair::<::OprfGroup>::generate_random(&mut rng); let mut mac = [0u8; MAC_SIZE]; rng.fill_bytes(&mut mac); - let mut server_nonce = vec![0u8; NonceLen::to_usize()]; + let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let ke2m: Vec = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat(); diff --git a/src/slow_hash.rs b/src/slow_hash.rs index bb666f2..b78756f 100644 --- a/src/slow_hash.rs +++ b/src/slow_hash.rs @@ -37,7 +37,7 @@ impl SlowHash for argon2::Argon2<'_> { input: GenericArray::OutputSize>, ) -> Result, InternalPakeError> { let params = argon2::Argon2::default(); - let mut output = alloc::vec![0u8; ::OutputSize::to_usize()]; + let mut output = alloc::vec![0u8; ::OutputSize::USIZE]; params .hash_password_into( argon2::Algorithm::Argon2id, diff --git a/src/tests/full_test.rs b/src/tests/full_test.rs index ad17387..e70826a 100644 --- a/src/tests/full_test.rs +++ b/src/tests/full_test.rs @@ -14,7 +14,6 @@ use alloc::vec; use alloc::vec::Vec; use core::slice::from_raw_parts; use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; -use generic_bytes::SizedBytes; use rand::rngs::OsRng; use serde_json::Value; use zeroize::Zeroize; @@ -149,7 +148,6 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters { } } -#[cfg(feature = "std")] fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String { let mut s = alloc::string::String::new(); s.push_str("{\n"); @@ -273,7 +271,6 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String { s } -#[cfg(feature = "std")] fn generate_parameters() -> TestVectorParameters { use crate::{group::Group, key_exchange::tripledh::NonceLen, keypair::KeyPair}; use generic_array::typenum::Unsigned; @@ -298,9 +295,9 @@ fn generate_parameters() -> TestVectorParameters { rng.fill_bytes(&mut masking_nonce); let mut envelope_nonce = [0u8; 32]; rng.fill_bytes(&mut envelope_nonce); - let mut client_nonce = vec![0u8; NonceLen::to_usize()]; + let mut client_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); - let mut server_nonce = vec![0u8; NonceLen::to_usize()]; + let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let fake_sk: Vec = fake_kp.private().to_vec(); @@ -448,7 +445,6 @@ fn generate_parameters() -> TestVectorParameters { } } -#[cfg(feature = "std")] #[test] fn generate_test_vectors() { let parameters = generate_parameters::(); diff --git a/src/tests/opaque_test_vectors.rs b/src/tests/opaque_test_vectors.rs index 42011f0..b91bc76 100644 --- a/src/tests/opaque_test_vectors.rs +++ b/src/tests/opaque_test_vectors.rs @@ -4,15 +4,14 @@ // LICENSE file in the root directory of this source tree. use crate::{ - ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, keypair::PrivateKey, - opaque::*, slow_hash::NoOpHash, tests::mock_rng::CycleRng, *, + ciphersuite::CipherSuite, errors::*, group::Group, key_exchange::tripledh::TripleDH, opaque::*, + slow_hash::NoOpHash, tests::mock_rng::CycleRng, *, }; use alloc::string::ToString; use alloc::vec::Vec; use alloc::{format, vec}; use curve25519_dalek::ristretto::RistrettoPoint; use generic_array::typenum::Unsigned; -use generic_bytes::SizedBytes; use serde_json::Value; // Tests @@ -755,7 +754,7 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameter dummy_private_key: parse_default!( values, "client_private_key", - vec![0u8; as SizedBytes>::Len::to_usize()] + vec![0u8; ::ScalarLen::USIZE] ), dummy_masking_key: parse_default!(values, "masking_key", vec![0u8; 64]), context: parse!(values, "Context"),