34#ifndef DETERMINISTICESPASYNCWEBSERVER_SSH_TRANSPORT_H
35#define DETERMINISTICESPASYNCWEBSERVER_SSH_TRANSPORT_H
48#define SSH_VERSION_MAX 256
54static constexpr size_t SSH_KEXINIT_S_MAX = 704;
57#define SSH_SERVER_VERSION "SSH-2.0-DetWS_1.0"
125 uint8_t
i_s[SSH_KEXINIT_S_MAX];
279int ssh_kex_exchange_hash(uint8_t i,
const uint8_t *e_be,
const uint8_t *f_be,
const uint8_t *k_be,
const uint8_t *ks,
311int ssh_kexdh_build_reply(
const uint8_t *ks,
size_t ks_len,
const uint8_t *f_be,
const uint8_t *sig,
size_t sig_len,
312 uint8_t *out,
size_t *out_len,
size_t cap);
337int ssh_kexdh_handle(uint8_t i,
const uint8_t *payload,
size_t len, uint8_t *reply_out,
size_t *reply_len,
size_t cap);
373bool ssh_rekey_due(uint32_t seq_send, uint32_t seq_recv, uint32_t elapsed_ms, uint32_t pkt_threshold,
374 uint32_t time_threshold_ms);
User-facing configuration for DeterministicESPAsyncWebServer.
#define SSH_KEXINIT_MAX
Max stored size of the CLIENT KEXINIT payload (I_C, for the exchange hash).
#define MAX_SSH_CONNS
Maximum simultaneous SSH connections.
SSH session key material - types, pools, and security model.
SHA-256 (FIPS 180-4) - streaming context and one-shot API.
#define SSH_SHA256_DIGEST_LEN
SHA-256 digest length in bytes.
int ssh_kex_generate(uint8_t i)
Generate the server ephemeral for the negotiated KEX method (call after parse).
bool ssh_kex_prefer_rsa(void)
Current negotiation preference (true = prefer RSA/DH, the ESP32-accelerated path).
bool ssh_hostkey_ed25519_available(void)
True if an ssh-ed25519 host key has been installed.
int ssh_transport_recv_banner(uint8_t i, const uint8_t *data, size_t len, size_t *consumed)
Feed raw bytes while awaiting the client identification string.
void ssh_hostkey_ed25519_set(const uint8_t seed[32])
Install an ssh-ed25519 host key from its 32-byte seed (RFC 8032 private key).
int ssh_extinfo_build(uint8_t *out, size_t *len, size_t cap)
Build SSH_MSG_EXT_INFO advertising server-sig-algs (RFC 8308).
#define SSH_VERSION_MAX
Max stored length of an SSH identification string (RFC 4253 §4.2: 255).
SshHostkeyAlg
Negotiated host-key / signature algorithm.
@ SSH_HOSTKEY_RSA_SHA512
rsa-sha2-512 (same "ssh-rsa" key, SHA-512 signature; RFC 8332)
@ SSH_HOSTKEY_ECDSA_NISTP256
ecdsa-sha2-nistp256 (NIST P-256, RFC 5656)
@ SSH_HOSTKEY_RSA_SHA256
rsa-sha2-256 (HW-accelerated on ESP32)
@ SSH_HOSTKEY_ED25519
ssh-ed25519 (RFC 8032)
int ssh_kexinit_build(uint8_t i, uint8_t *payload, size_t *len, size_t cap)
Build the server KEXINIT payload for slot i (RFC 4253 §7.1).
void ssh_hostkey_ecdsa_set(const uint8_t priv[32])
Install an ecdsa-sha2-nistp256 host key from its 32-byte P-256 private scalar.
void ssh_newkeys_complete(uint8_t i)
Complete the NEWKEYS exchange: activate the inbound direction and advance phase.
bool ssh_rekey_needed(uint8_t i)
True if slot i has reached the re-key threshold (RFC 4253 §9).
void ssh_newkeys_sent(uint8_t i)
Activate the outbound direction after emitting our SSH_MSG_NEWKEYS.
int ssh_transport_begin_rekey(uint8_t i, uint8_t *out, size_t *out_len, size_t cap)
Begin a server-initiated re-key by emitting a fresh KEXINIT.
bool ssh_hostkey_ecdsa_available(void)
True if an ecdsa-sha2-nistp256 host key has been installed.
SshKexAlg
SSH transport/session state for one connection (BSS pool).
@ SSH_KEX_MLKEM768_X25519
mlkem768x25519-sha256 (PQ/T hybrid, draft-ietf-sshm-mlkem-hybrid-kex)
@ SSH_KEX_ECDH_NISTP256
ecdh-sha2-nistp256 (NIST P-256 ECDH, RFC 5656 §4)
@ SSH_KEX_CURVE25519
curve25519-sha256 (RFC 8731, X25519)
@ SSH_KEX_DH_GROUP14
diffie-hellman-group14-sha256 (HW-accelerated MPI on ESP32)
SshPhase
SSH connection lifecycle phase.
@ SSH_PHASE_KEXINIT
Awaiting the client KEXINIT.
@ SSH_PHASE_AUTH
User authentication in progress (RFC 4252).
@ SSH_PHASE_SERVICE
Awaiting SERVICE_REQUEST ("ssh-userauth").
@ SSH_PHASE_OPEN
Authenticated; connection/channel protocol active.
@ SSH_PHASE_NEWKEYS
Awaiting SSH_MSG_NEWKEYS.
@ SSH_PHASE_BANNER
Awaiting the client identification string.
@ SSH_PHASE_DH_INIT
Awaiting SSH_MSG_KEXDH_INIT.
bool ssh_rekey_due(uint32_t seq_send, uint32_t seq_recv, uint32_t elapsed_ms, uint32_t pkt_threshold, uint32_t time_threshold_ms)
Pure re-key decision (RFC 4253 §9: "after each gigabyte ... or after each hour").
int ssh_kexdh_build_reply(const uint8_t *ks, size_t ks_len, const uint8_t *f_be, const uint8_t *sig, size_t sig_len, uint8_t *out, size_t *out_len, size_t cap)
Build SSH_MSG_KEXDH_REPLY (RFC 4253 §8, RFC 8332 §3).
SshSession ssh_sess[MAX_SSH_CONNS]
Static pool of SSH session state (BSS), one per SSH slot.
void ssh_kex_set_prefer_rsa(bool prefer)
Steer KEX / host-key negotiation toward RSA + DH-group14 (default) or toward the modern curve25519 + ...
int ssh_kexinit_parse(uint8_t i, const uint8_t *payload, size_t len)
Parse and negotiate the client KEXINIT payload (RFC 4253 §7.1).
void ssh_transport_init(uint8_t i)
Reset transport state for slot i to the start of a handshake.
int ssh_kexdh_handle(uint8_t i, const uint8_t *payload, size_t len, uint8_t *reply_out, size_t *reply_len, size_t cap)
Handle KEXDH/ECDH_INIT (msg 30) end-to-end and produce the reply payload.
int ssh_kex_exchange_hash(uint8_t i, const uint8_t *e_be, const uint8_t *f_be, const uint8_t *k_be, const uint8_t *ks, size_t ks_len, uint8_t out[SSH_SHA256_DIGEST_LEN])
Compute the SSH exchange hash H (RFC 4253 §8).
int ssh_transport_server_banner(uint8_t *out, size_t *out_len, size_t cap)
Write the server identification string ("SSH-2.0-…\r\n") to out.
int ssh_kexdh_parse_init(const uint8_t *payload, size_t len, uint8_t e_be[256])
Parse SSH_MSG_KEXDH_INIT, extracting the client DH value e.
bool ext_info_c
Client advertised ext-info-c (RFC 8308): send EXT_INFO.
uint8_t banner_buf[SSH_VERSION_MAX]
Accumulator for the inbound banner.
SshKexAlg kex_alg
negotiated in KEXINIT.
uint8_t ecdh_pk[32]
Server X25519 ephemeral public (curve25519 KEX only).
SshHostkeyAlg hostkey_alg
negotiated in KEXINIT.
uint16_t i_c_len
Length of i_c.
uint8_t session_id[SSH_SHA256_DIGEST_LEN]
H from the first KEX (RFC 4253 §7.2).
bool have_session_id
True once the first KEX completes.
SshPhase phase
Current handshake phase.
char v_c[SSH_VERSION_MAX]
Client identification string (no CR LF).
uint16_t i_s_len
Length of i_s.
bool authed
True after successful user authentication.
uint8_t mac_alg
SSH_MAC_* negotiated in KEXINIT (aes cipher only; 0 = hmac-sha2-256).
uint16_t banner_len
Bytes buffered in banner_buf.
uint8_t i_c[SSH_KEXINIT_MAX]
Client KEXINIT payload (for H).
uint32_t last_kex_ms
detws_millis() when the last KEX completed (server-initiated re-key timer).
uint8_t auth_failures
Failed USERAUTH_REQUESTs (brute-force limit, RFC 4252 §4).
uint8_t i_s[SSH_KEXINIT_S_MAX]
Server KEXINIT payload (for H).
uint8_t ecdh_sk[32]
Server X25519 ephemeral private (curve25519 KEX only; wiped after).
uint8_t cipher_alg
SSH_CIPHER_* negotiated in KEXINIT (0 = aes256-ctr).
uint16_t v_c_len
Length of v_c.