pub mod access_control;
mod addresses;
mod api;
mod decryptor;
mod encryptor;
mod encryptor_worker;
pub(crate) mod handshake;
mod key_tracker;
mod listener;
mod message;
mod nonce;
mod nonce_tracker;
mod options;
mod registry;
mod role;
pub mod trust_policy;
pub use access_control::*;
pub(crate) use addresses::*;
pub use api::*;
pub(crate) use decryptor::*;
pub(crate) use encryptor_worker::*;
pub(crate) use handshake::*;
pub(crate) use listener::*;
pub use message::*;
pub use nonce::*;
pub use options::*;
pub use registry::*;
pub(crate) use role::*;
pub use trust_policy::*;
#[cfg(test)]
mod tests {
use crate::secure_channel::{decryptor::Decryptor, encryptor::Encryptor};
use ockam_core::compat::rand::RngCore;
use ockam_core::Result;
use ockam_vault::{SoftwareVaultForSecureChannels, VaultForSecureChannels};
use rand::seq::SliceRandom;
use rand::thread_rng;
#[tokio::test]
async fn test_encrypt_decrypt_normal_flow() {
let (mut encryptor, mut decryptor) = create_encryptor_decryptor().await.unwrap();
for n in 0..100 {
let msg = vec![n];
let mut ciphertext = vec![0u8; 1 + 24];
ciphertext[8..9].copy_from_slice(msg.as_slice());
encryptor.encrypt(&mut ciphertext).await.unwrap();
assert_eq!(
msg,
decryptor
.decrypt(ciphertext.as_mut_slice())
.await
.unwrap()
.0
);
}
}
#[tokio::test]
async fn test_encrypt_decrypt_with_message_lost() {
let (mut encryptor, mut decryptor) = create_encryptor_decryptor().await.unwrap();
for n in 0..100 {
let msg = vec![n];
let mut ciphertext = vec![0u8; 1 + 24];
ciphertext[8..9].copy_from_slice(msg.as_slice());
encryptor.encrypt(&mut ciphertext).await.unwrap();
if n % 3 == 0 {
assert_eq!(
msg,
decryptor
.decrypt(ciphertext.as_mut_slice())
.await
.unwrap()
.0
);
}
}
}
#[tokio::test]
async fn test_encrypt_decrypt_out_of_order() {
let (mut encryptor, mut decryptor) = create_encryptor_decryptor().await.unwrap();
let mut all_msgs: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
for n in 0..100 {
let mut batch: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
for m in 0..30 {
let msg = vec![n, m];
let mut ciphertext = vec![0u8; 2 + 24];
ciphertext[8..10].copy_from_slice(msg.as_slice());
encryptor.encrypt(&mut ciphertext).await.unwrap();
batch.push((msg, ciphertext));
}
batch.shuffle(&mut thread_rng());
all_msgs.append(&mut batch);
}
for (plaintext, ciphertext) in all_msgs.iter() {
assert_eq!(
plaintext,
&decryptor
.decrypt(ciphertext.clone().as_mut_slice())
.await
.unwrap()
.0
);
}
for (_plaintext, ciphertext) in all_msgs.iter() {
assert!(decryptor
.decrypt(ciphertext.clone().as_mut_slice())
.await
.is_err());
}
let msg = vec![1, 1];
let mut ciphertext = vec![0u8; 2 + 24];
ciphertext[8..10].copy_from_slice(msg.as_slice());
encryptor.encrypt(&mut ciphertext).await.unwrap();
assert_eq!(
msg,
decryptor
.decrypt(ciphertext.clone().as_mut_slice())
.await
.unwrap()
.0
);
}
#[tokio::test]
async fn test_attack_nonce() {
let (mut encryptor, mut decryptor) = create_encryptor_decryptor().await.unwrap();
for n in 0..100 {
let msg = vec![n];
let mut ciphertext = vec![0u8; 1 + 24];
ciphertext[8..9].copy_from_slice(msg.as_slice());
encryptor.encrypt(&mut ciphertext).await.unwrap();
let mut trash_packet = ciphertext.clone();
trash_packet[ciphertext.len() - 1] ^= 0b1000_0000;
let mut bad_nonce_msg = Vec::new();
let bad_nonce: u64 = 1000000;
bad_nonce_msg.extend_from_slice(&bad_nonce.to_be_bytes());
bad_nonce_msg.extend_from_slice(&ciphertext[8..]);
assert!(decryptor
.decrypt(trash_packet.clone().as_mut_slice())
.await
.is_err());
assert!(decryptor
.decrypt(bad_nonce_msg.clone().as_mut_slice())
.await
.is_err());
assert_eq!(
msg,
decryptor
.decrypt(ciphertext.clone().as_mut_slice())
.await
.unwrap()
.0
);
}
}
async fn create_encryptor_decryptor() -> Result<(Encryptor, Decryptor)> {
let vault1 = SoftwareVaultForSecureChannels::create().await?;
let vault2 = SoftwareVaultForSecureChannels::create().await?;
let mut rng = thread_rng();
let mut key = [0u8; 32];
rng.fill_bytes(&mut key);
let key_on_v1 = vault1.import_secret_buffer(key.to_vec()).await?;
let key_on_v1 = vault1.convert_secret_buffer_to_aead_key(key_on_v1).await?;
let key_on_v2 = vault2.import_secret_buffer(key.to_vec()).await?;
let key_on_v2 = vault2.convert_secret_buffer_to_aead_key(key_on_v2).await?;
Ok((
Encryptor::new(key_on_v1, 0.into(), vault1, true),
Decryptor::new(key_on_v2, vault2),
))
}
}