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

NIST P-256 primitives for SSH: ECDSA signatures and ECDH (RFC 5656 / FIPS 186-4). More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Functions

bool ssh_ecdsa_p256_pubkey (uint8_t pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
 Derive the uncompressed public point Q = d*G from a P-256 private scalar.
 
bool ssh_ecdsa_p256_sign (uint8_t sig[SSH_ECDSA_P256_SIG_LEN], const uint8_t *msg, size_t mlen, const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
 Sign mlen bytes of msg with a P-256 private key (ECDSA, SHA-256).
 
bool ssh_ecdsa_p256_verify (const uint8_t pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t *msg, size_t mlen, const uint8_t sig[SSH_ECDSA_P256_SIG_LEN])
 Verify a P-256 ECDSA signature (SHA-256) against an uncompressed public point.
 
bool ssh_ecdsa_p256_ecdh (uint8_t shared_x[SSH_ECDSA_P256_COORD_LEN], const uint8_t peer_pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
 P-256 ECDH: the shared-secret X coordinate of d * Q_peer (RFC 5656 §4 / RFC 5903).
 

Detailed Description

NIST P-256 primitives for SSH: ECDSA signatures and ECDH (RFC 5656 / FIPS 186-4).

Backs three P-256 SSH mechanisms, all sharing the one curve:

  • ecdsa-sha2-nistp256 host key + client publickey auth (RFC 5656 §3): the server signs the KEX exchange hash with its P-256 host key and verifies a client's signature.
  • ecdh-sha2-nistp256 key exchange (RFC 5656 §4): the P-256 ECDH shared secret. ECDSA always hashes the message with SHA-256 (nistp256 pairs with SHA-256, RFC 5656 §6.2.1).

═══════════════════════════════════════════════════════════════════════════ ARDUINO VS NATIVE ═══════════════════════════════════════════════════════════════════════════

Arduino: mbedTLS (mbedtls_ecdsa_*, mbedtls_ecp_*) - hardware-accelerated big-integer math on the ESP32 and side-channel-hardened. This is the production path. Signing uses the ESP32 hardware RNG (randomized ECDSA, RFC 6979 not required for validity).

Native: self-contained software P-256 - 256-bit field/scalar arithmetic (bit-serial reduction mod p and mod n), Jacobian point arithmetic, and RFC 6979 deterministic signing so the sign path is byte-exact against the RFC 6979 A.2.5 (P-256/SHA-256) known-answer vectors. Test-only, like the native RSA path; not compiled into firmware.

═══════════════════════════════════════════════════════════════════════════ WIRE FORMATS (assembled by the SSH transport/auth layers, not here) ═══════════════════════════════════════════════════════════════════════════

Public-key blob (RFC 5656 §3.1): string("ecdsa-sha2-nistp256") || string("nistp256") || string(Q) where Q is the uncompressed point 0x04 || X || Y (65 bytes). This module exposes Q as ssh_ecdsa_p256_pubkey; the layers wrap it.

Signature blob (RFC 5656 §3.1.2): string("ecdsa-sha2-nistp256") || string( mpint(r) || mpint(s) ) This module exposes the raw r || s (32 + 32 big-endian); the layers mpint-wrap them.

ECDH shared secret (RFC 5656 §4): K = the X coordinate of d * Q_peer. ssh_ecdsa_p256_ecdh returns the raw 32-byte X; the transport encodes it as an mpint in the exchange hash and the key derivation.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file ssh_ecdsa.h.

Function Documentation

◆ ssh_ecdsa_p256_pubkey()

bool ssh_ecdsa_p256_pubkey ( uint8_t  pub[SSH_ECDSA_P256_PUB_LEN],
const uint8_t  priv[SSH_ECDSA_P256_PRIV_LEN] 
)

Derive the uncompressed public point Q = d*G from a P-256 private scalar.

Parameters
[out]pub65-byte uncompressed point 0x04 || X || Y.
[in]priv32-byte big-endian private scalar d (must satisfy 1 <= d < n).
Returns
true on success, false if priv is 0 or >= the group order n.

Definition at line 79 of file ssh_ecdsa.cpp.

Referenced by ssh_hostkey_ecdsa_set(), ssh_kex_generate(), and ssh_kexdh_handle().

◆ ssh_ecdsa_p256_sign()

bool ssh_ecdsa_p256_sign ( uint8_t  sig[SSH_ECDSA_P256_SIG_LEN],
const uint8_t *  msg,
size_t  mlen,
const uint8_t  priv[SSH_ECDSA_P256_PRIV_LEN] 
)

Sign mlen bytes of msg with a P-256 private key (ECDSA, SHA-256).

The message is hashed with SHA-256 internally. Native builds sign deterministically (RFC 6979); Arduino builds sign with the hardware RNG. Both produce a valid signature.

Parameters
[out]sig64-byte raw signature r || s (big-endian, 32 + 32).
[in]msgMessage to sign (typically the KEX exchange hash H).
[in]mlenLength of msg.
[in]priv32-byte big-endian private scalar d.
Returns
true on success, false on invalid key or internal failure.

Definition at line 106 of file ssh_ecdsa.cpp.

References ssh_sha256(), and SSH_SHA256_DIGEST_LEN.

◆ ssh_ecdsa_p256_verify()

bool ssh_ecdsa_p256_verify ( const uint8_t  pub[SSH_ECDSA_P256_PUB_LEN],
const uint8_t *  msg,
size_t  mlen,
const uint8_t  sig[SSH_ECDSA_P256_SIG_LEN] 
)

Verify a P-256 ECDSA signature (SHA-256) against an uncompressed public point.

Parameters
[in]pub65-byte uncompressed point 0x04 || X || Y (rejected if not on-curve).
[in]msgSigned message.
[in]mlenLength of msg.
[in]sig64-byte raw signature r || s (big-endian, 32 + 32).
Returns
true if the signature is valid, false otherwise.

Definition at line 136 of file ssh_ecdsa.cpp.

References ssh_sha256(), and SSH_SHA256_DIGEST_LEN.

◆ ssh_ecdsa_p256_ecdh()

bool ssh_ecdsa_p256_ecdh ( uint8_t  shared_x[SSH_ECDSA_P256_COORD_LEN],
const uint8_t  peer_pub[SSH_ECDSA_P256_PUB_LEN],
const uint8_t  priv[SSH_ECDSA_P256_PRIV_LEN] 
)

P-256 ECDH: the shared-secret X coordinate of d * Q_peer (RFC 5656 §4 / RFC 5903).

Backs the ecdh-sha2-nistp256 SSH key exchange. Validates that peer_pub is a valid on-curve point and that the product is not the identity; the returned 32-byte big-endian X coordinate is the shared field element the transport encodes as an mpint.

Parameters
[out]shared_x32-byte big-endian X coordinate of d * Q_peer.
[in]peer_pub65-byte uncompressed peer point 0x04 || X || Y.
[in]priv32-byte big-endian private scalar d (1 <= d < n).
Returns
true on success, false on an invalid peer point / scalar or an identity result.

Definition at line 166 of file ssh_ecdsa.cpp.

Referenced by ssh_kexdh_handle().