9#ifndef PROTOCORE_SSH_COMMON_H
10#define PROTOCORE_SSH_COMMON_H
12#include "cellularum_laboro/cellularum_laboro.h"
18#include "memoria_operor/memoria_operor.h"
20#include "octetus_introitus_exitus/octetus_introitus_exitus.h"
29#define SSH_VERSION_MAX 256
32#define SSH_VERSION_CONTENT_MAX 253
40#define PROTOCORE_SSH_KEXINIT_S_MAX 704
46#if PROTOCORE_ENABLE_SSH_CLIENT && PROTOCORE_ENABLE_SSH_SERVER
47#define PROTOCORE_SSH_I_C_MAX SSH_KEXINIT_MAX
48#define PROTOCORE_SSH_I_S_MAX SSH_KEXINIT_MAX
49#elif PROTOCORE_ENABLE_SSH_CLIENT
50#define PROTOCORE_SSH_I_C_MAX PROTOCORE_SSH_KEXINIT_S_MAX
51#define PROTOCORE_SSH_I_S_MAX SSH_KEXINIT_MAX
53#define PROTOCORE_SSH_I_C_MAX SSH_KEXINIT_MAX
54#define PROTOCORE_SSH_I_S_MAX PROTOCORE_SSH_KEXINIT_S_MAX
58#define SSH_SERVER_VERSION "SSH-2.0-1.0"
61#define SSH_CLIENT_VERSION "SSH-2.0-PROTOCORE_client_1.0"
139#define SSH_OFF_GCM_C2S 0u
140#define SSH_OFF_GCM_S2C (SSH_OFF_GCM_C2S + PROTOCORE_AESGCM_BORROW)
141#define SSH_OFF_CHACHA_C2S (SSH_OFF_GCM_S2C + PROTOCORE_AESGCM_BORROW)
142#define SSH_OFF_CHACHA_S2C (SSH_OFF_CHACHA_C2S + PROTOCORE_CHACHAPOLY_KEY_LEN)
143#define SSH_OFF_MAC_C2S (SSH_OFF_CHACHA_S2C + PROTOCORE_CHACHAPOLY_KEY_LEN)
144#define SSH_OFF_MAC_S2C (SSH_OFF_MAC_C2S + 64u)
145#define SSH_OFF_AES_KEY_C2S (SSH_OFF_MAC_S2C + 64u)
146#define SSH_OFF_AES_KEY_S2C (SSH_OFF_AES_KEY_C2S + PROTOCORE_AES256CTR_KEY_LEN)
147#define SSH_OFF_AES_IV_C2S (SSH_OFF_AES_KEY_S2C + PROTOCORE_AES256CTR_KEY_LEN)
148#define SSH_OFF_AES_IV_S2C (SSH_OFF_AES_IV_C2S + PROTOCORE_AES256CTR_CTR_LEN)
149#define SSH_EPOCH_STRIDE (SSH_OFF_AES_IV_S2C + PROTOCORE_AES256CTR_CTR_LEN)
169#define SSH_OFF_WIRE 0u
175#define SSH_OFF_V_C (SSH_OFF_WIRE + SSH_WIRE_CAP)
176#define SSH_OFF_V_S (SSH_OFF_V_C + SSH_VERSION_MAX)
177#define SSH_OFF_SESSION_ID (SSH_OFF_V_S + SSH_VERSION_MAX)
178#define SSH_OFF_EPOCH_0 (SSH_OFF_SESSION_ID + SSH_KEXHASH_MAX_LEN)
179#define SSH_OFF_EPOCH_1 (SSH_OFF_EPOCH_0 + SSH_EPOCH_STRIDE)
180#define SSH_SESSION_END (SSH_OFF_EPOCH_1 + SSH_EPOCH_STRIDE)
185#define SSH_OFF_IDENT SSH_SESSION_END
186#define SSH_OFF_I_C (SSH_OFF_IDENT + SSH_VERSION_MAX)
187#define SSH_OFF_I_S (SSH_OFF_I_C + PROTOCORE_SSH_I_C_MAX)
188#define SSH_OFF_KEXINIT (SSH_OFF_I_S + PROTOCORE_SSH_I_S_MAX)
189#define SSH_OFF_CPUB (SSH_OFF_KEXINIT + PROTOCORE_SSH_KEXINIT_S_MAX)
190#define SSH_OFF_DH_Y (SSH_OFF_CPUB + PROTOCORE_SSH_CPUB_MAX)
191#define SSH_OFF_DH_F (SSH_OFF_DH_Y + sizeof(protocore_bignum))
192#define SSH_OFF_DH_K (SSH_OFF_DH_F + sizeof(protocore_bignum))
193#define SSH_OFF_ECDH_SK (SSH_OFF_DH_K + sizeof(protocore_bignum))
194#define SSH_OFF_ECDH_PK (SSH_OFF_ECDH_SK + 32u)
196#define SSH_ECDH_PAIR_LEN 64u
197#define SSH_OFF_CRYPTO_WORK (SSH_OFF_ECDH_PK + 32u)
198#define SSH_EXCHANGE_END (SSH_OFF_CRYPTO_WORK + PROTOCORE_CRYPTO_BORROW_MAX)
204#define SSH_OFF_MAC_WORK SSH_EXCHANGE_END
205#define SSH_OFF_CIPHER_WORK (SSH_OFF_MAC_WORK + PROTOCORE_HMAC_SHA256_BORROW)
206#if PROTOCORE_CHACHAPOLY_BORROW > PROTOCORE_AES256CTR_BORROW
207#define SSH_CIPHER_WORK_LEN PROTOCORE_CHACHAPOLY_BORROW
209#if PROTOCORE_CHACHAPOLY_BORROW <= PROTOCORE_AES256CTR_BORROW
210#define SSH_CIPHER_WORK_LEN PROTOCORE_AES256CTR_BORROW
212#define SSH_PACKET_END (SSH_OFF_CIPHER_WORK + SSH_CIPHER_WORK_LEN)
216#define SSH_OFF_RX_READ SSH_PACKET_END
217#define SSH_OFF_RX_ASM (SSH_OFF_RX_READ + RX_BUF_SIZE)
220#define SSH_RX_ASM_CAP ((size_t)SSH_RFC_MAX_PAYLOAD)
223#define SSH_SLOT_BORROW (SSH_OFF_RX_ASM + SSH_RX_ASM_CAP)
228#define SSH_SESSION_SIZE (SSH_SESSION_END - SSH_OFF_V_C)
229#define SSH_EXCHANGE_SIZE (SSH_EXCHANGE_END - SSH_OFF_IDENT)
230#define SSH_PACKET_SIZE (SSH_PACKET_END - SSH_OFF_MAC_WORK)
231#define SSH_RX_SIZE (SSH_SLOT_BORROW - SSH_OFF_RX_READ)
238static inline uint32_t read_u32_be(
const uint8_t *p)
240 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
244static inline void write_u32_be(uint8_t *p, uint32_t v)
246 p[0] = (uint8_t)(v >> 24);
247 p[1] = (uint8_t)(v >> 16);
248 p[2] = (uint8_t)(v >> 8);
255 EMBED_CALL(byteio.put_be, OctetusCfg, .write_span = w, .value = (uint64_t)n, .bytes = 4);
256 EMBED_CALL(byteio.raw, OctetusCfg, .write_span = w, .src = data, .bytes = n);
276 while (off < len && be[off] == 0)
282 EMBED_CALL(byteio.put_be, OctetusCfg, .write_span = w, .value = 0, .bytes = 4);
286 uint64_t mlen = (uint64_t)(len - off);
291 EMBED_CALL(byteio.put_be, OctetusCfg, .write_span = w, .value = mlen, .bytes = 4);
294 EMBED_CALL(byteio.put, OctetusCfg, .write_span = w, .byte = 0x00);
296 EMBED_CALL(byteio.raw, OctetusCfg, .write_span = w, .src = be + off, .bytes = len - off);
310#define SSH_SEQ_CLOSE_THRESHOLD 0xFFFFFFF0u
322#if PROTOCORE_ENABLE_SSH_ZLIB
323#define SSH_MAX_EFFECTIVE_PAYLOAD (2 + SSH_RFC_MAX_PAYLOAD + (SSH_RFC_MAX_PAYLOAD >> 3) + 32)
325#define SSH_MAX_EFFECTIVE_PAYLOAD (SSH_RFC_MAX_PAYLOAD)
327#define SSH_MAX_PAD 32
328#define SSH_MAX_MAC 64
329#define SSH_PKT_WIRE_MAX ((size_t)(4 + 1 + SSH_MAX_EFFECTIVE_PAYLOAD + SSH_MAX_PAD + SSH_MAX_MAC))
338#define SSH_RFC_MAX_PAYLOAD 32768u
341#define SSH_RFC_MAX_PACKET 35000u
347#define SSH_WIRE_CAP ((size_t)131072u)
350 "the wire span must hold two of the 35000-byte packets RFC 4253 sec 6.1 requires processing");
359#if PROTOCORE_ENABLE_SSH_ZLIB
360#define PROTOCORE_PLAINTEXT_WORK_SSH_TRANSPORT ((size_t)(SSH_PKT_BUF_SIZE + 64 + SSH_PKT_BUF_SIZE))
362#define PROTOCORE_PLAINTEXT_WORK_SSH_TRANSPORT ((size_t)(SSH_PKT_BUF_SIZE + 64))
369 "PROTOCORE_WORK_SSH_CONN must cover one transient payload: raise it in protocore_config.h");
375 "PROTOCORE_SSH_SLOT_BYTES must cover one connection's whole span: raise it in protocore_config.h, "
376 "which sums it into the secure arena");
380#if PROTOCORE_ENABLE_PQC_KEX
382 "PROTOCORE_SSH_CPUB_MAX must cover an ML-KEM-768 C_INIT: raise it in protocore_config.h");
384#if PROTOCORE_ENABLE_SSH_SNTRUP761
386 "PROTOCORE_SSH_CPUB_MAX must cover an sntrup761 C_INIT: raise it in protocore_config.h");
391 "a slot's crypto_work must cover the RFC 4253 sec 7.2 KDF: raise PROTOCORE_CRYPTO_BORROW_MAX");
401#define SSH_WIRE_PAYLOAD_OFF 5
426 mmgr_cspan c = {.buf = r->
buf, .len = r->
len, .pos = r->
off, .err = EMBED_FALSE};
428 if (!EMBED_CALL(byteio.take_be, OctetusCfg, .read_span = &c, .bytes = 4, .out = &v))
439 mmgr_cspan c = {.buf = r->
buf, .len = r->
len, .pos = r->
off, .err = EMBED_FALSE};
440 const uint8_t *p = NULL;
442 if (!EMBED_CALL(byteio.rd_str, OctetusCfg, .read_span = &c, .blob = &p, .blob_bytes = &got))
462static proto_bool read_string(
const uint8_t *p,
size_t len,
size_t *off,
char *out,
size_t outcap)
464 mmgr_cspan c = {.buf = p, .len = len, .pos = *off, .err = EMBED_FALSE};
465 const uint8_t *s = NULL;
467 if (!EMBED_CALL(byteio.rd_str, OctetusCfg, .read_span = &c, .blob = &s, .blob_bytes = &n))
476 EMBED_CALL(memor.cpy, MemoriaCfg, .dst = out, .src = s, .bytes = n);
AES-256-CTR stream cipher (aes256-ctr, RFC 4344 §4).
2048-bit big-integer arithmetic for DH-group14 and RSA-2048.
#define PROTOCORE_CRYPTO_BORROW_MAX
#define PROTOCORE_SSH_KDF_BORROW
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define SSH_PKT_BUF_SIZE
Packet assembly buffer per SSH connection (bytes).
#define PROTOCORE_SSH_SLOT_BYTES
One connection's whole span: the wire, the session, the exchange, the packet and the rx regions end t...
chacha20-poly1305@openssh.com AEAD cipher (OpenSSH PROTOCOL.chacha20poly1305).
#define PROTOCORE_INLINE
Linkage for a leaf primitive whose body is cheaper than the call that reaches it.
#define PROTOCORE_WORK_SSH_CONN
#define PROTOCORE_SSH_CPUB_MAX
Reverse-SSH tunnel: max concurrent forwarded-tcpip channels bridged at once. A relay that forwards to...
HMAC-SHA2-256 (RFC 2104 + FIPS 198-1) - streaming context and one-shot API.
#define MLKEM768_EK_BYTES
encapsulation key (public key): 384*k + 32
PROTOCORE_INLINE void protocore_ssh_wr_cstr(mmgr_span *w, const char *s)
Append a NUL-terminated s as a string, its length taken up to the span's capacity.
#define SSH_RFC_MAX_PACKET
Largest total packet RFC 4253 sec 6.1 requires an implementation to process.
enum PROTO_ENUM_PACKED SshOpenFailureReason
Channel open failure reason codes (RFC 4254 sec 5.1).
enum PROTO_ENUM_PACKED SshDisconnectReason
Disconnect reason codes (RFC 4253 sec 11.1, numbered by RFC 4250 sec 4.2.2).
PROTOCORE_INLINE void protocore_ssh_wr_str(mmgr_span *w, const void *data, size_t n)
Append a string: uint32 length, then n bytes of data.
PROTOCORE_INLINE const uint8_t * protocore_ssh_rd_string(Rd *r, uint32_t *n)
PROTOCORE_INLINE void protocore_ssh_wr_mpint(mmgr_span *w, const uint8_t *be, size_t len)
Append len big-endian bytes as an mpint: leading zero bytes stripped, a 0x00 prepended when the top b...
PROTOCORE_BEGIN_DECLS enum PROTO_ENUM_PACKED SshMsgId
Protocol opcodes, by the number each RFC assigns it (RFC 4250 sec 4.1.2).
#define SSH_SLOT_BORROW
One connection's whole span, and the stride between slots.
@ SSH_DISCONNECT_SERVICE_NOT_AVAILABLE
@ SSH_DISCONNECT_MAC_ERROR
@ SSH_MSG_REQUEST_FAILURE
@ SSH_MSG_USERAUTH_REQUEST
@ SSH_MSG_CHANNEL_EXTENDED_DATA
@ SSH_MSG_USERAUTH_BANNER
@ SSH_OPEN_CONNECT_FAILED
@ SSH_OPEN_ADMINISTRATIVELY_PROHIBITED
@ SSH_MSG_CHANNEL_WINDOW_ADJUST
@ SSH_MSG_USERAUTH_FAILURE
@ SSH_MSG_REQUEST_SUCCESS
@ SSH_DISCONNECT_BY_APPLICATION
@ SSH_MSG_CHANNEL_FAILURE
@ SSH_OPEN_UNKNOWN_CHANNEL_TYPE
@ SSH_MSG_CHANNEL_OPEN_CONFIRMATION
@ SSH_MSG_USERAUTH_INFO_RESPONSE
@ SSH_OPEN_RESOURCE_SHORTAGE
@ SSH_MSG_SERVICE_REQUEST
@ SSH_MSG_CHANNEL_REQUEST
@ SSH_MSG_CHANNEL_OPEN_FAILURE
@ SSH_MSG_USERAUTH_INFO_REQUEST
@ SSH_DISCONNECT_TOO_MANY_CONNECTIONS
@ SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE
@ SSH_MSG_CHANNEL_SUCCESS
@ SSH_MSG_USERAUTH_SUCCESS
@ SSH_DISCONNECT_PROTOCOL_ERROR
PROTOCORE_INLINE uint32_t protocore_ssh_rd_u32(Rd *r)
PROTOCORE_INLINE uint8_t protocore_ssh_rd_u8(Rd *r)
Streamlined NTRU Prime sntrup761 KEM - keygen, encapsulation, decapsulation.
#define PROTOCORE_SNTRUP761_PK_BYTES
public key (Rq-encoded h)
One key-exchange digest that dispatches SHA-256 or SHA-512 by the negotiated method.
#define PROTO_FALSE
the false value
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
_Bool proto_bool
The truth value.
#define PROTO_TRUE
the true value, spelled so a caller never writes a bare 1
#define PROTOCORE_END_DECLS