From 90a761c18659919f466715714395ce27425c45f7 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 4 Nov 2024 19:57:53 -0500 Subject: [PATCH] std.crypto.tls: make verify data checks timing safe --- lib/std/crypto/tls.zig | 3 ++- lib/std/crypto/tls/Client.zig | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/std/crypto/tls.zig b/lib/std/crypto/tls.zig index 6479c77d75..8c7d3fcdb6 100644 --- a/lib/std/crypto/tls.zig +++ b/lib/std/crypto/tls.zig @@ -442,7 +442,7 @@ pub fn HandshakeCipherT(comptime AeadType: type, comptime HashType: type, compti transcript_hash: A.Hash, version: union { tls_1_2: struct { - server_verify_data: [12]u8, + expected_server_verify_data: [A.verify_data_length]u8, app_cipher: A.Tls_1_2, }, tls_1_3: struct { @@ -479,6 +479,7 @@ pub fn ApplicationCipherT(comptime AeadType: type, comptime HashType: type, comp pub const record_iv_length = explicit_iv_length; pub const mac_length = AEAD.tag_length; pub const mac_key_length = Hmac.key_length_min; + pub const verify_data_length = 12; tls_1_2: Tls_1_2, tls_1_3: Tls_1_3, diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index a8624fd03f..6d9a75dc22 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -662,21 +662,20 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In &.{ "key expansion", &server_hello_rand, &client_hello_rand }, @sizeOf(P.Tls_1_2), ); - const verify_data_len = 12; const client_verify_cleartext = .{@intFromEnum(tls.HandshakeType.finished)} ++ array(u24, u8, hmacExpandLabel( P.Hmac, &master_secret, &.{ "client finished", &p.transcript_hash.peek() }, - verify_data_len, + P.verify_data_length, )); p.transcript_hash.update(&client_verify_cleartext); p.version = .{ .tls_1_2 = .{ - .server_verify_data = hmacExpandLabel( + .expected_server_verify_data = hmacExpandLabel( P.Hmac, &master_secret, &.{ "server finished", &p.transcript_hash.finalResult() }, - verify_data_len, + P.verify_data_length, ), .app_cipher = std.mem.bytesToValue(P.Tls_1_2, &key_block), } }; @@ -747,10 +746,11 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In .tls_1_3 => { const pv = &p.version.tls_1_3; const P = @TypeOf(p.*).A; + try hsd.ensure(P.Hmac.mac_length); const finished_digest = p.transcript_hash.peek(); p.transcript_hash.update(wrapped_handshake); const expected_server_verify_data = tls.hmac(P.Hmac, &finished_digest, pv.server_finished_key); - if (!mem.eql(u8, &expected_server_verify_data, hsd.buf)) return error.TlsDecryptError; + if (!std.crypto.timing_safe.eql([P.Hmac.mac_length]u8, expected_server_verify_data, hsd.array(P.Hmac.mac_length).*)) return error.TlsDecryptError; const handshake_hash = p.transcript_hash.finalResult(); const verify_data = tls.hmac(P.Hmac, &handshake_hash, pv.client_finished_key); const out_cleartext = .{@intFromEnum(tls.HandshakeType.finished)} ++ @@ -788,8 +788,9 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In }, .tls_1_2 => { const pv = &p.version.tls_1_2; - try hsd.ensure(12); - if (!std.mem.eql(u8, hsd.array(12), &pv.server_verify_data)) return error.TlsDecryptError; + const P = @TypeOf(p.*).A; + try hsd.ensure(P.verify_data_length); + if (!std.crypto.timing_safe.eql([P.verify_data_length]u8, pv.expected_server_verify_data, hsd.array(P.verify_data_length).*)) return error.TlsDecryptError; break :app_cipher @unionInit(tls.ApplicationCipher, @tagName(tag), .{ .tls_1_2 = pv.app_cipher }); }, else => unreachable,