mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Fix TLS 1.2 client key exchange to use negotiated named group (#25007)
The TLS 1.2 implementation was incorrectly hardcoded to always send the secp256r1 public key in the client key exchange message, regardless of which elliptic curve the server actually negotiated. This caused TLS handshake failures with servers that preferred other curves like X25519. This fix: - Tracks the negotiated named group from the server key exchange message - Dynamically selects the correct public key (X25519, secp256r1, or secp384r1) based on what the server negotiated - Properly constructs the client key exchange message with the appropriate key size for each curve type Fixes TLS 1.2 connections to servers like ziglang.freetls.fastly.net that prefer X25519 over secp256r1.
This commit is contained in:
parent
a4cb636658
commit
9c3e09cbee
1 changed files with 19 additions and 6 deletions
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue