Skip to main content

Module protocol

Module protocol 

Source
Expand description

The ssh-agent wire protocol — the isolated, untrusted parsing/encoding surface (KOV-13, decision Q1: a minimal in-crate parser, synchronous, no ssh-agent-lib, no tokio).

This module is the agent’s attack surface: any local process that can reach the socket speaks it. It is therefore deliberately small (exactly the two request opcodes kovra answers) and defensive:

  • every length prefix is bounds-checked against the remaining buffer and a hard MAX_FRAME_LEN cap, so a malicious length cannot trigger a huge allocation or an over-read;
  • any malformed / oversized / unknown message is rejected with an Err, which the daemon turns into a single SSH_AGENT_FAILURE byte — it never panics and never indexes out of bounds;
  • it sees no key bytes except at the final response-encoding step, and even there only the public blob and the (already-produced) signature blob.

FUZZ TARGET (Phase 4): parse_request and read_frame are the entry points to fuzz — feed arbitrary bytes, assert they never panic and only ever return Ok(Request) or Err(AgentError::Protocol).

Structs§

Identity
One advertised identity (a public-key blob + comment) for the answer.

Enums§

Request
A parsed client request — only the two opcodes kovra answers. Everything else is rejected before this type is constructed.

Constants§

MAX_FRAME_LEN
Hard cap on a single agent frame (length-prefix value). The ssh-agent protocol’s own limit is 256 KiB; we use the same so a hostile peer cannot ask us to allocate gigabytes from a 4-byte length. Anything larger is rejected.
SSH_AGENTC_REQUEST_IDENTITIES
Client → agent: list identities.
SSH_AGENTC_SIGN_REQUEST
Client → agent: sign request.
SSH_AGENT_FAILURE
Agent → client: generic failure (also our reply to anything unknown/malformed).
SSH_AGENT_IDENTITIES_ANSWER
Agent → client: identities answer.
SSH_AGENT_SIGN_RESPONSE
Agent → client: sign response.

Functions§

encode_failure
Encode the single-byte SSH_AGENT_FAILURE body.
encode_identities_answer
Encode the body of an SSH_AGENT_IDENTITIES_ANSWER: byte type || u32 nkeys || (string key_blob || string comment)*.
encode_sign_response
Encode the body of an SSH_AGENT_SIGN_RESPONSE: byte type || string signature. The signature is the already-wrapped string algorithm || string blob value produced by core.
frame
Frame a message body for the wire: a u32 big-endian length prefix followed by the body. The total frame is 4 + body.len().
parse_request
Parse a single agent request body (the bytes after the 4-byte frame length — i.e. starting at the message-type byte). Returns Err for any unknown opcode, trailing garbage, or malformed field; the daemon maps that to SSH_AGENT_FAILURE. Never panics (fuzz-target contract).
read_frame
Read one length-prefixed frame from stream, returning its body (the bytes after the 4-byte length). Enforces MAX_FRAME_LEN before allocating, so a forged length cannot exhaust memory. Ok(None) on a clean EOF at a frame boundary (the peer closed the connection).