Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssh-cipher: add AAD support to ChaCha20Poly1305 #281

Merged
merged 1 commit into from
Aug 15, 2024

Conversation

tarcieri
Copy link
Member

@tarcieri tarcieri commented Aug 15, 2024

From PROTOCOL.chacha20poly1305:

Once the entire packet has been received, the MAC MUST be checked
before decryption. A per-packet Poly1305 key is generated as described
above and the MAC tag calculated using Poly1305 with this key over the
ciphertext of the packet length and the payload together.

This implements AAD which pads the input to the Poly1305 block size, inputting it first before the ciphertext.

It should be sufficient for SSH packet encryption use cases, although unfortunately we have no test vectors other than the ones in the ssh-key crate (which are unaffected by this change). Test vectors added.

Closes #279

@tarcieri tarcieri requested a review from baloo August 15, 2024 00:13
@baloo
Copy link
Member

baloo commented Aug 15, 2024

I still have trouble wrapping my head around chacha poly for ssh.
My current implementation (which I only tested with aes128-ctr) looks like this:
https://github.com/baloo/SSH/blob/66451ca513d6550c64965c8fb5bf9ad6625e8801/ssh-protocol/src/codec/cipher.rs#L107-L115

When I parse the packet the length of the payload should be encrypted, I don't know if the payload I'm trying to parse is long enough, or if it even includes the aad and I need to read the first block size worth of payload and bypass the aad check.
I don't know how to do anything equivalent with an aead yet (whether that it be aes-gcm or chacha).

All that to say, I will ask for some time to make a proper review, because I don't know how to review it yet :D

EDIT: ha well, that's is all in PROTOCOL.chacha20poly1305, there are two ciphers.

@tarcieri
Copy link
Member Author

tarcieri commented Aug 15, 2024

Yeah, per PROTOCOL.chacha20poly1305 it acts a bit differently than the other modes including AES-GCM, with two instances of ChaCha20Poly1305 one instance of unauthenticated ChaCha20 for length encryption, and a separately keyed instance of ChaCha20Poly1305 which authenticates the ChaCha20 length ciphertext retroactively as AAD along with encrypting/decrypting the packet body.

I suppose one question is this implements the AAD in a somewhat general purpose manner whereas perhaps it should be constrained solely for the purpose of authenticating these lengths, returning an error otherwise. We now implement a more special case API.

@Noratrieb
Copy link

Noratrieb commented Aug 15, 2024

A test vector extracted from my working implementation (https://github.com/Noratrieb/fakessh/blob/f4ba9a2939104f24390ba168db44fc73c5df4999/ssh-transport/src/crypto.rs#L456) (printed with {:x?}):
key: 37, 9a, 8c, a9, e7, e7, 5, 76, 36, 33, 21, 35, 11, e8, d9, 2e, b1, 48, a4, 6f, 1d, d0, 4, 5e, c8, 16, 4e, 5d, 23, e4, 56, eb
nonce: 0, 0, 0, 0, 0, 0, 0, 3
AAD (encrypted length): 57, 9, db, 2d
ciphertext: 6d, cf, b0, 3b, e8, a5, 5e, 7f, 2, 20, 46, 56, 72, ed, d9, 21, 48, 9e, a0, 17, 11, 98, e8, a7
tag: 3e, 82, fe, a, 2d, b7, 12, 8d, 58, ef, 8d, 90, 47, 96, 3c, a3
plaintext: 6, 5, 0, 0, 0, c, 73, 73, 68, 2d, 75, 73, 65, 72, 61, 75, 74, 68, de, 59, 49, ab, 6, 1f

@tarcieri tarcieri force-pushed the ssh-cipher/chacha20poly1305-aad branch 2 times, most recently from e8caa83 to 9c0bda9 Compare August 15, 2024 18:56
From PROTOCOL.chacha20poly1305:

  Once the entire packet has been received, the MAC MUST be checked
  before decryption. A per-packet Poly1305 key is generated as described
  above and the MAC tag calculated using Poly1305 with this key over the
  ciphertext of the packet length and the payload together.

This adds an `aad_len` parameter which decomposes the input buffer into
a portion to be only authenticated (in packet encryption, this is used
for a 4-byte encrypted length header), which comes prior to the portion
to be encrypted.

Ideally we could implement the `AeadInPlace` trait, however this
approach has been used instead because the protocol uses unpadded
Poly1305, where we don't support buffered input and it must be computed
from a single contiguous slice using `Poly1305::compute_unpadded`.

Closes #279
@tarcieri tarcieri force-pushed the ssh-cipher/chacha20poly1305-aad branch from 9c0bda9 to d83646f Compare August 15, 2024 18:59
@tarcieri tarcieri merged commit edaf770 into master Aug 15, 2024
30 checks passed
@tarcieri tarcieri deleted the ssh-cipher/chacha20poly1305-aad branch August 15, 2024 19:04
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.

ssh-cipher chacha20-poly1305 cannot be used for implementing packet encryption
3 participants