From 8ee35498eaf7813b82c1c696360b7ac85414151f Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 25 Jun 2025 00:17:29 +0200 Subject: [PATCH] Publicly Expose `trait KeyExchange` (#379) * Clean up types used in `trait KeyExchange` * Expose `trait KeyExchange` publicly --- src/ciphersuite.rs | 2 +- src/envelope.rs | 2 +- src/key_exchange/mod.rs | 431 +++++++++++++++++++++++++++- src/key_exchange/shared.rs | 28 +- src/key_exchange/sigma_i/message.rs | 42 +-- src/key_exchange/sigma_i/mod.rs | 64 ++--- src/key_exchange/sigma_i/shared.rs | 2 +- src/key_exchange/traits.rs | 402 -------------------------- src/key_exchange/tripledh.rs | 55 ++-- src/keypair.rs | 11 +- src/lib.rs | 2 +- src/messages.rs | 14 +- src/opaque.rs | 34 +-- src/serialization/tests.rs | 2 +- src/tests/full_test.rs | 2 +- src/tests/test_opaque_vectors.rs | 4 +- 16 files changed, 558 insertions(+), 539 deletions(-) delete mode 100644 src/key_exchange/traits.rs diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index c6699f3..9e1b722 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -18,7 +18,7 @@ use generic_array::ArrayLength; use crate::envelope::NonceLen; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::Group; -use crate::key_exchange::traits::KeyExchange; +use crate::key_exchange::KeyExchange; use crate::ksf::Ksf; use crate::opaque::MaskedResponseLen; diff --git a/src/envelope.rs b/src/envelope.rs index cbd1c23..c41d190 100644 --- a/src/envelope.rs +++ b/src/envelope.rs @@ -22,7 +22,7 @@ use crate::ciphersuite::{CipherSuite, KeGroup, OprfHash}; use crate::errors::{InternalError, ProtocolError}; use crate::hash::OutputSize; use crate::key_exchange::group::Group; -use crate::key_exchange::traits::SerializedIdentifiers; +use crate::key_exchange::SerializedIdentifiers; use crate::keypair::{KeyPair, PrivateKey, PublicKey}; use crate::opaque::Identifiers; use crate::serialization::{GenericArrayExt, SliceExt, UpdateExt}; diff --git a/src/key_exchange/mod.rs b/src/key_exchange/mod.rs index 5cd3eb9..6b16dd9 100644 --- a/src/key_exchange/mod.rs +++ b/src/key_exchange/mod.rs @@ -12,7 +12,434 @@ pub mod group; pub(crate) mod shared; pub mod sigma_i; -pub(crate) mod traits; pub mod tripledh; -pub use crate::key_exchange::traits::KeyExchange; +use core::iter; +use core::ops::Add; + +use derive_where::derive_where; +use digest::core_api::{BlockSizeUser, CoreProxy}; +use digest::Output; +use generic_array::sequence::Concat; +use generic_array::typenum::{IsLess, Le, NonZero, Sum, U2, U256}; +use generic_array::{ArrayLength, GenericArray}; +use rand::{CryptoRng, RngCore}; +use voprf::{BlindedElement, EvaluationElement}; +use zeroize::{Zeroize, ZeroizeOnDrop}; + +#[cfg(test)] +use crate::ciphersuite::KeHash; +use crate::ciphersuite::{CipherSuite, OprfGroup}; +use crate::errors::ProtocolError; +use crate::hash::{Hash, ProxyHash}; +use crate::key_exchange::group::Group; +use crate::key_exchange::shared::{NonceLen, STR_CONTEXT}; +use crate::keypair::{PrivateKey, PublicKey}; +use crate::opaque::{Identifiers, MaskedResponse, MaskedResponseLen}; +use crate::serialization::{i2osp, SliceExt}; + +/// The key exchange trait. +pub trait KeyExchange +where + ::Core: ProxyHash, + <::Core as BlockSizeUser>::BlockSize: IsLess, + Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, +{ + /// The group used for the key exchange. + type Group: Group; + /// The hash used for the key exchange. + type Hash: Hash; + + /// Client state. + type KE1State: ZeroizeOnDrop + Clone; + /// Server state. + type KE2State: ZeroizeOnDrop + Clone; + /// First message sent by the client. + type KE1Message: ZeroizeOnDrop + Clone; + /// Server state builder. + type KE2Builder<'a, CS: CipherSuite>: ZeroizeOnDrop + Clone; + /// Server data for the remote key interaction. + type KE2BuilderData<'a, CS: 'static + CipherSuite>; + /// Server remote key input. + type KE2BuilderInput; + /// Message sent by the server. + type KE2Message: ZeroizeOnDrop + Clone; + /// Second message sent by the client. + type KE3Message: ZeroizeOnDrop + Clone; + + /// Client generates [`KE1Message`](Self::KE1Message) and + /// [`KE1State`](Self::KE1State). + fn generate_ke1( + rng: &mut R, + ) -> Result, ProtocolError>; + + /// Server generates [`KE2Builder`](Self::KE2Builder). + fn ke2_builder<'a, CS: CipherSuite, R: RngCore + CryptoRng>( + rng: &mut R, + credential_request: SerializedCredentialRequest, + ke1_message: Self::KE1Message, + credential_response: SerializedCredentialResponse, + client_s_pk: PublicKey, + identifiers: SerializedIdentifiers<'a, Self::Group>, + context: SerializedContext<'a>, + ) -> Result, ProtocolError>; + + /// Server returns the data for the remote key interaction. + fn ke2_builder_data<'a, CS: CipherSuite>( + builder: &'a Self::KE2Builder<'_, CS>, + ) -> Self::KE2BuilderData<'a, CS>; + + /// Server generates the input without a remote key. + fn generate_ke2_input, R: CryptoRng + RngCore>( + builder: &Self::KE2Builder<'_, CS>, + rng: &mut R, + server_s_sk: &PrivateKey, + ) -> Self::KE2BuilderInput; + + /// Server generates [`KE2Message`](Self::KE2Message) and + /// [`KE2State`](Self::KE2State). + fn build_ke2>( + builder: Self::KE2Builder<'_, CS>, + input: Self::KE2BuilderInput, + ) -> Result, ProtocolError>; + + /// Client generates [`KE3Message`](Self::KE3Message) and the session key. + #[allow(clippy::too_many_arguments)] + fn generate_ke3, R: CryptoRng + RngCore>( + rng: &mut R, + credential_request: SerializedCredentialRequest, + ke1_message: Self::KE1Message, + credential_response: SerializedCredentialResponse, + ke1_state: &Self::KE1State, + ke2_message: Self::KE2Message, + server_s_pk: PublicKey, + client_s_sk: PrivateKey, + identifiers: SerializedIdentifiers<'_, Self::Group>, + context: SerializedContext<'_>, + ) -> Result, ProtocolError>; + + /// Server generates the session key. + fn finish_ke>( + ke2_state: &Self::KE2State, + ke3_message: Self::KE3Message, + identifiers: Identifiers<'_>, + context: SerializedContext<'_>, + ) -> Result, ProtocolError>; +} + +/// Serialized form of [`CredentialRequest`](crate::CredentialRequest). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "") +)] +#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize)] +pub struct SerializedCredentialRequest( + GenericArray as voprf::Group>::ElemLen>, +); + +impl SerializedCredentialRequest { + pub(crate) fn new(blinded_element: &BlindedElement) -> Self { + Self(blinded_element.serialize()) + } + + /// Returns the serialized form of + /// [`CredentialRequest`](crate::CredentialRequest) in multiple byte slices. + pub fn iter(&self) -> impl Clone + Iterator { + iter::once(self.0.as_slice()) + } + + /// Returns a [`SerializedCredentialRequest`] deserialized from the given + /// `bytes`. + pub fn deserialize_take(bytes: &mut &[u8]) -> Result { + Ok(Self(bytes.take_array("blinded element")?)) + } +} + +type SerializedCredentialRequestLen = as voprf::Group>::ElemLen; + +impl Serialize for SerializedCredentialRequest { + type Len = SerializedCredentialRequestLen; + + fn serialize(&self) -> GenericArray { + self.0.clone() + } +} + +/// Serialized form of [`CredentialResponse`](crate::CredentialResponse). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "") +)] +#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] +pub struct SerializedCredentialResponse { + evaluation_element: GenericArray as voprf::Group>::ElemLen>, + masking_nonce: GenericArray, + masked_response: MaskedResponse, +} + +impl SerializedCredentialResponse { + pub(crate) fn new( + evaluation_element: &EvaluationElement, + masking_nonce: GenericArray, + masked_response: MaskedResponse, + ) -> Self { + Self { + evaluation_element: evaluation_element.serialize(), + masking_nonce, + masked_response, + } + } + + /// Returns the serialized form of + /// [`CredentialResponse`](crate::CredentialResponse) in multiple byte + /// slices. + pub fn iter(&self) -> impl Clone + Iterator { + [self.evaluation_element.as_slice(), &self.masking_nonce] + .into_iter() + .chain(self.masked_response.iter()) + } + + /// Returns a [`SerializedCredentialRequest`] deserialized from the given + /// `bytes`. + pub fn deserialize_take(input: &mut &[u8]) -> Result { + Ok(Self { + evaluation_element: input.take_array("evaluation element")?, + masking_nonce: input.take_array("masking nonce")?, + masked_response: MaskedResponse::deserialize_take(input)?, + }) + } +} + +type SerializedCredentialResponseLen = + Sum as voprf::Group>::ElemLen, NonceLen>, MaskedResponseLen>; + +impl Serialize for SerializedCredentialResponse +where + as voprf::Group>::ElemLen: Add, + Sum< as voprf::Group>::ElemLen, NonceLen>: + ArrayLength + Add>, + SerializedCredentialResponseLen: ArrayLength, +{ + type Len = SerializedCredentialResponseLen; + + fn serialize(&self) -> GenericArray { + self.evaluation_element + .clone() + .concat(self.masking_nonce) + .concat(self.masked_response.serialize()) + } +} + +/// Serialized form of a `context` given in +/// [`ClientLoginFinishParameters`](crate::ClientLoginFinishParameters) or +/// [`ServerLoginParameters`](crate::ServerLoginParameters). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "") +)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] +pub struct SerializedContext<'a> { + length: GenericArray, + #[zeroize(skip)] + context: &'a [u8], +} + +impl<'a> SerializedContext<'a> { + pub(crate) fn from(context: Option<&'a [u8]>) -> Result { + let context = context.unwrap_or(&[]); + + Ok(Self { + length: i2osp::(context.len())?, + context, + }) + } + + /// Returns the serialized form of `context` in multiple byte slices. + pub fn iter(&self) -> impl Clone + Iterator { + iter::once(STR_CONTEXT).chain([self.length.as_slice(), self.context]) + } +} + +/// Serialized form of [`Identifiers`](crate::Identifiers). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound(deserialize = "'de: 'a", serialize = "")) +)] +#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] +pub struct SerializedIdentifiers<'a, G: Group> { + /// Client identifiers. + pub client: SerializedIdentifier<'a, G>, + /// Server identifiers. + pub server: SerializedIdentifier<'a, G>, +} + +/// Serialized form of a single identifier from +/// [`Identifiers`](crate::Identifiers). +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound(deserialize = "'de: 'a", serialize = "")) +)] +#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] +pub struct SerializedIdentifier<'a, G: Group> { + length: GenericArray, + identifier: Identifier<'a, G>, +} + +#[cfg_attr( + feature = "serde", + derive(serde::Deserialize, serde::Serialize), + serde(bound = "") +)] +#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] +enum Identifier<'a, G: Group> { + Owned(GenericArray), + #[derive_where(skip_inner(Zeroize))] + Borrowed(&'a [u8]), +} + +impl<'a, G: Group> SerializedIdentifiers<'a, G> { + pub(crate) fn from_identifiers( + ids: Identifiers<'a>, + client_s_pk: GenericArray, + server_s_pk: GenericArray, + ) -> Result { + let client = SerializedIdentifier::from_identifier(ids.client, client_s_pk)?; + let server = SerializedIdentifier::from_identifier(ids.server, server_s_pk)?; + + Ok(Self { client, server }) + } +} + +impl<'a, G: Group> SerializedIdentifier<'a, G> { + /// Creates a [`SerializedIdentifier`] an identifier or the corresponding + /// static public key. + pub fn from_identifier( + id: Option<&'a [u8]>, + s_pk: GenericArray, + ) -> Result { + if let Some(id) = id { + Ok(SerializedIdentifier { + length: i2osp::(id.len())?, + identifier: Identifier::Borrowed(id), + }) + } else { + Ok(SerializedIdentifier { + length: i2osp::(s_pk.len())?, + identifier: Identifier::Owned(s_pk), + }) + } + } + + /// Returns the serialized form of an identifier in multiple byte slices. + pub fn iter(&self) -> impl Clone + Iterator { + [self.length.as_slice()] + .into_iter() + .chain(match &self.identifier { + Identifier::Owned(bytes) => [bytes.as_slice()], + Identifier::Borrowed(bytes) => [*bytes], + }) + } +} + +/// Deserialization trait for key exchange types. +pub trait Deserialize: Sized { + /// Deserialize [`Self`] from the given `bytes`. + /// + /// The deserialized bytes must be taken from `bytes`. + fn deserialize_take(bytes: &mut &[u8]) -> Result; +} + +/// Serialization trait for key exchange types. +pub trait Serialize { + /// The length of the serialized types. + type Len: ArrayLength; + + /// Serialize [`Self`] to a fixed-length byte array. + fn serialize(&self) -> GenericArray; +} + +/// Result type of [`KeyExchange::generate_ke1()`]. +pub struct GenerateKe1Result { + /// The client state. + pub state: KE::KE1State, + /// The first client message. + pub message: KE::KE1Message, +} + +/// Result type of [`KeyExchange::build_ke2()`]. +pub struct GenerateKe2Result { + /// The server state. + pub state: ::KE2State, + /// The server message. + pub message: ::KE2Message, + #[cfg(test)] + pub(crate) handshake_secret: Output>, + #[cfg(test)] + pub(crate) km2: Output>, +} + +/// Result type of [`KeyExchange::generate_ke3()`]. +pub struct GenerateKe3Result { + /// The session key. + pub session_key: Output, + /// The second client message. + pub message: KE::KE3Message, + #[cfg(test)] + pub(crate) handshake_secret: Output, + #[cfg(test)] + pub(crate) km3: Output, +} + +pub(crate) type Ke1StateLen = + <::KE1State as Serialize>::Len; +pub(crate) type Ke1MessageLen = + <::KE1Message as Serialize>::Len; +pub(crate) type Ke2StateLen = + <::KE2State as Serialize>::Len; +pub(crate) type Ke2MessageLen = + <::KE2Message as Serialize>::Len; +pub(crate) type Ke3MessageLen = + <::KE3Message as Serialize>::Len; + +////////////////////////// +// Test Implementations // +//===================== // +////////////////////////// + +#[cfg(test)] +use crate::serialization::AssertZeroized; + +#[cfg(test)] +impl AssertZeroized for SerializedCredentialRequest { + fn assert_zeroized(&self) { + let Self(blinded_element) = self; + + for byte in blinded_element.iter() { + assert_eq!(byte, &0); + } + } +} + +#[cfg(test)] +impl AssertZeroized for SerializedCredentialResponse { + fn assert_zeroized(&self) { + let Self { + evaluation_element, + masking_nonce, + masked_response, + } = self; + + for byte in evaluation_element + .iter() + .chain(masking_nonce) + .chain(masked_response.iter().flatten()) + { + assert_eq!(byte, &0); + } + } +} diff --git a/src/key_exchange/shared.rs b/src/key_exchange/shared.rs index ed1dd26..d730683 100644 --- a/src/key_exchange/shared.rs +++ b/src/key_exchange/shared.rs @@ -17,14 +17,14 @@ use generic_array::{ArrayLength, GenericArray}; use hkdf::{Hkdf, HkdfExtract}; use rand::{CryptoRng, RngCore}; +use super::{ + Deserialize, GenerateKe1Result, KeyExchange, Serialize, SerializedContext, + SerializedCredentialRequest, SerializedCredentialResponse, SerializedIdentifiers, +}; use crate::ciphersuite::{CipherSuite, KeGroup, KeHash}; use crate::errors::{InternalError, ProtocolError}; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::Group; -use crate::key_exchange::traits::{ - CredentialRequestParts, CredentialResponseParts, Deserialize, Serialize, SerializedContext, - SerializedIdentifiers, -}; use crate::keypair::{KeyPair, PrivateKey, PublicKey}; use crate::serialization::{i2osp, SliceExt, UpdateExt}; @@ -100,9 +100,13 @@ pub(super) struct DerivedKeys { // Helper functions -pub(super) fn generate_ke1( +pub(super) fn generate_ke1< + R: RngCore + CryptoRng, + KE: KeyExchange, KE1Message = Ke1Message>, + G: Group, +>( rng: &mut R, -) -> Result<(Ke1State, Ke1Message), ProtocolError> { +) -> Result, ProtocolError> { let client_e_kp = KeyPair::::derive_random(rng); let client_nonce = generate_nonce::(rng); @@ -111,13 +115,13 @@ pub(super) fn generate_ke1( client_e_pk: client_e_kp.public().clone(), }; - Ok(( - Ke1State { + Ok(GenerateKe1Result { + state: Ke1State { client_e_sk: client_e_kp.private().clone(), client_nonce, }, - ke1_message, - )) + message: ke1_message, + }) } // Generate a random nonce up to NonceLen::USIZE bytes. @@ -130,9 +134,9 @@ pub(super) fn generate_nonce(rng: &mut R) -> GenericArra pub(super) fn transcript( context: &SerializedContext<'_>, identifiers: &SerializedIdentifiers<'_, KeGroup>, - credential_request: &CredentialRequestParts, + credential_request: &SerializedCredentialRequest, ke1_message: &Ke1MessageIter, - credential_response: &CredentialResponseParts, + credential_response: &SerializedCredentialResponse, server_nonce: GenericArray, server_e_pk: &GenericArray, ) -> KeHash { diff --git a/src/key_exchange/sigma_i/message.rs b/src/key_exchange/sigma_i/message.rs index 4a167ee..a9bdcf2 100644 --- a/src/key_exchange/sigma_i/message.rs +++ b/src/key_exchange/sigma_i/message.rs @@ -20,10 +20,10 @@ use crate::errors::ProtocolError; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::{Ke1MessageIter, Ke1MessageIterLen, NonceLen}; -use crate::key_exchange::traits::{ - CredentialRequestParts, CredentialRequestPartsLen, CredentialResponseParts, - CredentialResponsePartsLen, Deserialize, Serialize, SerializedContext, SerializedIdentifier, - SerializedIdentifiers, +use crate::key_exchange::{ + Deserialize, Serialize, SerializedContext, SerializedCredentialRequest, + SerializedCredentialRequestLen, SerializedCredentialResponse, SerializedCredentialResponseLen, + SerializedIdentifier, SerializedIdentifiers, }; use crate::opaque::MaskedResponseLen; use crate::serialization::{SliceExt, UpdateExt}; @@ -99,9 +99,9 @@ pub struct MessageBuilder<'a, CS: CipherSuite> { )] #[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize, ZeroizeOnDrop)] pub struct CachedMessage { - pub(super) credential_request: CredentialRequestParts, + pub(super) credential_request: SerializedCredentialRequest, pub(super) ke1_message: Ke1MessageIter, - pub(super) credential_response: CredentialResponseParts, + pub(super) credential_response: SerializedCredentialResponse, pub(super) server_nonce: GenericArray, pub(super) server_e_pk: GenericArray, pub(super) server_mac: Output>, @@ -231,9 +231,9 @@ impl<'a, CS: CipherSuite> MessageBuilder<'a, CS> { impl Deserialize for CachedMessage { fn deserialize_take(input: &mut &[u8]) -> Result { Ok(Self { - credential_request: CredentialRequestParts::deserialize_take(input)?, + credential_request: SerializedCredentialRequest::deserialize_take(input)?, ke1_message: Ke1MessageIter::deserialize_take(input)?, - credential_response: CredentialResponseParts::deserialize_take(input)?, + credential_response: SerializedCredentialResponse::deserialize_take(input)?, server_nonce: input.take_array("server nonce")?, server_e_pk: input.take_array("serialized server ephemeral key")?, server_mac: input.take_array("server mac")?, @@ -246,8 +246,8 @@ type CachedMessageLen = Sum< Sum< Sum< Sum< - Sum, Ke1MessageIterLen>, - CredentialResponsePartsLen, + Sum, Ke1MessageIterLen>, + SerializedCredentialResponseLen, >, NonceLen, >, @@ -258,23 +258,25 @@ type CachedMessageLen = Sum< impl Serialize for CachedMessage where - CredentialRequestPartsLen: ArrayLength + Add>, - Sum, Ke1MessageIterLen>: - ArrayLength + Add>, - Sum, Ke1MessageIterLen>, CredentialResponsePartsLen>: - ArrayLength + Add, + SerializedCredentialRequestLen: ArrayLength + Add>, + Sum, Ke1MessageIterLen>: + ArrayLength + Add>, + Sum< + Sum, Ke1MessageIterLen>, + SerializedCredentialResponseLen, + >: ArrayLength + Add, Sum< Sum< - Sum, Ke1MessageIterLen>, - CredentialResponsePartsLen, + Sum, Ke1MessageIterLen>, + SerializedCredentialResponseLen, >, NonceLen, >: ArrayLength + Add, Sum< Sum< Sum< - Sum, Ke1MessageIterLen>, - CredentialResponsePartsLen, + Sum, Ke1MessageIterLen>, + SerializedCredentialResponseLen, >, NonceLen, >, @@ -288,7 +290,7 @@ where as voprf::Group>::ElemLen: Add, Sum< as voprf::Group>::ElemLen, NonceLen>: ArrayLength + Add>, - CredentialResponsePartsLen: ArrayLength, + SerializedCredentialResponseLen: ArrayLength, { type Len = CachedMessageLen; diff --git a/src/key_exchange/sigma_i/mod.rs b/src/key_exchange/sigma_i/mod.rs index ca29d8d..62cf203 100644 --- a/src/key_exchange/sigma_i/mod.rs +++ b/src/key_exchange/sigma_i/mod.rs @@ -35,6 +35,11 @@ use zeroize::Zeroize; use self::message::Role; pub use self::message::{CachedMessage, HashOutput, Message, MessageBuilder, VerifyMessage}; +use super::{ + Deserialize, GenerateKe1Result, GenerateKe2Result, GenerateKe3Result, KeyExchange, Serialize, + SerializedContext, SerializedCredentialRequest, SerializedCredentialResponse, + SerializedIdentifier, SerializedIdentifiers, +}; use crate::ciphersuite::{CipherSuite, KeGroup, KeHash}; use crate::envelope::NonceLen; use crate::errors::{InternalError, ProtocolError}; @@ -42,11 +47,6 @@ use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::Group; use crate::key_exchange::shared::{derive_keys, generate_ke1, generate_nonce, transcript}; pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State}; -use crate::key_exchange::traits::{ - CredentialRequestParts, CredentialResponseParts, Deserialize, GenerateKe2Result, - GenerateKe3Result, KeyExchange, Sealed, Serialize, SerializedContext, SerializedIdentifier, - SerializedIdentifiers, -}; use crate::keypair::{KeyPair, PrivateKey, PublicKey}; use crate::opaque::Identifiers; use crate::serialization::{SliceExt, UpdateExt}; @@ -156,9 +156,9 @@ pub struct Ke2Builder<'a, CS: CipherSuite, KE: Group> { expected_mac: Output>, session_key: Output>, #[cfg(test)] - km3: Output>, - #[cfg(test)] handshake_secret: Output>, + #[cfg(test)] + km2: Output>, } /// The server state produced after the second key exchange message @@ -239,15 +239,15 @@ where fn generate_ke1( rng: &mut R, - ) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> { + ) -> Result, ProtocolError> { generate_ke1(rng) } fn ke2_builder<'a, CS: CipherSuite, R: RngCore + CryptoRng>( rng: &mut R, - credential_request: CredentialRequestParts, + credential_request: SerializedCredentialRequest, ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, + credential_response: SerializedCredentialResponse, client_s_pk: PublicKey, identifiers: SerializedIdentifiers<'a, KeGroup>, context: SerializedContext<'a>, @@ -309,9 +309,9 @@ where expected_mac: client_mac, session_key: derived_keys.session_key, #[cfg(test)] - km3: derived_keys.km3, - #[cfg(test)] handshake_secret: derived_keys.handshake_secret, + #[cfg(test)] + km2: derived_keys.km2, }) } @@ -333,33 +333,33 @@ where builder: Self::KE2Builder<'_, CS>, input: Self::KE2BuilderInput, ) -> Result, ProtocolError> { - Ok(( - Ke2State { + Ok(GenerateKe2Result { + state: Ke2State { client_s_pk: builder.client_s_pk.clone(), session_key: builder.session_key.clone(), verify_state: input.1, expected_mac: builder.expected_mac.clone(), }, - Ke2Message { + message: Ke2Message { server_nonce: builder.server_nonce, server_e_pk: builder.server_e_pk.clone(), signature: input.0, mac: builder.transcript.cache.server_mac.clone(), }, #[cfg(test)] - builder.handshake_secret.clone(), + handshake_secret: builder.handshake_secret.clone(), #[cfg(test)] - builder.km3.clone(), - )) + km2: builder.km2.clone(), + }) } fn generate_ke3, R: CryptoRng + RngCore>( rng: &mut R, - credential_request: CredentialRequestParts, + credential_request: SerializedCredentialRequest, ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, - ke2_message: Self::KE2Message, + credential_response: SerializedCredentialResponse, ke1_state: &Self::KE1State, + ke2_message: Self::KE2Message, server_s_pk: PublicKey, client_s_sk: PrivateKey, identifiers: SerializedIdentifiers<'_, KeGroup>, @@ -427,22 +427,22 @@ where &ke2_message.signature, )?; - Ok(( - derived_keys.session_key, - Ke3Message { + Ok(GenerateKe3Result { + session_key: derived_keys.session_key, + message: Ke3Message { signature, mac: client_mac, }, #[cfg(test)] - derived_keys.handshake_secret, + handshake_secret: derived_keys.handshake_secret, #[cfg(test)] - derived_keys.km3, - )) + km3: derived_keys.km3, + }) } fn finish_ke>( - ke3_message: Self::KE3Message, ke2_state: &Self::KE2State, + ke3_message: Self::KE3Message, identifiers: Identifiers<'_>, context: SerializedContext<'_>, ) -> Result, ProtocolError> { @@ -468,14 +468,6 @@ where } } -impl Sealed for SigmaI -where - KEH::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ -} - impl Deserialize for Ke2State where SIG::VerifyState: Deserialize, diff --git a/src/key_exchange/sigma_i/shared.rs b/src/key_exchange/sigma_i/shared.rs index e576dd4..f462090 100644 --- a/src/key_exchange/sigma_i/shared.rs +++ b/src/key_exchange/sigma_i/shared.rs @@ -11,7 +11,7 @@ use digest::{Output, OutputSizeUser}; use generic_array::{ArrayLength, GenericArray}; use crate::errors::ProtocolError; -use crate::key_exchange::traits::{Deserialize, Serialize}; +use crate::key_exchange::{Deserialize, Serialize}; use crate::serialization::SliceExt; /// Pre-hash of the message to be verified. diff --git a/src/key_exchange/traits.rs b/src/key_exchange/traits.rs deleted file mode 100644 index d36a2f5..0000000 --- a/src/key_exchange/traits.rs +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (c) Meta Platforms, Inc. and affiliates. -// -// This source code is dual-licensed under either the MIT license found in the -// LICENSE-MIT file in the root directory of this source tree or the Apache -// License, Version 2.0 found in the LICENSE-APACHE file in the root directory -// of this source tree. You may select, at your option, one of the above-listed -// licenses. - -use core::iter; -use core::ops::Add; - -use derive_where::derive_where; -use digest::core_api::{BlockSizeUser, CoreProxy}; -use digest::Output; -use generic_array::sequence::Concat; -use generic_array::typenum::{IsLess, Le, NonZero, Sum, U2, U256}; -use generic_array::{ArrayLength, GenericArray}; -use rand::{CryptoRng, RngCore}; -use voprf::{BlindedElement, EvaluationElement}; -use zeroize::{Zeroize, ZeroizeOnDrop}; - -#[cfg(test)] -use crate::ciphersuite::KeHash; -use crate::ciphersuite::{CipherSuite, OprfGroup}; -use crate::errors::ProtocolError; -use crate::hash::{Hash, ProxyHash}; -use crate::key_exchange::group::Group; -use crate::key_exchange::shared::{NonceLen, STR_CONTEXT}; -use crate::keypair::{PrivateKey, PublicKey}; -use crate::opaque::{Identifiers, MaskedResponse, MaskedResponseLen}; -use crate::serialization::{i2osp, SliceExt}; - -/// The key exchange trait. This is only exposed so users can use it in generics -/// and qualified bounds. -#[allow(private_bounds)] -pub trait KeyExchange: Sealed -where - ::Core: ProxyHash, - <::Core as BlockSizeUser>::BlockSize: IsLess, - Le<<::Core as BlockSizeUser>::BlockSize, U256>: NonZero, -{ - /// The group used for the key exchange. - type Group: Group; - /// The has used for the key exchange. - type Hash: Hash; - - #[doc(hidden)] - type KE1State: ZeroizeOnDrop + Clone; - #[doc(hidden)] - type KE2State: ZeroizeOnDrop + Clone; - #[doc(hidden)] - type KE1Message: ZeroizeOnDrop + Clone; - #[doc(hidden)] - type KE2Builder<'a, CS: CipherSuite>: ZeroizeOnDrop + Clone; - #[doc(hidden)] - type KE2BuilderData<'a, CS: 'static + CipherSuite>; - #[doc(hidden)] - type KE2BuilderInput; - #[doc(hidden)] - type KE2Message: ZeroizeOnDrop + Clone; - #[doc(hidden)] - type KE3Message: ZeroizeOnDrop + Clone; - - #[doc(hidden)] - fn generate_ke1( - rng: &mut R, - ) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>; - - #[doc(hidden)] - fn ke2_builder<'a, CS: CipherSuite, R: RngCore + CryptoRng>( - rng: &mut R, - credential_request: CredentialRequestParts, - ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, - client_s_pk: PublicKey, - identifiers: SerializedIdentifiers<'a, Self::Group>, - context: SerializedContext<'a>, - ) -> Result, ProtocolError>; - - #[doc(hidden)] - fn ke2_builder_data<'a, CS: CipherSuite>( - builder: &'a Self::KE2Builder<'_, CS>, - ) -> Self::KE2BuilderData<'a, CS>; - - #[doc(hidden)] - fn generate_ke2_input, R: CryptoRng + RngCore>( - builder: &Self::KE2Builder<'_, CS>, - rng: &mut R, - server_s_sk: &PrivateKey, - ) -> Self::KE2BuilderInput; - - #[doc(hidden)] - fn build_ke2>( - builder: Self::KE2Builder<'_, CS>, - input: Self::KE2BuilderInput, - ) -> Result, ProtocolError>; - - #[doc(hidden)] - #[allow(clippy::too_many_arguments)] - fn generate_ke3, R: CryptoRng + RngCore>( - rng: &mut R, - credential_request: CredentialRequestParts, - ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, - ke2_message: Self::KE2Message, - ke1_state: &Self::KE1State, - server_s_pk: PublicKey, - client_s_sk: PrivateKey, - identifiers: SerializedIdentifiers<'_, Self::Group>, - context: SerializedContext<'_>, - ) -> Result, ProtocolError>; - - #[doc(hidden)] - fn finish_ke>( - ke3_message: Self::KE3Message, - ke2_state: &Self::KE2State, - identifiers: Identifiers<'_>, - context: SerializedContext<'_>, - ) -> Result, ProtocolError>; -} - -pub(super) trait Sealed {} - -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound = "") -)] -#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize)] -pub struct CredentialRequestParts( - GenericArray as voprf::Group>::ElemLen>, -); - -impl CredentialRequestParts { - pub(crate) fn new(blinded_element: &BlindedElement) -> Self { - Self(blinded_element.serialize()) - } - - pub fn iter(&self) -> impl Clone + Iterator { - iter::once(self.0.as_slice()) - } - - pub fn deserialize_take(input: &mut &[u8]) -> Result { - Ok(Self(input.take_array("blinded element")?)) - } -} - -pub type CredentialRequestPartsLen = as voprf::Group>::ElemLen; - -impl Serialize for CredentialRequestParts { - type Len = CredentialRequestPartsLen; - - fn serialize(&self) -> GenericArray { - self.0.clone() - } -} - -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound = "") -)] -#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] -pub struct CredentialResponseParts { - evaluation_element: GenericArray as voprf::Group>::ElemLen>, - masking_nonce: GenericArray, - masked_response: MaskedResponse, -} - -impl CredentialResponseParts { - pub(crate) fn new( - evaluation_element: &EvaluationElement, - masking_nonce: GenericArray, - masked_response: MaskedResponse, - ) -> Self { - Self { - evaluation_element: evaluation_element.serialize(), - masking_nonce, - masked_response, - } - } - - pub fn iter(&self) -> impl Clone + Iterator { - [self.evaluation_element.as_slice(), &self.masking_nonce] - .into_iter() - .chain(self.masked_response.iter()) - } - - pub fn deserialize_take(input: &mut &[u8]) -> Result { - Ok(Self { - evaluation_element: input.take_array("evaluation element")?, - masking_nonce: input.take_array("masking nonce")?, - masked_response: MaskedResponse::deserialize_take(input)?, - }) - } -} - -pub type CredentialResponsePartsLen = - Sum as voprf::Group>::ElemLen, NonceLen>, MaskedResponseLen>; - -impl Serialize for CredentialResponseParts -where - as voprf::Group>::ElemLen: Add, - Sum< as voprf::Group>::ElemLen, NonceLen>: - ArrayLength + Add>, - CredentialResponsePartsLen: ArrayLength, -{ - type Len = CredentialResponsePartsLen; - - fn serialize(&self) -> GenericArray { - self.evaluation_element - .clone() - .concat(self.masking_nonce) - .concat(self.masked_response.serialize()) - } -} - -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound = "") -)] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] -pub struct SerializedContext<'a> { - length: GenericArray, - #[zeroize(skip)] - context: &'a [u8], -} - -impl<'a> SerializedContext<'a> { - pub(crate) fn from(context: Option<&'a [u8]>) -> Result { - let context = context.unwrap_or(&[]); - - Ok(Self { - length: i2osp::(context.len())?, - context, - }) - } - - pub fn iter(&self) -> impl Clone + Iterator { - iter::once(STR_CONTEXT).chain([self.length.as_slice(), self.context]) - } -} - -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound(deserialize = "'de: 'a", serialize = "")) -)] -#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] -pub struct SerializedIdentifiers<'a, G: Group> { - pub client: SerializedIdentifier<'a, G>, - pub server: SerializedIdentifier<'a, G>, -} - -/// Computes `I2OSP(len(input), max_bytes) || input` and helps hold output -/// without allocation. -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound(deserialize = "'de: 'a", serialize = "")) -)] -#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] -pub struct SerializedIdentifier<'a, G: Group> { - length: GenericArray, - identifier: Identifier<'a, G>, -} - -#[cfg_attr( - feature = "serde", - derive(serde::Deserialize, serde::Serialize), - serde(bound = "") -)] -#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)] -enum Identifier<'a, G: Group> { - Owned(GenericArray), - #[derive_where(skip_inner(Zeroize))] - Borrowed(&'a [u8]), -} - -impl<'a, G: Group> SerializedIdentifiers<'a, G> { - pub(crate) fn from_identifiers( - ids: Identifiers<'a>, - client_s_pk: GenericArray, - server_s_pk: GenericArray, - ) -> Result { - let client = SerializedIdentifier::from_identifier(ids.client, client_s_pk)?; - let server = SerializedIdentifier::from_identifier(ids.server, server_s_pk)?; - - Ok(Self { client, server }) - } -} - -impl<'a, G: Group> SerializedIdentifier<'a, G> { - pub fn from_identifier( - id: Option<&'a [u8]>, - s_pk: GenericArray, - ) -> Result { - if let Some(id) = id { - Ok(SerializedIdentifier { - length: i2osp::(id.len())?, - identifier: Identifier::Borrowed(id), - }) - } else { - Ok(SerializedIdentifier { - length: i2osp::(s_pk.len())?, - identifier: Identifier::Owned(s_pk), - }) - } - } - - pub(crate) fn iter(&self) -> impl Clone + Iterator { - // Some magic to make it output the same type in all branches. - [self.length.as_slice()] - .into_iter() - .chain(match &self.identifier { - Identifier::Owned(bytes) => [bytes.as_slice()], - Identifier::Borrowed(bytes) => [*bytes], - }) - } -} - -pub trait Deserialize: Sized { - fn deserialize_take(input: &mut &[u8]) -> Result; -} - -pub trait Serialize { - type Len: ArrayLength; - - fn serialize(&self) -> GenericArray; -} - -#[cfg(not(test))] -pub type GenerateKe2Result = ( - ::KE2State, - ::KE2Message, -); -#[cfg(test)] -pub type GenerateKe2Result = ( - ::KE2State, - ::KE2Message, - Output>, - Output>, -); -#[cfg(not(test))] -pub type GenerateKe3Result = (Output, K::KE3Message); -#[cfg(test)] -pub type GenerateKe3Result = ( - Output, - K::KE3Message, - Output, - Output, -); - -pub type Ke1StateLen = - <::KE1State as Serialize>::Len; -pub type Ke1MessageLen = - <::KE1Message as Serialize>::Len; -pub type Ke2StateLen = - <::KE2State as Serialize>::Len; -pub type Ke2MessageLen = - <::KE2Message as Serialize>::Len; -pub type Ke3MessageLen = - <::KE3Message as Serialize>::Len; - -////////////////////////// -// Test Implementations // -//===================== // -////////////////////////// - -#[cfg(test)] -use crate::serialization::AssertZeroized; - -#[cfg(test)] -impl AssertZeroized for CredentialRequestParts { - fn assert_zeroized(&self) { - let Self(blinded_element) = self; - - for byte in blinded_element.iter() { - assert_eq!(byte, &0); - } - } -} - -#[cfg(test)] -impl AssertZeroized for CredentialResponseParts { - fn assert_zeroized(&self) { - let Self { - evaluation_element, - masking_nonce, - masked_response, - } = self; - - for byte in evaluation_element - .iter() - .chain(masking_nonce) - .chain(masked_response.iter().flatten()) - { - assert_eq!(byte, &0); - } - } -} diff --git a/src/key_exchange/tripledh.rs b/src/key_exchange/tripledh.rs index 9624d7b..673ef07 100644 --- a/src/key_exchange/tripledh.rs +++ b/src/key_exchange/tripledh.rs @@ -22,16 +22,17 @@ use rand::{CryptoRng, RngCore}; use subtle::{ConstantTimeEq, CtOption}; use zeroize::{Zeroize, ZeroizeOnDrop}; +use super::{ + Deserialize, GenerateKe1Result, GenerateKe2Result, GenerateKe3Result, KeyExchange, Serialize, + SerializedContext, SerializedCredentialRequest, SerializedCredentialResponse, + SerializedIdentifiers, +}; use crate::ciphersuite::{CipherSuite, KeGroup}; use crate::errors::{InternalError, ProtocolError}; use crate::hash::{Hash, OutputSize, ProxyHash}; use crate::key_exchange::group::Group; use crate::key_exchange::shared::{self, NonceLen}; pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State}; -use crate::key_exchange::traits::{ - CredentialRequestParts, CredentialResponseParts, Deserialize, GenerateKe2Result, - GenerateKe3Result, KeyExchange, Sealed, Serialize, SerializedContext, SerializedIdentifiers, -}; use crate::keypair::{KeyPair, PrivateKey, PublicKey}; use crate::opaque::Identifiers; use crate::serialization::SliceExt; @@ -151,15 +152,15 @@ where fn generate_ke1( rng: &mut R, - ) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> { + ) -> Result, ProtocolError> { shared::generate_ke1(rng) } fn ke2_builder<'a, CS: CipherSuite, R: RngCore + CryptoRng>( rng: &mut R, - credential_request: CredentialRequestParts, + credential_request: SerializedCredentialRequest, ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, + credential_response: SerializedCredentialResponse, client_s_pk: PublicKey, identifiers: SerializedIdentifiers<'_, KeGroup>, context: SerializedContext<'a>, @@ -240,30 +241,30 @@ where ); let expected_mac = mac_hasher.finalize().into_bytes(); - Ok(( - Ke2State { + Ok(GenerateKe2Result { + state: Ke2State { session_key: derived_keys.session_key, expected_mac, }, - Ke2Message { + message: Ke2Message { server_nonce: builder.server_nonce, server_e_pk: builder.server_e_pk.clone(), mac, }, #[cfg(test)] - derived_keys.handshake_secret, + handshake_secret: derived_keys.handshake_secret, #[cfg(test)] - derived_keys.km2, - )) + km2: derived_keys.km2, + }) } fn generate_ke3, R: CryptoRng + RngCore>( _: &mut R, - credential_request: CredentialRequestParts, + credential_request: SerializedCredentialRequest, ke1_message: Self::KE1Message, - credential_response: CredentialResponseParts, - ke2_message: Self::KE2Message, + credential_response: SerializedCredentialResponse, ke1_state: &Self::KE1State, + ke2_message: Self::KE2Message, server_s_pk: PublicKey, client_s_sk: PrivateKey, identifiers: SerializedIdentifiers<'_, KeGroup>, @@ -309,21 +310,21 @@ where Hmac::::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?; Mac::update(&mut client_mac, &transcript_hasher.finalize()); - Ok(( - derived_keys.session_key, - Ke3Message { + Ok(GenerateKe3Result { + session_key: derived_keys.session_key, + message: Ke3Message { mac: client_mac.finalize().into_bytes(), }, #[cfg(test)] - derived_keys.handshake_secret, + handshake_secret: derived_keys.handshake_secret, #[cfg(test)] - derived_keys.km3, - )) + km3: derived_keys.km3, + }) } fn finish_ke( - ke3_message: Self::KE3Message, ke2_state: &Self::KE2State, + ke3_message: Self::KE3Message, _: Identifiers<'_>, _: SerializedContext<'_>, ) -> Result, ProtocolError> { @@ -336,14 +337,6 @@ where } } -impl Sealed for TripleDh -where - H::Core: ProxyHash, - ::BlockSize: IsLess, - Le<::BlockSize, U256>: NonZero, -{ -} - //////////////////////////////////////////////// // Trait Implementations // // ========================================== // diff --git a/src/keypair.rs b/src/keypair.rs index db7fdfe..353b915 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -97,7 +97,8 @@ impl PrivateKey { PublicKey(G::public_key(self.0)) } - pub(crate) fn serialize(&self) -> GenericArray { + /// Serializes this private key to a fixed-length byte array. + pub fn serialize(&self) -> GenericArray { G::serialize_sk(self.0) } @@ -149,8 +150,10 @@ pub trait PrivateKeySerialization: Clone { fn serialize_key_pair(key_pair: &KeyPair) -> GenericArray; /// Deserialization from bytes + /// + /// The deserialized bytes must be taken from `bytes`. fn deserialize_take_key_pair( - input: &mut &[u8], + bytes: &mut &[u8], ) -> Result, ProtocolError>; } @@ -281,7 +284,9 @@ pub trait OprfSeedSerialization: Sized { fn serialize(&self) -> GenericArray; /// Deserialization from bytes - fn deserialize_take(input: &mut &[u8]) -> Result>; + /// + /// The deserialized bytes must be taken from `bytes`. + fn deserialize_take(bytes: &mut &[u8]) -> Result>; } impl OprfSeedSerialization for OprfSeed { diff --git a/src/lib.rs b/src/lib.rs index 0667ca5..d66e604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1349,9 +1349,9 @@ mod tests; // Exports -pub use ciphersuite::CipherSuite; pub use rand; +pub use crate::ciphersuite::CipherSuite; #[cfg(feature = "curve25519")] pub use crate::key_exchange::group::curve25519::Curve25519; #[cfg(feature = "ed25519")] diff --git a/src/messages.rs b/src/messages.rs index 8bb5d8a..74b6c71 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -25,9 +25,9 @@ use crate::errors::ProtocolError; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; -use crate::key_exchange::traits::{ - CredentialRequestParts, CredentialResponseParts, Deserialize, Ke1MessageLen, Ke2MessageLen, - Ke3MessageLen, KeyExchange, Serialize, +use crate::key_exchange::{ + Deserialize, Ke1MessageLen, Ke2MessageLen, Ke3MessageLen, KeyExchange, Serialize, + SerializedCredentialRequest, SerializedCredentialResponse, }; use crate::keypair::PublicKey; use crate::opaque::{ @@ -359,8 +359,8 @@ impl CredentialRequest { }) } - pub(crate) fn to_parts(&self) -> CredentialRequestParts { - CredentialRequestParts::new(&self.blinded_element) + pub(crate) fn to_parts(&self) -> SerializedCredentialRequest { + SerializedCredentialRequest::new(&self.blinded_element) } /// Only used for testing purposes @@ -415,8 +415,8 @@ impl CredentialResponse { }) } - pub(crate) fn to_parts(&self) -> CredentialResponseParts { - CredentialResponseParts::new( + pub(crate) fn to_parts(&self) -> SerializedCredentialResponse { + SerializedCredentialResponse::new( &self.evaluation_element, self.masking_nonce, self.masked_response.clone(), diff --git a/src/opaque.rs b/src/opaque.rs index cc7d95f..c164a18 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -27,9 +27,9 @@ use crate::errors::{InternalError, ProtocolError}; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; -use crate::key_exchange::traits::{ - CredentialResponseParts, Deserialize, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, - Serialize, SerializedContext, SerializedIdentifiers, +use crate::key_exchange::{ + Deserialize, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, Serialize, + SerializedContext, SerializedCredentialResponse, SerializedIdentifiers, }; use crate::keypair::{ KeyPair, OprfSeed, OprfSeedSerialization, PrivateKey, PrivateKeySerialization, PublicKey, @@ -503,18 +503,18 @@ impl ClientLogin { password: &[u8], ) -> Result, ProtocolError> { let blind_result = blind::(rng, password)?; - let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(rng)?; + let ke1_result = CS::KeyExchange::generate_ke1(rng)?; let credential_request = CredentialRequest { blinded_element: blind_result.message, - ke1_message, + ke1_message: ke1_result.message, }; Ok(ClientLoginStartResult { message: credential_request.clone(), state: Self { oprf_client: blind_result.state, - ke1_state, + ke1_state: ke1_result.state, credential_request, }, }) @@ -582,8 +582,8 @@ impl ClientLogin { self.credential_request.to_parts(), self.credential_request.ke1_message.clone(), credential_response.to_parts(), - credential_response.ke2_message, &self.ke1_state, + credential_response.ke2_message, server_s_pk.clone(), opened_envelope.client_static_keypair.private().clone(), opened_envelope.identifiers, @@ -592,17 +592,17 @@ impl ClientLogin { Ok(ClientLoginFinishResult { message: CredentialFinalization { - ke3_message: result.1, + ke3_message: result.message, }, - session_key: result.0, + session_key: result.session_key, export_key: opened_envelope.export_key, server_s_pk, #[cfg(test)] state: self, #[cfg(test)] - handshake_secret: result.2, + handshake_secret: result.handshake_secret, #[cfg(test)] - client_mac_key: result.3, + client_mac_key: result.km3, }) } } @@ -679,7 +679,7 @@ impl ServerLogin { let server = voprf::OprfServer::new_with_key(&oprf_key).map_err(ProtocolError::from)?; let evaluation_element = server.blind_evaluate(&credential_request.blinded_element); - let credential_response = CredentialResponseParts::new( + let credential_response = SerializedCredentialResponse::new( &evaluation_element, masking_nonce, masked_response.clone(), @@ -743,18 +743,18 @@ impl ServerLogin { evaluation_element: builder.evaluation_element.clone(), masking_nonce: *builder.masking_nonce.deref(), masked_response: builder.masked_response.clone(), - ke2_message: result.1, + ke2_message: result.message, }; Ok(ServerLoginStartResult { message: credential_response, state: Self { - ke2_state: result.0, + ke2_state: result.state, }, #[cfg(test)] - handshake_secret: result.2, + handshake_secret: result.handshake_secret, #[cfg(test)] - server_mac_key: result.3, + server_mac_key: result.km2, #[cfg(test)] oprf_key: builder.oprf_key.deref().clone(), }) @@ -797,8 +797,8 @@ impl ServerLogin { let context = SerializedContext::from(parameters.context)?; let session_key = ::finish_ke( - message.ke3_message, &self.ke2_state, + message.ke3_message, parameters.identifiers, context, )?; diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index 6b422a1..4c40b12 100644 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -25,7 +25,7 @@ use crate::errors::*; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; -use crate::key_exchange::traits::{ +use crate::key_exchange::{ Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize, }; use crate::keypair::KeyPair; diff --git a/src/tests/full_test.rs b/src/tests/full_test.rs index c1dcab0..79dbf67 100644 --- a/src/tests/full_test.rs +++ b/src/tests/full_test.rs @@ -27,7 +27,7 @@ use crate::errors::*; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; -use crate::key_exchange::traits::{ +use crate::key_exchange::{ Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize, }; use crate::ksf::Identity; diff --git a/src/tests/test_opaque_vectors.rs b/src/tests/test_opaque_vectors.rs index 1b8ccf4..c8e3ed7 100644 --- a/src/tests/test_opaque_vectors.rs +++ b/src/tests/test_opaque_vectors.rs @@ -23,9 +23,7 @@ use crate::errors::*; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; -use crate::key_exchange::traits::{ - Deserialize, Ke1MessageLen, Ke2MessageLen, KeyExchange, Serialize, -}; +use crate::key_exchange::{Deserialize, Ke1MessageLen, Ke2MessageLen, KeyExchange, Serialize}; use crate::ksf::Identity; use crate::messages::{ CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen,