Fix all-zero content encryption key (CEK) for AES-CBC-HMAC JWE encryption#132
Open
zandbelt wants to merge 1 commit into
Open
Fix all-zero content encryption key (CEK) for AES-CBC-HMAC JWE encryption#132zandbelt wants to merge 1 commit into
zandbelt wants to merge 1 commit into
Conversation
_cjose_jwe_set_cek_aes_cbc() allocated the content-encryption key with _cjose_jwe_malloc(keysize, !random, ...) -- the random flag was inverted (the AES-GCM sibling correctly passes `random`). On the encryption path random is true, so !random zero-filled the CEK instead of generating random bytes. As a result every JWE produced with an AES-CBC-HMAC enc (A128CBC-HS256 / A192CBC-HS384 / A256CBC-HS512) combined with a non-dir key-management alg (A128/192/256KW, RSA-OAEP, RSA1_5) was encrypted and MAC'd under an all-zero key -- a complete loss of confidentiality and integrity for those ciphertexts. "dir" (key supplied by the JWK) and the AES-GCM enc values were unaffected. Pass `random` so the CEK is generated from RAND_bytes, and correct the now-inaccurate comment to match the GCM path. Add a regression test that encrypts the same plaintext twice and asserts the encrypted_key differs (it is byte-identical with a fixed zero CEK because AES key wrap is deterministic). Signed-off-by: Hans Zandbelt <hans.zandbelt@openidc.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
When encrypting a JWE with an AES-CBC-HMAC content-encryption algorithm
(
A128CBC-HS256,A192CBC-HS384,A256CBC-HS512) and a key-managementalgorithm that generates a fresh content-encryption key (CEK), the CEK is
all zero bytes instead of being randomly generated. The produced JWE is
therefore encrypted and authenticated under a fixed, publicly known key.
Impact
For affected JWEs both confidentiality and integrity are lost:
decrypted by anyone, and
recomputed and the content forged.
This affects the encryption side (JWEs produced by cjose). Existing
ciphertexts produced with an affected algorithm pair should be treated as
compromised.
Affected configurations
Triggered only when both hold at encryption time:
encis one ofA128CBC-HS256,A192CBC-HS384,A256CBC-HS512, andalgis one ofA128KW,A192KW,A256KW,RSA-OAEP,RSA1_5(any algthat asks cjose to generate a random CEK).
Not affected:
dir(CEK comes from the JWK), all AES-GCMencvalues,ECDH-ES(CEK is derived via Concat-KDF), and the decryption path.Root cause
_cjose_jwe_set_cek_aes_cbc()allocated the CEK with therandomflaginverted:
_cjose_jwe_malloc(..., random=true, ...)fills the buffer viaRAND_bytes,while
random=falsezero-fills it. On the encryption path the caller passesrandom = true, so!randomzero-fills the CEK. The sibling AES-GCM helper_cjose_jwe_set_cek_aes_gcm()correctly passesrandom, which is why GCM isunaffected. The defect dates back to #68 ("Better support for AES-CBC-HMAC
with other key management algs").
Fix
Pass
randomdirectly so the CEK is generated fromRAND_bytes:Testing
Adds
test_cjose_jwe_encrypt_cbc_cek_randomtotest/check_jwe.c: it encryptsthe same plaintext twice for each AES-CBC-HMAC variant and asserts the
encrypted_keydiffers. Because AES Key Wrap is deterministic, a fixed CEKyields a byte-identical
encrypted_key— so this test fails before the fix andpasses after it. Full suite passes (
Checks: 77, Failures: 0, Errors: 0).References
The same issue was found and fixed in the maintained fork (OpenIDC/cjose,
v0.6.2.6) and is tracked in security advisory
GHSA-f6wf-pqg3-6wqq.