Add zeroize on drop for remaining intermediate API states and tests

This commit is contained in:
Kevin Lewi
2021-06-04 16:37:54 -07:00
committed by Kevin Lewi
parent 468e0690d7
commit 8bc5e7dc02
9 changed files with 605 additions and 56 deletions
Generated
+3 -1
View File
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aead"
version = "0.3.2"
@@ -556,7 +558,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "opaque-ke"
version = "0.5.0"
version = "0.5.1-pre.1"
dependencies = [
"anyhow",
"base64",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "opaque-ke"
version = "0.5.0"
version = "0.5.1-pre.1"
repository = "https://github.com/novifinancial/opaque-ke"
keywords = ["cryptography", "crypto", "opaque", "passwords", "authentication"]
description = "An implementation of the OPAQUE password-authenticated key exchange protocol"
+38 -1
View File
@@ -16,6 +16,7 @@ use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
use zeroize::Zeroize;
// Constant string used as salt for HKDF computation
const STR_PAD: &[u8] = b"Pad";
@@ -24,7 +25,8 @@ const STR_EXPORT_KEY: &[u8] = b"ExportKey";
const NONCE_LEN: usize = 32;
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Zeroize)]
#[zeroize(drop)]
pub(crate) enum InnerEnvelopeMode {
Base = 1,
CustomIdentifier = 2,
@@ -41,6 +43,8 @@ impl TryFrom<u8> for InnerEnvelopeMode {
}
}
#[derive(Clone, Zeroize)]
#[zeroize(drop)]
pub(crate) struct InnerEnvelope {
mode: InnerEnvelopeMode,
nonce: Vec<u8>,
@@ -78,6 +82,15 @@ impl InnerEnvelope {
bytes[NONCE_LEN + key_len..].to_vec(),
))
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
/* Cannot easily get raw pointer of enum value, otherwise would do self.mode.as_ptr() */
(self.nonce.as_ptr(), self.nonce.len()),
(self.ciphertext.as_ptr(), self.ciphertext.len()),
]
}
}
/// This struct is an instantiation of the envelope as described in
@@ -90,6 +103,7 @@ impl InnerEnvelope {
/// The specification update has simplified this assumption by taking
/// an XOR-based approach without compromising on security, and to avoid
/// the confusion around the implementation of an RKR-secure encryption.
#[derive(Clone)]
pub(crate) struct Envelope<D: Hash> {
inner_envelope: InnerEnvelope,
hmac: GenericArray<u8, <D as Digest>::OutputSize>,
@@ -284,6 +298,29 @@ impl<D: Hash> Envelope<D> {
),
})
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
[
self.inner_envelope.as_byte_ptrs(),
vec![(self.hmac.as_ptr(), self.hmac.len())],
]
.concat()
}
}
// This can't be derived because of the use of a phantom parameter
impl<D: Hash> Zeroize for Envelope<D> {
fn zeroize(&mut self) {
self.inner_envelope.zeroize();
self.hmac.zeroize();
}
}
impl<D: Hash> Drop for Envelope<D> {
fn drop(&mut self) {
self.zeroize();
}
}
// Helper functions
+11 -2
View File
@@ -12,10 +12,11 @@ use crate::{
use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
use zeroize::Zeroize;
pub trait KeyExchange<D: Hash, G: Group> {
type KE1State: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
type KE2State: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
type KE1State: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytesWithPointers + Zeroize;
type KE2State: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytesWithPointers + Zeroize;
type KE1Message: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
type KE2Message: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
type KE3Message: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
@@ -62,3 +63,11 @@ pub trait KeyExchange<D: Hash, G: Group> {
pub trait ToBytes {
fn to_bytes(&self) -> Vec<u8>;
}
pub trait ToBytesWithPointers {
fn to_bytes(&self) -> Vec<u8>;
// Only used for tests to grab raw pointers to data
#[cfg(test)]
fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)>;
}
+47 -10
View File
@@ -11,7 +11,7 @@ use crate::{
},
group::Group,
hash::Hash,
key_exchange::traits::{KeyExchange, ToBytes},
key_exchange::traits::{KeyExchange, ToBytes, ToBytesWithPointers},
keypair::{Key, KeyPair, SizedBytesExt},
serialization::{serialize, tokenize},
};
@@ -24,6 +24,7 @@ use generic_bytes::SizedBytes;
use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
use std::convert::TryFrom;
@@ -237,7 +238,8 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
}
/// The client state produced after the first key exchange message
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Zeroize)]
#[zeroize(drop)]
pub struct Ke1State {
client_e_sk: Key,
client_nonce: GenericArray<u8, NonceLen>,
@@ -267,11 +269,22 @@ impl TryFrom<&[u8]> for Ke1State {
}
}
impl ToBytes for Ke1State {
impl ToBytesWithPointers for Ke1State {
fn to_bytes(&self) -> Vec<u8> {
let output: Vec<u8> = [&self.client_e_sk.to_arr(), &self.client_nonce[..]].concat();
output
}
#[cfg(test)]
fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(
self.client_e_sk.as_ptr(),
<Key as SizedBytes>::Len::to_usize(),
),
(self.client_nonce.as_ptr(), NonceLen::to_usize()),
]
}
}
impl ToBytes for Ke1Message {
@@ -311,15 +324,22 @@ pub struct Ke2State<HashLen: ArrayLength<u8>> {
session_key: GenericArray<u8, HashLen>,
}
/// The second key exchange message
pub struct Ke2Message<HashLen: ArrayLength<u8>> {
server_nonce: GenericArray<u8, NonceLen>,
server_e_pk: Key,
e_info: Vec<u8>,
mac: GenericArray<u8, HashLen>,
// This can't be derived because of the use of a phantom parameter
impl<HashLen: ArrayLength<u8>> Zeroize for Ke2State<HashLen> {
fn zeroize(&mut self) {
self.km3.zeroize();
self.hashed_transcript.zeroize();
self.session_key.zeroize();
}
}
impl<HashLen: ArrayLength<u8>> ToBytes for Ke2State<HashLen> {
impl<HashLen: ArrayLength<u8>> Drop for Ke2State<HashLen> {
fn drop(&mut self) {
self.zeroize();
}
}
impl<HashLen: ArrayLength<u8>> ToBytesWithPointers for Ke2State<HashLen> {
fn to_bytes(&self) -> Vec<u8> {
[
&self.km3[..],
@@ -328,6 +348,23 @@ impl<HashLen: ArrayLength<u8>> ToBytes for Ke2State<HashLen> {
]
.concat()
}
#[cfg(test)]
fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(self.km3.as_ptr(), HashLen::to_usize()),
(self.hashed_transcript.as_ptr(), HashLen::to_usize()),
(self.session_key.as_ptr(), HashLen::to_usize()),
]
}
}
/// The second key exchange message
pub struct Ke2Message<HashLen: ArrayLength<u8>> {
server_nonce: GenericArray<u8, NonceLen>,
server_e_pk: Key,
e_info: Vec<u8>,
mac: GenericArray<u8, HashLen>,
}
impl<HashLen: ArrayLength<u8>> TryFrom<&[u8]> for Ke2State<HashLen> {
+61 -1
View File
@@ -5,8 +5,12 @@
//! Contains the keypair types that must be supplied for the OPAQUE API
#![allow(unsafe_code)]
use crate::errors::InternalPakeError;
use crate::group::Group;
#[cfg(test)]
use generic_array::typenum::Unsigned;
use generic_array::{typenum::U32, GenericArray};
use generic_bytes::{SizedBytes, TryFromSizedBytesError};
#[cfg(test)]
@@ -31,13 +35,27 @@ pub trait SizedBytesExt: SizedBytes {
impl<T> SizedBytesExt for T where T: SizedBytes {}
/// A Keypair trait with public-private verification
#[derive(Clone, Debug, PartialEq, Eq, Zeroize)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct KeyPair<G> {
pk: Key,
sk: Key,
_g: PhantomData<G>,
}
// This can't be derived because of the use of a phantom parameter
impl<G> Zeroize for KeyPair<G> {
fn zeroize(&mut self) {
self.pk.zeroize();
self.sk.zeroize();
}
}
impl<G> Drop for KeyPair<G> {
fn drop(&mut self) {
self.zeroize();
}
}
impl<G: Group> KeyPair<G> {
/// The public key component
pub fn public(&self) -> &Key {
@@ -100,6 +118,14 @@ impl<G: Group> KeyPair<G> {
let pk = Self::public_from_private(&sk);
Self::new(pk, sk)
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(self.pk.as_ptr(), <Key as SizedBytes>::Len::to_usize()),
(self.sk.as_ptr(), <Key as SizedBytes>::Len::to_usize()),
]
}
}
#[cfg(test)]
@@ -149,7 +175,41 @@ impl SizedBytes for Key {
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::*;
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
use rand::rngs::OsRng;
use std::slice::from_raw_parts;
#[test]
fn test_zeroize_key() -> Result<(), ProtocolError> {
let key_len = <Key as SizedBytes>::Len::to_usize();
let mut key = Key(vec![1u8; key_len]);
let ptr = key.as_ptr();
key.zeroize();
let bytes = unsafe { from_raw_parts(ptr, key_len) };
assert!(bytes.iter().all(|&x| x == 0));
Ok(())
}
#[test]
fn test_zeroize_keypair() -> Result<(), ProtocolError> {
let mut rng = OsRng;
let mut keypair = KeyPair::<RistrettoPoint>::generate_random(&mut rng);
let ptrs = keypair.as_byte_ptrs();
keypair.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
proptest! {
#[test]
+131 -35
View File
@@ -11,7 +11,7 @@ use crate::{
errors::{utils::check_slice_size_atleast, InternalPakeError, PakeError, ProtocolError},
group::Group,
hash::Hash,
key_exchange::traits::{KeyExchange, ToBytes},
key_exchange::traits::{KeyExchange, ToBytesWithPointers},
keypair::{Key, KeyPair, SizedBytesExt},
map_to_curve::GroupWithMapToCurve,
oprf,
@@ -73,6 +73,14 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
},
})
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(self.token.data.as_ptr(), self.token.data.len()),
/* cannot provide raw pointer to self.token.blind until this is exposed in curve25519_dalek::scalar::Scalar */
]
}
}
/// Optional parameters for client registration finish
@@ -140,6 +148,9 @@ pub struct ClientRegistrationFinishResult<CS: CipherSuite> {
pub message: RegistrationUpload<CS>,
/// The export key output by client registration
pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
/// Instance of the ClientRegistration, only used in tests for checking zeroize
#[cfg(test)]
pub state: ClientRegistration<CS>,
}
impl<CS: CipherSuite> ClientRegistration<CS> {
@@ -203,38 +214,12 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
client_s_pk: client_static_keypair.public().clone(),
},
export_key,
#[cfg(test)]
state: self,
})
}
}
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ClientRegistration<CS> {
fn zeroize(&mut self) {
self.token.data.zeroize();
self.token.blind.zeroize();
}
}
impl<CS: CipherSuite> Drop for ClientRegistration<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ClientLogin<CS> {
fn zeroize(&mut self) {
self.token.data.zeroize();
self.token.blind.zeroize();
}
}
impl<CS: CipherSuite> Drop for ClientLogin<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
/// Contains the fields that are returned by a server registration start
pub struct ServerRegistrationStartResult<CS: CipherSuite> {
/// The registration resposne message to send to the client
@@ -295,6 +280,21 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
})
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
[
match &self.envelope {
Some(env) => env.as_byte_ptrs(),
None => vec![],
},
match &self.client_s_pk {
Some(pk) => vec![(pk.as_ptr(), pk.len())],
None => vec![],
},
/* cannot provide raw pointer to self.oprf_key until this is exposed in curve25519_dalek::scalar::Scalar */
].concat()
}
/// From the client's "blinded" password, returns a response to be
/// sent back to the client, as well as a ServerRegistration
///
@@ -380,7 +380,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
Ok(Self {
envelope: Some(message.envelope),
client_s_pk: Some(message.client_s_pk),
oprf_key: self.oprf_key,
oprf_key: self.oprf_key.clone(),
})
}
}
@@ -440,6 +440,18 @@ impl<CS: CipherSuite> ClientLogin<CS> {
serialized_credential_request,
})
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
[
vec![
(self.token.data.as_ptr(), self.token.data.len()),
/* cannot provide raw pointer to self.token.blind until this is exposed in curve25519_dalek::scalar::Scalar */
],
self.ke1_state.as_byte_ptrs(),
vec![ (self.serialized_credential_request.as_ptr(), self.serialized_credential_request.len()) ],
].concat()
}
}
/// Optional parameters for client login start
@@ -488,6 +500,9 @@ pub struct ClientLoginFinishResult<CS: CipherSuite> {
pub server_s_pk: Key,
/// The confidential info sent by the client
pub confidential_info: Vec<u8>,
/// Instance of the ClientLogin, only used in tests for checking zeroize
#[cfg(test)]
pub state: ClientLogin<CS>,
}
impl<CS: CipherSuite> ClientLogin<CS> {
@@ -626,6 +641,8 @@ impl<CS: CipherSuite> ClientLogin<CS> {
session_key,
export_key: opened_envelope.export_key.clone(),
server_s_pk: l2.server_s_pk,
#[cfg(test)]
state: self,
})
}
}
@@ -665,9 +682,13 @@ pub struct ServerLoginStartResult<CS: CipherSuite> {
}
/// Contains the fields that are returned by a server login finish
pub struct ServerLoginFinishResult {
pub struct ServerLoginFinishResult<CS: CipherSuite> {
/// The session key between client and server
pub session_key: Vec<u8>,
_cs: PhantomData<CS>,
/// Instance of the ClientRegistration, only used in tests for checking zeroize
#[cfg(test)]
pub state: ServerLogin<CS>,
}
impl<CS: CipherSuite> ServerLogin<CS> {
@@ -728,6 +749,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
) -> Result<ServerLoginStartResult<CS>, ProtocolError> {
let client_s_pk = password_file
.client_s_pk
.clone()
.ok_or(InternalPakeError::SealError)?;
let (e_info, optional_ids) = match params {
@@ -740,7 +762,10 @@ impl<CS: CipherSuite> ServerLogin<CS> {
}
};
let envelope = password_file.envelope.ok_or(InternalPakeError::SealError)?;
let envelope = password_file
.envelope
.clone()
.ok_or(InternalPakeError::SealError)?;
if envelope.get_mode() != mode_from_ids(&optional_ids) {
return Err(InternalPakeError::IncompatibleEnvelopeModeError.into());
}
@@ -827,9 +852,9 @@ impl<CS: CipherSuite> ServerLogin<CS> {
/// # Ok::<(), ProtocolError>(())
/// ```
pub fn finish(
&self,
self,
message: CredentialFinalization<CS>,
) -> Result<ServerLoginFinishResult, ProtocolError> {
) -> Result<ServerLoginFinishResult<CS>, ProtocolError> {
let session_key = <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::finish_ke(
message.ke3_message,
&self.ke2_state,
@@ -841,11 +866,82 @@ impl<CS: CipherSuite> ServerLogin<CS> {
err => err,
})?;
Ok(ServerLoginFinishResult { session_key })
Ok(ServerLoginFinishResult {
session_key,
_cs: PhantomData,
#[cfg(test)]
state: self,
})
}
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
self.ke2_state.as_byte_ptrs()
}
}
// Zeroize on drop implementations
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ClientRegistration<CS> {
fn zeroize(&mut self) {
self.token.data.zeroize();
self.token.blind.zeroize();
}
}
impl<CS: CipherSuite> Drop for ClientRegistration<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ServerRegistration<CS> {
fn zeroize(&mut self) {
self.envelope.zeroize();
self.client_s_pk.zeroize();
self.oprf_key.zeroize();
}
}
impl<CS: CipherSuite> Drop for ServerRegistration<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ClientLogin<CS> {
fn zeroize(&mut self) {
self.token.data.zeroize();
self.token.blind.zeroize();
self.ke1_state.zeroize();
self.serialized_credential_request.zeroize();
}
}
impl<CS: CipherSuite> Drop for ClientLogin<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
// This can't be derived because of the use of a phantom parameter
impl<CS: CipherSuite> Zeroize for ServerLogin<CS> {
fn zeroize(&mut self) {
self.ke2_state.zeroize();
}
}
impl<CS: CipherSuite> Drop for ServerLogin<CS> {
fn drop(&mut self) {
self.zeroize();
}
}
// Helper functions
fn get_password_derived_key<G: GroupWithMapToCurve, SH: SlowHash<D>, D: Hash>(
token: &oprf::Token<G>,
beta: G,
+312 -4
View File
@@ -3,6 +3,8 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
#![allow(unsafe_code)]
use crate::{
ciphersuite::CipherSuite,
errors::*,
@@ -19,6 +21,8 @@ use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes;
use rand::{rngs::OsRng, RngCore};
use serde_json::Value;
use std::slice::from_raw_parts;
use zeroize::Zeroize;
// Tests
// =====
@@ -65,6 +69,8 @@ pub struct TestVectorParameters {
pub session_key: Vec<u8>,
}
static STR_PASSWORD: &str = "password";
static TEST_VECTOR: &str = r#"
{
"client_s_pk": "6e0a6082dd29936c44b47ecb8a5fe72e4b321a0ac314b0080ca4c48afdabd215",
@@ -416,7 +422,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
server_registration_state,
client_login_state,
server_login_state,
session_key: client_login_finish_result.session_key,
session_key: client_login_finish_result.session_key.clone(),
export_key: client_registration_finish_result.export_key.to_vec(),
}
}
@@ -623,7 +629,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
assert_eq!(
hex::encode(parameters.session_key),
hex::encode(server_login_result.session_key)
hex::encode(&server_login_result.session_key)
);
Ok(())
@@ -680,8 +686,8 @@ fn test_complete_flow(
.finish(client_login_finish_result.message)?;
assert_eq!(
hex::encode(server_login_finish_result.session_key),
hex::encode(client_login_finish_result.session_key)
hex::encode(&server_login_finish_result.session_key),
hex::encode(&client_login_finish_result.session_key)
);
assert_eq!(
hex::encode(client_registration_finish_result.export_key),
@@ -706,3 +712,305 @@ fn test_complete_flow_success() -> Result<(), ProtocolError> {
fn test_complete_flow_fail() -> Result<(), ProtocolError> {
test_complete_flow(b"good password", b"bad password")
}
// Zeroize tests
#[test]
fn test_zeroize_client_registration_start() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let mut state = client_registration_start_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_server_registration_start() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let mut state = server_registration_start_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_client_registration_finish() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let mut state = client_registration_finish_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)?;
let mut state = p_file;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_client_login_start() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
ClientLoginStartParameters::default(),
)?;
let mut state = client_login_start_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_server_login_start() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)?;
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
ClientLoginStartParameters::default(),
)?;
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
p_file,
&server_kp.private(),
client_login_start_result.message,
ServerLoginStartParameters::default(),
)?;
let mut state = server_login_start_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)?;
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
ClientLoginStartParameters::default(),
)?;
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
p_file,
&server_kp.private(),
client_login_start_result.message,
ServerLoginStartParameters::default(),
)?;
let client_login_finish_result = client_login_start_result.state.finish(
server_login_start_result.message,
ClientLoginFinishParameters::default(),
)?;
let mut state = client_login_finish_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
#[test]
fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)?;
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
STR_PASSWORD.as_bytes(),
ClientLoginStartParameters::default(),
)?;
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
p_file,
&server_kp.private(),
client_login_start_result.message,
ServerLoginStartParameters::default(),
)?;
let client_login_finish_result = client_login_start_result.state.finish(
server_login_start_result.message,
ClientLoginFinishParameters::default(),
)?;
let server_login_finish_result = server_login_start_result
.state
.finish(client_login_finish_result.message)?;
let mut state = server_login_finish_result.state;
let ptrs = state.as_byte_ptrs();
state.zeroize();
for (ptr, len) in ptrs {
let bytes = unsafe { from_raw_parts(ptr, len) };
assert!(bytes.iter().all(|&x| x == 0));
}
Ok(())
}
+1 -1
View File
@@ -576,7 +576,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
assert_eq!(
hex::encode(parameters.session_key),
hex::encode(server_login_result.session_key)
hex::encode(&server_login_result.session_key)
);
}
Ok(())