From 0e4371b5ec9ce9ad86438ae65d949f5ff4b6e472 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Fri, 29 May 2026 12:12:26 +0200 Subject: [PATCH] crypto.aes_ccm: immediately reject large messages on decryption AES-CCM has pretty low limits. With a 13 byte nonce, we only have 2 bytes left to encode the message length, so it can't encrypt messages larger than 65535 bytes. In the encryption function we immediately rejected messages that would be too large. But not in the decryption function. So, do it as well in the decryption function. Message larger than the encodable length will never be valid ciphertexts. --- lib/std/crypto/aes_ccm.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/std/crypto/aes_ccm.zig b/lib/std/crypto/aes_ccm.zig index a06ce51221c0926664669fc76e86d83d1c1bc7a9..69a8f776eacfa0b587900bfd5fb1ec2508e2dd44 100644 --- a/lib/std/crypto/aes_ccm.zig +++ b/lib/std/crypto/aes_ccm.zig @@ -122,6 +122,9 @@ fn AesCcm(comptime BlockCipher: type, comptime tag_len: usize, comptime nonce_le ) AuthenticationError!void { assert(m.len == c.len); + const max_msg_len: u64 = if (L >= 8) std.math.maxInt(u64) else (@as(u64, 1) << @as(u6, @intCast(L * 8))) - 1; + if (c.len > max_msg_len) return error.AuthenticationFailed; + const cipher_ctx = BlockCipher.initEnc(key); // Decrypt the ciphertext using CTR mode (starting from counter = 1) @@ -874,3 +877,11 @@ test "Aes256Ccm0 - Basic encryption-only round-trip" { try testing.expectEqualSlices(u8, m[0..], m2[0..]); } + +test "Aes256Ccm decryption of oversized ciphertext" { + const key: [32]u8 = @splat(0); + const nonce: [13]u8 = @splat(0); + const tag: [Aes256Ccm16.tag_length]u8 = @splat(0); + var buf: [65536]u8 = @splat(0); + try testing.expectError(error.AuthenticationFailed, Aes256Ccm16.decrypt(&buf, &buf, tag, "", nonce, key)); +} -- 2.54.0