surface the potential breakages out of copy_from_slice

This commit is contained in:
François Garillot
2020-09-19 19:16:31 -04:00
parent 3c555e82ae
commit 3c2a208606
5 changed files with 31 additions and 26 deletions
+3 -2
View File
@@ -58,6 +58,7 @@ pub fn hash_to_point(bytes: &[u8]) -> EdwardsPoint {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::convert::TryInto;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Signal tests from // // Signal tests from //
@@ -73,8 +74,8 @@ mod tests {
#[test] #[test]
fn elligator_correct() { fn elligator_correct() {
let bytes: Vec<u8> = (0u8..32u8).collect(); let bytes: Vec<u8> = (0u8..32u8).collect();
let mut bits_in = [0u8; 32]; let bits_in: [u8; 32] = (&bytes[..]).try_into().expect("Range invariant broken");
bits_in.copy_from_slice(&bytes);
let fe = FieldElement51::from_bytes(&bits_in); let fe = FieldElement51::from_bytes(&bits_in);
let eg = elligator_signal(&fe); let eg = elligator_signal(&fe);
assert_eq!(eg.to_bytes(), ELLIGATOR_CORRECT_OUTPUT); assert_eq!(eg.to_bytes(), ELLIGATOR_CORRECT_OUTPUT);
+11 -6
View File
@@ -19,6 +19,7 @@ use generic_array::{
ArrayLength, GenericArray, ArrayLength, GenericArray,
}; };
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use std::convert::TryInto;
use std::ops::Mul; use std::ops::Mul;
use zeroize::Zeroize; use zeroize::Zeroize;
@@ -86,7 +87,8 @@ impl Group for RistrettoPoint {
element_bits: &GenericArray<u8, Self::ElemLen>, element_bits: &GenericArray<u8, Self::ElemLen>,
) -> Result<Self, InternalPakeError> { ) -> Result<Self, InternalPakeError> {
CompressedRistretto::from_slice(element_bits) CompressedRistretto::from_slice(element_bits)
.decompress().ok_or(InternalPakeError::PointError) .decompress()
.ok_or(InternalPakeError::PointError)
} }
// serialization of a group element // serialization of a group element
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> { fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
@@ -96,8 +98,9 @@ impl Group for RistrettoPoint {
type UniformBytesLen = U64; type UniformBytesLen = U64;
fn hash_to_curve(uniform_bytes: &GenericArray<u8, Self::UniformBytesLen>) -> Self { fn hash_to_curve(uniform_bytes: &GenericArray<u8, Self::UniformBytesLen>) -> Self {
let mut bits = [0u8; 64]; let bits: [u8; 64] = (&uniform_bytes[..])
bits.copy_from_slice(&uniform_bytes); .try_into()
.expect("GenericArray has a type-level length");
RistrettoPoint::from_uniform_bytes(&bits) RistrettoPoint::from_uniform_bytes(&bits)
} }
@@ -130,7 +133,8 @@ impl Group for EdwardsPoint {
element_bits: &GenericArray<u8, Self::ElemLen>, element_bits: &GenericArray<u8, Self::ElemLen>,
) -> Result<Self, InternalPakeError> { ) -> Result<Self, InternalPakeError> {
let point = CompressedEdwardsY::from_slice(element_bits) let point = CompressedEdwardsY::from_slice(element_bits)
.decompress().ok_or(InternalPakeError::PointError)?; .decompress()
.ok_or(InternalPakeError::PointError)?;
if point.is_small_order() { if point.is_small_order() {
return Err(InternalPakeError::SubGroupError); return Err(InternalPakeError::SubGroupError);
@@ -190,8 +194,9 @@ mod tests {
]; ];
fn deserialize_point(pt: &[u8]) -> Result<EdwardsPoint> { fn deserialize_point(pt: &[u8]) -> Result<EdwardsPoint> {
let mut bytes = [0u8; 32]; let bytes: [u8; 32] = (&pt[..32])
bytes.copy_from_slice(&pt[..32]); .try_into()
.expect("Slice pattern invariant broken");
curve25519_dalek::edwards::CompressedEdwardsY(bytes) curve25519_dalek::edwards::CompressedEdwardsY(bytes)
.decompress() .decompress()
+5 -4
View File
@@ -16,6 +16,7 @@ use proptest::prelude::*;
#[cfg(test)] #[cfg(test)]
use rand::{rngs::StdRng, SeedableRng}; use rand::{rngs::StdRng, SeedableRng};
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use std::convert::TryInto;
use std::fmt::Debug; use std::fmt::Debug;
use x25519_dalek::{PublicKey, StaticSecret}; use x25519_dalek::{PublicKey, StaticSecret};
@@ -216,15 +217,15 @@ impl KeyPair for X25519KeyPair {
} }
fn public_from_private(secret: &Self::Repr) -> Self::Repr { fn public_from_private(secret: &Self::Repr) -> Self::Repr {
let mut secret_data = [0u8; 32]; let secret_data: [u8; 32] = (&secret.0[..])
secret_data.copy_from_slice(&secret.0[..]); .try_into()
.expect("Keypair::Repr invariant broken");
let base_data = ::x25519_dalek::X25519_BASEPOINT_BYTES; let base_data = ::x25519_dalek::X25519_BASEPOINT_BYTES;
Key(::x25519_dalek::x25519(secret_data, base_data).to_vec()) Key(::x25519_dalek::x25519(secret_data, base_data).to_vec())
} }
fn check_public_key(key: Self::Repr) -> Result<Self::Repr, InternalPakeError> { fn check_public_key(key: Self::Repr) -> Result<Self::Repr, InternalPakeError> {
let mut key_bytes = [0u8; 32]; let key_bytes: [u8; 32] = (&key[..]).try_into().expect("Key invariant broken");
key_bytes.copy_from_slice(&key);
let point = ::curve25519_dalek::montgomery::MontgomeryPoint(key_bytes) let point = ::curve25519_dalek::montgomery::MontgomeryPoint(key_bytes)
.to_edwards(1) .to_edwards(1)
.ok_or(InternalPakeError::PointError)?; .ok_or(InternalPakeError::PointError)?;
+6 -13
View File
@@ -533,14 +533,12 @@ where
/// byte representation for the server's registration state /// byte representation for the server's registration state
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec(); let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec();
match &self.client_s_pk { self.client_s_pk
Some(v) => output.extend_from_slice(&v.to_arr()), .iter()
None => {} .for_each(|v| output.extend_from_slice(&v));
}; self.envelope
match &self.envelope { .iter()
Some(v) => output.extend_from_slice(&v.to_bytes()), .for_each(|v| output.extend_from_slice(&v.to_bytes()));
None => {}
};
output output
} }
@@ -641,8 +639,6 @@ where
/// The state elements the client holds to perform a login /// The state elements the client holds to perform a login
pub struct ClientLogin<CS: CipherSuite> { pub struct ClientLogin<CS: CipherSuite> {
/// A choice of the keypair type
_key_format: PhantomData<CS::KeyFormat>,
/// A blinding factor, which is used to mask (and unmask) secret /// A blinding factor, which is used to mask (and unmask) secret
/// information before transmission /// information before transmission
blinding_factor: <CS::Group as Group>::Scalar, blinding_factor: <CS::Group as Group>::Scalar,
@@ -675,7 +671,6 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
)?; )?;
let password = bytes[scalar_len + ke1_state_size..].to_vec(); let password = bytes[scalar_len + ke1_state_size..].to_vec();
Ok(Self { Ok(Self {
_key_format: PhantomData,
blinding_factor, blinding_factor,
password, password,
ke1_state, ke1_state,
@@ -745,7 +740,6 @@ impl<CS: CipherSuite> ClientLogin<CS> {
Ok(( Ok((
l1, l1,
Self { Self {
_key_format: PhantomData,
blinding_factor, blinding_factor,
password: password.to_vec(), password: password.to_vec(),
ke1_state, ke1_state,
@@ -986,7 +980,6 @@ impl<CS: CipherSuite> ServerLogin<CS> {
} }
// Helper functions // Helper functions
fn get_password_derived_key<G: Group, SH: SlowHash<D>, D: Hash>( fn get_password_derived_key<G: Group, SH: SlowHash<D>, D: Hash>(
password: Vec<u8>, password: Vec<u8>,
beta: G, beta: G,
+6 -1
View File
@@ -558,7 +558,12 @@ fn test_complete_flow(
hex::encode(login_export_key) hex::encode(login_export_key)
); );
} else { } else {
let res = matches!(client_login_result, Err(ProtocolError::VerificationError(PakeError::InvalidLoginError))); let res = matches!(
client_login_result,
Err(ProtocolError::VerificationError(
PakeError::InvalidLoginError
))
);
assert!(res); assert!(res);
} }