Remove Zeroize Tests (#381)

* Remove Zeroize tests

* Remove `Zeroize` requirements from `Group::Pk`

* Remove `Copy` requirements from `Group::Pk`

* Change to `ZeroizeOnDrop` requirements for `Group::Sk`

* Add note why we don't use `elliptic_curve::PublicKey`
This commit is contained in:
daxpedda
2025-07-17 13:15:30 -07:00
committed by GitHub
parent 1b6633cdcc
commit c04fb97b5c
21 changed files with 110 additions and 841 deletions
+8 -30
View File
@@ -16,7 +16,7 @@ use generic_array::GenericArray;
use generic_array::typenum::U32;
use rand::{CryptoRng, RngCore};
use subtle::ConstantTimeEq;
use zeroize::Zeroize;
use zeroize::ZeroizeOnDrop;
use super::Group;
use crate::errors::{InternalError, ProtocolError};
@@ -33,7 +33,7 @@ impl Group for Curve25519 {
type Sk = Scalar;
type SkLen = U32;
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
pk.0.to_bytes().into()
}
@@ -56,11 +56,11 @@ impl Group for Curve25519 {
Ok(Scalar(scalar::clamp_integer(seed.into())))
}
fn public_key(sk: Self::Sk) -> Self::Pk {
fn public_key(sk: &Self::Sk) -> Self::Pk {
NonIdentity(MontgomeryPoint::mul_base_clamped(sk.0))
}
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.0.into()
}
@@ -72,14 +72,14 @@ impl Group for Curve25519 {
}
impl DiffieHellman<Curve25519> for Scalar {
fn diffie_hellman(self, pk: NonIdentity) -> GenericArray<u8, U32> {
Curve25519::serialize_pk(NonIdentity(pk.0.mul_clamped(self.0)))
fn diffie_hellman(&self, pk: &NonIdentity) -> GenericArray<u8, U32> {
Curve25519::serialize_pk(&NonIdentity(pk.0.mul_clamped(self.0)))
}
}
/// Non-identity point wrapper for [`MontgomeryPoint`].
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct NonIdentity(
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_pk"))]
MontgomeryPoint,
@@ -113,7 +113,7 @@ where
/// Curve25519 scalar.
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
#[derive(Clone, Debug, Eq, Hash, PartialEq, ZeroizeOnDrop)]
pub struct Scalar(
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_sk"))] [u8; 32],
);
@@ -142,28 +142,6 @@ where
.map_err(D::Error::custom)
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl AssertZeroized for NonIdentity {
fn assert_zeroized(&self) {
assert_eq!(self.0, MontgomeryPoint::default());
}
}
#[cfg(test)]
impl AssertZeroized for Scalar {
fn assert_zeroized(&self) {
assert_eq!(*self, Scalar(<_>::default()));
}
}
#[test]
fn non_zero_scalar() {
use std::vec;
+7 -45
View File
@@ -21,7 +21,7 @@ use generic_array::GenericArray;
use generic_array::sequence::Concat;
use generic_array::typenum::{U32, U64};
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
use super::Group;
use crate::ciphersuite::CipherSuite;
@@ -41,7 +41,7 @@ impl Group for Ed25519 {
type Sk = SigningKey;
type SkLen = U32;
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
pk.compressed.0.into()
}
@@ -62,11 +62,11 @@ impl Group for Ed25519 {
Ok(SigningKey::from_bytes(seed.into()))
}
fn public_key(sk: Self::Sk) -> Self::Pk {
fn public_key(sk: &Self::Sk) -> Self::Pk {
sk.verifying_key
}
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.sk.into()
}
@@ -300,7 +300,7 @@ impl serde::Serialize for VerifyingKey {
/// Ed25519 signing key.
// We store the `ExpandedSecret` in memory to avoid computing it on demand and then discarding it
// again.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
#[derive(Clone, Debug, Eq, PartialEq, ZeroizeOnDrop)]
pub struct SigningKey {
// `ed25519_dalek::SigningKey` doesn't implement `Zeroize`. See
// https://github.com/dalek-cryptography/curve25519-dalek/pull/747
@@ -428,44 +428,6 @@ impl Zeroize for Signature {
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl AssertZeroized for VerifyingKey {
fn assert_zeroized(&self) {
use curve25519_dalek::traits::Identity;
let Self { point, compressed } = self;
assert_eq!(point, &EdwardsPoint::identity());
assert_eq!(compressed, &EdwardsPoint::identity().compress());
}
}
#[cfg(test)]
impl AssertZeroized for SigningKey {
fn assert_zeroized(&self) {
let Self {
sk,
verifying_key,
scalar,
hash_prefix,
} = self;
verifying_key.assert_zeroized();
for byte in sk.iter().chain(scalar.to_bytes().iter()).chain(hash_prefix) {
assert_eq!(byte, &0);
}
}
}
#[cfg(test)]
mod test {
use std::iter;
@@ -497,7 +459,7 @@ mod test {
let verifying_key = VerifyingKey::from(&signing_key);
verifying_key.verify(&message, &signature).unwrap();
let custom_pk = Ed25519::public_key(custom_sk);
let custom_pk = Ed25519::public_key(&custom_sk);
verify(
&custom_pk,
false,
@@ -533,7 +495,7 @@ mod test {
.verify_prehashed(message, None, &signature)
.unwrap();
let custom_pk = Ed25519::public_key(custom_sk);
let custom_pk = Ed25519::public_key(&custom_sk);
verify(
&custom_pk,
true,
+25 -48
View File
@@ -15,13 +15,11 @@ use elliptic_curve::group::GroupEncoding;
use elliptic_curve::ops::MulByGenerator;
use elliptic_curve::sec1::{ModulusSize, ToEncodedPoint};
use elliptic_curve::{
CurveArithmetic, FieldBytesSize, Group as _, NonZeroScalar, ProjectivePoint, Scalar, SecretKey,
point,
CurveArithmetic, FieldBytesSize, NonZeroScalar, ProjectivePoint, Scalar, SecretKey, point,
};
use generic_array::GenericArray;
use rand::{CryptoRng, RngCore};
use voprf::Mode;
use zeroize::Zeroize;
use super::{Group, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
use crate::errors::{InternalError, ProtocolError};
@@ -36,15 +34,18 @@ where
Repr = GenericArray<u8, <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize>,
> + ToEncodedPoint<Self>,
{
// We don't use `elliptic_curve::PublicKey` because it stores its internals in a
// format ideal for serialization and not computation. This is inconsistent with
// our other implementations.
type Pk = NonIdentity<Self>;
type PkLen = <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize;
type Sk = NonZeroScalar<Self>;
type Sk = SecretKey<Self>;
type SkLen = FieldBytesSize<Self>;
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
GenericArray::clone_from_slice(pk.0.to_encoded_point(true).as_bytes())
}
@@ -56,7 +57,7 @@ where
}
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
SecretKey::<Self>::random(rng).to_nonzero_scalar()
SecretKey::<Self>::random(rng)
}
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError> {
@@ -64,29 +65,31 @@ where
.map(|scalar| {
NonZeroScalar::new(scalar).expect("`voprf::derive_key()` returned a zero scalar")
})
.map(SecretKey::from)
.map_err(InternalError::from)
}
fn public_key(sk: Self::Sk) -> Self::Pk {
fn public_key(sk: &Self::Sk) -> Self::Pk {
// Non-panicking version in https://github.com/RustCrypto/traits/pull/1833.
NonIdentity(
point::NonIdentity::new(ProjectivePoint::<Self>::mul_by_generator(&*sk))
.expect("multiplying with a non-zero scalar can never yield the identity element"),
point::NonIdentity::new(ProjectivePoint::<Self>::mul_by_generator(
&sk.to_nonzero_scalar(),
))
.expect("multiplying with a non-zero scalar can never yield the identity element"),
)
}
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.into()
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.to_bytes()
}
fn deserialize_take_sk(bytes: &mut &[u8]) -> Result<Self::Sk, ProtocolError> {
SecretKey::<Self>::from_bytes(&bytes.take_array("secret key")?)
.map(|secret_key| secret_key.to_nonzero_scalar())
.map_err(|_| ProtocolError::SerializationError)
}
}
impl<G> DiffieHellman<G> for NonZeroScalar<G>
impl<G> DiffieHellman<G> for SecretKey<G>
where
G: CurveArithmetic + voprf::CipherSuite<Group = G> + voprf::Group<Scalar = Scalar<G>>,
FieldBytesSize<G>: ModulusSize,
@@ -95,15 +98,19 @@ where
> + ToEncodedPoint<G>,
{
fn diffie_hellman(
self,
pk: NonIdentity<G>,
&self,
pk: &NonIdentity<G>,
) -> GenericArray<u8, <FieldBytesSize<G> as ModulusSize>::CompressedPointSize> {
GenericArray::clone_from_slice((pk.0 * self).to_encoded_point(true).as_bytes())
GenericArray::clone_from_slice(
(pk.0 * self.to_nonzero_scalar())
.to_encoded_point(true)
.as_bytes(),
)
}
}
/// Wrapper around [`NonIdentity`](point::NonIdentity) to implement [`Zeroize`].
// TODO: remove after https://github.com/RustCrypto/traits/pull/1832.
/// Wrapper around [`NonIdentity`](point::NonIdentity) to [`Eq`].
// TODO: remove after https://github.com/RustCrypto/traits/pull/1834.
#[derive_where(Clone, Copy)]
#[cfg_attr(
feature = "serde",
@@ -133,33 +140,3 @@ impl<G: CurveArithmetic> PartialEq for NonIdentity<G> {
}
impl<G: CurveArithmetic> Eq for NonIdentity<G> {}
impl<G: CurveArithmetic> Zeroize for NonIdentity<G> {
fn zeroize(&mut self) {
self.0 = point::NonIdentity::new(ProjectivePoint::<G>::generator()).unwrap();
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl<G: CurveArithmetic> AssertZeroized for NonIdentity<G> {
fn assert_zeroized(&self) {
assert_eq!(self.0.to_point(), ProjectivePoint::<G>::generator());
}
}
#[cfg(test)]
impl<G: CurveArithmetic> AssertZeroized for NonZeroScalar<G> {
fn assert_zeroized(&self) {
use elliptic_curve::Field;
assert_eq!(**self, Scalar::<G>::ONE);
}
}
+6 -6
View File
@@ -18,7 +18,7 @@ pub mod ristretto255;
use generic_array::{ArrayLength, GenericArray};
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
use zeroize::ZeroizeOnDrop;
use crate::errors::{InternalError, ProtocolError};
@@ -27,16 +27,16 @@ const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 33] = *b"OPAQUE-DeriveDiffieHellmanK
/// A group representation for use in the key exchange
pub trait Group {
/// Public key
type Pk: Copy + Zeroize;
type Pk: Clone;
/// Length of the public key
type PkLen: ArrayLength<u8>;
/// Secret key
type Sk: Copy + Zeroize;
type Sk: Clone + ZeroizeOnDrop;
/// Length of the secret key
type SkLen: ArrayLength<u8>;
/// Serializes `self`
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen>;
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen>;
/// Return a public key from its fixed-length bytes representation
///
@@ -50,10 +50,10 @@ pub trait Group {
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError>;
/// Return a public key from its secret key
fn public_key(sk: Self::Sk) -> Self::Pk;
fn public_key(sk: &Self::Sk) -> Self::Pk;
/// Serializes `self`
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen>;
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen>;
/// Return a public key from its fixed-length bytes representation
///
+8 -30
View File
@@ -19,7 +19,7 @@ use generic_array::GenericArray;
use generic_array::typenum::{IsLess, IsLessOrEqual, U32, U256};
use rand::{CryptoRng, RngCore};
use voprf::Mode;
use zeroize::Zeroize;
use zeroize::ZeroizeOnDrop;
use super::{Group, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
use crate::errors::{InternalError, ProtocolError};
@@ -37,7 +37,7 @@ impl Group for Ristretto255 {
type Sk = NonZeroScalar;
type SkLen = U32;
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
pk.0.compress().to_bytes().into()
}
@@ -64,11 +64,11 @@ impl Group for Ristretto255 {
.map_err(InternalError::from)
}
fn public_key(sk: Self::Sk) -> Self::Pk {
fn public_key(sk: &Self::Sk) -> Self::Pk {
NonIdentity(RISTRETTO_BASEPOINT_POINT * sk.0)
}
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.0.to_bytes().into()
}
@@ -81,14 +81,14 @@ impl Group for Ristretto255 {
}
impl DiffieHellman<Ristretto255> for NonZeroScalar {
fn diffie_hellman(self, pk: NonIdentity) -> GenericArray<u8, U32> {
Ristretto255::serialize_pk(NonIdentity(pk.0 * self.0))
fn diffie_hellman(&self, pk: &NonIdentity) -> GenericArray<u8, U32> {
Ristretto255::serialize_pk(&NonIdentity(pk.0 * self.0))
}
}
/// Non-identity point wrapper for [`RistrettoPoint`].
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct NonIdentity(
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_pk"))] RistrettoPoint,
);
@@ -119,7 +119,7 @@ where
/// Non-zero scalar wrapper for [`Scalar`]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
#[derive(Clone, Debug, Eq, Hash, PartialEq, ZeroizeOnDrop)]
pub struct NonZeroScalar(
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_sk"))] Scalar,
);
@@ -223,25 +223,3 @@ impl voprf::Group for Ristretto255 {
<voprf::Ristretto255 as voprf::Group>::deserialize_scalar(scalar_bits)
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl AssertZeroized for NonIdentity {
fn assert_zeroized(&self) {
assert_eq!(self.0, RistrettoPoint::default());
}
}
#[cfg(test)]
impl AssertZeroized for NonZeroScalar {
fn assert_zeroized(&self) {
assert_eq!(self.0, Scalar::default());
}
}
-38
View File
@@ -405,41 +405,3 @@ 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);
}
}
}
+2 -55
View File
@@ -50,7 +50,7 @@ static STR_OPAQUE: &[u8] = b"OPAQUE-";
/// [`TripleDh`](crate::TripleDh) and [`SigmaI`](crate::SigmaI).
pub trait DiffieHellman<G: Group> {
/// Diffie-Hellman key exchange.
fn diffie_hellman(self, pk: G::Pk) -> GenericArray<u8, G::PkLen>;
fn diffie_hellman(&self, pk: &G::Pk) -> GenericArray<u8, G::PkLen>;
}
/// The client state produced after the first key exchange message
@@ -82,6 +82,7 @@ pub struct Ke1State<G: Group> {
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; G::Pk)]
pub struct Ke1Message<G: Group> {
pub(super) client_nonce: GenericArray<u8, NonceLen>,
#[derive_where(skip(Zeroize))]
pub(super) client_e_pk: PublicKey<G>,
}
@@ -345,57 +346,3 @@ where
self.client_nonce.concat(self.client_e_pk.clone())
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl<G: Group> AssertZeroized for Ke1State<G>
where
G::Sk: AssertZeroized,
{
fn assert_zeroized(&self) {
let Self {
client_e_sk,
client_nonce,
} = self;
client_e_sk.assert_zeroized();
assert_eq!(client_nonce, &GenericArray::default());
}
}
#[cfg(test)]
impl<G: Group> AssertZeroized for Ke1Message<G>
where
G::Pk: AssertZeroized,
{
fn assert_zeroized(&self) {
let Self {
client_nonce,
client_e_pk,
} = self;
assert_eq!(client_nonce, &GenericArray::default());
client_e_pk.assert_zeroized();
}
}
#[cfg(test)]
impl<G: Group> AssertZeroized for Ke1MessageIter<G> {
fn assert_zeroized(&self) {
let Self {
client_nonce,
client_e_pk,
} = self;
for byte in client_nonce.iter().chain(client_e_pk) {
assert_eq!(byte, &0);
}
}
}
+8 -8
View File
@@ -16,8 +16,8 @@ use digest::core_api::BlockSizeUser;
use digest::{FixedOutputReset, HashMarker};
use ecdsa::{PrimeCurve, SignatureSize, hazmat};
use elliptic_curve::{
CurveArithmetic, Field, FieldBytes, FieldBytesEncoding, FieldBytesSize, NonZeroScalar,
PrimeField, Scalar,
CurveArithmetic, Field, FieldBytes, FieldBytesEncoding, FieldBytesSize, PrimeField, Scalar,
SecretKey,
};
use generic_array::{ArrayLength, GenericArray};
use rand::{CryptoRng, RngCore};
@@ -39,7 +39,7 @@ pub struct Ecdsa<G, H>(PhantomData<(G, H)>);
impl<G, H> SignatureProtocol for Ecdsa<G, H>
where
G: CurveArithmetic + Group<Sk = NonZeroScalar<G>, Pk = NonIdentity<G>> + PrimeCurve,
G: CurveArithmetic + Group<Sk = SecretKey<G>, Pk = NonIdentity<G>> + PrimeCurve,
SignatureSize<G>: ArrayLength<u8>,
H: Clone
+ Default
@@ -88,14 +88,14 @@ where
}
}
fn sign<R, C, H>(sk: &NonZeroScalar<C>, rng: &mut R, pre_hash: &[u8]) -> ecdsa::Signature<C>
fn sign<R, C, H>(sk: &SecretKey<C>, rng: &mut R, pre_hash: &[u8]) -> ecdsa::Signature<C>
where
R: CryptoRng + RngCore,
C: CurveArithmetic + PrimeCurve,
SignatureSize<C>: ArrayLength<u8>,
H: Default + BlockSizeUser + FixedOutputReset<OutputSize = FieldBytesSize<C>> + HashMarker,
{
let repr = sk.to_repr();
let repr = sk.to_bytes();
let order = C::ORDER.encode_field_bytes();
let z =
hazmat::bits2field::<C>(pre_hash).expect("hash output can not be shorter than a scalar");
@@ -109,7 +109,7 @@ where
let k =
Scalar::<C>::from_repr(rfc6979::generate_k::<H, _>(&repr, &order, &z, &ad)).unwrap();
if let Ok((signature, _)) = hazmat::sign_prehashed::<C, _>(sk, k, &z) {
if let Ok((signature, _)) = hazmat::sign_prehashed::<C, _>(&sk.to_nonzero_scalar(), k, &z) {
break signature;
}
}
@@ -175,14 +175,14 @@ fn ecdsa() {
let hash = Sha256::new_with_prefix(message);
let sk = NistP256::random_sk(&mut OsRng);
let signing_key = SigningKey::from(sk);
let signing_key = SigningKey::from(sk.clone());
let signature: Signature = signing_key.sign_digest_with_rng(&mut rng, hash.clone());
let custom_signature = sign::<_, _, Sha256>(&sk, &mut rng, &hash.clone().finalize());
assert_eq!(signature, custom_signature);
let pk = NistP256::public_key(sk);
let pk = NistP256::public_key(&sk);
let verifying_key = VerifyingKey::from(PublicKey::from(pk.0));
verifying_key
+7 -1
View File
@@ -192,12 +192,18 @@ impl<CS: CipherSuite, KE: Group> CachedMessage<CS, KE> {
derive(serde::Deserialize, serde::Serialize),
serde(bound = "")
)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub(super) enum Role {
Server,
Client,
}
impl Zeroize for Role {
fn zeroize(&mut self) {
*self = Self::Server;
}
}
enum Stage {
Sign,
Verify,
+4 -58
View File
@@ -155,7 +155,9 @@ pub trait SignatureProtocol {
pub struct Ke2Builder<'a, CS: CipherSuite, KE: Group> {
transcript: Message<'a, CS, KE>,
server_nonce: GenericArray<u8, NonceLen>,
#[derive_where(skip(Zeroize))]
client_s_pk: PublicKey<KeGroup<CS>>,
#[derive_where(skip(Zeroize))]
server_e_pk: PublicKey<KE>,
expected_mac: Output<KeHash<CS>>,
session_key: Output<KeHash<CS>>,
@@ -179,6 +181,7 @@ pub struct Ke2Builder<'a, CS: CipherSuite, KE: Group> {
#[derive_where(Clone, ZeroizeOnDrop)]
#[derive_where(Debug, Eq, Hash, PartialEq; <SIG::Group as Group>::Pk, SIG::VerifyState<CS, KE>)]
pub struct Ke2State<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> {
#[derive_where(skip(Zeroize))]
client_s_pk: PublicKey<SIG::Group>,
session_key: Output<KeHash<CS>>,
verify_state: SIG::VerifyState<CS, KE>,
@@ -203,6 +206,7 @@ where
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
server_nonce: GenericArray<u8, NonceLen>,
#[derive_where(skip(Zeroize))]
server_e_pk: PublicKey<KE>,
signature: SIG::Signature,
mac: Output<KEH>,
@@ -583,61 +587,3 @@ where
SIG::serialize_signature(&self.signature).concat(self.mac.clone())
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::key_exchange::shared::Ke1MessageIter;
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl<CS: CipherSuite, KE: Group> AssertZeroized for CachedMessage<CS, KE>
where
Ke1MessageIter<KE>: AssertZeroized,
{
fn assert_zeroized(&self) {
let Self {
credential_request,
ke1_message,
credential_response,
server_nonce,
server_e_pk,
server_mac,
} = self;
credential_request.assert_zeroized();
ke1_message.assert_zeroized();
credential_response.assert_zeroized();
for byte in server_nonce.iter().chain(server_e_pk).chain(server_mac) {
assert_eq!(byte, &0);
}
}
}
#[cfg(test)]
impl<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> AssertZeroized for Ke2State<CS, SIG, KE>
where
<SIG::Group as Group>::Pk: AssertZeroized,
SIG::VerifyState<CS, KE>: AssertZeroized,
{
fn assert_zeroized(&self) {
let Self {
client_s_pk,
session_key,
verify_state,
expected_mac,
} = self;
client_s_pk.assert_zeroized();
verify_state.assert_zeroized();
for byte in session_key.iter().chain(expected_mac) {
assert_eq!(byte, &0);
}
}
}
-15
View File
@@ -37,18 +37,3 @@ impl<H: OutputSizeUser> Serialize for PreHash<H> {
self.0.clone()
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl<H: OutputSizeUser> AssertZeroized for PreHash<H> {
fn assert_zeroized(&self) {
assert_eq!(self.0, GenericArray::default());
}
}
+5 -28
View File
@@ -109,6 +109,7 @@ where
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
server_nonce: GenericArray<u8, NonceLen>,
#[derive_where(skip(Zeroize))]
server_e_pk: PublicKey<G>,
mac: Output<H>,
}
@@ -375,6 +376,8 @@ where
}
}
/// TODO: implement via derive after hash crates get `Zeroize` support in
/// `digest` v11.
impl<G: Group, H: Hash> Drop for Ke2Builder<G, H>
where
H::Core: ProxyHash,
@@ -382,21 +385,17 @@ where
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
fn drop(&mut self) {
struct AssertZeroizeOnDrop<'a, T: ZeroizeOnDrop>(#[allow(unused)] &'a T);
let Self {
server_nonce,
transcript_hasher,
client_e_pk,
server_e_pk,
client_e_pk: _,
server_e_pk: _,
shared_secret_1,
shared_secret_3,
} = self;
server_nonce.zeroize();
transcript_hasher.reset();
let _ = AssertZeroizeOnDrop(client_e_pk);
let _ = AssertZeroizeOnDrop(server_e_pk);
shared_secret_1.zeroize();
shared_secret_3.zeroize();
}
@@ -469,25 +468,3 @@ where
self.mac.clone()
}
}
//////////////////////////
// Test Implementations //
//===================== //
//////////////////////////
#[cfg(test)]
use crate::serialization::AssertZeroized;
#[cfg(test)]
impl<H: OutputSizeUser> AssertZeroized for Ke2State<H> {
fn assert_zeroized(&self) {
let Self {
session_key,
expected_mac,
} = self;
for byte in session_key.iter().chain(expected_mac) {
assert_eq!(byte, &0);
}
}
}