// Copyright (C) 2019 Eloïs SANCHEZ.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
//! Test Public Key Secure Transport Layer in minimal mode.
use pkstl::*;
use ring::signature::{Ed25519KeyPair, KeyPair};
use std::io::{BufWriter, Write};
trait AsOptRef {
fn as_opt_ref(&self) -> Option<&[u8]>;
}
impl AsOptRef for Option> {
fn as_opt_ref(&self) -> Option<&[u8]> {
match self {
Some(ref datas) => Some(&datas[..]),
None => None,
}
}
}
fn client_infos(server_sig_kp: &[u8]) -> Result<(MinimalSecureLayer, Ed25519KeyPair)> {
// Create client sig keypair
let client_sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref())
.map_err(|_| Error::FailtoGenSigKeyPair)?;
// Create client secure layer
let client_msl =
MinimalSecureLayer::create(SecureLayerConfig::default(), Some(server_sig_kp.to_vec()))?;
Ok((client_msl, client_sig_kp))
}
fn server_infos() -> Result<(MinimalSecureLayer, Ed25519KeyPair)> {
// Create server secure layer
let server_msl = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?;
// Create server sig keypair
let server_sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref())
.map_err(|_| Error::FailtoGenSigKeyPair)?;
Ok((server_msl, server_sig_kp))
}
fn send_connect_msg_inner(
sender_msl: &mut MinimalSecureLayer,
sender_sig_kp: &Ed25519KeyPair,
receiver_msl: &mut MinimalSecureLayer,
custom_datas: Option>,
) -> Result> {
// Create and sign connect message
let connect_msg = sender_msl.create_connect_message(
sender_sig_kp.public_key().as_ref(),
custom_datas.as_opt_ref(),
)?;
let sig = sender_sig_kp.sign(&connect_msg);
// Write connect message and it's sig in channel
let mut channel = BufWriter::new(Vec::with_capacity(1_000));
channel
.write(&connect_msg)
.map_err(|_| Error::BufferFlushError)?;
channel
.write(sig.as_ref())
.map_err(|_| Error::BufferFlushError)?;
// Receiver read connect message from channel
let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?;
receiver_msl.read(&channel[..])
}
#[inline]
fn send_connect_msg(
sender_msl: &mut MinimalSecureLayer,
sender_sig_kp: &Ed25519KeyPair,
receiver_msl: &mut MinimalSecureLayer,
custom_datas: Option>,
) -> Result<()> {
let connect_msg_received = send_connect_msg_inner(
sender_msl,
sender_sig_kp,
receiver_msl,
custom_datas.clone(),
)?
.expect("Must be receive a message");
assert_eq!(
Message::Connect {
sig_algo: SIG_ALGO_ED25519_ARRAY,
sig_pubkey: sender_sig_kp.public_key().as_ref().to_vec(),
custom_datas,
},
connect_msg_received,
);
Ok(())
}
#[inline]
fn send_ack_msg(
sender_msl: &mut MinimalSecureLayer,
sender_sig_kp: &Ed25519KeyPair,
receiver_msl: &mut MinimalSecureLayer,
custom_datas: Option>,
) -> Result<()> {
let msg_received = send_ack_msg_inner(
sender_msl,
sender_sig_kp,
receiver_msl,
custom_datas.as_opt_ref(),
)?
.expect("Must be receive a message");
assert_eq!(Message::Ack { custom_datas }, msg_received,);
Ok(())
}
fn send_ack_msg_inner<'a>(
sender_msl: &mut MinimalSecureLayer,
sender_sig_kp: &Ed25519KeyPair,
receiver_msl: &'a mut MinimalSecureLayer,
custom_datas: Option<&[u8]>,
) -> Result> {
// Create and sign server ack message
let ack_msg = sender_msl.create_ack_message(custom_datas)?;
let sig = sender_sig_kp.sign(&ack_msg);
// Write server ack message and it's sig in channel
let mut channel = BufWriter::new(Vec::with_capacity(1_000));
channel
.write(&ack_msg)
.map_err(|_| Error::BufferFlushError)?;
channel
.write(sig.as_ref())
.map_err(|_| Error::BufferFlushError)?;
// Client read server ack message from channel
let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?;
receiver_msl.read(&channel[..])
}
#[inline]
fn send_user_msg(
sender_msl: &mut MinimalSecureLayer,
receiver_msl: &mut MinimalSecureLayer,
datas: Vec,
) -> Result<()> {
let msg_received = send_user_msg_inner(sender_msl, receiver_msl, datas.clone())?
.expect("Must be receive a message");
assert_eq!(
Message::Message {
custom_datas: Some(datas),
},
msg_received,
);
Ok(())
}
fn send_user_msg_inner(
sender_msl: &mut MinimalSecureLayer,
receiver_msl: &mut MinimalSecureLayer,
datas: Vec,
) -> Result> {
// Client write one message in channel
let mut channel = BufWriter::new(Vec::with_capacity(1_000));
sender_msl.write_message(&datas, &mut channel)?;
// Server read client message from channel
let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?;
receiver_msl.read(&channel[..])
}
#[test]
fn server_recv_ack_early() -> Result<()> {
//////////////////////////
// SERVER INFOS
//////////////////////////
let (mut server_msl, server_sig_kp) = server_infos()?;
//////////////////////////
// CLIENT INFOS
//////////////////////////
let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?;
//////////////////////////
// SERVER CONNECT MSG
//////////////////////////
send_connect_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![5, 1, 1, 5]),
)?;
//////////////////////////
// CLIENT ACK MSG
//////////////////////////
assert_eq!(
None,
send_ack_msg_inner(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(&[7, 1, 1, 7]),
)?
);
//////////////////////////
// CLIENT CONNECT MSG
//////////////////////////
send_connect_msg(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(vec![5, 4, 4, 5]),
)?;
//////////////////////////
// SERVER ACK MSG
//////////////////////////
send_ack_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![3, 1, 1, 3]),
)?;
/////////////////////////////////////////
// RECEIVE CLIENT USER MSG TOO EARLY
/////////////////////////////////////////
assert_eq!(
None,
send_user_msg_inner(&mut client_msl, &mut server_msl, vec![5, 2, 2, 5],)?
);
//////////////////////////////////////////
// GET CLIENT ACK MSG RECEIVED TOO EARLY
//////////////////////////////////////////
assert_eq!(
Some(Message::Ack {
custom_datas: Some(vec![7, 1, 1, 7]),
}),
server_msl.take_ack_msg_recv_too_early()?
);
assert_eq!(None, server_msl.take_ack_msg_recv_too_early()?);
//////////////////////////////////////////
// GET CLIENT USER MSG RECEIVED TOO EARLY
//////////////////////////////////////////
assert_eq!(
vec![Message::Message {
custom_datas: Some(vec![5, 2, 2, 5]),
}],
server_msl.drain_tmp_stack_user_msgs()?
);
assert_eq!(
Vec::::with_capacity(0),
server_msl.drain_tmp_stack_user_msgs()?
);
Ok(())
}
#[test]
fn disordered_passing_case() -> Result<()> {
//////////////////////////
// SERVER INFOS
//////////////////////////
let (mut server_msl, server_sig_kp) = server_infos()?;
//////////////////////////
// CLIENT INFOS
//////////////////////////
let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?;
//////////////////////////
// CLIENT CONNECT MSG
//////////////////////////
send_connect_msg(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(vec![5, 4, 4, 5]),
)?;
//////////////////////////
// SERVER ACK MSG
//////////////////////////
send_ack_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![5, 8, 8, 5]),
)?;
//////////////////////////
// SERVER CONNECT MSG
//////////////////////////
send_connect_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![5, 1, 1, 5]),
)?;
//////////////////////////
// CLIENT ACK MSG
//////////////////////////
send_ack_msg(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(vec![7, 4, 4, 7]),
)?;
//////////////////////////
// SERVER USER MSG
//////////////////////////
send_user_msg(&mut server_msl, &mut client_msl, vec![1, 5, 5, 1])?;
Ok(())
}
#[test]
fn test_middle_man_detection() -> Result<()> {
//////////////////////////
// SERVER INFOS
//////////////////////////
let (_server_msl, server_sig_kp) = server_infos()?;
//////////////////////////
// MIDDLE MAN INFOS
//////////////////////////
let (mut middle_msl, middle_sig_kp) = server_infos()?;
//////////////////////////
// CLIENT INFOS
//////////////////////////
let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?;
//////////////////////////
// CLIENT CONNECT MSG
//////////////////////////
send_connect_msg(
&mut client_msl,
&client_sig_kp,
&mut middle_msl,
Some(vec![7, 6, 5, 4]),
)?;
//////////////////////////
// MIDDLE MAN CONNECT MSG
//////////////////////////
let result = send_connect_msg(
&mut middle_msl,
&middle_sig_kp,
&mut client_msl,
Some(vec![7, 5, 6, 4]),
);
if let Err(Error::UnexpectedRemoteSigPubKey) = result {
Ok(())
} else {
println!("unexpected result={:?}", result);
panic!();
}
}
#[test]
fn ordered_passing_case() -> Result<()> {
//////////////////////////
// SERVER INFOS
//////////////////////////
let (mut server_msl, server_sig_kp) = server_infos()?;
//////////////////////////
// CLIENT INFOS
//////////////////////////
let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?;
//////////////////////////
// CLIENT CONNECT MSG
//////////////////////////
send_connect_msg(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(vec![5, 4, 4, 5]),
)?;
//////////////////////////
// SERVER CONNECT MSG
//////////////////////////
send_connect_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![5, 6, 6, 5]),
)?;
//////////////////////////
// SERVER ACK MSG
//////////////////////////
send_ack_msg(
&mut server_msl,
&server_sig_kp,
&mut client_msl,
Some(vec![5, 8, 8, 5]),
)?;
//////////////////////////
// CLIENT ACK MSG
//////////////////////////
send_ack_msg(
&mut client_msl,
&client_sig_kp,
&mut server_msl,
Some(vec![5, 9, 9, 5]),
)?;
// Negociation must be successfull, so we can clone secure layer
client_msl.try_clone()?;
server_msl.try_clone()?;
// After clone, we can't change config
let result = client_msl.change_config(SecureLayerConfig::default());
if let Err(Error::ForbidChangeConfAfterClone) = result {
// OK
} else {
println!("unexpected result={:?}", result);
panic!();
}
//////////////////////////
// CLIENT USER MSG
//////////////////////////
send_user_msg(&mut client_msl, &mut server_msl, vec![5, 7, 7, 5])?;
//////////////////////////
// SERVER USER MSG
//////////////////////////
send_user_msg(&mut server_msl, &mut client_msl, vec![7, 4, 4, 7])?;
Ok(())
}