Critical fix: KEXINIT exchange hash encoding (prepend SSH_MSG_KEXINIT byte)
OpenSSH kexgex.c source code analysis: - KEXINIT payload stored without SSH_MSG_KEXINIT type byte - Exchange hash prepends SSH_MSG_KEXINIT byte (20) with adjusted length Before fix: - client_kexinit_payload included SSH_MSG_KEXINIT byte - Direct use without prepending After fix: - Remove SSH_MSG_KEXINIT byte from payload - Prepend byte (20) in exchange hash with length+1 - Both kex_exchange.rs and kex_complete.rs updated Testing result: MAC still fails, indicating additional encoding issues Next: Detailed comparison of all exchange hash components
This commit is contained in:
@@ -215,11 +215,25 @@ impl KexExchangeHandler {
|
||||
hasher.update(&(server_version.len() as u32).to_be_bytes());
|
||||
hasher.update(server_version.as_bytes());
|
||||
|
||||
hasher.update(&(client_kexinit_payload.len() as u32).to_be_bytes());
|
||||
hasher.update(client_kexinit_payload);
|
||||
// OpenSSH kexgex.c: "kexinit messages: fake header: len+SSH2_MSG_KEXINIT"
|
||||
// KEXINIT payload should NOT include SSH_MSG_KEXINIT type byte
|
||||
// OpenSSH stores payload starting from cookie, prepends SSH_MSG_KEXINIT in exchange hash
|
||||
|
||||
hasher.update(&(server_kexinit_payload.len() as u32).to_be_bytes());
|
||||
hasher.update(server_kexinit_payload);
|
||||
// Remove SSH_MSG_KEXINIT type byte from payloads (our payload includes it)
|
||||
let client_kexinit_without_type = &client_kexinit_payload[1..];
|
||||
let server_kexinit_without_type = &server_kexinit_payload[1..];
|
||||
|
||||
info!("I_C (client KEXINIT without type byte): {} bytes (first byte should be cookie)", client_kexinit_without_type.len());
|
||||
info!("I_S (server KEXINIT without type byte): {} bytes", server_kexinit_without_type.len());
|
||||
|
||||
// Exchange hash: uint32(len+1) + uint8(SSH_MSG_KEXINIT) + payload_without_type
|
||||
hasher.update(&((client_kexinit_without_type.len() + 1) as u32).to_be_bytes());
|
||||
hasher.update(&[20]); // SSH_MSG_KEXINIT type byte
|
||||
hasher.update(client_kexinit_without_type);
|
||||
|
||||
hasher.update(&((server_kexinit_without_type.len() + 1) as u32).to_be_bytes());
|
||||
hasher.update(&[20]); // SSH_MSG_KEXINIT type byte
|
||||
hasher.update(server_kexinit_without_type);
|
||||
|
||||
hasher.update(&(host_key_blob.len() as u32).to_be_bytes());
|
||||
hasher.update(host_key_blob);
|
||||
|
||||
Reference in New Issue
Block a user