use crate::header::Counter;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Secret {
key: Vec<u8>,
salt: Vec<u8>,
auth: Option<Vec<u8>>,
}
impl Secret {
pub(crate) fn aead(key: Vec<u8>, salt: Vec<u8>) -> Self {
Self {
key,
salt,
auth: None,
}
}
#[cfg(aes_ctr)]
pub(crate) fn aes_ctr(key: Vec<u8>, salt: Vec<u8>, auth: Vec<u8>) -> Self {
Self {
key,
salt,
auth: Some(auth),
}
}
pub(crate) fn key(&self) -> &[u8] {
&self.key
}
pub(crate) fn salt(&self) -> &[u8] {
&self.salt
}
#[cfg(aes_ctr)]
pub(crate) fn auth(&self) -> Option<&[u8]> {
self.auth.as_deref()
}
pub(crate) fn create_nonce<const LEN: usize>(&self, counter: Counter) -> [u8; LEN] {
let salt = self.salt();
let be_counter = counter.to_be_bytes();
let mut counter = be_counter.iter().rev();
let mut iv = [0u8; LEN];
let n = salt.len().min(LEN);
for i in (0..n).rev() {
iv[i] = salt[i];
if let Some(counter_byte) = counter.next() {
iv[i] ^= counter_byte;
}
}
iv
}
#[cfg(all(test, crypto_backend))]
pub(crate) fn from_test_vector(test_vec: &crate::test_vectors::SframeTest) -> Self {
Secret::aead(test_vec.sframe_key.clone(), test_vec.sframe_salt.clone())
}
}
#[cfg(test)]
mod test {
use crate::test_vectors::get_sframe_test_vector;
use crate::{crypto::cipher_suite::CipherSuite, util::test::assert_bytes_eq};
use super::Secret;
use test_case::test_case;
const NONCE_LEN: usize = 12;
#[test_case(CipherSuite::AesGcm128Sha256; "AesGcm128Sha256")]
#[test_case(CipherSuite::AesGcm256Sha512; "AesGcm256Sha512")]
#[cfg_attr(feature = "openssl", test_case(CipherSuite::AesCtr128HmacSha256_80; "AesCtr128HmacSha256_80"))]
#[cfg_attr(feature = "openssl", test_case(CipherSuite::AesCtr128HmacSha256_64; "AesCtr128HmacSha256_64"))]
#[cfg_attr(feature = "openssl", test_case(CipherSuite::AesCtr128HmacSha256_32; "AesCtr128HmacSha256_32"))]
fn create_correct_nonce(cipher_suite: CipherSuite) {
let test_vec = get_sframe_test_vector(&cipher_suite.to_string());
let secret = Secret::aead(test_vec.sframe_key.clone(), test_vec.sframe_salt.clone());
let nonce: [u8; NONCE_LEN] = secret.create_nonce(test_vec.counter);
assert_bytes_eq(&nonce, &test_vec.nonce);
}
}