[Bug 3553] New: PROTOCOL.key format specification is incorrect for encryption using AEAD transports

bugzilla-daemon at mindrot.org bugzilla-daemon at mindrot.org
Sun Mar 26 16:37:34 AEDT 2023


            Bug ID: 3553
           Summary: PROTOCOL.key format specification is incorrect for
                    encryption using AEAD transports
           Product: Portable OpenSSH
           Version: 9.3p1
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P5
         Component: Documentation
          Assignee: unassigned-bugs at mindrot.org
          Reporter: thestr4d at gmail.com

`ssh-keygen` allows encrypting private keys with any symmetric
transport cipher that OpenSSH supports. This includes AEADs like
`aes256-gcm at openssh.com` and `chacha20-poly1305 at openssh.com`.
`ssh-keygen` does not default to using AEADs, but other ecosystem
players do so (e.g. 1Password uses `aes256-gcm at openssh.com` when a user
provides a passphrase during export of an SSH private key).

`PROTOCOL.key` specifies that the encrypted list of private keys is
encoded as a `string` (u32 length followed by that many bytes). A plain
reading of this specification is that this field contains the
ciphertext for whatever encryption scheme is being used (so for the
`none` scheme it is just the encoded plaintext, for `aes256-cbc` it is
the AES256-CBC-encrypted ciphertext, and so on).

However, when an AEAD is used, `ssh-keygen` does not encode the full
AEAD ciphertext in the `string` field. Instead, the fixed-length tag is
appended as raw bytes, and the `string` field only covers the
variable-length unauthenticated ciphertext part of the AEAD ciphertext
(or, hopefully equivalently for OpenSSH, the length field of the
`string` encodes the length of the plaintext, regardless of how it is

This leads to two problems:
- If key parsing is implemented following the specification in
`PROTOCOL.key`, the tag gets ignored, and the last `len(tag)` bytes of
the unauthenticated ciphertext are interpreted as the tag. This could
lead to a parser error if the plaintext is shorter than the tag, or if
the parser checks that all data is consumed (if the outer format does
not have follow-on data; the spec does not prohibit it), but is more
likely to result in a decryption error (leading the developer on a wild
goose chase trying to figure out why their cryptography library is
broken - hi!).
- Parsing of keys encoded by `ssh-keygen` (and by other ecosystem
players following its implementation-specific details) now needs to be
interleaved with interpretation. It is necessary to parse the
`ciphername` field, interpret it to determine what the expected tag
length is, and then provide that as input to the remainder of the

I don't know what the intended specification is here; it looks like
`ssh-keygen` was itself updated after the fact to parse this format
That change was made in 2015, so it's too late to fix `ssh-keygen` to
follow the specification in `PROTOCOL.key`. `PROTOCOL.key` needs to be
treated as incorrect, and updated to specify the actual key format
generated and used in production.

You are receiving this mail because:
You are watching the assignee of the bug.

More information about the openssh-bugs mailing list