DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ssh_dh.cpp File Reference

DH-group14-SHA256 key exchange implementation. More...

Go to the source code of this file.

Functions

void ssh_rng_fill (uint8_t *buf, size_t len)
 Fill len bytes of buf with cryptographically random data.
 
int ssh_dh_generate (uint8_t i)
 Generate the server ephemeral DH key pair for connection slot i.
 
void ssh_kdf_derive (const uint8_t K_be[256], const uint8_t H[SSH_SHA256_DIGEST_LEN], const uint8_t session_id[SSH_SHA256_DIGEST_LEN], char label, uint8_t *out, size_t out_len, bool k_is_string)
 RFC 4253 §7.2 key derivation for any length up to SSH_KDF_MAX.
 
void ssh_dh_derive_keys_sid (uint8_t i, const uint8_t K_be[256], const uint8_t H[SSH_SHA256_DIGEST_LEN], const uint8_t session_id[SSH_SHA256_DIGEST_LEN], uint8_t cipher_alg, uint8_t mac_alg, bool k_is_string)
 Derive session keys with an explicit session id (RFC 4253 §7.2).
 
void ssh_dh_derive_keys (uint8_t i, const uint8_t K_be[256], const uint8_t H[SSH_SHA256_DIGEST_LEN])
 Derive the six session keys from shared secret K and exchange hash H.
 

Detailed Description

DH-group14-SHA256 key exchange implementation.

Definition in file ssh_dh.cpp.

Function Documentation

◆ ssh_rng_fill()

void ssh_rng_fill ( uint8_t *  buf,
size_t  len 
)

Fill len bytes of buf with cryptographically random data.

On Arduino: uses esp_fill_random() (hardware RNG seeded by analog noise). On native: uses esp_fill_random() from the Arduino.h mock, which is a time-seeded PRNG - NOT secure, for testing only.

Definition at line 18 of file ssh_dh.cpp.

Referenced by ssh_dh_generate(), ssh_kex_generate(), and ssh_kexinit_build().

◆ ssh_dh_generate()

int ssh_dh_generate ( uint8_t  i)

Generate the server ephemeral DH key pair for connection slot i.

Fills ssh_dh[i].y with random bytes (2048-bit private scalar), then computes ssh_dh[i].f = 2^y mod p (the server's public DH value).

The caller must send f in SSH_MSG_KEXDH_REPLY after this returns.

Parameters
iSSH connection slot index.
Returns
0 on success, -1 if i is out of range.

Definition at line 27 of file ssh_dh.cpp.

References bn_expmod_group14(), SshBigNum::d, SshDhState::f, group14_g, SshDhState::kex_done, MAX_SSH_CONNS, SSH_BN_LIMBS, ssh_dh, ssh_rng_fill(), and SshDhState::y.

Referenced by ssh_kex_generate().

◆ ssh_kdf_derive()

void ssh_kdf_derive ( const uint8_t  K_be[256],
const uint8_t  H[SSH_SHA256_DIGEST_LEN],
const uint8_t  session_id[SSH_SHA256_DIGEST_LEN],
char  label,
uint8_t *  out,
size_t  out_len,
bool  k_is_string = false 
)

RFC 4253 §7.2 key derivation for any length up to SSH_KDF_MAX.

Produces K1 || K2 || ... where K1 = HASH(K || H || label || session_id) and each Ki+1 = HASH(K || H || K1..Ki), filling out (out_len bytes). K is encoded as an mpint (classical KEX) or, when k_is_string, a plain 32-byte SSH string (the mlkem768x25519-sha256 hybrid). Every algorithm negotiated today needs <= 32 B (one block); the chain exists for spec-completeness / future ciphers needing longer key material. out_len is clamped to SSH_KDF_MAX.

Definition at line 110 of file ssh_dh.cpp.

References SSH_KDF_MAX, SSH_SHA256_DIGEST_LEN, ssh_sha256_final(), ssh_sha256_init(), and ssh_sha256_update().

Referenced by ssh_dh_derive_keys_sid().

◆ ssh_dh_derive_keys_sid()

void ssh_dh_derive_keys_sid ( uint8_t  i,
const uint8_t  K_be[256],
const uint8_t  H[SSH_SHA256_DIGEST_LEN],
const uint8_t  session_id[SSH_SHA256_DIGEST_LEN],
uint8_t  cipher_alg,
uint8_t  mac_alg,
bool  k_is_string = false 
)

Derive session keys with an explicit session id (RFC 4253 §7.2).

Same as ssh_dh_derive_keys() but uses session_id for the session-id component of every key, which on a re-key must remain the exchange hash H from the first KEX (while H is the current re-key exchange hash).

Parameters
iSlot index.
K_beShared secret K, big-endian, 256 bytes.
HCurrent exchange hash, 32 bytes.
session_idSession id (H of the first KEX), 32 bytes.
k_is_stringEncode K as a plain SSH string (hybrid KEX) instead of an mpint (classical).

Definition at line 151 of file ssh_dh.cpp.

References SshKeyMat::active, SshKeyMat::c2s_ctx, SshKeyMat::chacha_key_c2s, SshKeyMat::chacha_key_s2c, SshKeyMat::cipher_mode, SshKeyMat::gcm_c2s, SshKeyMat::gcm_s2c, SshKeyMat::mac_key_c2s, SshKeyMat::mac_key_s2c, SshKeyMat::mac_mode, MAX_SSH_CONNS, SshKeyMat::s2c_ctx, ssh_aes256ctr_init(), ssh_aesgcm_init(), SSH_CHACHAPOLY_KEY_LEN, SSH_CIPHER_AES256GCM, SSH_CIPHER_CHACHA20POLY1305, ssh_kdf_derive(), ssh_keys, and SSH_SHA256_DIGEST_LEN.

Referenced by ssh_dh_derive_keys(), and ssh_kexdh_handle().

◆ ssh_dh_derive_keys()

void ssh_dh_derive_keys ( uint8_t  i,
const uint8_t  K_be[256],
const uint8_t  H[SSH_SHA256_DIGEST_LEN] 
)

Derive the six session keys from shared secret K and exchange hash H.

Implements RFC 4253 §7.2 key derivation: IV_c2s = SHA256(K || H || 'A' || session_id) [first 16 bytes] IV_s2c = SHA256(K || H || 'B' || session_id) [first 16 bytes] key_c2s = SHA256(K || H || 'C' || session_id) [32 bytes] key_s2c = SHA256(K || H || 'D' || session_id) [32 bytes] mac_c2s = SHA256(K || H || 'E' || session_id) [32 bytes] mac_s2c = SHA256(K || H || 'F' || session_id) [32 bytes]

Installs the derived keys into ssh_keys[i]. Does NOT zero K or H - the caller does that.

Parameters
iSlot index.
K_beShared secret K, big-endian, 256 bytes.
HExchange hash, 32 bytes (also used as session_id).

Definition at line 221 of file ssh_dh.cpp.

References SSH_CIPHER_AES256CTR, ssh_dh_derive_keys_sid(), and SSH_MAC_HMAC_SHA256.