|
ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
|
RFC 4253 transport layer: identification exchange, algorithm negotiation, key exchange. More...
#include "crypto/aead/aesgcm/aesgcm.h"#include "crypto/aead/chachapoly/chachapoly.h"#include "crypto/asymmetric/bignum/bignum.h"#include "crypto/cipher/aes256ctr/aes256ctr.h"#include "crypto/hash/sha256/sha256.h"#include "locus_carcerum/locus_carcerum.h"#include "network_drivers/presentation/ssh/common/common.h"#include "network_drivers/presentation/ssh/transport/phase_machine/phase_machine.h"#include "protocore_config.h"Go to the source code of this file.
Classes | |
| struct | SshDir |
| One direction's codec state, handed to the packet layer per call. More... | |
| struct | SshSession |
| SSH transport/session state for one connection (BSS pool). More... | |
| struct | SshPacketArgs |
| RFC 4253 sec 6 binary packet: the bytes a receive consumes, and the body it carries. More... | |
| struct | SshTransportOut |
| Where a build or a send writes, and what it wrote. More... | |
| struct | SshKexHashArgs |
| RFC 4253 sec 8: every term the exchange hash H is taken over, and where H lands. More... | |
| struct | SshRekeyArgs |
| RFC 4253 sec 9 key re-exchange: what has passed since the last one, against its budget. More... | |
| struct | SshTransportVars |
| struct | SshTransportNs |
| The entries. More... | |
| struct | SshKdfInputs |
| One key exchange's derivation inputs, passed by reference. More... | |
| struct | SshPacketState |
| Per-connection SSH binary packet state. More... | |
| 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... | |
| struct | SshKexEphemeral |
Macros | |
| #define | SSH_TRANSPORT (&SshTransport) |
| Reader shorthand: SSH_TRANSPORT->kexinit_parse(...). | |
| #define | SSH_KDF_MAX (4 * PROTOCORE_SHA256_DIGEST_LEN) |
| Max bytes ssh_kdf_derive() can produce (4 SHA-256 blocks). | |
| #define | SSH_UNIMPLEMENTED_LEN 5u |
| Bytes in an SSH_MSG_UNIMPLEMENTED payload: the message number and one uint32. | |
Typedefs | |
| typedef enum PROTO_ENUM_PACKED | SshKexAlg |
| Negotiated key-exchange method. | |
| typedef enum PROTO_ENUM_PACKED | SshHostkeyAlg |
| Negotiated host-key / signature algorithm. | |
| typedef void(* | ssh_msg_handler_t) (uint8_t slot, uint8_t msg_type, const uint8_t *payload, size_t payload_len) |
| Callback invoked once per complete, verified inbound SSH message. | |
Functions | |
| void | ssh_kex_set_prefer_rsa (proto_bool prefer) |
| Steer KEX and host-key negotiation toward RSA with DH-group14, or toward curve25519 with ed25519. | |
| proto_bool | ssh_kex_prefer_rsa (void) |
| Current negotiation preference (true = prefer RSA / DH). | |
| const uint8_t * | ssh_session_id (uint8_t i, size_t *len) |
The session identifier for slot i, or null before the first key exchange completes. | |
| void | ssh_session_id_latch (uint8_t i, const uint8_t *h, size_t h_len) |
Latch the first exchange's hash as slot i's session identifier (RFC 4253 sec 7.2). | |
| proto_bool | ssh_kex_is_sha512 (SshKexAlg a) |
True when a hashes with SHA-512 rather than SHA-256 (RFC 8268, RFC 8731). | |
| proto_bool | ssh_hostkey_verify (uint8_t i, const uint8_t *ks, size_t ks_len, const uint8_t *sig, size_t sig_len, const uint8_t *h, size_t h_len) |
| Verify the server's signature over the exchange hash with its host key (RFC 4253 sec 8). | |
| void | protocore_ssh_transport_recv_ident (uint8_t *work) |
| void | protocore_ssh_transport_send_ident (uint8_t *work) |
| void | protocore_ssh_transport_kexinit_build (uint8_t *work) |
| void | protocore_ssh_transport_kexinit_parse (uint8_t *work) |
| void | protocore_ssh_transport_kex_generate (uint8_t *work) |
| void | protocore_ssh_transport_exchange_hash (uint8_t *work) |
| void | protocore_ssh_transport_kexdh_reply (uint8_t *work) |
| void | protocore_ssh_transport_newkeys_sent (uint8_t *work) |
| void | protocore_ssh_transport_newkeys_complete (uint8_t *work) |
| void | protocore_ssh_transport_rekey_due (uint8_t *work) |
| void | protocore_ssh_transport_begin_rekey (uint8_t *work) |
| uint8_t * | protocore_ssh_transport_span (void) |
| The PROTOCORE_SSH_TRANSPORT_BORROW bytes this module's state lives in. | |
| void | ssh_pkt_init (uint8_t i) |
Initialize the packet state for SSH connection slot i. | |
| void | ssh_transport_init (uint8_t i) |
Bind the session state for SSH connection slot i to the slot's storage. | |
| proto_bool | ssh_pkt_slot_storage (SshPacketState *s) |
| Take the slot's one persistent borrow if it has none yet, and split it. | |
| void | ssh_pkt_set_client (uint8_t i) |
Mark slot i as the SSH client role (call once, right after ssh_pkt_init). | |
| int | ssh_pkt_send_at (uint8_t i, uint8_t *wire, size_t payload_len, size_t *out_len, size_t wire_cap, const SshDir *dir) |
Frame the payload_len bytes already written at wire + SSH_WIRE_PAYLOAD_OFF. | |
| int | ssh_pkt_emit (uint8_t i, const uint8_t *payload, size_t len, const SshDir *dir) |
Frame payload for slot i into the secure pool and raise the flag a worker drains. | |
| int | ssh_pkt_send (uint8_t i, const uint8_t *payload, size_t payload_len, uint8_t *out, size_t *out_len, size_t out_cap, const SshDir *dir) |
| Build and send one SSH binary packet. | |
| int | ssh_pkt_recv (uint8_t i, const uint8_t *data, size_t len, ssh_msg_handler_t handler, const SshDir *dir) |
Receive and process one or more SSH binary packets from data. | |
| int | ssh_pkt_disconnect (uint8_t i, uint32_t reason_code, uint8_t *out, size_t *out_len, size_t out_cap, const SshDir *dir) |
Send SSH_MSG_DISCONNECT with reason reason_code. | |
| int | ssh_pkt_unimplemented (uint8_t i, uint8_t *out, size_t *out_len, size_t out_cap) |
Build the SSH_MSG_UNIMPLEMENTED payload answering the packet slot i last received. | |
| int | ssh_dh_generate (uint8_t i) |
Generate slot i's DH ephemeral: a random y, and f = g^y mod p (RFC 4253 sec 8). | |
| void | ssh_kdf_derive (const SshKdfInputs *in, char label, uint8_t *out, size_t out_len) |
Derive the RFC 4253 sec 7.2 keys from K, H and the session id into slot i's epoch, one letter per direction. | |
| void | ssh_kex_install_keys (uint8_t i, const SshKdfInputs *in) |
| int | ssh_pkt_build_disconnect (uint32_t reason_code, const char *desc, size_t desc_len, uint8_t *out, size_t *out_len, size_t cap) |
| Send DISCONNECT with the no-more-auth-methods reason, then drop. | |
| int | ssh_transport_dispatch (uint8_t i, uint8_t msg_type, const uint8_t *payload, size_t len) |
| Dispatch one decrypted message; 50 and above go up to the authentication protocol. | |
| void | ssh_transport_key_re_exchange (uint8_t i) |
Emit a fresh KEXINIT for slot i once its volume or time budget is spent. | |
| int | ssh_transport_service_request (const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap) |
| Handle SSH_MSG_SERVICE_REQUEST; emit SERVICE_ACCEPT for ssh-userauth (RFC 4253 sec 10). | |
| int | ssh_transport_version_exchange_recv (uint8_t i, const uint8_t *buf, size_t n, size_t *off) |
Take the peer identification string off buf (RFC 4253 sec 4.2). | |
| proto_bool | ssh_kex_shared_secret (const SshKexEphemeral *e, const uint8_t *peer_pub, uint32_t peer_pub_len, uint8_t k_be[256]) |
| Compute K from the peer's exchange value, for the role that sent the first message. | |
| proto_bool | ssh_pubkey_blob_valid (const uint8_t *blob, uint32_t blob_len) |
True when blob holds a public key in one of the formats this build decodes. | |
| proto_bool | ssh_pubkey_algo_supported (const char *pk_algo, const uint8_t *blob, uint32_t blob_len) |
True when pk_algo names an algorithm this end verifies, and blob is of its key type. | |
| proto_bool | ssh_pubkey_verify (uint8_t i, const char *pk_algo, const uint8_t *blob, uint32_t blob_len, const uint8_t *sig, uint32_t sig_len, const uint8_t *signed_data, size_t signed_len) |
Verify sig over signed_data against the public key in blob, out of slot i's crypto_work. The key type comes from the blob; pk_algo steers the RSA signature hash (RFC 8332). | |
Variables | |
| SshSession | ssh_sess [MAX_SSH_CONNS] |
| Static pool of SSH session state (BSS), one per SSH slot. | |
| SshTransportVars | SshTransportV |
| The operands and the outcome. | |
| SshPacketState | ssh_pkt [MAX_SSH_CONNS] |
| Static packet state pool (BSS). One entry per SSH slot. | |
| SshKeyMat | ssh_keys [MAX_SSH_CONNS][2] |
| Pool of session key material, two epochs per MAX_SSH_CONNS. | |
| SshDhState | ssh_dh [MAX_SSH_CONNS] |
| Pool of ephemeral DH state, one entry per MAX_SSH_CONNS. | |
RFC 4253 transport layer: identification exchange, algorithm negotiation, key exchange.
Definition in file transport.h.
| #define SSH_TRANSPORT (&SshTransport) |
Reader shorthand: SSH_TRANSPORT->kexinit_parse(...).
Definition at line 325 of file transport.h.
| #define SSH_KDF_MAX (4 * PROTOCORE_SHA256_DIGEST_LEN) |
Max bytes ssh_kdf_derive() can produce (4 SHA-256 blocks).
Definition at line 344 of file transport.h.
| #define SSH_UNIMPLEMENTED_LEN 5u |
Bytes in an SSH_MSG_UNIMPLEMENTED payload: the message number and one uint32.
Definition at line 552 of file transport.h.
| typedef enum PROTO_ENUM_PACKED SshKexAlg |
Negotiated key-exchange method.
| typedef enum PROTO_ENUM_PACKED SshHostkeyAlg |
Negotiated host-key / signature algorithm.
| typedef void(* ssh_msg_handler_t) (uint8_t slot, uint8_t msg_type, const uint8_t *payload, size_t payload_len) |
Callback invoked once per complete, verified inbound SSH message.
| slot | SSH slot index. |
| msg_type | First payload byte (SSH message number). |
| payload | Decrypted message payload (includes msg_type at [0]). |
| payload_len | Length of payload. |
Definition at line 511 of file transport.h.
| enum PROTO_ENUM_PACKED |
Negotiated key-exchange method.
| Enumerator | |
|---|---|
| SSH_KEX_DH_GROUP14 | diffie-hellman-group14-sha256 (RFC 8268) |
| SSH_KEX_CURVE25519 | curve25519-sha256 (RFC 8731) |
| SSH_KEX_MLKEM768_X25519 | mlkem768x25519-sha256 |
| SSH_KEX_ECDH_NISTP256 | ecdh-sha2-nistp256 (RFC 5656 sec 4) |
| SSH_KEX_SNTRUP761_X25519 | sntru.nosp@m.p761.nosp@m.x2551.nosp@m.9-sh.nosp@m.a512@.nosp@m.open.nosp@m.ssh.c.nosp@m.om |
| SSH_HOSTKEY_RSA_SHA256 | rsa-sha2-256 (RFC 8332) |
| SSH_HOSTKEY_ED25519 | ssh-ed25519 (RFC 8709) |
| SSH_HOSTKEY_RSA_SHA512 | rsa-sha2-512 (RFC 8332) |
| SSH_HOSTKEY_ECDSA_NISTP256 | ecdsa-sha2-nistp256 (RFC 5656) |
Definition at line 38 of file transport.h.
| enum PROTO_ENUM_PACKED |
Negotiated host-key / signature algorithm.
| Enumerator | |
|---|---|
| SSH_KEX_DH_GROUP14 | diffie-hellman-group14-sha256 (RFC 8268) |
| SSH_KEX_CURVE25519 | curve25519-sha256 (RFC 8731) |
| SSH_KEX_MLKEM768_X25519 | mlkem768x25519-sha256 |
| SSH_KEX_ECDH_NISTP256 | ecdh-sha2-nistp256 (RFC 5656 sec 4) |
| SSH_KEX_SNTRUP761_X25519 | sntru.nosp@m.p761.nosp@m.x2551.nosp@m.9-sh.nosp@m.a512@.nosp@m.open.nosp@m.ssh.c.nosp@m.om |
| SSH_HOSTKEY_RSA_SHA256 | rsa-sha2-256 (RFC 8332) |
| SSH_HOSTKEY_ED25519 | ssh-ed25519 (RFC 8709) |
| SSH_HOSTKEY_RSA_SHA512 | rsa-sha2-512 (RFC 8332) |
| SSH_HOSTKEY_ECDSA_NISTP256 | ecdsa-sha2-nistp256 (RFC 5656) |
Definition at line 48 of file transport.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 578 of file transport.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 586 of file transport.h.
| void ssh_kex_set_prefer_rsa | ( | proto_bool | prefer | ) |
Steer KEX and host-key negotiation toward RSA with DH-group14, or toward curve25519 with ed25519.
Both suites are advertised whatever this is set to; it orders them, so a peer that supports only one still connects. Runtime-selectable, before the handshake.
| proto_bool ssh_kex_prefer_rsa | ( | void | ) |
Current negotiation preference (true = prefer RSA / DH).
| const uint8_t * ssh_session_id | ( | uint8_t | i, |
| size_t * | len | ||
| ) |
The session identifier for slot i, or null before the first key exchange completes.
RFC 4253 sec 10: "When the service starts, it may have access to the session identifier generated during the key exchange." It is the first exchange's hash H (sec 7.2) and does not change on a re-exchange, so a service that binds to it stays bound.
| i | SSH slot index. |
| len | Set to the identifier's length: 32 for the SHA-256 methods, 64 for the SHA-512 one. |
| void ssh_session_id_latch | ( | uint8_t | i, |
| const uint8_t * | h, | ||
| size_t | h_len | ||
| ) |
Latch the first exchange's hash as slot i's session identifier (RFC 4253 sec 7.2).
"The exchange hash H from the first key exchange is additionally used as the session identifier." Both roles compute H in their own half of sec 8 and hand it here; the second and later exchanges are ignored, so the identifier never moves under a service that bound to it.
| proto_bool ssh_kex_is_sha512 | ( | SshKexAlg | a | ) |
True when a hashes with SHA-512 rather than SHA-256 (RFC 8268, RFC 8731).
| proto_bool ssh_hostkey_verify | ( | uint8_t | i, |
| const uint8_t * | ks, | ||
| size_t | ks_len, | ||
| const uint8_t * | sig, | ||
| size_t | sig_len, | ||
| const uint8_t * | h, | ||
| size_t | h_len | ||
| ) |
Verify the server's signature over the exchange hash with its host key (RFC 4253 sec 8).
| i | the SSH slot the exchange belongs to |
| ks | the host key blob the server sent |
| ks_len | its length |
| sig | the signature blob |
| sig_len | its length |
| h | the exchange hash the signature is taken over |
| h_len | its length |
| void protocore_ssh_transport_recv_ident | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_send_ident | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_kexinit_build | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_kexinit_parse | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_kex_generate | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_exchange_hash | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_kexdh_reply | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_newkeys_sent | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_newkeys_complete | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_rekey_due | ( | uint8_t * | work | ) |
| void protocore_ssh_transport_begin_rekey | ( | uint8_t * | work | ) |
| uint8_t * protocore_ssh_transport_span | ( | void | ) |
The PROTOCORE_SSH_TRANSPORT_BORROW bytes this module's state lives in.
Stated beside the namespace rather than on it: an entry takes a borrow, and this is where that borrow comes from. Taken once from the end of the pool, which no mark and no release walks, so the state lasts the life of the program.
| void ssh_pkt_init | ( | uint8_t | i | ) |
Initialize the packet state for SSH connection slot i.
Zeroes the sequence numbers and the transmit state, keeping the slot's storage pointers. The protocol flags are the session's (ssh_transport.h) and are reset by ssh_transport_init().
| i | SSH slot index. |
| void ssh_transport_init | ( | uint8_t | i | ) |
Bind the session state for SSH connection slot i to the slot's storage.
Zeroes the session, then points each of its buffers and both key epochs at their offsets within the slot, leaves the phase at SSH_PHASE_IDENT with the first key exchange already running, and marks both epochs inactive.
| i | SSH slot index. |
| proto_bool ssh_pkt_slot_storage | ( | SshPacketState * | s | ) |
Take the slot's one persistent borrow if it has none yet, and split it.
Sets SshPacketState::tx_wire, SshPacketState::mac_work and SshPacketState::crypto_work. Idempotent, and false only when the pool cannot cover the slot.
| void ssh_pkt_set_client | ( | uint8_t | i | ) |
Mark slot i as the SSH client role (call once, right after ssh_pkt_init).
Flips the send/receive key direction: the client encrypts with the c2s key set and decrypts with the s2c one, the mirror of the server. Without this a slot defaults to the server role.
| int ssh_pkt_send_at | ( | uint8_t | i, |
| uint8_t * | wire, | ||
| size_t | payload_len, | ||
| size_t * | out_len, | ||
| size_t | wire_cap, | ||
| const SshDir * | dir | ||
| ) |
Frame the payload_len bytes already written at wire + SSH_WIRE_PAYLOAD_OFF.
The in-place form of ssh_pkt_send(): same framing, padding, encryption and MAC, over a payload the caller has already placed. wire holds the finished packet on return.
| int ssh_pkt_emit | ( | uint8_t | i, |
| const uint8_t * | payload, | ||
| size_t | len, | ||
| const SshDir * | dir | ||
| ) |
Frame payload for slot i into the secure pool and raise the flag a worker drains.
Borrows the wire buffer itself, for a caller that already holds its message somewhere else - handshake and control traffic, which is small and infrequent. On return the packet is framed and SshPacketState::tx_ready is set; a worker puts the bytes on the wire and releases the borrow. This layer never reaches the wire.
| int ssh_pkt_send | ( | uint8_t | i, |
| const uint8_t * | payload, | ||
| size_t | payload_len, | ||
| uint8_t * | out, | ||
| size_t * | out_len, | ||
| size_t | out_cap, | ||
| const SshDir * | dir | ||
| ) |
Build and send one SSH binary packet.
Frames payload according to RFC 4253 §6:
The serialized packet is written into out. *out_len is set to the number of bytes written. out must be at least (4 + 1 + payload_len + 16 + 32) bytes.
| i | SSH slot index. |
| payload | Plaintext SSH message payload. |
| payload_len | Length of payload. |
| out | Output buffer for the wire packet. |
| out_len | Set to the number of bytes written into out. |
| out_cap | Capacity of out. |
| int ssh_pkt_recv | ( | uint8_t | i, |
| const uint8_t * | data, | ||
| size_t | len, | ||
| ssh_msg_handler_t | handler, | ||
| const SshDir * | dir | ||
| ) |
Receive and process one or more SSH binary packets from data.
Appends len bytes from data to the receive buffer for slot i, then extracts complete packets. For each complete packet:
handler(slot, msg_type, payload, payload_len) for the payload.| i | SSH slot index. |
| data | Received bytes (from TCP). |
| len | Number of bytes in data. |
| handler | Callback invoked once per complete, verified packet. |
| int ssh_pkt_disconnect | ( | uint8_t | i, |
| uint32_t | reason_code, | ||
| uint8_t * | out, | ||
| size_t * | out_len, | ||
| size_t | out_cap, | ||
| const SshDir * | dir | ||
| ) |
Send SSH_MSG_DISCONNECT with reason reason_code.
Sends the packet, then zeroes the packet state and key material for slot i.
| i | SSH slot index. |
| reason_code | One of SSH_DISCONNECT_* constants. |
| out | Output buffer for the wire packet. |
| out_len | Set to the number of bytes written. |
| out_cap | Capacity of out. |
| int ssh_pkt_unimplemented | ( | uint8_t | i, |
| uint8_t * | out, | ||
| size_t * | out_len, | ||
| size_t | out_cap | ||
| ) |
Build the SSH_MSG_UNIMPLEMENTED payload answering the packet slot i last received.
"An implementation MUST respond to all unrecognized messages with an SSH_MSG_UNIMPLEMENTED message in the order in which the messages were received." The sequence number it carries is the receive counter's, which this layer owns; the caller frames and sends the payload.
| i | SSH slot index. |
| out | Output buffer for the payload. |
| out_len | Set to SSH_UNIMPLEMENTED_LEN. |
| out_cap | Capacity of out. |
| int ssh_dh_generate | ( | uint8_t | i | ) |
Generate slot i's DH ephemeral: a random y, and f = g^y mod p (RFC 4253 sec 8).
| void ssh_kdf_derive | ( | const SshKdfInputs * | in, |
| char | label, | ||
| uint8_t * | out, | ||
| size_t | out_len | ||
| ) |
Derive the RFC 4253 sec 7.2 keys from K, H and the session id into slot i's epoch, one letter per direction.
One RFC 4253 sec 7.2 derivation: out_len bytes of the key label names.
"Encryption keys MUST be computed as HASH, of a known value and K": K1 = HASH(K || H || X || session_id) with X the label byte, and where more bytes are wanted than one hash gives, "the key is extended by computing HASH of the concatenation of K and H and the entire key so far" - K2 = HASH(K || H || K1), K3 = HASH(K || H || K1 || K2), key = K1 || K2 || K3.
| label | 'A'..'F', the six keys sec 7.2 lists in order. |
| out_len | Bytes wanted, clamped to SSH_KDF_MAX. |
| void ssh_kex_install_keys | ( | uint8_t | i, |
| const SshKdfInputs * | in | ||
| ) |
| int ssh_pkt_build_disconnect | ( | uint32_t | reason_code, |
| const char * | desc, | ||
| size_t | desc_len, | ||
| uint8_t * | out, | ||
| size_t * | out_len, | ||
| size_t | cap | ||
| ) |
Send DISCONNECT with the no-more-auth-methods reason, then drop.
Build an SSH_MSG_DISCONNECT payload (RFC 4253 sec 11.1).
| reason_code | One of SSH_DISCONNECT_* constants. |
| desc | Description bytes, sent as the message's first string. |
| desc_len | Length of desc. |
| out | Output buffer for the payload. |
| out_len | Set to the number of bytes written. |
| cap | Capacity of out. |
cap cannot hold the whole message. | int ssh_transport_dispatch | ( | uint8_t | i, |
| uint8_t | msg_type, | ||
| const uint8_t * | payload, | ||
| size_t | len | ||
| ) |
Dispatch one decrypted message; 50 and above go up to the authentication protocol.
| void ssh_transport_key_re_exchange | ( | uint8_t | i | ) |
Emit a fresh KEXINIT for slot i once its volume or time budget is spent.
| int ssh_transport_service_request | ( | const uint8_t * | payload, |
| size_t | len, | ||
| uint8_t * | out, | ||
| size_t * | out_len, | ||
| size_t | cap | ||
| ) |
Handle SSH_MSG_SERVICE_REQUEST; emit SERVICE_ACCEPT for ssh-userauth (RFC 4253 sec 10).
out, or -1 if the service is not "ssh-userauth" or the message is malformed. | int ssh_transport_version_exchange_recv | ( | uint8_t | i, |
| const uint8_t * | buf, | ||
| size_t | n, | ||
| size_t * | off | ||
| ) |
Take the peer identification string off buf (RFC 4253 sec 4.2).
off is left at the first binary packet byte. | proto_bool ssh_kex_shared_secret | ( | const SshKexEphemeral * | e, |
| const uint8_t * | peer_pub, | ||
| uint32_t | peer_pub_len, | ||
| uint8_t | k_be[256] | ||
| ) |
Compute K from the peer's exchange value, for the role that sent the first message.
One switch over the negotiated method, beside the responder half that shares this file: RFC 4253 sec 8 is the transport's, whichever end is running it. K is written right-aligned into k_be, which is how sec 8 and sec 7.2 both consume it - as an mpint for the classical methods, and as a fixed 32 or 64-byte string for the hybrids.
| e | This end's ephemeral for the exchange. |
| peer_pub | The peer's exchange value: Q_S, f, or ciphertext || Q_S for a hybrid. |
| peer_pub_len | Length of peer_pub; each method checks it against its own. |
| k_be | 256 bytes, zeroed then filled from the right. |
| proto_bool ssh_pubkey_blob_valid | ( | const uint8_t * | blob, |
| uint32_t | blob_len | ||
| ) |
True when blob holds a public key in one of the formats this build decodes.
| proto_bool ssh_pubkey_algo_supported | ( | const char * | pk_algo, |
| const uint8_t * | blob, | ||
| uint32_t | blob_len | ||
| ) |
True when pk_algo names an algorithm this end verifies, and blob is of its key type.
RFC 4252 sec 7: "Any public key algorithm may be offered for use in authentication... If the server does not support some algorithm, it MUST simply reject the request." The name arrives independently of the blob, so both are checked against what the blob parsers here accept: either RSA signature name takes an "ssh-rsa" blob, the other two take a blob named for themselves.
| proto_bool ssh_pubkey_verify | ( | uint8_t | i, |
| const char * | pk_algo, | ||
| const uint8_t * | blob, | ||
| uint32_t | blob_len, | ||
| const uint8_t * | sig, | ||
| uint32_t | sig_len, | ||
| const uint8_t * | signed_data, | ||
| size_t | signed_len | ||
| ) |
Verify sig over signed_data against the public key in blob, out of slot i's crypto_work. The key type comes from the blob; pk_algo steers the RSA signature hash (RFC 8332).
|
extern |
Static pool of SSH session state (BSS), one per SSH slot.
|
extern |
The operands and the outcome.
|
extern |
Static packet state pool (BSS). One entry per SSH slot.
|
extern |
Pool of session key material, two epochs per MAX_SSH_CONNS.
RFC 4253 sec 7.3 switches each direction on its own NEWKEYS, so a re-key derives into the epoch neither direction is reading and each direction moves to it when its NEWKEYS crosses. The SshDir the codec is handed selects which one that site reads. Zeroed on connection close by ssh_keymat_wipe(slot).
|
extern |
Pool of ephemeral DH state, one entry per MAX_SSH_CONNS.