Conversation
RFC 4251 § 5 requires redundant leading `0x00` bytes to be omitted, but some SSH implementations send them anyway: older Huawei network devices, for example, place a redundant leading zero in the RSA exponent or modulus of their `ssh-rsa` host key, which previously made the whole key unparseable. OpenSSH tolerates this on the receiving side (`sshbuf_get_bignum2_bytes_direct` trims leading zeros rather than rejecting the message), so normalize the value in `Decode for Mpint` instead of failing. Negative values and already-canonical encodings are preserved verbatim. `Mpint::from_bytes` still rejects redundant leading zeros, so locally constructed values keep being held to RFC 4251. Signed-off-by: 胡飞 <1835698775@qq.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Decode for Mpintnormalizes redundant leading zero bytes instead of rejecting them.RFC 4251 § 5 requires redundant leading
0x00bytes to be omitted frommpintencodings, but some SSH implementations send them anyway. One observed case: an older
Huawei VRP switch puts a redundant leading zero into the RSA exponent and modulus of its
ssh-rsahost key, which makes the whole host key unparseable — the connection cannot beestablished at all, even after negotiating a legacy KEX.
OpenSSH tolerates this on the receiving side.
sshbuf_get_bignum2_bytes_direct()(
sshbuf-getput-basic.c) trims leading zeros rather than rejecting the message:Note that the "negative" check inspects the first byte before trimming, so any value
that starts with
0x00is accepted regardless of what follows.A redundant leading zero cannot change the interpretation of the value, so how strict a
reader is here is a policy question rather than a correctness one. #290/#291 already
accepted the mirror image of this — "Leading zeros must be stripped from
mpintvalues(per RFC 4251)" — so tolerating extra leading zeros on the receiving side seems
consistent.
Changes:
Decode for Mpintnormalizes the value: redundant leading0x00bytes are stripped,and a single
0x00is re-added when the remaining value is positive with its MSB set,i.e. the result is always canonically encoded. Negative values and already-canonical
encodings are preserved byte for byte.
TryFrom<Box<[u8]>>(and thereforeMpint::from_bytes) is intentionally left strict,so RFC 4251 still governs values constructed locally, and the existing
reject_extra_leading_zeroescontract is unchanged. Only the wire parsing path islenient.
ssh-encoding(normalization, zero, preservation ofcanonical/negative encodings, normalized value equals the canonical value) plus an
end-to-end case in
ssh-keythat parses a non-canonicalssh-rsapublic key blob.Reproducer note: we could not capture the exact bytes from the device, but building an
ssh-rsablob withe = 00 01 00 01andn = 00 00 80 01reproduces the reportedfailure verbatim (
ssh_key::Error::Encoding(MpintEncoding)), which is exactly what thessh-keyregression test covers.Checks run locally, all passing: