|
DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
|
SSH session key material - types, pools, and security model. More...
#include "ServerConfig.h"#include "network_drivers/presentation/ssh/crypto/ssh_aes256ctr.h"#include "network_drivers/presentation/ssh/crypto/ssh_aesgcm.h"#include "network_drivers/presentation/ssh/crypto/ssh_bignum.h"#include "network_drivers/presentation/ssh/crypto/ssh_chachapoly.h"#include <stddef.h>#include <stdint.h>#include <string.h>Go to the source code of this file.
Classes | |
| struct | SshKeyMat |
| AES-256-CTR + HMAC-SHA2-256 session keys for one SSH connection. More... | |
| struct | SshDhState |
| Ephemeral Diffie-Hellman state for one SSH connection. More... | |
Enumerations | |
| enum | { SSH_CIPHER_AES256CTR = 0 , SSH_CIPHER_CHACHA20POLY1305 = 1 , SSH_CIPHER_AES256GCM = 2 } |
| Negotiated bulk cipher for a session. More... | |
| enum | { SSH_MAC_HMAC_SHA256 = 0 , SSH_MAC_HMAC_SHA512 = 1 , SSH_MAC_HMAC_SHA256_ETM = 2 , SSH_MAC_HMAC_SHA512_ETM = 3 } |
| Negotiated MAC for the aes256-ctr cipher (unused with the chacha AEAD). More... | |
Variables | |
| SshKeyMat | ssh_keys [MAX_SSH_CONNS] |
| Pool of session key material, one entry per MAX_SSH_CONNS. | |
| SshDhState | ssh_dh [MAX_SSH_CONNS] |
| Pool of ephemeral DH state, one entry per MAX_SSH_CONNS. | |
SSH session key material - types, pools, and security model.
═══════════════════════════════════════════════════════════════════════════ SECURITY MODEL - READ BEFORE MODIFYING ANYTHING IN THIS FILE ═══════════════════════════════════════════════════════════════════════════
The fundamental threat this layout defends against is buffer-overflow key extraction: an attacker who can cause an out-of-bounds read or write in the packet receive path (ssh_pool[].pkt_buf) should not be able to reach AES session keys or HMAC keys in the same memory operation.
DEFENSE 1 - Physical BSS separation ───────────────────────────────────── All three pools are SEPARATE static symbols:
ssh_pool[MAX_SSH_CONNS] - packet assembly buffers, protocol state ssh_keys[MAX_SSH_CONNS] - AES-256 key schedules + HMAC keys ssh_dh[MAX_SSH_CONNS] - ephemeral DH scalar (y), server public (f), K
The linker places these as independent objects. An overflow inside pkt_buf must cross the entire ssh_pool[] symbol, then any objects the linker placed between it and ssh_keys[], before reaching key material. On ESP32 with the default linker script this is a different RAM region than a linear overflow from pkt_buf would reach.
An attacker relying on a single linear write cannot bridge both gaps in one step. This is not mitigation-by-obscurity - it is the same "separate key store" principle used by HSMs, but implemented in software via linker symbol separation.
DEFENSE 2 - RSA host private key is NEVER stored in static memory ────────────────────────────────────────────────────────────────── The RSA-2048 private key (d, p, q, dp, dq, qInv) is loaded from NVS (encrypted flash on ESP32) into a LOCAL STACK FRAME inside ssh_rsa_sign(). It is explicitly zeroed (via volatile memset, which the compiler cannot elide) before ssh_rsa_sign() returns.
Consequences:
DEFENSE 3 - DH ephemeral scalar zeroing ───────────────────────────────────────── y (2048-bit private DH scalar) lives in ssh_dh[slot].y. After ssh_dh_finish() derives K it calls ssh_wipe() on the entire SshDhState struct, which uses a volatile loop to zero all 801 bytes including y, f, and K. K must be zeroed after session keys are derived from it (RFC 4253 §7.2 makes no requirement, but it reduces long-term exposure).
DEFENSE 4 - crypto_work scratch buffer zeroing ──────────────────────────────────────────────── crypto_work[SSH_CRYPTO_WORK_SIZE] is used for Montgomery multiplication temporaries (up to 516 bytes of intermediate products that contain combinations of y, K, and d fragments). It is zeroed via ssh_wipe() immediately after every call to bn_expmod_group14() or ssh_rsa_sign().
DEFENSE 5 - MAC-verify-before-use (all packet input) ────────────────────────────────────────────────────── After key exchange, every inbound SSH binary packet is:
If HMAC verification fails the connection is closed immediately. No plaintext bytes are acted upon before the MAC is confirmed valid. This prevents padding oracle and chosen-ciphertext attacks.
DEFENSE 6 - Sequence number overflow guard ──────────────────────────────────────────── RFC 4253 §9.3.4 requires rekeying before the sequence number wraps. If seq_c2s or seq_s2c reaches 0xFFFFFFFF the connection is closed. (Rekeying is not yet implemented; close-on-wrap is the safe fallback.)
WHAT THIS DOES NOT PROTECT AGAINST ────────────────────────────────────
═══════════════════════════════════════════════════════════════════════════
Definition in file ssh_keymat.h.
| anonymous enum |
Negotiated bulk cipher for a session.
| Enumerator | |
|---|---|
| SSH_CIPHER_AES256CTR | aes256-ctr + a separate HMAC (the fallback) |
| SSH_CIPHER_CHACHA20POLY1305 | chach.nosp@m.a20-.nosp@m.poly1.nosp@m.305@.nosp@m.opens.nosp@m.sh.c.nosp@m.om (AEAD; no separate MAC) |
| SSH_CIPHER_AES256GCM | aes25.nosp@m.6-gc.nosp@m.m@ope.nosp@m.nssh.nosp@m..com (AEAD, RFC 5647; no separate MAC) |
Definition at line 116 of file ssh_keymat.h.
| anonymous enum |
Negotiated MAC for the aes256-ctr cipher (unused with the chacha AEAD).
| Enumerator | |
|---|---|
| SSH_MAC_HMAC_SHA256 | hmac-sha2-256 (encrypt-and-MAC, RFC 4253) |
| SSH_MAC_HMAC_SHA512 | hmac-sha2-512 (encrypt-and-MAC) |
| SSH_MAC_HMAC_SHA256_ETM | hmac-.nosp@m.sha2.nosp@m.-256-.nosp@m.etm@.nosp@m.opens.nosp@m.sh.c.nosp@m.om (encrypt-then-MAC) |
| SSH_MAC_HMAC_SHA512_ETM | hmac-.nosp@m.sha2.nosp@m.-512-.nosp@m.etm@.nosp@m.opens.nosp@m.sh.c.nosp@m.om (encrypt-then-MAC) |
Definition at line 124 of file ssh_keymat.h.
|
extern |
Pool of session key material, one entry per MAX_SSH_CONNS.
Separate BSS symbol from ssh_pool[] - see security model. Zeroed on connection close by ssh_keymat_wipe(slot).
Definition at line 16 of file ssh_keymat.cpp.
Referenced by ssh_dh_derive_keys_sid(), ssh_pkt_recv(), and ssh_pkt_send().
|
extern |
Pool of ephemeral DH state, one entry per MAX_SSH_CONNS.
Definition at line 17 of file ssh_keymat.cpp.
Referenced by ssh_dh_generate(), and ssh_kexdh_handle().