use alloc::vec::Vec;
pub const SSH_MSG_KEX_ECDH_INIT: u8 = 30;
pub const SSH_MSG_KEX_ECDH_REPLY: u8 = 31;
#[allow(dead_code)]
pub const SSH_MSG_KEX_DH_GEX_REQUEST_OLD: u8 = 30;
pub const SSH_MSG_KEX_DH_GEX_GROUP: u8 = 31;
pub const SSH_MSG_KEX_DH_GEX_INIT: u8 = 32;
pub const SSH_MSG_KEX_DH_GEX_REPLY: u8 = 33;
pub const SSH_MSG_KEX_DH_GEX_REQUEST: u8 = 34;
#[derive(Clone)]
pub struct KexContext<'a> {
pub v_c: &'a [u8],
pub v_s: &'a [u8],
pub i_c: &'a [u8],
pub i_s: &'a [u8],
}
#[derive(Debug, Clone)]
pub struct KexInitOut {
pub payload: Vec<u8>,
}
#[derive(Clone)]
#[non_exhaustive]
pub struct KexOutput {
pub k: Vec<u8>,
pub h: Vec<u8>,
}
impl Drop for KexOutput {
fn drop(&mut self) {
purecrypto::zeroize::Zeroize::zeroize(&mut self.k);
}
}
impl purecrypto::zeroize::ZeroizeOnDrop for KexOutput {}
impl core::fmt::Debug for KexOutput {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("KexOutput")
.field("h", &self.h)
.finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
#[test]
fn kex_output_debug_redacts_shared_secret() {
let out = KexOutput {
k: alloc::vec![0xAA; 8],
h: alloc::vec![0x11, 0x22],
};
let s = format!("{out:?}");
assert!(s.contains("h: [17, 34]"), "{s}");
assert!(!s.contains("170"), "shared secret leaked: {s}");
assert!(!s.contains("k:"), "shared secret field printed: {s}");
}
}