-
Notifications
You must be signed in to change notification settings - Fork 29
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
Misuse issue in (X)ChaCha20 and (X)ChaCha20-Poly1305 APIs #308
Comments
A third option would be to check all the error conditions before any output is written. But I think you're right that we shouldn't ever write plaintext to the output buffer, even if we immediately overwrite it. One particularly bad situation is if the user sets up the output buffer to be memory-mapped to a file. In that case, there's a chance the plaintext is written to disk and is then far more observable. |
Just a note that the removal of
Very good point! We'll use the proposed approach instead then. |
…tream can be reliably produced (see #308)
…before all needed keystream blocks are guaranteed to be produced (#309) * aead: Do not copy plaintext into dst_out before we know next keystream can be reliably produced (see #308) * nit * chacha20: Do not copy plaintext into dst_out before we know next keystream can be reliably produced (see #308) * chacha20: Add test for #308 * nit * nit * chacha20poly1305: Add P/A/C_MAX length checks for maximum values specified in RFC 8439 * xchacha20poly1305: Add length errors to docs refencing the new checks in chacha20poly1305:: * chacha20poly1305: Check A_MAX on open() * doc: Clarification on (X)ChaCha20-based constructions and their behaviour if dst_out is longer then input * clippy: Allow extreme comparisons for AD in AEAD
During a review of parts of the codebase, I've come across a rather unfortunate misuse possibility in ChaCha20, which also affects ChaCha20-Poly1305, but much more limited therein.
(X)ChaCha20
In
orion::hazardous::stream::chacha20::encrypt()
we allow the user to specify theinitial_counter
, that the ChaCha20 state should be initialized with (also known as the block counter). If thisinitial_counter
is too large, meaning would overflow when adding 1, then we return an error.orion/src/hazardous/stream/chacha20.rs
Line 303 in 1ee15eb
The problem is, that before this error is returned, we have already copied the plaintext to the output destination
dst_out
(in order to later XOR it with the keystream).orion/src/hazardous/stream/chacha20.rs
Line 347 in 1ee15eb
If the
initial_counter.checked_add(1)
returnsErr()
the plaintext bytes that were supposed to be XORed with the next keystream bytes, remain in plaintext in the output buffer.While we do return an error, and a user should not use the output of
encrypt()
if it returns an error, they might reasonably expect thatdst_out
not contain a copy of some plaintext bytes.This issue also applies to XChaCha20, as it uses
chacha20::encrypt()
.(X)ChaCha20-Poly1305
The impact on (X)ChaCha20-Poly1305 is more limited, as the user cannot specify the
initial_counter
. However, the plaintext is encrypted with an initial block counter of 1, because the first is used for the Poly1305 key generation. Thus, plaintext bytes may be left in the output buffer if the length of the plaintext is one block less than the maximum (max is2^32-1 * 64
bytes), which is very unlikely to happen in real-world use.For the
streaming
implementation, one block less than the required amount for (X)ChaCha20-Poly1305, is required to hit this, as the initial counter there used internally starts with 2, for plaintext bytes.Solution
The obvious solution here seems to be, to only copy anything to the output buffer that is ciphertext. Thus, we change the underlying XOR macro usage in ChaCha20 and can take the same approach when processing plaintext bytes in AEAD. In AEAD, we could maybe even get a bit of speedup as we could then encrypt and authenticate the ciphertext block individually, instead of making two passes over the plaintext and ciphertext bytes (first encrypt, then authenticate).
We could also discuss removing the option to set
initial_counter
for (X)ChaCha20, in a future major release, as there seems to be no real use for it.cc @vlmutolo
The text was updated successfully, but these errors were encountered: