Publicly Expose trait KeyExchange (#379)
* Clean up types used in `trait KeyExchange` * Expose `trait KeyExchange` publicly
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ use generic_array::ArrayLength;
|
|||||||
use crate::envelope::NonceLen;
|
use crate::envelope::NonceLen;
|
||||||
use crate::hash::{Hash, OutputSize, ProxyHash};
|
use crate::hash::{Hash, OutputSize, ProxyHash};
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::traits::KeyExchange;
|
use crate::key_exchange::KeyExchange;
|
||||||
use crate::ksf::Ksf;
|
use crate::ksf::Ksf;
|
||||||
use crate::opaque::MaskedResponseLen;
|
use crate::opaque::MaskedResponseLen;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ use crate::ciphersuite::{CipherSuite, KeGroup, OprfHash};
|
|||||||
use crate::errors::{InternalError, ProtocolError};
|
use crate::errors::{InternalError, ProtocolError};
|
||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
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::keypair::{KeyPair, PrivateKey, PublicKey};
|
||||||
use crate::opaque::Identifiers;
|
use crate::opaque::Identifiers;
|
||||||
use crate::serialization::{GenericArrayExt, SliceExt, UpdateExt};
|
use crate::serialization::{GenericArrayExt, SliceExt, UpdateExt};
|
||||||
|
|||||||
+429
-2
@@ -12,7 +12,434 @@
|
|||||||
pub mod group;
|
pub mod group;
|
||||||
pub(crate) mod shared;
|
pub(crate) mod shared;
|
||||||
pub mod sigma_i;
|
pub mod sigma_i;
|
||||||
pub(crate) mod traits;
|
|
||||||
pub mod tripledh;
|
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
|
||||||
|
<Self::Hash as CoreProxy>::Core: ProxyHash,
|
||||||
|
<<Self::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||||
|
Le<<<Self::Hash as CoreProxy>::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<CS: CipherSuite>: ZeroizeOnDrop + Clone;
|
||||||
|
/// First message sent by the client.
|
||||||
|
type KE1Message: ZeroizeOnDrop + Clone;
|
||||||
|
/// Server state builder.
|
||||||
|
type KE2Builder<'a, CS: CipherSuite<KeyExchange = Self>>: ZeroizeOnDrop + Clone;
|
||||||
|
/// Server data for the remote key interaction.
|
||||||
|
type KE2BuilderData<'a, CS: 'static + CipherSuite>;
|
||||||
|
/// Server remote key input.
|
||||||
|
type KE2BuilderInput<CS: CipherSuite>;
|
||||||
|
/// 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<R: RngCore + CryptoRng>(
|
||||||
|
rng: &mut R,
|
||||||
|
) -> Result<GenerateKe1Result<Self>, ProtocolError>;
|
||||||
|
|
||||||
|
/// Server generates [`KE2Builder`](Self::KE2Builder).
|
||||||
|
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||||
|
rng: &mut R,
|
||||||
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
|
ke1_message: Self::KE1Message,
|
||||||
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
|
client_s_pk: PublicKey<Self::Group>,
|
||||||
|
identifiers: SerializedIdentifiers<'a, Self::Group>,
|
||||||
|
context: SerializedContext<'a>,
|
||||||
|
) -> Result<Self::KE2Builder<'a, CS>, ProtocolError>;
|
||||||
|
|
||||||
|
/// Server returns the data for the remote key interaction.
|
||||||
|
fn ke2_builder_data<'a, CS: CipherSuite<KeyExchange = Self>>(
|
||||||
|
builder: &'a Self::KE2Builder<'_, CS>,
|
||||||
|
) -> Self::KE2BuilderData<'a, CS>;
|
||||||
|
|
||||||
|
/// Server generates the input without a remote key.
|
||||||
|
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||||
|
builder: &Self::KE2Builder<'_, CS>,
|
||||||
|
rng: &mut R,
|
||||||
|
server_s_sk: &PrivateKey<Self::Group>,
|
||||||
|
) -> Self::KE2BuilderInput<CS>;
|
||||||
|
|
||||||
|
/// Server generates [`KE2Message`](Self::KE2Message) and
|
||||||
|
/// [`KE2State`](Self::KE2State).
|
||||||
|
fn build_ke2<CS: CipherSuite<KeyExchange = Self>>(
|
||||||
|
builder: Self::KE2Builder<'_, CS>,
|
||||||
|
input: Self::KE2BuilderInput<CS>,
|
||||||
|
) -> Result<GenerateKe2Result<CS>, ProtocolError>;
|
||||||
|
|
||||||
|
/// Client generates [`KE3Message`](Self::KE3Message) and the session key.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||||
|
rng: &mut R,
|
||||||
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
|
ke1_message: Self::KE1Message,
|
||||||
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
|
ke1_state: &Self::KE1State,
|
||||||
|
ke2_message: Self::KE2Message,
|
||||||
|
server_s_pk: PublicKey<Self::Group>,
|
||||||
|
client_s_sk: PrivateKey<Self::Group>,
|
||||||
|
identifiers: SerializedIdentifiers<'_, Self::Group>,
|
||||||
|
context: SerializedContext<'_>,
|
||||||
|
) -> Result<GenerateKe3Result<Self>, ProtocolError>;
|
||||||
|
|
||||||
|
/// Server generates the session key.
|
||||||
|
fn finish_ke<CS: CipherSuite<KeyExchange = Self>>(
|
||||||
|
ke2_state: &Self::KE2State<CS>,
|
||||||
|
ke3_message: Self::KE3Message,
|
||||||
|
identifiers: Identifiers<'_>,
|
||||||
|
context: SerializedContext<'_>,
|
||||||
|
) -> Result<Output<Self::Hash>, 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<CS: CipherSuite>(
|
||||||
|
GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> SerializedCredentialRequest<CS> {
|
||||||
|
pub(crate) fn new(blinded_element: &BlindedElement<CS::OprfCs>) -> Self {
|
||||||
|
Self(blinded_element.serialize())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the serialized form of
|
||||||
|
/// [`CredentialRequest`](crate::CredentialRequest) in multiple byte slices.
|
||||||
|
pub fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
||||||
|
iter::once(self.0.as_slice())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`SerializedCredentialRequest`] deserialized from the given
|
||||||
|
/// `bytes`.
|
||||||
|
pub fn deserialize_take(bytes: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||||
|
Ok(Self(bytes.take_array("blinded element")?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SerializedCredentialRequestLen<CS: CipherSuite> = <OprfGroup<CS> as voprf::Group>::ElemLen;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> Serialize for SerializedCredentialRequest<CS> {
|
||||||
|
type Len = SerializedCredentialRequestLen<CS>;
|
||||||
|
|
||||||
|
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||||
|
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<CS: CipherSuite> {
|
||||||
|
evaluation_element: GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||||
|
masking_nonce: GenericArray<u8, NonceLen>,
|
||||||
|
masked_response: MaskedResponse<CS>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> SerializedCredentialResponse<CS> {
|
||||||
|
pub(crate) fn new(
|
||||||
|
evaluation_element: &EvaluationElement<CS::OprfCs>,
|
||||||
|
masking_nonce: GenericArray<u8, NonceLen>,
|
||||||
|
masked_response: MaskedResponse<CS>,
|
||||||
|
) -> 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<Item = &[u8]> {
|
||||||
|
[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<Self, ProtocolError> {
|
||||||
|
Ok(Self {
|
||||||
|
evaluation_element: input.take_array("evaluation element")?,
|
||||||
|
masking_nonce: input.take_array("masking nonce")?,
|
||||||
|
masked_response: MaskedResponse::deserialize_take(input)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SerializedCredentialResponseLen<CS: CipherSuite> =
|
||||||
|
Sum<Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>, MaskedResponseLen<CS>>;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> Serialize for SerializedCredentialResponse<CS>
|
||||||
|
where
|
||||||
|
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
||||||
|
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
||||||
|
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
||||||
|
SerializedCredentialResponseLen<CS>: ArrayLength<u8>,
|
||||||
|
{
|
||||||
|
type Len = SerializedCredentialResponseLen<CS>;
|
||||||
|
|
||||||
|
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||||
|
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<u8, U2>,
|
||||||
|
#[zeroize(skip)]
|
||||||
|
context: &'a [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SerializedContext<'a> {
|
||||||
|
pub(crate) fn from(context: Option<&'a [u8]>) -> Result<Self, ProtocolError> {
|
||||||
|
let context = context.unwrap_or(&[]);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
length: i2osp::<U2>(context.len())?,
|
||||||
|
context,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the serialized form of `context` in multiple byte slices.
|
||||||
|
pub fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
||||||
|
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<u8, U2>,
|
||||||
|
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<u8, G::PkLen>),
|
||||||
|
#[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<u8, G::PkLen>,
|
||||||
|
server_s_pk: GenericArray<u8, G::PkLen>,
|
||||||
|
) -> Result<Self, ProtocolError> {
|
||||||
|
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<u8, G::PkLen>,
|
||||||
|
) -> Result<Self, ProtocolError> {
|
||||||
|
if let Some(id) = id {
|
||||||
|
Ok(SerializedIdentifier {
|
||||||
|
length: i2osp::<U2>(id.len())?,
|
||||||
|
identifier: Identifier::Borrowed(id),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(SerializedIdentifier {
|
||||||
|
length: i2osp::<U2>(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<Item = &[u8]> {
|
||||||
|
[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<Self, ProtocolError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialization trait for key exchange types.
|
||||||
|
pub trait Serialize {
|
||||||
|
/// The length of the serialized types.
|
||||||
|
type Len: ArrayLength<u8>;
|
||||||
|
|
||||||
|
/// Serialize [`Self`] to a fixed-length byte array.
|
||||||
|
fn serialize(&self) -> GenericArray<u8, Self::Len>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result type of [`KeyExchange::generate_ke1()`].
|
||||||
|
pub struct GenerateKe1Result<KE: KeyExchange + ?Sized> {
|
||||||
|
/// The client state.
|
||||||
|
pub state: KE::KE1State,
|
||||||
|
/// The first client message.
|
||||||
|
pub message: KE::KE1Message,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result type of [`KeyExchange::build_ke2()`].
|
||||||
|
pub struct GenerateKe2Result<CS: CipherSuite> {
|
||||||
|
/// The server state.
|
||||||
|
pub state: <CS::KeyExchange as KeyExchange>::KE2State<CS>,
|
||||||
|
/// The server message.
|
||||||
|
pub message: <CS::KeyExchange as KeyExchange>::KE2Message,
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) handshake_secret: Output<KeHash<CS>>,
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) km2: Output<KeHash<CS>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result type of [`KeyExchange::generate_ke3()`].
|
||||||
|
pub struct GenerateKe3Result<KE: KeyExchange + ?Sized> {
|
||||||
|
/// The session key.
|
||||||
|
pub session_key: Output<KE::Hash>,
|
||||||
|
/// The second client message.
|
||||||
|
pub message: KE::KE3Message,
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) handshake_secret: Output<KE::Hash>,
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) km3: Output<KE::Hash>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) type Ke1StateLen<CS: CipherSuite> =
|
||||||
|
<<CS::KeyExchange as KeyExchange>::KE1State as Serialize>::Len;
|
||||||
|
pub(crate) type Ke1MessageLen<CS: CipherSuite> =
|
||||||
|
<<CS::KeyExchange as KeyExchange>::KE1Message as Serialize>::Len;
|
||||||
|
pub(crate) type Ke2StateLen<CS: CipherSuite> =
|
||||||
|
<<CS::KeyExchange as KeyExchange>::KE2State<CS> as Serialize>::Len;
|
||||||
|
pub(crate) type Ke2MessageLen<CS: CipherSuite> =
|
||||||
|
<<CS::KeyExchange as KeyExchange>::KE2Message as Serialize>::Len;
|
||||||
|
pub(crate) type Ke3MessageLen<CS: CipherSuite> =
|
||||||
|
<<CS::KeyExchange as KeyExchange>::KE3Message as Serialize>::Len;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Test Implementations //
|
||||||
|
//===================== //
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::serialization::AssertZeroized;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl<CS: CipherSuite> AssertZeroized for SerializedCredentialRequest<CS> {
|
||||||
|
fn assert_zeroized(&self) {
|
||||||
|
let Self(blinded_element) = self;
|
||||||
|
|
||||||
|
for byte in blinded_element.iter() {
|
||||||
|
assert_eq!(byte, &0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl<CS: CipherSuite> AssertZeroized for SerializedCredentialResponse<CS> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+16
-12
@@ -17,14 +17,14 @@ use generic_array::{ArrayLength, GenericArray};
|
|||||||
use hkdf::{Hkdf, HkdfExtract};
|
use hkdf::{Hkdf, HkdfExtract};
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
Deserialize, GenerateKe1Result, KeyExchange, Serialize, SerializedContext,
|
||||||
|
SerializedCredentialRequest, SerializedCredentialResponse, SerializedIdentifiers,
|
||||||
|
};
|
||||||
use crate::ciphersuite::{CipherSuite, KeGroup, KeHash};
|
use crate::ciphersuite::{CipherSuite, KeGroup, KeHash};
|
||||||
use crate::errors::{InternalError, ProtocolError};
|
use crate::errors::{InternalError, ProtocolError};
|
||||||
use crate::hash::{Hash, OutputSize, ProxyHash};
|
use crate::hash::{Hash, OutputSize, ProxyHash};
|
||||||
use crate::key_exchange::group::Group;
|
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::keypair::{KeyPair, PrivateKey, PublicKey};
|
||||||
use crate::serialization::{i2osp, SliceExt, UpdateExt};
|
use crate::serialization::{i2osp, SliceExt, UpdateExt};
|
||||||
|
|
||||||
@@ -100,9 +100,13 @@ pub(super) struct DerivedKeys<H: OutputSizeUser> {
|
|||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
||||||
pub(super) fn generate_ke1<R: RngCore + CryptoRng, G: Group>(
|
pub(super) fn generate_ke1<
|
||||||
|
R: RngCore + CryptoRng,
|
||||||
|
KE: KeyExchange<KE1State = Ke1State<G>, KE1Message = Ke1Message<G>>,
|
||||||
|
G: Group,
|
||||||
|
>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<(Ke1State<G>, Ke1Message<G>), ProtocolError> {
|
) -> Result<GenerateKe1Result<KE>, ProtocolError> {
|
||||||
let client_e_kp = KeyPair::<G>::derive_random(rng);
|
let client_e_kp = KeyPair::<G>::derive_random(rng);
|
||||||
let client_nonce = generate_nonce::<R>(rng);
|
let client_nonce = generate_nonce::<R>(rng);
|
||||||
|
|
||||||
@@ -111,13 +115,13 @@ pub(super) fn generate_ke1<R: RngCore + CryptoRng, G: Group>(
|
|||||||
client_e_pk: client_e_kp.public().clone(),
|
client_e_pk: client_e_kp.public().clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((
|
Ok(GenerateKe1Result {
|
||||||
Ke1State {
|
state: Ke1State {
|
||||||
client_e_sk: client_e_kp.private().clone(),
|
client_e_sk: client_e_kp.private().clone(),
|
||||||
client_nonce,
|
client_nonce,
|
||||||
},
|
},
|
||||||
ke1_message,
|
message: ke1_message,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a random nonce up to NonceLen::USIZE bytes.
|
// Generate a random nonce up to NonceLen::USIZE bytes.
|
||||||
@@ -130,9 +134,9 @@ pub(super) fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArra
|
|||||||
pub(super) fn transcript<CS: CipherSuite, KE: Group>(
|
pub(super) fn transcript<CS: CipherSuite, KE: Group>(
|
||||||
context: &SerializedContext<'_>,
|
context: &SerializedContext<'_>,
|
||||||
identifiers: &SerializedIdentifiers<'_, KeGroup<CS>>,
|
identifiers: &SerializedIdentifiers<'_, KeGroup<CS>>,
|
||||||
credential_request: &CredentialRequestParts<CS>,
|
credential_request: &SerializedCredentialRequest<CS>,
|
||||||
ke1_message: &Ke1MessageIter<KE>,
|
ke1_message: &Ke1MessageIter<KE>,
|
||||||
credential_response: &CredentialResponseParts<CS>,
|
credential_response: &SerializedCredentialResponse<CS>,
|
||||||
server_nonce: GenericArray<u8, NonceLen>,
|
server_nonce: GenericArray<u8, NonceLen>,
|
||||||
server_e_pk: &GenericArray<u8, KE::PkLen>,
|
server_e_pk: &GenericArray<u8, KE::PkLen>,
|
||||||
) -> KeHash<CS> {
|
) -> KeHash<CS> {
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ use crate::errors::ProtocolError;
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::{Ke1MessageIter, Ke1MessageIterLen, NonceLen};
|
use crate::key_exchange::shared::{Ke1MessageIter, Ke1MessageIterLen, NonceLen};
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{
|
||||||
CredentialRequestParts, CredentialRequestPartsLen, CredentialResponseParts,
|
Deserialize, Serialize, SerializedContext, SerializedCredentialRequest,
|
||||||
CredentialResponsePartsLen, Deserialize, Serialize, SerializedContext, SerializedIdentifier,
|
SerializedCredentialRequestLen, SerializedCredentialResponse, SerializedCredentialResponseLen,
|
||||||
SerializedIdentifiers,
|
SerializedIdentifier, SerializedIdentifiers,
|
||||||
};
|
};
|
||||||
use crate::opaque::MaskedResponseLen;
|
use crate::opaque::MaskedResponseLen;
|
||||||
use crate::serialization::{SliceExt, UpdateExt};
|
use crate::serialization::{SliceExt, UpdateExt};
|
||||||
@@ -99,9 +99,9 @@ pub struct MessageBuilder<'a, CS: CipherSuite> {
|
|||||||
)]
|
)]
|
||||||
#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize, ZeroizeOnDrop)]
|
#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct CachedMessage<CS: CipherSuite, KE: Group> {
|
pub struct CachedMessage<CS: CipherSuite, KE: Group> {
|
||||||
pub(super) credential_request: CredentialRequestParts<CS>,
|
pub(super) credential_request: SerializedCredentialRequest<CS>,
|
||||||
pub(super) ke1_message: Ke1MessageIter<KE>,
|
pub(super) ke1_message: Ke1MessageIter<KE>,
|
||||||
pub(super) credential_response: CredentialResponseParts<CS>,
|
pub(super) credential_response: SerializedCredentialResponse<CS>,
|
||||||
pub(super) server_nonce: GenericArray<u8, NonceLen>,
|
pub(super) server_nonce: GenericArray<u8, NonceLen>,
|
||||||
pub(super) server_e_pk: GenericArray<u8, KE::PkLen>,
|
pub(super) server_e_pk: GenericArray<u8, KE::PkLen>,
|
||||||
pub(super) server_mac: Output<KeHash<CS>>,
|
pub(super) server_mac: Output<KeHash<CS>>,
|
||||||
@@ -231,9 +231,9 @@ impl<'a, CS: CipherSuite> MessageBuilder<'a, CS> {
|
|||||||
impl<CS: CipherSuite, KE: Group> Deserialize for CachedMessage<CS, KE> {
|
impl<CS: CipherSuite, KE: Group> Deserialize for CachedMessage<CS, KE> {
|
||||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
credential_request: CredentialRequestParts::deserialize_take(input)?,
|
credential_request: SerializedCredentialRequest::deserialize_take(input)?,
|
||||||
ke1_message: Ke1MessageIter::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_nonce: input.take_array("server nonce")?,
|
||||||
server_e_pk: input.take_array("serialized server ephemeral key")?,
|
server_e_pk: input.take_array("serialized server ephemeral key")?,
|
||||||
server_mac: input.take_array("server mac")?,
|
server_mac: input.take_array("server mac")?,
|
||||||
@@ -246,8 +246,8 @@ type CachedMessageLen<CS: CipherSuite, KE: Group> = Sum<
|
|||||||
Sum<
|
Sum<
|
||||||
Sum<
|
Sum<
|
||||||
Sum<
|
Sum<
|
||||||
Sum<CredentialRequestPartsLen<CS>, Ke1MessageIterLen<KE>>,
|
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||||
CredentialResponsePartsLen<CS>,
|
SerializedCredentialResponseLen<CS>,
|
||||||
>,
|
>,
|
||||||
NonceLen,
|
NonceLen,
|
||||||
>,
|
>,
|
||||||
@@ -258,23 +258,25 @@ type CachedMessageLen<CS: CipherSuite, KE: Group> = Sum<
|
|||||||
|
|
||||||
impl<CS: CipherSuite, KE: Group> Serialize for CachedMessage<CS, KE>
|
impl<CS: CipherSuite, KE: Group> Serialize for CachedMessage<CS, KE>
|
||||||
where
|
where
|
||||||
CredentialRequestPartsLen<CS>: ArrayLength<u8> + Add<Ke1MessageIterLen<KE>>,
|
SerializedCredentialRequestLen<CS>: ArrayLength<u8> + Add<Ke1MessageIterLen<KE>>,
|
||||||
Sum<CredentialRequestPartsLen<CS>, Ke1MessageIterLen<KE>>:
|
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>:
|
||||||
ArrayLength<u8> + Add<CredentialResponsePartsLen<CS>>,
|
ArrayLength<u8> + Add<SerializedCredentialResponseLen<CS>>,
|
||||||
Sum<Sum<CredentialRequestPartsLen<CS>, Ke1MessageIterLen<KE>>, CredentialResponsePartsLen<CS>>:
|
Sum<
|
||||||
ArrayLength<u8> + Add<NonceLen>,
|
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||||
|
SerializedCredentialResponseLen<CS>,
|
||||||
|
>: ArrayLength<u8> + Add<NonceLen>,
|
||||||
Sum<
|
Sum<
|
||||||
Sum<
|
Sum<
|
||||||
Sum<CredentialRequestPartsLen<CS>, Ke1MessageIterLen<KE>>,
|
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||||
CredentialResponsePartsLen<CS>,
|
SerializedCredentialResponseLen<CS>,
|
||||||
>,
|
>,
|
||||||
NonceLen,
|
NonceLen,
|
||||||
>: ArrayLength<u8> + Add<KE::PkLen>,
|
>: ArrayLength<u8> + Add<KE::PkLen>,
|
||||||
Sum<
|
Sum<
|
||||||
Sum<
|
Sum<
|
||||||
Sum<
|
Sum<
|
||||||
Sum<CredentialRequestPartsLen<CS>, Ke1MessageIterLen<KE>>,
|
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||||
CredentialResponsePartsLen<CS>,
|
SerializedCredentialResponseLen<CS>,
|
||||||
>,
|
>,
|
||||||
NonceLen,
|
NonceLen,
|
||||||
>,
|
>,
|
||||||
@@ -288,7 +290,7 @@ where
|
|||||||
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
||||||
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
||||||
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
||||||
CredentialResponsePartsLen<CS>: ArrayLength<u8>,
|
SerializedCredentialResponseLen<CS>: ArrayLength<u8>,
|
||||||
{
|
{
|
||||||
type Len = CachedMessageLen<CS, KE>;
|
type Len = CachedMessageLen<CS, KE>;
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ use zeroize::Zeroize;
|
|||||||
|
|
||||||
use self::message::Role;
|
use self::message::Role;
|
||||||
pub use self::message::{CachedMessage, HashOutput, Message, MessageBuilder, VerifyMessage};
|
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::ciphersuite::{CipherSuite, KeGroup, KeHash};
|
||||||
use crate::envelope::NonceLen;
|
use crate::envelope::NonceLen;
|
||||||
use crate::errors::{InternalError, ProtocolError};
|
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::group::Group;
|
||||||
use crate::key_exchange::shared::{derive_keys, generate_ke1, generate_nonce, transcript};
|
use crate::key_exchange::shared::{derive_keys, generate_ke1, generate_nonce, transcript};
|
||||||
pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State};
|
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::keypair::{KeyPair, PrivateKey, PublicKey};
|
||||||
use crate::opaque::Identifiers;
|
use crate::opaque::Identifiers;
|
||||||
use crate::serialization::{SliceExt, UpdateExt};
|
use crate::serialization::{SliceExt, UpdateExt};
|
||||||
@@ -156,9 +156,9 @@ pub struct Ke2Builder<'a, CS: CipherSuite, KE: Group> {
|
|||||||
expected_mac: Output<KeHash<CS>>,
|
expected_mac: Output<KeHash<CS>>,
|
||||||
session_key: Output<KeHash<CS>>,
|
session_key: Output<KeHash<CS>>,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
km3: Output<KeHash<CS>>,
|
|
||||||
#[cfg(test)]
|
|
||||||
handshake_secret: Output<KeHash<CS>>,
|
handshake_secret: Output<KeHash<CS>>,
|
||||||
|
#[cfg(test)]
|
||||||
|
km2: Output<KeHash<CS>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The server state produced after the second key exchange message
|
/// The server state produced after the second key exchange message
|
||||||
@@ -239,15 +239,15 @@ where
|
|||||||
|
|
||||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> {
|
) -> Result<GenerateKe1Result<Self>, ProtocolError> {
|
||||||
generate_ke1(rng)
|
generate_ke1(rng)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
credential_request: CredentialRequestParts<CS>,
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
credential_response: CredentialResponseParts<CS>,
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
client_s_pk: PublicKey<Self::Group>,
|
client_s_pk: PublicKey<Self::Group>,
|
||||||
identifiers: SerializedIdentifiers<'a, KeGroup<CS>>,
|
identifiers: SerializedIdentifiers<'a, KeGroup<CS>>,
|
||||||
context: SerializedContext<'a>,
|
context: SerializedContext<'a>,
|
||||||
@@ -309,9 +309,9 @@ where
|
|||||||
expected_mac: client_mac,
|
expected_mac: client_mac,
|
||||||
session_key: derived_keys.session_key,
|
session_key: derived_keys.session_key,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
km3: derived_keys.km3,
|
|
||||||
#[cfg(test)]
|
|
||||||
handshake_secret: derived_keys.handshake_secret,
|
handshake_secret: derived_keys.handshake_secret,
|
||||||
|
#[cfg(test)]
|
||||||
|
km2: derived_keys.km2,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,33 +333,33 @@ where
|
|||||||
builder: Self::KE2Builder<'_, CS>,
|
builder: Self::KE2Builder<'_, CS>,
|
||||||
input: Self::KE2BuilderInput<CS>,
|
input: Self::KE2BuilderInput<CS>,
|
||||||
) -> Result<GenerateKe2Result<CS>, ProtocolError> {
|
) -> Result<GenerateKe2Result<CS>, ProtocolError> {
|
||||||
Ok((
|
Ok(GenerateKe2Result {
|
||||||
Ke2State {
|
state: Ke2State {
|
||||||
client_s_pk: builder.client_s_pk.clone(),
|
client_s_pk: builder.client_s_pk.clone(),
|
||||||
session_key: builder.session_key.clone(),
|
session_key: builder.session_key.clone(),
|
||||||
verify_state: input.1,
|
verify_state: input.1,
|
||||||
expected_mac: builder.expected_mac.clone(),
|
expected_mac: builder.expected_mac.clone(),
|
||||||
},
|
},
|
||||||
Ke2Message {
|
message: Ke2Message {
|
||||||
server_nonce: builder.server_nonce,
|
server_nonce: builder.server_nonce,
|
||||||
server_e_pk: builder.server_e_pk.clone(),
|
server_e_pk: builder.server_e_pk.clone(),
|
||||||
signature: input.0,
|
signature: input.0,
|
||||||
mac: builder.transcript.cache.server_mac.clone(),
|
mac: builder.transcript.cache.server_mac.clone(),
|
||||||
},
|
},
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
builder.handshake_secret.clone(),
|
handshake_secret: builder.handshake_secret.clone(),
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
builder.km3.clone(),
|
km2: builder.km2.clone(),
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
credential_request: CredentialRequestParts<CS>,
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
credential_response: CredentialResponseParts<CS>,
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
ke2_message: Self::KE2Message,
|
|
||||||
ke1_state: &Self::KE1State,
|
ke1_state: &Self::KE1State,
|
||||||
|
ke2_message: Self::KE2Message,
|
||||||
server_s_pk: PublicKey<Self::Group>,
|
server_s_pk: PublicKey<Self::Group>,
|
||||||
client_s_sk: PrivateKey<Self::Group>,
|
client_s_sk: PrivateKey<Self::Group>,
|
||||||
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
||||||
@@ -427,22 +427,22 @@ where
|
|||||||
&ke2_message.signature,
|
&ke2_message.signature,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok((
|
Ok(GenerateKe3Result {
|
||||||
derived_keys.session_key,
|
session_key: derived_keys.session_key,
|
||||||
Ke3Message {
|
message: Ke3Message {
|
||||||
signature,
|
signature,
|
||||||
mac: client_mac,
|
mac: client_mac,
|
||||||
},
|
},
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.handshake_secret,
|
handshake_secret: derived_keys.handshake_secret,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.km3,
|
km3: derived_keys.km3,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_ke<CS: CipherSuite<KeyExchange = Self>>(
|
fn finish_ke<CS: CipherSuite<KeyExchange = Self>>(
|
||||||
ke3_message: Self::KE3Message,
|
|
||||||
ke2_state: &Self::KE2State<CS>,
|
ke2_state: &Self::KE2State<CS>,
|
||||||
|
ke3_message: Self::KE3Message,
|
||||||
identifiers: Identifiers<'_>,
|
identifiers: Identifiers<'_>,
|
||||||
context: SerializedContext<'_>,
|
context: SerializedContext<'_>,
|
||||||
) -> Result<Output<KEH>, ProtocolError> {
|
) -> Result<Output<KEH>, ProtocolError> {
|
||||||
@@ -468,14 +468,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SIG: SignatureProtocol, KE: 'static + Group, KEH: Hash> Sealed for SigmaI<SIG, KE, KEH>
|
|
||||||
where
|
|
||||||
KEH::Core: ProxyHash,
|
|
||||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
|
||||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> Deserialize for Ke2State<CS, SIG, KE>
|
impl<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> Deserialize for Ke2State<CS, SIG, KE>
|
||||||
where
|
where
|
||||||
SIG::VerifyState<CS, KE>: Deserialize,
|
SIG::VerifyState<CS, KE>: Deserialize,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use digest::{Output, OutputSizeUser};
|
|||||||
use generic_array::{ArrayLength, GenericArray};
|
use generic_array::{ArrayLength, GenericArray};
|
||||||
|
|
||||||
use crate::errors::ProtocolError;
|
use crate::errors::ProtocolError;
|
||||||
use crate::key_exchange::traits::{Deserialize, Serialize};
|
use crate::key_exchange::{Deserialize, Serialize};
|
||||||
use crate::serialization::SliceExt;
|
use crate::serialization::SliceExt;
|
||||||
|
|
||||||
/// Pre-hash of the message to be verified.
|
/// Pre-hash of the message to be verified.
|
||||||
|
|||||||
@@ -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
|
|
||||||
<Self::Hash as CoreProxy>::Core: ProxyHash,
|
|
||||||
<<Self::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
|
||||||
Le<<<Self::Hash as CoreProxy>::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<CS: CipherSuite>: ZeroizeOnDrop + Clone;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE1Message: ZeroizeOnDrop + Clone;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE2Builder<'a, CS: CipherSuite<KeyExchange = Self>>: ZeroizeOnDrop + Clone;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE2BuilderData<'a, CS: 'static + CipherSuite>;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE2BuilderInput<CS: CipherSuite>;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE2Message: ZeroizeOnDrop + Clone;
|
|
||||||
#[doc(hidden)]
|
|
||||||
type KE3Message: ZeroizeOnDrop + Clone;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
|
||||||
rng: &mut R,
|
|
||||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
|
||||||
rng: &mut R,
|
|
||||||
credential_request: CredentialRequestParts<CS>,
|
|
||||||
ke1_message: Self::KE1Message,
|
|
||||||
credential_response: CredentialResponseParts<CS>,
|
|
||||||
client_s_pk: PublicKey<Self::Group>,
|
|
||||||
identifiers: SerializedIdentifiers<'a, Self::Group>,
|
|
||||||
context: SerializedContext<'a>,
|
|
||||||
) -> Result<Self::KE2Builder<'a, CS>, ProtocolError>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn ke2_builder_data<'a, CS: CipherSuite<KeyExchange = Self>>(
|
|
||||||
builder: &'a Self::KE2Builder<'_, CS>,
|
|
||||||
) -> Self::KE2BuilderData<'a, CS>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
|
||||||
builder: &Self::KE2Builder<'_, CS>,
|
|
||||||
rng: &mut R,
|
|
||||||
server_s_sk: &PrivateKey<Self::Group>,
|
|
||||||
) -> Self::KE2BuilderInput<CS>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn build_ke2<CS: CipherSuite<KeyExchange = Self>>(
|
|
||||||
builder: Self::KE2Builder<'_, CS>,
|
|
||||||
input: Self::KE2BuilderInput<CS>,
|
|
||||||
) -> Result<GenerateKe2Result<CS>, ProtocolError>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
|
||||||
rng: &mut R,
|
|
||||||
credential_request: CredentialRequestParts<CS>,
|
|
||||||
ke1_message: Self::KE1Message,
|
|
||||||
credential_response: CredentialResponseParts<CS>,
|
|
||||||
ke2_message: Self::KE2Message,
|
|
||||||
ke1_state: &Self::KE1State,
|
|
||||||
server_s_pk: PublicKey<Self::Group>,
|
|
||||||
client_s_sk: PrivateKey<Self::Group>,
|
|
||||||
identifiers: SerializedIdentifiers<'_, Self::Group>,
|
|
||||||
context: SerializedContext<'_>,
|
|
||||||
) -> Result<GenerateKe3Result<Self>, ProtocolError>;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
fn finish_ke<CS: CipherSuite<KeyExchange = Self>>(
|
|
||||||
ke3_message: Self::KE3Message,
|
|
||||||
ke2_state: &Self::KE2State<CS>,
|
|
||||||
identifiers: Identifiers<'_>,
|
|
||||||
context: SerializedContext<'_>,
|
|
||||||
) -> Result<Output<Self::Hash>, 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<CS: CipherSuite>(
|
|
||||||
GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> CredentialRequestParts<CS> {
|
|
||||||
pub(crate) fn new(blinded_element: &BlindedElement<CS::OprfCs>) -> Self {
|
|
||||||
Self(blinded_element.serialize())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
|
||||||
iter::once(self.0.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
|
||||||
Ok(Self(input.take_array("blinded element")?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CredentialRequestPartsLen<CS: CipherSuite> = <OprfGroup<CS> as voprf::Group>::ElemLen;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> Serialize for CredentialRequestParts<CS> {
|
|
||||||
type Len = CredentialRequestPartsLen<CS>;
|
|
||||||
|
|
||||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
|
||||||
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<CS: CipherSuite> {
|
|
||||||
evaluation_element: GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
|
||||||
masking_nonce: GenericArray<u8, NonceLen>,
|
|
||||||
masked_response: MaskedResponse<CS>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> CredentialResponseParts<CS> {
|
|
||||||
pub(crate) fn new(
|
|
||||||
evaluation_element: &EvaluationElement<CS::OprfCs>,
|
|
||||||
masking_nonce: GenericArray<u8, NonceLen>,
|
|
||||||
masked_response: MaskedResponse<CS>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
evaluation_element: evaluation_element.serialize(),
|
|
||||||
masking_nonce,
|
|
||||||
masked_response,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
|
||||||
[self.evaluation_element.as_slice(), &self.masking_nonce]
|
|
||||||
.into_iter()
|
|
||||||
.chain(self.masked_response.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
|
||||||
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<CS: CipherSuite> =
|
|
||||||
Sum<Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>, MaskedResponseLen<CS>>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> Serialize for CredentialResponseParts<CS>
|
|
||||||
where
|
|
||||||
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
|
||||||
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
|
||||||
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
|
||||||
CredentialResponsePartsLen<CS>: ArrayLength<u8>,
|
|
||||||
{
|
|
||||||
type Len = CredentialResponsePartsLen<CS>;
|
|
||||||
|
|
||||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
|
||||||
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<u8, U2>,
|
|
||||||
#[zeroize(skip)]
|
|
||||||
context: &'a [u8],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializedContext<'a> {
|
|
||||||
pub(crate) fn from(context: Option<&'a [u8]>) -> Result<Self, ProtocolError> {
|
|
||||||
let context = context.unwrap_or(&[]);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
length: i2osp::<U2>(context.len())?,
|
|
||||||
context,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
|
||||||
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<u8, U2>,
|
|
||||||
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<u8, G::PkLen>),
|
|
||||||
#[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<u8, G::PkLen>,
|
|
||||||
server_s_pk: GenericArray<u8, G::PkLen>,
|
|
||||||
) -> Result<Self, ProtocolError> {
|
|
||||||
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<u8, G::PkLen>,
|
|
||||||
) -> Result<Self, ProtocolError> {
|
|
||||||
if let Some(id) = id {
|
|
||||||
Ok(SerializedIdentifier {
|
|
||||||
length: i2osp::<U2>(id.len())?,
|
|
||||||
identifier: Identifier::Borrowed(id),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(SerializedIdentifier {
|
|
||||||
length: i2osp::<U2>(s_pk.len())?,
|
|
||||||
identifier: Identifier::Owned(s_pk),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn iter(&self) -> impl Clone + Iterator<Item = &[u8]> {
|
|
||||||
// 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<Self, ProtocolError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Serialize {
|
|
||||||
type Len: ArrayLength<u8>;
|
|
||||||
|
|
||||||
fn serialize(&self) -> GenericArray<u8, Self::Len>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
pub type GenerateKe2Result<CS: CipherSuite> = (
|
|
||||||
<CS::KeyExchange as KeyExchange>::KE2State<CS>,
|
|
||||||
<CS::KeyExchange as KeyExchange>::KE2Message,
|
|
||||||
);
|
|
||||||
#[cfg(test)]
|
|
||||||
pub type GenerateKe2Result<CS: CipherSuite> = (
|
|
||||||
<CS::KeyExchange as KeyExchange>::KE2State<CS>,
|
|
||||||
<CS::KeyExchange as KeyExchange>::KE2Message,
|
|
||||||
Output<KeHash<CS>>,
|
|
||||||
Output<KeHash<CS>>,
|
|
||||||
);
|
|
||||||
#[cfg(not(test))]
|
|
||||||
pub type GenerateKe3Result<K: KeyExchange> = (Output<K::Hash>, K::KE3Message);
|
|
||||||
#[cfg(test)]
|
|
||||||
pub type GenerateKe3Result<K: KeyExchange> = (
|
|
||||||
Output<K::Hash>,
|
|
||||||
K::KE3Message,
|
|
||||||
Output<K::Hash>,
|
|
||||||
Output<K::Hash>,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub type Ke1StateLen<CS: CipherSuite> =
|
|
||||||
<<CS::KeyExchange as KeyExchange>::KE1State as Serialize>::Len;
|
|
||||||
pub type Ke1MessageLen<CS: CipherSuite> =
|
|
||||||
<<CS::KeyExchange as KeyExchange>::KE1Message as Serialize>::Len;
|
|
||||||
pub type Ke2StateLen<CS: CipherSuite> =
|
|
||||||
<<CS::KeyExchange as KeyExchange>::KE2State<CS> as Serialize>::Len;
|
|
||||||
pub type Ke2MessageLen<CS: CipherSuite> =
|
|
||||||
<<CS::KeyExchange as KeyExchange>::KE2Message as Serialize>::Len;
|
|
||||||
pub type Ke3MessageLen<CS: CipherSuite> =
|
|
||||||
<<CS::KeyExchange as KeyExchange>::KE3Message as Serialize>::Len;
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Test Implementations //
|
|
||||||
//===================== //
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use crate::serialization::AssertZeroized;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
impl<CS: CipherSuite> AssertZeroized for CredentialRequestParts<CS> {
|
|
||||||
fn assert_zeroized(&self) {
|
|
||||||
let Self(blinded_element) = self;
|
|
||||||
|
|
||||||
for byte in blinded_element.iter() {
|
|
||||||
assert_eq!(byte, &0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
impl<CS: CipherSuite> AssertZeroized for CredentialResponseParts<CS> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,16 +22,17 @@ use rand::{CryptoRng, RngCore};
|
|||||||
use subtle::{ConstantTimeEq, CtOption};
|
use subtle::{ConstantTimeEq, CtOption};
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
Deserialize, GenerateKe1Result, GenerateKe2Result, GenerateKe3Result, KeyExchange, Serialize,
|
||||||
|
SerializedContext, SerializedCredentialRequest, SerializedCredentialResponse,
|
||||||
|
SerializedIdentifiers,
|
||||||
|
};
|
||||||
use crate::ciphersuite::{CipherSuite, KeGroup};
|
use crate::ciphersuite::{CipherSuite, KeGroup};
|
||||||
use crate::errors::{InternalError, ProtocolError};
|
use crate::errors::{InternalError, ProtocolError};
|
||||||
use crate::hash::{Hash, OutputSize, ProxyHash};
|
use crate::hash::{Hash, OutputSize, ProxyHash};
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::{self, NonceLen};
|
use crate::key_exchange::shared::{self, NonceLen};
|
||||||
pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State};
|
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::keypair::{KeyPair, PrivateKey, PublicKey};
|
||||||
use crate::opaque::Identifiers;
|
use crate::opaque::Identifiers;
|
||||||
use crate::serialization::SliceExt;
|
use crate::serialization::SliceExt;
|
||||||
@@ -151,15 +152,15 @@ where
|
|||||||
|
|
||||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> {
|
) -> Result<GenerateKe1Result<Self>, ProtocolError> {
|
||||||
shared::generate_ke1(rng)
|
shared::generate_ke1(rng)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
credential_request: CredentialRequestParts<CS>,
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
credential_response: CredentialResponseParts<CS>,
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
client_s_pk: PublicKey<G>,
|
client_s_pk: PublicKey<G>,
|
||||||
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
||||||
context: SerializedContext<'a>,
|
context: SerializedContext<'a>,
|
||||||
@@ -240,30 +241,30 @@ where
|
|||||||
);
|
);
|
||||||
let expected_mac = mac_hasher.finalize().into_bytes();
|
let expected_mac = mac_hasher.finalize().into_bytes();
|
||||||
|
|
||||||
Ok((
|
Ok(GenerateKe2Result {
|
||||||
Ke2State {
|
state: Ke2State {
|
||||||
session_key: derived_keys.session_key,
|
session_key: derived_keys.session_key,
|
||||||
expected_mac,
|
expected_mac,
|
||||||
},
|
},
|
||||||
Ke2Message {
|
message: Ke2Message {
|
||||||
server_nonce: builder.server_nonce,
|
server_nonce: builder.server_nonce,
|
||||||
server_e_pk: builder.server_e_pk.clone(),
|
server_e_pk: builder.server_e_pk.clone(),
|
||||||
mac,
|
mac,
|
||||||
},
|
},
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.handshake_secret,
|
handshake_secret: derived_keys.handshake_secret,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.km2,
|
km2: derived_keys.km2,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||||
_: &mut R,
|
_: &mut R,
|
||||||
credential_request: CredentialRequestParts<CS>,
|
credential_request: SerializedCredentialRequest<CS>,
|
||||||
ke1_message: Self::KE1Message,
|
ke1_message: Self::KE1Message,
|
||||||
credential_response: CredentialResponseParts<CS>,
|
credential_response: SerializedCredentialResponse<CS>,
|
||||||
ke2_message: Self::KE2Message,
|
|
||||||
ke1_state: &Self::KE1State,
|
ke1_state: &Self::KE1State,
|
||||||
|
ke2_message: Self::KE2Message,
|
||||||
server_s_pk: PublicKey<G>,
|
server_s_pk: PublicKey<G>,
|
||||||
client_s_sk: PrivateKey<G>,
|
client_s_sk: PrivateKey<G>,
|
||||||
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
|
||||||
@@ -309,21 +310,21 @@ where
|
|||||||
Hmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
Hmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||||
Mac::update(&mut client_mac, &transcript_hasher.finalize());
|
Mac::update(&mut client_mac, &transcript_hasher.finalize());
|
||||||
|
|
||||||
Ok((
|
Ok(GenerateKe3Result {
|
||||||
derived_keys.session_key,
|
session_key: derived_keys.session_key,
|
||||||
Ke3Message {
|
message: Ke3Message {
|
||||||
mac: client_mac.finalize().into_bytes(),
|
mac: client_mac.finalize().into_bytes(),
|
||||||
},
|
},
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.handshake_secret,
|
handshake_secret: derived_keys.handshake_secret,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
derived_keys.km3,
|
km3: derived_keys.km3,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_ke<CS: CipherSuite>(
|
fn finish_ke<CS: CipherSuite>(
|
||||||
ke3_message: Self::KE3Message,
|
|
||||||
ke2_state: &Self::KE2State<CS>,
|
ke2_state: &Self::KE2State<CS>,
|
||||||
|
ke3_message: Self::KE3Message,
|
||||||
_: Identifiers<'_>,
|
_: Identifiers<'_>,
|
||||||
_: SerializedContext<'_>,
|
_: SerializedContext<'_>,
|
||||||
) -> Result<Output<H>, ProtocolError> {
|
) -> Result<Output<H>, ProtocolError> {
|
||||||
@@ -336,14 +337,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group + 'static, H: Hash> Sealed for TripleDh<G, H>
|
|
||||||
where
|
|
||||||
H::Core: ProxyHash,
|
|
||||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
|
||||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
// Trait Implementations //
|
// Trait Implementations //
|
||||||
// ========================================== //
|
// ========================================== //
|
||||||
|
|||||||
+8
-3
@@ -97,7 +97,8 @@ impl<G: Group> PrivateKey<G> {
|
|||||||
PublicKey(G::public_key(self.0))
|
PublicKey(G::public_key(self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn serialize(&self) -> GenericArray<u8, G::SkLen> {
|
/// Serializes this private key to a fixed-length byte array.
|
||||||
|
pub fn serialize(&self) -> GenericArray<u8, G::SkLen> {
|
||||||
G::serialize_sk(self.0)
|
G::serialize_sk(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,8 +150,10 @@ pub trait PrivateKeySerialization<G: Group>: Clone {
|
|||||||
fn serialize_key_pair(key_pair: &KeyPair<G, Self>) -> GenericArray<u8, Self::Len>;
|
fn serialize_key_pair(key_pair: &KeyPair<G, Self>) -> GenericArray<u8, Self::Len>;
|
||||||
|
|
||||||
/// Deserialization from bytes
|
/// Deserialization from bytes
|
||||||
|
///
|
||||||
|
/// The deserialized bytes must be taken from `bytes`.
|
||||||
fn deserialize_take_key_pair(
|
fn deserialize_take_key_pair(
|
||||||
input: &mut &[u8],
|
bytes: &mut &[u8],
|
||||||
) -> Result<KeyPair<G, Self>, ProtocolError<Self::Error>>;
|
) -> Result<KeyPair<G, Self>, ProtocolError<Self::Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +284,9 @@ pub trait OprfSeedSerialization<H, E>: Sized {
|
|||||||
fn serialize(&self) -> GenericArray<u8, Self::Len>;
|
fn serialize(&self) -> GenericArray<u8, Self::Len>;
|
||||||
|
|
||||||
/// Deserialization from bytes
|
/// Deserialization from bytes
|
||||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError<E>>;
|
///
|
||||||
|
/// The deserialized bytes must be taken from `bytes`.
|
||||||
|
fn deserialize_take(bytes: &mut &[u8]) -> Result<Self, ProtocolError<E>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: OutputSizeUser, E> OprfSeedSerialization<H, E> for OprfSeed<H> {
|
impl<H: OutputSizeUser, E> OprfSeedSerialization<H, E> for OprfSeed<H> {
|
||||||
|
|||||||
+1
-1
@@ -1349,9 +1349,9 @@ mod tests;
|
|||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
|
|
||||||
pub use ciphersuite::CipherSuite;
|
|
||||||
pub use rand;
|
pub use rand;
|
||||||
|
|
||||||
|
pub use crate::ciphersuite::CipherSuite;
|
||||||
#[cfg(feature = "curve25519")]
|
#[cfg(feature = "curve25519")]
|
||||||
pub use crate::key_exchange::group::curve25519::Curve25519;
|
pub use crate::key_exchange::group::curve25519::Curve25519;
|
||||||
#[cfg(feature = "ed25519")]
|
#[cfg(feature = "ed25519")]
|
||||||
|
|||||||
+7
-7
@@ -25,9 +25,9 @@ use crate::errors::ProtocolError;
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::NonceLen;
|
use crate::key_exchange::shared::NonceLen;
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{
|
||||||
CredentialRequestParts, CredentialResponseParts, Deserialize, Ke1MessageLen, Ke2MessageLen,
|
Deserialize, Ke1MessageLen, Ke2MessageLen, Ke3MessageLen, KeyExchange, Serialize,
|
||||||
Ke3MessageLen, KeyExchange, Serialize,
|
SerializedCredentialRequest, SerializedCredentialResponse,
|
||||||
};
|
};
|
||||||
use crate::keypair::PublicKey;
|
use crate::keypair::PublicKey;
|
||||||
use crate::opaque::{
|
use crate::opaque::{
|
||||||
@@ -359,8 +359,8 @@ impl<CS: CipherSuite> CredentialRequest<CS> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_parts(&self) -> CredentialRequestParts<CS> {
|
pub(crate) fn to_parts(&self) -> SerializedCredentialRequest<CS> {
|
||||||
CredentialRequestParts::new(&self.blinded_element)
|
SerializedCredentialRequest::new(&self.blinded_element)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only used for testing purposes
|
/// Only used for testing purposes
|
||||||
@@ -415,8 +415,8 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_parts(&self) -> CredentialResponseParts<CS> {
|
pub(crate) fn to_parts(&self) -> SerializedCredentialResponse<CS> {
|
||||||
CredentialResponseParts::new(
|
SerializedCredentialResponse::new(
|
||||||
&self.evaluation_element,
|
&self.evaluation_element,
|
||||||
self.masking_nonce,
|
self.masking_nonce,
|
||||||
self.masked_response.clone(),
|
self.masked_response.clone(),
|
||||||
|
|||||||
+17
-17
@@ -27,9 +27,9 @@ use crate::errors::{InternalError, ProtocolError};
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::NonceLen;
|
use crate::key_exchange::shared::NonceLen;
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{
|
||||||
CredentialResponseParts, Deserialize, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange,
|
Deserialize, Ke1MessageLen, Ke1StateLen, Ke2StateLen, KeyExchange, Serialize,
|
||||||
Serialize, SerializedContext, SerializedIdentifiers,
|
SerializedContext, SerializedCredentialResponse, SerializedIdentifiers,
|
||||||
};
|
};
|
||||||
use crate::keypair::{
|
use crate::keypair::{
|
||||||
KeyPair, OprfSeed, OprfSeedSerialization, PrivateKey, PrivateKeySerialization, PublicKey,
|
KeyPair, OprfSeed, OprfSeedSerialization, PrivateKey, PrivateKeySerialization, PublicKey,
|
||||||
@@ -503,18 +503,18 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
password: &[u8],
|
password: &[u8],
|
||||||
) -> Result<ClientLoginStartResult<CS>, ProtocolError> {
|
) -> Result<ClientLoginStartResult<CS>, ProtocolError> {
|
||||||
let blind_result = blind::<CS, _>(rng, password)?;
|
let blind_result = blind::<CS, _>(rng, password)?;
|
||||||
let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(rng)?;
|
let ke1_result = CS::KeyExchange::generate_ke1(rng)?;
|
||||||
|
|
||||||
let credential_request = CredentialRequest {
|
let credential_request = CredentialRequest {
|
||||||
blinded_element: blind_result.message,
|
blinded_element: blind_result.message,
|
||||||
ke1_message,
|
ke1_message: ke1_result.message,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ClientLoginStartResult {
|
Ok(ClientLoginStartResult {
|
||||||
message: credential_request.clone(),
|
message: credential_request.clone(),
|
||||||
state: Self {
|
state: Self {
|
||||||
oprf_client: blind_result.state,
|
oprf_client: blind_result.state,
|
||||||
ke1_state,
|
ke1_state: ke1_result.state,
|
||||||
credential_request,
|
credential_request,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -582,8 +582,8 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
self.credential_request.to_parts(),
|
self.credential_request.to_parts(),
|
||||||
self.credential_request.ke1_message.clone(),
|
self.credential_request.ke1_message.clone(),
|
||||||
credential_response.to_parts(),
|
credential_response.to_parts(),
|
||||||
credential_response.ke2_message,
|
|
||||||
&self.ke1_state,
|
&self.ke1_state,
|
||||||
|
credential_response.ke2_message,
|
||||||
server_s_pk.clone(),
|
server_s_pk.clone(),
|
||||||
opened_envelope.client_static_keypair.private().clone(),
|
opened_envelope.client_static_keypair.private().clone(),
|
||||||
opened_envelope.identifiers,
|
opened_envelope.identifiers,
|
||||||
@@ -592,17 +592,17 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
|
|
||||||
Ok(ClientLoginFinishResult {
|
Ok(ClientLoginFinishResult {
|
||||||
message: CredentialFinalization {
|
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,
|
export_key: opened_envelope.export_key,
|
||||||
server_s_pk,
|
server_s_pk,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
state: self,
|
state: self,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
handshake_secret: result.2,
|
handshake_secret: result.handshake_secret,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
client_mac_key: result.3,
|
client_mac_key: result.km3,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -679,7 +679,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
|||||||
let server = voprf::OprfServer::new_with_key(&oprf_key).map_err(ProtocolError::from)?;
|
let server = voprf::OprfServer::new_with_key(&oprf_key).map_err(ProtocolError::from)?;
|
||||||
let evaluation_element = server.blind_evaluate(&credential_request.blinded_element);
|
let evaluation_element = server.blind_evaluate(&credential_request.blinded_element);
|
||||||
|
|
||||||
let credential_response = CredentialResponseParts::new(
|
let credential_response = SerializedCredentialResponse::new(
|
||||||
&evaluation_element,
|
&evaluation_element,
|
||||||
masking_nonce,
|
masking_nonce,
|
||||||
masked_response.clone(),
|
masked_response.clone(),
|
||||||
@@ -743,18 +743,18 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
|||||||
evaluation_element: builder.evaluation_element.clone(),
|
evaluation_element: builder.evaluation_element.clone(),
|
||||||
masking_nonce: *builder.masking_nonce.deref(),
|
masking_nonce: *builder.masking_nonce.deref(),
|
||||||
masked_response: builder.masked_response.clone(),
|
masked_response: builder.masked_response.clone(),
|
||||||
ke2_message: result.1,
|
ke2_message: result.message,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ServerLoginStartResult {
|
Ok(ServerLoginStartResult {
|
||||||
message: credential_response,
|
message: credential_response,
|
||||||
state: Self {
|
state: Self {
|
||||||
ke2_state: result.0,
|
ke2_state: result.state,
|
||||||
},
|
},
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
handshake_secret: result.2,
|
handshake_secret: result.handshake_secret,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
server_mac_key: result.3,
|
server_mac_key: result.km2,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
oprf_key: builder.oprf_key.deref().clone(),
|
oprf_key: builder.oprf_key.deref().clone(),
|
||||||
})
|
})
|
||||||
@@ -797,8 +797,8 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
|||||||
let context = SerializedContext::from(parameters.context)?;
|
let context = SerializedContext::from(parameters.context)?;
|
||||||
|
|
||||||
let session_key = <CS::KeyExchange as KeyExchange>::finish_ke(
|
let session_key = <CS::KeyExchange as KeyExchange>::finish_ke(
|
||||||
message.ke3_message,
|
|
||||||
&self.ke2_state,
|
&self.ke2_state,
|
||||||
|
message.ke3_message,
|
||||||
parameters.identifiers,
|
parameters.identifiers,
|
||||||
context,
|
context,
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use crate::errors::*;
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::NonceLen;
|
use crate::key_exchange::shared::NonceLen;
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{
|
||||||
Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize,
|
Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize,
|
||||||
};
|
};
|
||||||
use crate::keypair::KeyPair;
|
use crate::keypair::KeyPair;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use crate::errors::*;
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::NonceLen;
|
use crate::key_exchange::shared::NonceLen;
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{
|
||||||
Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize,
|
Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize,
|
||||||
};
|
};
|
||||||
use crate::ksf::Identity;
|
use crate::ksf::Identity;
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ use crate::errors::*;
|
|||||||
use crate::hash::OutputSize;
|
use crate::hash::OutputSize;
|
||||||
use crate::key_exchange::group::Group;
|
use crate::key_exchange::group::Group;
|
||||||
use crate::key_exchange::shared::NonceLen;
|
use crate::key_exchange::shared::NonceLen;
|
||||||
use crate::key_exchange::traits::{
|
use crate::key_exchange::{Deserialize, Ke1MessageLen, Ke2MessageLen, KeyExchange, Serialize};
|
||||||
Deserialize, Ke1MessageLen, Ke2MessageLen, KeyExchange, Serialize,
|
|
||||||
};
|
|
||||||
use crate::ksf::Identity;
|
use crate::ksf::Identity;
|
||||||
use crate::messages::{
|
use crate::messages::{
|
||||||
CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen,
|
CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen,
|
||||||
|
|||||||
Reference in New Issue
Block a user