From 3221389b28ed03ae372b43ac04a9c11e94534128 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 20 Apr 2026 12:10:24 +0200 Subject: [PATCH] std.crypto.tls.Client: reject KeyUpdate with invalid body length We were reading `handshake[0]` without checking the body length. A TLS 1.3 KeyUpdate handshake message must contain exactly one byte. --- lib/std/crypto/tls/Client.zig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index 11eb30f226f217f9f28771f01aa53b8ccb21ccc0..f69a976c32ff6439daf587688304b6bc3d3df90b 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -1267,6 +1267,7 @@ fn readIndirect(c: *Client) Reader.Error!usize { // This client implementation ignores new session tickets. }, .key_update => { + if (handshake.len != 1) return failRead(c, error.TlsDecodeError); switch (c.application_cipher) { inline else => |*p| { const pv = &p.tls_1_3; @@ -1759,3 +1760,25 @@ test "TLS 1.2 record shorter than IV plus tag" { .{ .AES_128_GCM_SHA256 = .{ .tls_1_2 = mem.zeroes(P.Tls_1_2) } }, )); } + +test "zero-length key_update body" { + const Chacha = crypto.aead.chacha_poly.ChaCha20Poly1305; + const plaintext = [_]u8{ 0x18, 0x00, 0x00, 0x00, 0x16 }; + const header = [_]u8{ 0x17, 0x03, 0x03 } ++ mem.toBytes(big(@as(u16, plaintext.len + Chacha.tag_length))); + var ct: [plaintext.len]u8 = undefined; + var tag: [Chacha.tag_length]u8 = undefined; + Chacha.encrypt(&ct, &tag, &plaintext, &header, @splat(0), @splat(0)); + const wire = header ++ ct ++ tag; + try std.testing.expectEqual(error.TlsDecodeError, testReadError( + &wire, + .tls_1_3, + .{ .CHACHA20_POLY1305_SHA256 = .{ .tls_1_3 = .{ + .server_key = @splat(0), + .server_iv = @splat(0), + .client_secret = undefined, + .server_secret = undefined, + .client_key = undefined, + .client_iv = undefined, + } } }, + )); +} -- 2.54.0