Depth is a complete SSH-2.0 protocol implementation written entirely in x86_64 NASM assembly. A ~94 KB statically-linked ELF binary handles key exchange (Curve25519), host authentication (Ed25519), encrypted transport (ChaCha20-Poly1305), interactive shells (PTY), remote command execution, SFTP file transfers, and TCP port forwarding — all built from scratch with pure Linux syscalls, zero libc, zero dependencies.
- Highlights
- Quick Start
- Architecture
- Configuration
- Wire Protocol
- Internals
- Testing
- Project Structure
- Future Work
|
Full |
Complete elliptic curve cryptography from scratch. X25519 Diffie-Hellman for key exchange, Ed25519 for host key signatures. SHA-512 for Ed25519 internals, SHA-256 for exchange hash. All field arithmetic in pure assembly. |
|
RFC 4253/4254 compliant: version exchange, algorithm negotiation (KEXINIT), ECDH key exchange, NEWKEYS, service request, password authentication, channel multiplexing (up to 8 concurrent), PTY allocation, shell/exec requests, window management. |
The entire implementation — crypto primitives, SSH protocol, PTY handling, SFTP, port forwarding, TLS 1.3 — compiles to a ~94 KB statically-linked ELF. No libc, no dynamic linking, no runtime dependencies. Pure Linux syscalls via |
|
Full SFTPv3 implementation: open, read, write, close, stat, fstat, lstat, setstat, opendir, readdir, remove, mkdir, rmdir, rename, realpath. Handles concurrent shell + SFTP sessions through event-loop integration. |
Both local ( |
|
Full pseudoterminal support via |
Non-interactive |
| Requirement | Version |
|---|---|
| NASM | Latest |
| GNU ld | Any (static linking) |
| GCC | Any (for sc_reduce_c.c helper) |
| Python | >= 3.8 (for tests) |
| pytest | pip install pytest |
| cryptography | pip install cryptography |
# Clone
git clone https://github.com/Real-Fruit-Snacks/Depth.git
cd Depth
# Build everything (binary + all test harnesses)
make
# Run tests (268 tests)
make test
# Run the binary (bind mode, port 7777)
./build/depth
# Connect with OpenSSH
ssh -p 7777 svc@target
# Non-interactive command execution
ssh -p 7777 svc@target 'whoami'
# SFTP
sftp -P 7777 svc@target
# Port forwarding
ssh -L 8080:internal:80 -p 7777 svc@targetEdit include/config.inc before building:
server_ip: dd 0x0100007F ; 127.0.0.1 (network byte order)
server_port: dw 0xBB01 ; port 443 (big-endian)
ssh_username: db "svc"
ssh_password: db "changeme"
bind_mode: db 1 ; 0=reverse, 1=bind
bind_port: dw 7777[Operator] [Target]
OpenSSH ──────── TCP ──────────> depth (bind mode)
<── SSH-2.0 banner ────
── KEXINIT ───────────>
<── KEXINIT ──────────
── ECDH_INIT ─────────>
<── ECDH_REPLY ─────── (Ed25519 signed)
── NEWKEYS ───────────>
<── NEWKEYS ──────────
══ encrypted channel ══>
<══ encrypted channel ══
| Layer | Implementation |
|---|---|
| Transport | Raw TCP via Linux syscalls (socket, connect, bind, listen, accept) |
| Encryption | chacha20-poly1305@openssh.com — two-key AEAD, sequence-number nonce |
| Key Exchange | Curve25519 ECDH (curve25519-sha256), SHA-256 exchange hash |
| Host Auth | Ed25519 signatures (ssh-ed25519), SHA-512 internals |
| User Auth | Password authentication (ssh-userauth service) |
| Channels | Up to 8 multiplexed channels with independent window management |
| Shell | PTY via /dev/ptmx, poll-based I/O relay, child lifecycle management |
| Exec | Pipe-based bash -c for non-interactive commands, stdout/stderr merged |
| SFTP | SFTPv3 with 16 file handle slots, event-loop integrated |
| Forwarding | Local (direct-tcpip) and remote (tcpip-forward) TCP forwarding |
| TLS | Optional TLS 1.3 wrapping (X25519 + ChaCha20-Poly1305) via I/O dispatch |
| Key Derivation | HKDF-SHA256 with RFC 4253 key derivation (A-F letters) |
| MAC | hmac-sha2-256 advertised for compatibility (implicit with AEAD cipher) |
┌──────────────┬──────────┬───────────┬──────────┐
│ pkt_len (4B) │ pad (1B) │ payload │ padding │
│ big-endian │ │ │ >= 4B │
└──────────────┴──────────┴───────────┴──────────┘
total = 4 + pkt_len, aligned to 8 bytes
┌──────────────────┬────────────────────────┬──────────┐
│ enc_length (4B) │ enc_payload (N) │ MAC (16B)│
│ K2 stream cipher │ K1 ChaCha20 ctr=1 │ Poly1305 │
└──────────────────┴────────────────────────┴──────────┘
K2 encrypts length field (counter=0, seq as nonce)
K1 encrypts padded payload (counter=1)
Poly1305 key from K1 block 0
MAC covers enc_length + enc_payload
Client Server
│── SSH_MSG_KEX_ECDH_INIT ──────>│ (client ephemeral X25519 pub)
│ │ compute shared secret
│ │ compute exchange hash H
│ │ sign H with Ed25519 host key
│<── SSH_MSG_KEX_ECDH_REPLY ────│ (host pub + server ephem + signature)
│ verify Ed25519 signature │
│ derive 6 session keys (A-F) │ derive 6 session keys (A-F)
All cryptography implemented from scratch in x86_64 assembly:
| Primitive | File | Description |
|---|---|---|
| SHA-256 | sha256.asm |
FIPS 180-4, used for exchange hash and key derivation |
| SHA-512 | sha512.asm |
Used internally by Ed25519 |
| X25519 | curve25519.asm |
Curve25519 scalar multiplication for ECDH |
| Ed25519 | ed25519.asm |
Edwards-curve signatures (sign + verify) |
| ChaCha20 | ssh_aead.asm |
20-round stream cipher, 256-bit key |
| Poly1305 | ssh_aead.asm |
One-time MAC, mod 2^130-5 arithmetic |
| HMAC-SHA256 | hmac_sha256.asm |
Used by HKDF for key derivation |
| HKDF | hkdf.asm |
RFC 5869 extract-and-expand |
Each channel occupies a 48-byte state structure:
| Offset | Field | Description |
|---|---|---|
| 0 | LOCAL_ID |
Our channel number (0-7) |
| 4 | REMOTE_ID |
Peer's channel number |
| 8 | LOCAL_WINDOW |
Bytes we can still receive |
| 12 | REMOTE_WINDOW |
Bytes we can still send |
| 16 | LOCAL_MAXPKT |
Our max packet size |
| 20 | REMOTE_MAXPKT |
Peer's max packet size |
| 24 | WRITE_FD |
Write fd (PTY master or stdin pipe) |
| 28 | CHILD_PID |
Shell/exec child process ID |
| 32 | FLAGS |
Channel state flags |
| 36 | TYPE |
0=unused, 1=session, 2=direct-tcp, 3=sftp |
| 40 | FD |
Read fd (PTY master or stdout pipe) |
Platform-agnostic I/O through function pointers:
io_read_fn → net_read_exact (raw TCP)
tls_read_exact (TLS 1.3 wrapped)
io_write_fn → net_write_all (raw TCP)
tls_write_all (TLS 1.3 wrapped)
All SSH protocol code calls through io_read_fn / io_write_fn, enabling transparent TLS wrapping without modifying any protocol logic.
The v2 event loop allocates ~38 KB on the stack:
| Offset | Size | Purpose |
|---|---|---|
+0 |
32 KB | Receive/send buffer (encrypted packets) |
+32896 |
1 KB | Packet construction workspace |
+33920 |
104 B | pollfd array (13 entries: 1 ssh + 8 channels + 4 forwards) |
+34024 |
4 KB | I/O relay buffer |
+38128 |
16 B | PTY fd storage |
| Category | Tests | Description |
|---|---|---|
| SHA-256 | 8 | NIST vectors, empty input, streaming, large data |
| SHA-512 | 6 | NIST vectors, empty input, large data |
| X25519 | 7 | RFC 7748 vectors, all-zero rejection, identity |
| Ed25519 | 9 | RFC 8032 vectors, sign/verify roundtrip, invalid signatures |
| HMAC-SHA256 | 6 | RFC 4231 vectors, key lengths |
| HKDF | 6 | RFC 5869 vectors, extract/expand |
| SSH Encode | 14 | mpint, string, uint32 encoding/decoding |
| SSH AEAD | 15 | Encrypt/decrypt roundtrip, MAC verification, tamper detection |
| SSH Transport | 24 | Packet framing, KEXINIT building, name-list parsing |
| SSH KEX | 8 | Client/server key exchange, shared secret derivation |
| SSH Auth | 10 | Password auth, none probe, multi-attempt |
| SSH Channel | 14 | Open/confirm, data transfer, window management, EOF/close |
| SSH PTY | 12 | PTY allocation, shell spawn, pipe exec (8 tests), relay |
| SSH E2E | 4 | Build verification, ELF validation, full session |
| SSH Multi-channel | 6 | Concurrent channels, independent data streams |
| SSH Forwarding | 10 | Local forward, direct-tcpip channels |
| Remote Forward | 5 | Remote forward setup, forwarded-tcpip |
| SFTP | 12 | File operations, directory listing, read/write |
| Bind Mode | 8 | Server-mode operation, accept loop |
| Master Socket | 5 | Connection multiplexing |
| TLS 1.3 | 4 | Handshake, encrypted SSH over TLS |
| SNI/ALPN | 2 | TLS server name indication |
| Stress | 53 | Rapid I/O, large transfers, concurrent operations |
| Pubkey Auth | 5 | Ed25519 public key authentication flow |
# All tests
make test
# Specific category
python3 -m pytest tests/test_sha256.py -v
python3 -m pytest tests/test_ssh_pty.py::TestPipeExec -v
# Stress tests only
python3 -m pytest tests/test_ssh_stress.py -vEach test category has a NASM test harness (.asm) that exposes assembly functions to a Python test runner (.py) via stdin/stdout binary protocol.
Depth/
├── Makefile # Build targets for binary + 22 test harnesses
├── src/
│ ├── main.asm # Entry point: mode dispatch (bind/reverse)
│ ├── ssh_transport.asm # Version exchange, KEXINIT, ECDH, key derivation
│ ├── ssh_auth.asm # Password + pubkey authentication (client + server)
│ ├── ssh_channel.asm # Channel multiplexing, window management
│ ├── ssh_client.asm # v2 event loop: poll, dispatch, PTY/pipe relay
│ ├── ssh_pty.asm # PTY allocation, shell/exec spawn, pipe exec
│ ├── ssh_sftp.asm # SFTPv3 dispatch: 16 opcodes, handle table
│ ├── ssh_forward.asm # Local port forwarding (direct-tcpip)
│ ├── ssh_remote_forward.asm # Remote port forwarding (tcpip-forward)
│ ├── ssh_encode.asm # SSH wire encoding: mpint, string, uint32
│ ├── ssh_aead.asm # ChaCha20-Poly1305 AEAD encrypt/decrypt
│ ├── sha256.asm # SHA-256 (FIPS 180-4)
│ ├── sha512.asm # SHA-512 (for Ed25519)
│ ├── curve25519.asm # X25519 scalar multiplication
│ ├── ed25519.asm # Ed25519 sign + verify
│ ├── hmac_sha256.asm # HMAC-SHA256
│ ├── hkdf.asm # HKDF extract + expand
│ ├── net.asm # TCP networking (socket, connect, bind, accept)
│ ├── io_dispatch.asm # Function pointer I/O abstraction
│ ├── tls13.asm # TLS 1.3 handshake
│ ├── tls_io.asm # TLS record I/O
│ ├── tls_record.asm # TLS record framing
│ └── sc_reduce_c.c # Ed25519 scalar reduction (C helper)
├── include/
│ ├── ssh.inc # SSH constants, channel state struct, SFTP types
│ ├── syscall.inc # Linux syscall numbers
│ ├── config.inc # IP, port, credentials, mode settings
│ ├── tls.inc # TLS constants
│ ├── aead.inc # AEAD constants
│ ├── chacha20.inc # ChaCha20 constants
│ └── poly1305.inc # Poly1305 constants
├── tests/ # 25 NASM harnesses + 28 Python test runners
├── tools/
│ └── keygen.py # Ed25519 keypair generator
└── docs/
├── index.html # GitHub Pages landing page
└── banner.svg # Repository banner
- Exit status channel message (return real exit codes)
- Sequential bind-mode connections (accept loop after session ends)
- Terminal resize (SIGWINCH / window-change request)
- Rekey after data volume threshold
- Ed25519 public key authentication (live tested)
- Window adjust for large transfers
- Environment variable requests
Pure assembly. Full protocol. All the way down.
Depth — complete SSH-2.0 in ~94 KB of x86_64 NASM
For authorized use only. This tool is intended for legitimate security research, authorized penetration testing, and educational purposes. Unauthorized access to computer systems is illegal. Users are solely responsible for ensuring compliance with all applicable laws and obtaining proper authorization before use.