use crate::crypto::hash::HashFn;
use crate::types::Vec;
const MAX_INPUT_SIZE: usize = 257;
#[rustfmt::skip]
pub mod key_type {
pub const INITIAL_IV_CLIENT_TO_SERVER: u8 = b'A';
pub const INITIAL_IV_SERVER_TO_CLIENT: u8 = b'B';
pub const ENCRYPTION_KEY_CLIENT_TO_SERVER: u8 = b'C';
pub const ENCRYPTION_KEY_SERVER_TO_CLIENT: u8 = b'D';
pub const INTEGRITY_KEY_CLIENT_TO_SERVER: u8 = b'E';
pub const INTEGRITY_KEY_SERVER_TO_CLIENT: u8 = b'F';
}
pub fn sshkdf<H, const N: usize>(
shared_secret: &[u8],
exchange_hash: &[u8],
key_type: u8,
session_id: &[u8],
output: &mut [u8],
) where
H: HashFn<N>,
{
if output.is_empty() {
return;
}
let hash_len = N;
let mut input: Vec<u8, MAX_INPUT_SIZE> = Vec::new();
let mut temp_hash = [0u8; 64];
let temp_hash_slice = &mut temp_hash[..hash_len];
input.extend_from_slice(shared_secret);
input.extend_from_slice(exchange_hash);
input.push(key_type);
input.extend_from_slice(session_id);
let hash_result = H::hash(&[&input]);
temp_hash_slice.copy_from_slice(&hash_result);
let to_copy = output.len().min(hash_len);
output[..to_copy].copy_from_slice(&temp_hash_slice[..to_copy]);
let mut offset = to_copy;
while offset < output.len() {
input.clear();
input.extend_from_slice(shared_secret);
input.extend_from_slice(exchange_hash);
input.extend_from_slice(temp_hash_slice);
let hash_result = H::hash(&[&input]);
temp_hash_slice.copy_from_slice(&hash_result);
let remaining = output.len() - offset;
let to_copy = remaining.min(hash_len);
output[offset..offset + to_copy].copy_from_slice(&temp_hash_slice[..to_copy]);
offset += to_copy;
}
}