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_LENcap, 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 singleSSH_AGENT_FAILUREbyte — 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_FAILUREbody. - 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. Thesignatureis the already-wrappedstring algorithm || string blobvalue produced bycore. - frame
- Frame a message body for the wire: a
u32big-endian length prefix followed by the body. The total frame is4 + 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
Errfor any unknown opcode, trailing garbage, or malformed field; the daemon maps that toSSH_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). EnforcesMAX_FRAME_LENbefore allocating, so a forged length cannot exhaust memory.Ok(None)on a clean EOF at a frame boundary (the peer closed the connection).