diff --git a/src/quic/tls13.zig b/src/quic/tls13.zig index 33229fe..e788353 100644 --- a/src/quic/tls13.zig +++ b/src/quic/tls13.zig @@ -1827,19 +1827,21 @@ pub const Tls13Handshake = struct { // Decrypt ticket identity to get PSK if (identity_len < 16 + 1) return; // at least tag + 1 byte + var decrypted: [64]u8 = undefined; + var ct_copy: [decrypted.len + 16]u8 = undefined; + if (identity_len > ct_copy.len) return; const ciphertext_len = identity_len - 16; + if (ciphertext_len > decrypted.len) return; // Reconstruct nonce from ticket (we use the last 4 bytes of identity as hint) var ticket_nonce: [12]u8 = .{0} ** 12; // Use zeros as nonce — server encrypts with incrementing nonce_buf in [8..12] // We need to try nonce counter values. For simplicity, try a few. - var decrypted: [64]u8 = undefined; var psk_found = false; var found_psk: [32]u8 = undefined; for (0..256) |nonce_try| { std.mem.writeInt(u32, ticket_nonce[8..12], @intCast(nonce_try), .big); - var ct_copy: [80]u8 = undefined; @memcpy(ct_copy[0..identity_len], identity[0..identity_len]); const tag_start = ciphertext_len; const tag: [16]u8 = ct_copy[tag_start..][0..16].*; @@ -3104,6 +3106,33 @@ test "loopback PSK resumption: two handshakes with session ticket" { ); } +test "tryProcessPsk rejects oversized ticket identity before decrypt" { + const tp = transport_params.TransportParams{ + .initial_max_data = 1048576, + .initial_max_streams_bidi = 100, + }; + + const server_config = TlsConfig{ + .cert_chain_der = &.{}, + .private_key_bytes = &.{}, + .alpn = &[_][]const u8{"h3"}, + .ticket_key = .{0xA5} ** 16, + }; + + var handshake = Tls13Handshake.initServer(server_config, tp); + + var psk_ext: [124]u8 = .{0} ** 124; + std.mem.writeInt(u16, psk_ext[0..2], 87, .big); + std.mem.writeInt(u16, psk_ext[2..4], 81, .big); + std.mem.writeInt(u32, psk_ext[85..89], 0, .big); + std.mem.writeInt(u16, psk_ext[89..91], 33, .big); + psk_ext[91] = 32; + + handshake.tryProcessPsk("", "", 0, &psk_ext, 0, psk_ext.len); + + try std.testing.expect(!handshake.using_psk); +} + // NewSessionTicket roundtrip test test "NewSessionTicket: build and parse roundtrip" { const psk: [32]u8 = .{0x55} ** 32;