| ... | @@ -191,14 +191,14 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client | ... | @@ -191,14 +191,14 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 191 | }; | 191 | }; |
| 192 | const host_len: u16 = @intCast(host.len); | 192 | const host_len: u16 = @intCast(host.len); |
| 193 | | 193 | |
| 194 | var random_buffer: [128]u8 = undefined; | 194 | var random_buffer: [176]u8 = undefined; |
| 195 | crypto.random.bytes(&random_buffer); | 195 | crypto.random.bytes(&random_buffer); |
| 196 | const client_hello_rand = random_buffer[0..32].*; | 196 | const client_hello_rand = random_buffer[0..32].*; |
| 197 | var key_seq: u64 = 0; | 197 | var key_seq: u64 = 0; |
| 198 | var server_hello_rand: [32]u8 = undefined; | 198 | var server_hello_rand: [32]u8 = undefined; |
| 199 | const legacy_session_id = random_buffer[32..64].*; | 199 | const legacy_session_id = random_buffer[32..64].*; |
| 200 | | 200 | |
| 201 | var key_share = KeyShare.init(random_buffer[64..128].*) catch |err| switch (err) { | 201 | var key_share = KeyShare.init(random_buffer[64..176].*) catch |err| switch (err) { |
| 202 | // Only possible to happen if the seed is all zeroes. | 202 | // Only possible to happen if the seed is all zeroes. |
| 203 | error.IdentityElement => return error.InsufficientEntropy, | 203 | error.IdentityElement => return error.InsufficientEntropy, |
| 204 | }; | 204 | }; |
| ... | @@ -223,6 +223,7 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client | ... | @@ -223,6 +223,7 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 223 | })) ++ tls.extension(.supported_groups, array(u16, tls.NamedGroup, .{ | 223 | })) ++ tls.extension(.supported_groups, array(u16, tls.NamedGroup, .{ |
| 224 | .x25519_ml_kem768, | 224 | .x25519_ml_kem768, |
| 225 | .secp256r1, | 225 | .secp256r1, |
| | 226 | .secp384r1, |
| 226 | .x25519, | 227 | .x25519, |
| 227 | })) ++ tls.extension(.psk_key_exchange_modes, array(u8, tls.PskKeyExchangeMode, .{ | 228 | })) ++ tls.extension(.psk_key_exchange_modes, array(u8, tls.PskKeyExchangeMode, .{ |
| 228 | .psk_dhe_ke, | 229 | .psk_dhe_ke, |
| ... | @@ -233,6 +234,8 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client | ... | @@ -233,6 +234,8 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 233 | array(u16, u8, key_share.ml_kem768_kp.public_key.toBytes() ++ key_share.x25519_kp.public_key) ++ | 234 | array(u16, u8, key_share.ml_kem768_kp.public_key.toBytes() ++ key_share.x25519_kp.public_key) ++ |
| 234 | int(u16, @intFromEnum(tls.NamedGroup.secp256r1)) ++ | 235 | int(u16, @intFromEnum(tls.NamedGroup.secp256r1)) ++ |
| 235 | array(u16, u8, key_share.secp256r1_kp.public_key.toUncompressedSec1()) ++ | 236 | array(u16, u8, key_share.secp256r1_kp.public_key.toUncompressedSec1()) ++ |
| | 237 | int(u16, @intFromEnum(tls.NamedGroup.secp384r1)) ++ |
| | 238 | array(u16, u8, key_share.secp384r1_kp.public_key.toUncompressedSec1()) ++ |
| 236 | int(u16, @intFromEnum(tls.NamedGroup.x25519)) ++ | 239 | int(u16, @intFromEnum(tls.NamedGroup.x25519)) ++ |
| 237 | array(u16, u8, key_share.x25519_kp.public_key), | 240 | array(u16, u8, key_share.x25519_kp.public_key), |
| 238 | )); | 241 | )); |
| ... | @@ -1630,23 +1633,26 @@ inline fn big(x: anytype) @TypeOf(x) { | ... | @@ -1630,23 +1633,26 @@ inline fn big(x: anytype) @TypeOf(x) { |
| 1630 | } | 1633 | } |
| 1631 | | 1634 | |
| 1632 | const KeyShare = struct { | 1635 | const KeyShare = struct { |
| 1633 | x25519_kp: crypto.dh.X25519.KeyPair, | | |
| 1634 | secp256r1_kp: crypto.sign.ecdsa.EcdsaP256Sha256.KeyPair, | | |
| 1635 | ml_kem768_kp: crypto.kem.ml_kem.MLKem768.KeyPair, | 1636 | ml_kem768_kp: crypto.kem.ml_kem.MLKem768.KeyPair, |
| | 1637 | secp256r1_kp: crypto.sign.ecdsa.EcdsaP256Sha256.KeyPair, |
| | 1638 | secp384r1_kp: crypto.sign.ecdsa.EcdsaP384Sha384.KeyPair, |
| | 1639 | x25519_kp: crypto.dh.X25519.KeyPair, |
| 1636 | sk_buf: [sk_max_len]u8, | 1640 | sk_buf: [sk_max_len]u8, |
| 1637 | sk_len: std.math.IntFittingRange(0, sk_max_len), | 1641 | sk_len: std.math.IntFittingRange(0, sk_max_len), |
| 1638 | | 1642 | |
| 1639 | const sk_max_len = @max( | 1643 | const sk_max_len = @max( |
| 1640 | crypto.dh.X25519.shared_length + crypto.kem.ml_kem.MLKem768.shared_length, | 1644 | crypto.dh.X25519.shared_length + crypto.kem.ml_kem.MLKem768.shared_length, |
| 1641 | crypto.dh.X25519.shared_length, | | |
| 1642 | crypto.ecc.P256.scalar.encoded_length, | 1645 | crypto.ecc.P256.scalar.encoded_length, |
| | 1646 | crypto.ecc.P384.scalar.encoded_length, |
| | 1647 | crypto.dh.X25519.shared_length, |
| 1643 | ); | 1648 | ); |
| 1644 | | 1649 | |
| 1645 | fn init(seed: [64]u8) error{IdentityElement}!KeyShare { | 1650 | fn init(seed: [112]u8) error{IdentityElement}!KeyShare { |
| 1646 | return .{ | 1651 | return .{ |
| 1647 | .x25519_kp = try .create(seed[0..32].*), | | |
| 1648 | .secp256r1_kp = try .create(seed[32..64].*), | | |
| 1649 | .ml_kem768_kp = try .create(null), | 1652 | .ml_kem768_kp = try .create(null), |
| | 1653 | .secp256r1_kp = try .create(seed[0..32].*), |
| | 1654 | .secp384r1_kp = try .create(seed[32..80].*), |
| | 1655 | .x25519_kp = try .create(seed[80..112].*), |
| 1650 | .sk_buf = undefined, | 1656 | .sk_buf = undefined, |
| 1651 | .sk_len = 0, | 1657 | .sk_len = 0, |
| 1652 | }; | 1658 | }; |
| ... | @@ -1680,6 +1686,15 @@ const KeyShare = struct { | ... | @@ -1680,6 +1686,15 @@ const KeyShare = struct { |
| 1680 | @memcpy(ks.sk_buf[0..sk.len], &sk); | 1686 | @memcpy(ks.sk_buf[0..sk.len], &sk); |
| 1681 | ks.sk_len = sk.len; | 1687 | ks.sk_len = sk.len; |
| 1682 | }, | 1688 | }, |
| | 1689 | .secp384r1 => { |
| | 1690 | const PublicKey = crypto.sign.ecdsa.EcdsaP384Sha384.PublicKey; |
| | 1691 | const pk = PublicKey.fromSec1(server_pub_key) catch return error.TlsDecryptFailure; |
| | 1692 | const mul = pk.p.mulPublic(ks.secp384r1_kp.secret_key.bytes, .big) catch |
| | 1693 | return error.TlsDecryptFailure; |
| | 1694 | const sk = mul.affineCoordinates().x.toBytes(.big); |
| | 1695 | @memcpy(ks.sk_buf[0..sk.len], &sk); |
| | 1696 | ks.sk_len = sk.len; |
| | 1697 | }, |
| 1683 | .x25519 => { | 1698 | .x25519 => { |
| 1684 | const ksl = crypto.dh.X25519.public_length; | 1699 | const ksl = crypto.dh.X25519.public_length; |
| 1685 | if (server_pub_key.len != ksl) return error.TlsIllegalParameter; | 1700 | if (server_pub_key.len != ksl) return error.TlsIllegalParameter; |