Skip to content

ssh-encoding: add initial Mpint 16384-bit size limit - #615

Merged
tarcieri merged 1 commit into
masterfrom
ssh-encoding/mpint-size-limit
Nov 9, 2026
Merged

tarcieri merged 1 commit into
masterfrom
ssh-encoding/mpint-size-limit

Conversation

@tarcieri

@tarcieri tarcieri commented Nov 9, 2026

Copy link
Copy Markdown
Member

OpenSSH enforces the following limit on the size of mpint:

https://github.com/openssh/openssh-portable/blob/e416edf/sshbuf.h#L41

This commit enforces the same limit for the standard Mpint constructors. Unfortunately we support infallible From<Uint> impls that can't enforce the size limit, which are currently TODOs.

Perhaps before the next ssh-key release we can consider making another breaking release of ssh-encoding to address those TODOs properly.

See also: RustCrypto/RSA#793

OpenSSH enforces the following limit on the size of `mpint`:

https://github.com/openssh/openssh-portable/blob/e416edf/sshbuf.h#L41

This commit enforces the same limit for the standard `Mpint`
constructors. Unfortunately we support infallible `From<Uint>` impls
that can't enforce the size limit, which are currently TODOs.

Perhaps before the next `ssh-key` release we can consider making another
breaking release of `ssh-encoding` to address those TODOs properly.

See also: RustCrypto/RSA#793
@tarcieri
tarcieri merged commit cdb93f9 into master Nov 9, 2026
31 checks passed
tarcieri added a commit that referenced this pull request Nov 10, 2026
Move nested decoding, length bounds, completion checks, and failure
state into a shared `Decoder<R>` type which owns the underlying reader.

This removes considerable complexity from the reader types, including
their individual `Reader::read_prefixed` implementations and the
supporting macro, leaving them responsible only for supplying bytes and
reporting the remaining length.

Nested decoding now uses a common `read_nested` implementation which
temporarily narrows the decoder's bounds. Each nesting level uses the
same `Decoder<R>` type, preserving `no_alloc` support without the
recursively nested generic reader types that previously caused
monomorphization bloat.

This is a breaking change: `Decode` implementations now accept
`&mut Decoder<impl Reader>`, which is slightly uglier from an API
perspective but enables a much better underlying implementation.

A blanket `From<R>` implementation keeps call sites concise by allowing
`Reader`s to be converted into a `Decoder` with `into()`..

We are also motivated by #615 to make another breaking `ssh-encoding`
release before the next ssh-key release: making the remaining infallible
`Mpint` conversions fallible would allow its size limits to be enforced
consistently.

Because this is a breaking change, the versions of `ssh-cipher`,
`ssh-derive`, and `ssh-encoding` have all been bumped to v0.4.0-pre.
tarcieri added a commit that referenced this pull request Nov 10, 2026
Move nested decoding, length bounds, completion checks, and failure
state into a shared `Decoder<R>` type which owns the underlying reader.

This removes considerable complexity from the reader types, including
their individual `Reader::read_prefixed` implementations and the
supporting macro, leaving them responsible only for supplying bytes and
reporting the remaining length.

Nested decoding now uses a common `read_nested` implementation which
temporarily narrows the decoder's bounds. Each nesting level uses the
same `Decoder<R>` type, preserving `no_alloc` support without the
recursively nested generic reader types that previously caused
monomorphization bloat.

This is a breaking change: `Decode` implementations now accept
`&mut Decoder<impl Reader>`, which is slightly uglier from an API
perspective but enables a much better underlying implementation.

A blanket `From<R>` implementation keeps call sites concise by allowing
`Reader`s to be converted into a `Decoder` with `into()`..

We are also motivated by #615 to make another breaking `ssh-encoding`
release before the next ssh-key release: making the remaining infallible
`Mpint` conversions fallible would allow its size limits to be enforced
consistently.

Because this is a breaking change, the versions of `ssh-cipher`,
`ssh-derive`, and `ssh-encoding` have all been bumped to v0.4.0-pre.
tarcieri added a commit that referenced this pull request Nov 10, 2026
Move nested decoding, length bounds, completion checks, and failure
state into a shared `Decoder<R>` type which owns the underlying reader.

This removes considerable complexity from the reader types, including
their individual `Reader::read_prefixed` implementations and the
supporting macro, leaving them responsible only for supplying bytes and
reporting the remaining length.

Nested decoding now uses a common `read_nested` implementation which
temporarily narrows the decoder's bounds. Each nesting level uses the
same `Decoder<R>` type, preserving `no_alloc` support without the
recursively nested generic reader types that previously caused
monomorphization bloat.

This is a breaking change: `Decode` implementations now accept
`&mut Decoder<impl Reader>`, which is slightly uglier from an API
perspective but enables a much better underlying implementation.

A blanket `From<R>` implementation keeps call sites concise by allowing
`Reader`s to be converted into a `Decoder` with `into()`..

We are also motivated by #615 to make another breaking `ssh-encoding`
release before the next ssh-key release: making the remaining infallible
`Mpint` conversions fallible would allow its size limits to be enforced
consistently.

Because this is a breaking change, the versions of `ssh-cipher`,
`ssh-derive`, and `ssh-encoding` have all been bumped to v0.4.0-pre.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant