In all supported OpenSSL releases, ChaCha20-Poly1305 and AES-OCB decryption with an empty ciphertext can report success without verifying an explicitly supplied authentication tag when the operation is finalized through:
EVP_Cipher(ctx, out, NULL, 0);
This occurs with or without associated data (AAD). The provider operation reports success and EVP_Cipher returns the zero-byte output length, so a valid tag and a corrupted tag are indistinguishable to callers using the provider one-shot return convention.
PR #32173 corrected the behavior on master in commit 5741d29, but the correction is not present in any supported release branch.
The upstream correction is public, this issue tracks the corresponding stable-branch backports.
Impact
An empty plaintext doesn't imply that the AEAD operation authenticates nothing. The authentication tag also covers the key, nonce and any associated data. Associated data can contain protocol headers, transcript hashes, channel-binding values, sequence numbers or state identifiers.
The Noise Protocol Framework uses the current handshake hash as AEAD associated data and explicitly permits zero-length encrypted payloads that still contain authentication data:
https://noiseprotocol.org/noise.html
The WireGuard handshake response contains this concrete construction:
encrypted_nothing[AEAD_LEN(0)]
encrypted_nothing = AEAD(key, 0, [empty], responder.hash)
https://www.wireguard.com/protocol/
This demonstrates that AEAD fields containing only a tag are a deployed protocol construction. An OpenSSL application implementing an equivalent construction through the affected path can incorrectly accept a transcript, a key confirmation event, or an authenticated state transition.
The behavior of EVP_Cipher for empty input and return values depend on the implementation, and the API should be documented and deprecated separately.
Related work
In all supported OpenSSL releases, ChaCha20-Poly1305 and AES-OCB decryption with an empty ciphertext can report success without verifying an explicitly supplied authentication tag when the operation is finalized through:
This occurs with or without associated data (AAD). The provider operation reports success and
EVP_Cipherreturns the zero-byte output length, so a valid tag and a corrupted tag are indistinguishable to callers using the provider one-shot return convention.PR #32173 corrected the behavior on
masterin commit 5741d29, but the correction is not present in any supported release branch.The upstream correction is public, this issue tracks the corresponding stable-branch backports.
Impact
An empty plaintext doesn't imply that the AEAD operation authenticates nothing. The authentication tag also covers the key, nonce and any associated data. Associated data can contain protocol headers, transcript hashes, channel-binding values, sequence numbers or state identifiers.
The Noise Protocol Framework uses the current handshake hash as AEAD associated data and explicitly permits zero-length encrypted payloads that still contain authentication data:
https://noiseprotocol.org/noise.html
The WireGuard handshake response contains this concrete construction:
https://www.wireguard.com/protocol/
This demonstrates that AEAD fields containing only a tag are a deployed protocol construction. An OpenSSL application implementing an equivalent construction through the affected path can incorrectly accept a transcript, a key confirmation event, or an authenticated state transition.
The behavior of
EVP_Cipherfor empty input and return values depend on the implementation, and the API should be documented and deprecated separately.Related work
master.