diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index f9c897e3f0..8cfa942399 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -320,6 +320,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client var handshake_state: HandshakeState = .hello; var handshake_cipher: tls.HandshakeCipher = undefined; var main_cert_pub_key: CertificatePublicKey = undefined; + var tls12_negotiated_group: ?tls.NamedGroup = null; const now_sec = std.time.timestamp(); var cleartext_fragment_start: usize = 0; @@ -679,6 +680,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client const curve_type = hsd.decode(u8); if (curve_type != 0x03) return error.TlsIllegalParameter; // named_curve const named_group = hsd.decode(tls.NamedGroup); + tls12_negotiated_group = named_group; const key_size = hsd.decode(u8); try hsd.ensure(key_size); const server_pub_key = hsd.slice(key_size); @@ -691,10 +693,19 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client if (cipher_state != .cleartext) return error.TlsUnexpectedMessage; if (handshake_state != .server_hello_done) return error.TlsUnexpectedMessage; - const client_key_exchange_msg = .{@intFromEnum(tls.ContentType.handshake)} ++ + const public_key_bytes: []const u8 = switch (tls12_negotiated_group orelse .secp256r1) { + .secp256r1 => &key_share.secp256r1_kp.public_key.toUncompressedSec1(), + .secp384r1 => &key_share.secp384r1_kp.public_key.toUncompressedSec1(), + .x25519 => &key_share.x25519_kp.public_key, + else => return error.TlsIllegalParameter, + }; + + const client_key_exchange_prefix = .{@intFromEnum(tls.ContentType.handshake)} ++ int(u16, @intFromEnum(tls.ProtocolVersion.tls_1_2)) ++ - array(u16, u8, .{@intFromEnum(tls.HandshakeType.client_key_exchange)} ++ - array(u24, u8, array(u8, u8, key_share.secp256r1_kp.public_key.toUncompressedSec1()))); + int(u16, @intCast(public_key_bytes.len + 5)) ++ // record length + .{@intFromEnum(tls.HandshakeType.client_key_exchange)} ++ + int(u24, @intCast(public_key_bytes.len + 1)) ++ // handshake message length + .{@as(u8, @intCast(public_key_bytes.len))}; // public key length const client_change_cipher_spec_msg = .{@intFromEnum(tls.ContentType.change_cipher_spec)} ++ int(u16, @intFromEnum(tls.ProtocolVersion.tls_1_2)) ++ array(u16, tls.ChangeCipherSpecType, .{.change_cipher_spec}); @@ -703,7 +714,8 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client inline else => |*p| { const P = @TypeOf(p.*).A; p.transcript_hash.update(wrapped_handshake); - p.transcript_hash.update(client_key_exchange_msg[tls.record_header_len..]); + p.transcript_hash.update(client_key_exchange_prefix[tls.record_header_len..]); + p.transcript_hash.update(public_key_bytes); const master_secret = hmacExpandLabel(P.Hmac, pre_master_secret, &.{ "master secret", &client_hello_rand, @@ -757,8 +769,9 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client nonce, pv.app_cipher.client_write_key, ); - var all_msgs_vec: [3][]const u8 = .{ - &client_key_exchange_msg, + var all_msgs_vec: [4][]const u8 = .{ + &client_key_exchange_prefix, + public_key_bytes, &client_change_cipher_spec_msg, &client_verify_msg, };