// SPDX-License-Identifier: MIT OR Apache-2.0 // Copyright (c) VexaHub and contributors. // Copyright (c) Meta Platforms, Inc. and affiliates. use core::ops::Add; use std::vec; use std::vec::Vec; use digest::Output; use generic_array::ArrayLength; use generic_array::typenum::{Sum, Unsigned}; use proptest::collection::vec; use proptest::prelude::*; use rand::Rng; use rand::rand_core::UnwrapErr; use rand::rngs::SysRng; use voprf::Group as _; use crate::ciphersuite::{CipherSuite, KeGroup, OprfGroup, OprfHash}; use crate::envelope::{Envelope, EnvelopeLen, InnerEnvelopeMode}; use crate::errors::*; use crate::hash::OutputSize; use crate::key_exchange::group::Group; use crate::key_exchange::shared::NonceLen; use crate::key_exchange::{ Deserialize, Ke1MessageLen, Ke1StateLen, Ke2MessageLen, KeyExchange, Serialize, }; use crate::keypair::KeyPair; use crate::messages::CredentialResponseWithoutKeLen; use crate::opaque::{ClientLoginLen, ClientRegistrationLen, MaskedResponseLen}; use crate::serialization::{i2osp, os2ip}; use crate::*; #[cfg(feature = "ristretto255")] struct TripleDhRistretto255; #[cfg(feature = "ristretto255")] impl CipherSuite for TripleDhRistretto255 { type OprfCs = Ristretto255; type KeyExchange = TripleDh; type Ksf = ksf::Identity; } #[cfg(all(feature = "ristretto255", feature = "curve25519"))] struct TripleDhCurve25519; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] impl CipherSuite for TripleDhCurve25519 { type OprfCs = Ristretto255; type KeyExchange = TripleDh; type Ksf = ksf::Identity; } struct TripleDhP256; impl CipherSuite for TripleDhP256 { type OprfCs = p256::NistP256; type KeyExchange = TripleDh; type Ksf = ksf::Identity; } struct TripleDhP384; impl CipherSuite for TripleDhP384 { type OprfCs = p384::NistP384; type KeyExchange = TripleDh; type Ksf = ksf::Identity; } struct TripleDhP521; impl CipherSuite for TripleDhP521 { type OprfCs = p521::NistP521; type KeyExchange = TripleDh; type Ksf = ksf::Identity; } #[cfg(feature = "ecdsa")] struct SigmaIP256; #[cfg(feature = "ecdsa")] impl CipherSuite for SigmaIP256 { type OprfCs = p256::NistP256; type KeyExchange = SigmaI, p256::NistP256, sha2::Sha256>; type Ksf = ksf::Identity; } #[cfg(feature = "ecdsa")] struct SigmaIP384; #[cfg(feature = "ecdsa")] impl CipherSuite for SigmaIP384 { type OprfCs = p384::NistP384; type KeyExchange = SigmaI, p384::NistP384, sha2::Sha384>; type Ksf = ksf::Identity; } #[cfg(all(feature = "ristretto255", feature = "ed25519",))] struct SigmaIEd25519; #[cfg(all(feature = "ristretto255", feature = "ed25519",))] impl CipherSuite for SigmaIEd25519 { type OprfCs = Ristretto255; type KeyExchange = SigmaI, Ristretto255, sha2::Sha512>; type Ksf = ksf::Identity; } #[cfg(all(feature = "ristretto255", feature = "ed25519"))] struct SigmaIEd25519Ph; #[cfg(all(feature = "ristretto255", feature = "ed25519",))] impl CipherSuite for SigmaIEd25519Ph { type OprfCs = Ristretto255; type KeyExchange = SigmaI, Ristretto255, sha2::Sha512>; type Ksf = ksf::Identity; } #[cfg(feature = "ecdsa")] fn random_point() -> as Group>::Pk { let mut rng = UnwrapErr(SysRng); let sk = KeGroup::::random_sk(&mut rng); KeGroup::::public_key(&sk) } fn random_element() -> as voprf::Group>::Elem { let mut rng = UnwrapErr(SysRng); let scalar = OprfGroup::::random_scalar(&mut rng).unwrap(); OprfGroup::::base_elem() * &scalar } #[test] fn client_registration_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where // ClientRegistration: KgSk + KgPk as voprf::Group>::ScalarLen: Add< as voprf::Group>::ElemLen>, ClientRegistrationLen: ArrayLength, { let pw = b"hunter2"; let mut rng = UnwrapErr(SysRng); let blind_result = &voprf::OprfClient::::blind(pw, &mut rng)?; let bytes: Vec = blind_result .state .serialize() .iter() .chain(blind_result.message.serialize().iter()) .cloned() .collect(); let reg = ClientRegistration::::deserialize(&bytes)?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, bytes); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; Ok(()) } #[test] fn server_registration_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where // RegistrationUpload: (KePk + Hash) + Envelope as Group>::PkLen: Add>>, Sum< as Group>::PkLen, OutputSize>>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, // ServerRegistration = RegistrationUpload { // If we don't have envelope and client_pk, the server registration just let mut rng = UnwrapErr(SysRng); let mut masking_key = Output::>::default(); rng.fill_bytes(&mut masking_key); // Construct a mock envelope let mut mock_envelope_bytes = Vec::new(); // empty nonce mock_envelope_bytes.extend_from_slice(&[0; NonceLen::USIZE]); // ciphertext which is an encrypted private key //mock_envelope_bytes.extend_from_slice(&ciphertext); // length-MAC_SIZE hmac mock_envelope_bytes.extend_from_slice(&Output::>::default()); let mock_client_kp = KeyPair::>::derive_random(&mut rng); // serialization order: oprf_key, public key, envelope let mut bytes = Vec::::new(); bytes.extend_from_slice(&mock_client_kp.public().serialize()); bytes.extend_from_slice(&masking_key); bytes.extend_from_slice(&mock_envelope_bytes); let reg = ServerRegistration::::deserialize(&bytes)?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, bytes); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; Ok(()) } #[test] fn registration_request_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> { let elem = random_element::(); let elem_bytes = OprfGroup::::serialize_elem(elem); let mut input = Vec::new(); input.extend_from_slice(&elem_bytes); let r1 = RegistrationRequest::::deserialize(&input)?; let r1_bytes = r1.serialize(); assert_eq!(input, *r1_bytes); // Assert that identity group element is rejected let identity = OprfGroup::::identity_elem(); let identity_bytes = OprfGroup::::serialize_elem(identity).to_vec(); assert!(matches!( RegistrationRequest::::deserialize(&identity_bytes), Err(ProtocolError::LibraryError(InternalError::OprfError( voprf::Error::Deserialization, ))) )); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; Ok(()) } #[test] fn registration_response_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where // RegistrationResponse: KgPk + KePk as voprf::Group>::ElemLen: Add< as Group>::PkLen>, RegistrationResponseLen: ArrayLength, { let elem = random_element::(); let beta_bytes = OprfGroup::::serialize_elem(elem); let mut rng = UnwrapErr(SysRng); let skp = KeyPair::>::derive_random(&mut rng); let pubkey_bytes = skp.public().serialize(); let mut input = Vec::new(); input.extend_from_slice(&beta_bytes); input.extend_from_slice(&pubkey_bytes); let r2 = RegistrationResponse::::deserialize(&input)?; let r2_bytes = r2.serialize(); assert_eq!(input, *r2_bytes); // Assert that identity group element is rejected let identity = OprfGroup::::identity_elem(); let identity_bytes = OprfGroup::::serialize_elem(identity).to_vec(); assert!(matches!( RegistrationResponse::::deserialize( &[identity_bytes, pubkey_bytes.to_vec()].concat() ), Err(ProtocolError::LibraryError(InternalError::OprfError( voprf::Error::Deserialization, ))) )); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; Ok(()) } #[test] fn registration_upload_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where // RegistrationUpload: (KePk + Hash) + Envelope as Group>::PkLen: Add>>, Sum< as Group>::PkLen, OutputSize>>: ArrayLength + Add>, RegistrationUploadLen: ArrayLength, { let mut rng = UnwrapErr(SysRng); let skp = KeyPair::>::derive_random(&mut rng); let pubkey_bytes = skp.public().serialize(); let mut key = [0u8; 32]; rng.fill_bytes(&mut key); let mut nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut nonce); let mut masking_key = Output::>::default(); rng.fill_bytes(&mut masking_key); let randomized_pwd_hasher = hkdf::SimpleHkdf::>::new(None, &key); let (envelope, _, _) = Envelope::::seal_raw( &randomized_pwd_hasher, nonce.into(), [pubkey_bytes.as_slice()].into_iter(), InnerEnvelopeMode::Internal, )?; let envelope_bytes = envelope.serialize(); let mut input = Vec::new(); input.extend_from_slice(&pubkey_bytes); input.extend_from_slice(&masking_key); input.extend_from_slice(&envelope_bytes); let r3 = RegistrationUpload::::deserialize(&input)?; let r3_bytes = r3.serialize(); assert_eq!(input, *r3_bytes); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(feature = "ecdsa")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; #[cfg(all(feature = "ristretto255", feature = "ed25519"))] inner::()?; Ok(()) } #[test] fn triple_dh_credential_request_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE1Message: Deserialize + Serialize, // CredentialRequest: KgPk + Ke1Message as voprf::Group>::ElemLen: Add>, CredentialRequestLen: ArrayLength, { let mut rng = UnwrapErr(SysRng); let alpha = random_element::(); let alpha_bytes = OprfGroup::::serialize_elem(alpha); let client_e_kp = KeyPair::>::derive_random(&mut rng); let mut client_nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let ke1m: Vec = [ client_nonce.as_ref(), client_e_kp.public().serialize().as_ref(), ] .concat(); let mut input = Vec::new(); input.extend_from_slice(&alpha_bytes); input.extend_from_slice(&ke1m); let l1 = CredentialRequest::::deserialize(&input)?; let l1_bytes = l1.serialize(); assert_eq!(input, *l1_bytes); // Assert that identity group element is rejected let identity = OprfGroup::::identity_elem(); let identity_bytes = OprfGroup::::serialize_elem(identity).to_vec(); assert!(matches!( CredentialRequest::::deserialize(&[identity_bytes, ke1m.to_vec()].concat()), Err(ProtocolError::LibraryError(InternalError::OprfError( voprf::Error::Deserialization, ))) )); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_credential_response_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE2Message: Deserialize, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse as voprf::Group>::ElemLen: Add, Sum< as voprf::Group>::ElemLen, NonceLen>: ArrayLength + Add>, CredentialResponseWithoutKeLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message ::KE2Message: Serialize, CredentialResponseWithoutKeLen: Add>, CredentialResponseLen: ArrayLength, { let elem = random_element::(); let elem_bytes = OprfGroup::::serialize_elem(elem); let mut rng = UnwrapErr(SysRng); let mut masking_nonce = [0u8; 32]; rng.fill_bytes(&mut masking_nonce); let mut masked_response = vec![0u8; as voprf::Group>::ElemLen::USIZE + Envelope::::len()]; rng.fill_bytes(&mut masked_response); let server_e_kp = KeyPair::>::derive_random(&mut rng); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let mut server_nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let ke2m: Vec = [ server_nonce.as_ref(), server_e_kp.public().serialize().as_ref(), &mac, ] .concat(); let mut input = Vec::new(); input.extend_from_slice(&elem_bytes); input.extend_from_slice(&masking_nonce); input.extend_from_slice(&masked_response); input.extend_from_slice(&ke2m); let l2 = CredentialResponse::::deserialize(&input)?; let l2_bytes = l2.serialize(); assert_eq!(input, *l2_bytes); // Assert that identity group element is rejected let identity = OprfGroup::::identity_elem(); let identity_bytes = OprfGroup::::serialize_elem(identity).to_vec(); assert!(matches!( CredentialResponse::::deserialize( &[ identity_bytes, masking_nonce.to_vec(), masked_response, ke2m.to_vec() ] .concat() ), Err(ProtocolError::LibraryError(InternalError::OprfError( voprf::Error::Deserialization, ))) )); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] #[cfg(feature = "ecdsa")] fn sigma_i_ecdsa_credential_response_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE2Message: Deserialize, // CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse as voprf::Group>::ElemLen: Add, Sum< as voprf::Group>::ElemLen, NonceLen>: ArrayLength + Add>, CredentialResponseWithoutKeLen: ArrayLength, // CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message ::KE2Message: Serialize, CredentialResponseWithoutKeLen: Add>, CredentialResponseLen: ArrayLength, { let pt = random_point::(); let pt_bytes = KeGroup::::serialize_pk(&pt); let mut rng = UnwrapErr(SysRng); let mut masking_nonce = [0u8; 32]; rng.fill_bytes(&mut masking_nonce); let mut masked_response = vec![0u8; as voprf::Group>::ElemLen::USIZE + Envelope::::len()]; rng.fill_bytes(&mut masked_response); let server_e_kp = KeyPair::>::derive_random(&mut rng); let r = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let s = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let mut server_nonce = [0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let ke2m: Vec = [ server_nonce.as_ref(), server_e_kp.public().serialize().as_ref(), &r, &s, &mac, ] .concat(); let mut input = Vec::new(); input.extend_from_slice(&pt_bytes); input.extend_from_slice(&masking_nonce); input.extend_from_slice(&masked_response); input.extend_from_slice(&ke2m); let l2 = CredentialResponse::::deserialize(&input)?; let l2_bytes = l2.serialize(); assert_eq!(input, *l2_bytes); // Assert that identity group element is rejected let identity = OprfGroup::::identity_elem(); let identity_bytes = OprfGroup::::serialize_elem(identity).to_vec(); assert!(matches!( CredentialResponse::::deserialize( &[ identity_bytes, masking_nonce.to_vec(), masked_response, ke2m.to_vec() ] .concat() ), Err(ProtocolError::LibraryError(InternalError::OprfError( voprf::Error::Deserialization, ))) )); Ok(()) } inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_credential_finalization_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE3Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let input = mac; let l3 = CredentialFinalization::::deserialize(&input)?; let l3_bytes = l3.serialize(); assert_eq!(input.as_slice(), l3_bytes.as_slice()); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] #[cfg(feature = "ecdsa")] fn sigma_i_ecdsa_credential_finalization_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE3Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let r = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let s = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let mut input = Vec::new(); input.extend_from_slice(&r); input.extend_from_slice(&s); input.extend_from_slice(&mac); let l3 = CredentialFinalization::::deserialize(&input)?; let l3_bytes = l3.serialize(); assert_eq!(input.as_slice(), l3_bytes.as_slice()); Ok(()) } inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_client_login_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE1Message: Deserialize, ::KE1State: Deserialize, // CredentialRequest: KgPk + Ke1Message ::KE1Message: Serialize, as voprf::Group>::ElemLen: Add>, CredentialRequestLen: ArrayLength, // ClientLogin: KgSk + CredentialRequest + Ke1State as voprf::Group>::ScalarLen: Add>, ::KE1State: Serialize, Sum< as voprf::Group>::ScalarLen, CredentialRequestLen>: ArrayLength + Add>, ClientLoginLen: ArrayLength, { let pw = b"hunter2"; let mut rng = UnwrapErr(SysRng); let client_e_kp = KeyPair::>::derive_random(&mut rng); let mut client_nonce = [0; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let l1_data = [ client_e_kp.private().serialize().to_vec(), client_nonce.to_vec(), ] .concat(); let blind_result = voprf::OprfClient::::blind(pw, &mut rng)?; let credential_request = CredentialRequest:: { blinded_element: blind_result.message, ke1_message: ::KE1Message::deserialize_take( &mut ([ client_nonce.as_ref(), client_e_kp.public().serialize().as_ref(), ] .concat() .as_slice()), )?, }; let bytes: Vec = blind_result .state .serialize() .iter() .chain(credential_request.serialize().iter()) .chain(l1_data.iter()) .cloned() .collect(); let reg = ClientLogin::::deserialize(&bytes)?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, bytes); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_ke1_message_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE1Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let client_e_kp = KeyPair::>::derive_random(&mut rng); let mut client_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut client_nonce); let ke1m = [ client_nonce.as_slice(), client_e_kp.public().serialize().as_ref(), ] .concat(); let reg = ::KE1Message::deserialize_take(&mut (ke1m.as_slice()))?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke1m); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_ke2_message_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE2Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let server_e_kp = KeyPair::>::derive_random(&mut rng); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let ke2m: Vec = [ server_nonce.as_slice(), server_e_kp.public().serialize().as_ref(), &mac, ] .concat(); let reg = ::KE2Message::deserialize_take(&mut (ke2m.as_slice()))?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke2m); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] #[cfg(feature = "ecdsa")] fn sigma_i_ecdsa_ke2_message_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE2Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let server_e_kp = KeyPair::>::derive_random(&mut rng); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let mut server_nonce = vec![0u8; NonceLen::USIZE]; rng.fill_bytes(&mut server_nonce); let r = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let s = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let ke2m: Vec = [ server_nonce.as_slice(), server_e_kp.public().serialize().as_ref(), &r, &s, &mac, ] .concat(); let reg = ::KE2Message::deserialize_take(&mut (ke2m.as_slice()))?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke2m); Ok(()) } inner::()?; inner::()?; Ok(()) } #[test] fn triple_dh_ke3_message_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE3Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let ke3m: Vec = [mac].concat(); let reg = ::KE3Message::deserialize_take(&mut (ke3m.as_slice()))?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke3m); Ok(()) } #[cfg(feature = "ristretto255")] inner::()?; #[cfg(all(feature = "ristretto255", feature = "curve25519"))] inner::()?; inner::()?; inner::()?; inner::()?; Ok(()) } #[test] #[cfg(feature = "ecdsa")] fn sigma_i_ecdsa_ke3_message_roundtrip() -> Result<(), ProtocolError> { fn inner() -> Result<(), ProtocolError> where ::KE3Message: Deserialize + Serialize, { let mut rng = UnwrapErr(SysRng); let r = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let s = KeGroup::::serialize_sk(&KeGroup::::random_sk(&mut rng)); let mut mac = Output::>::default(); rng.fill_bytes(&mut mac); let ke3m: Vec = [mac.as_slice(), &r, &s].concat(); let reg = ::KE3Message::deserialize_take(&mut (ke3m.as_slice()))?; let reg_bytes = reg.serialize(); assert_eq!(*reg_bytes, ke3m); Ok(()) } inner::()?; inner::()?; Ok(()) } proptest! { #[test] fn test_i2osp_os2ip(bytes in vec(any::(), 0..size_of::())) { use generic_array::typenum::{U0, U1, U2, U3, U4, U5, U6, U7}; let input = os2ip(&bytes).unwrap(); let output = match bytes.len() { 0 => i2osp::(input).unwrap().to_vec(), 1 => i2osp::(input).unwrap().to_vec(), 2 => i2osp::(input).unwrap().to_vec(), 3 => i2osp::(input).unwrap().to_vec(), 4 => i2osp::(input).unwrap().to_vec(), 5 => i2osp::(input).unwrap().to_vec(), 6 => i2osp::(input).unwrap().to_vec(), 7 => i2osp::(input).unwrap().to_vec(), _ => unreachable!("unexpected size") }; assert_eq!(output, bytes); } } macro_rules! test { ($mod:ident, $CS:ty) => { mod $mod { use super::*; proptest! { #[test] fn test_nocrash_registration_request(bytes in vec(any::(), 0..200)) { let _ = RegistrationRequest::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_registration_response(bytes in vec(any::(), 0..200)) { let _ = RegistrationResponse::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_registration_upload(bytes in vec(any::(), 0..200)) { let _ = RegistrationUpload::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_credential_request(bytes in vec(any::(), 0..500)) { let _ = CredentialRequest::<$CS>::deserialize(&mut (bytes.as_slice())).map_or(true, |_| true); } #[test] fn test_nocrash_credential_response(bytes in vec(any::(), 0..500)) { let _ = CredentialResponse::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_credential_finalization(bytes in vec(any::(), 0..500)) { let _ = CredentialFinalization::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_client_registration(bytes in vec(any::(), 0..700)) { let _ = ClientRegistration::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_server_registration(bytes in vec(any::(), 0..700)) { let _ = ServerRegistration::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_client_login(bytes in vec(any::(), 0..700)) { let _ = ClientLogin::<$CS>::deserialize(&bytes).map_or(true, |_| true); } #[test] fn test_nocrash_server_login(bytes in vec(any::(), 0..700)) { let _ = ServerLogin::<$CS>::deserialize(&bytes).map_or(true, |_| true); } } } }; } #[cfg(feature = "ristretto255")] test!(triple_dh_ristretto255, TripleDhRistretto255); #[cfg(all(feature = "ristretto255", feature = "curve25519"))] test!(triple_dh_curve25519, TripleDhCurve25519); test!(triple_dh_p256, TripleDhP256); test!(triple_dh_p384, TripleDhP384); test!(triple_dh_p521, TripleDhP521); #[cfg(feature = "ecdsa")] test!(sigma_i_p256, SigmaIP256); #[cfg(feature = "ecdsa")] test!(sigma_i_p384, SigmaIP384); #[cfg(all(feature = "ristretto255", feature = "ed25519",))] test!(sigma_i_ed25519, SigmaIEd25519); #[cfg(all(feature = "ristretto255", feature = "ed25519"))] test!(sigma_i_ed25519_ph, SigmaIEd25519Ph);