authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-05-29 12:12:26+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-07-05 12:26:21+02:00
log0e4371b5ec9ce9ad86438ae65d949f5ff4b6e472
tree142d5e4fcb94f3a0474cba7a128f516e18ab7e92
parent05d745ea634b085380b94e47f006c1a80555aec2

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.

1 files changed, 11 insertions(+), 0 deletions(-)

lib/std/crypto/aes_ccm.zig+11
......@@ -122,6 +122,9 @@ fn AesCcm(comptime BlockCipher: type, comptime tag_len: usize, comptime nonce_le
122122 ) AuthenticationError!void {
123123 assert(m.len == c.len);
124124
125 const max_msg_len: u64 = if (L >= 8) std.math.maxInt(u64) else (@as(u64, 1) << @as(u6, @intCast(L * 8))) - 1;
126 if (c.len > max_msg_len) return error.AuthenticationFailed;
127
125128 const cipher_ctx = BlockCipher.initEnc(key);
126129
127130 // Decrypt the ciphertext using CTR mode (starting from counter = 1)
......@@ -874,3 +877,11 @@ test "Aes256Ccm0 - Basic encryption-only round-trip" {
874877
875878 try testing.expectEqualSlices(u8, m[0..], m2[0..]);
876879}
880
881test "Aes256Ccm decryption of oversized ciphertext" {
882 const key: [32]u8 = @splat(0);
883 const nonce: [13]u8 = @splat(0);
884 const tag: [Aes256Ccm16.tag_length]u8 = @splat(0);
885 var buf: [65536]u8 = @splat(0);
886 try testing.expectError(error.AuthenticationFailed, Aes256Ccm16.decrypt(&buf, &buf, tag, "", nonce, key));
887}