| ... | ... | @@ -191,14 +191,14 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 191 | 191 | }; |
| 192 | 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 | 195 | crypto.random.bytes(&random_buffer); |
| 196 | 196 | const client_hello_rand = random_buffer[0..32].*; |
| 197 | 197 | var key_seq: u64 = 0; |
| 198 | 198 | var server_hello_rand: [32]u8 = undefined; |
| 199 | 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 | 202 | // Only possible to happen if the seed is all zeroes. |
| 203 | 203 | error.IdentityElement => return error.InsufficientEntropy, |
| 204 | 204 | }; |
| ... | ... | @@ -223,6 +223,7 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 223 | 223 | })) ++ tls.extension(.supported_groups, array(u16, tls.NamedGroup, .{ |
| 224 | 224 | .x25519_ml_kem768, |
| 225 | 225 | .secp256r1, |
| 226 | .secp384r1, |
| 226 | 227 | .x25519, |
| 227 | 228 | })) ++ tls.extension(.psk_key_exchange_modes, array(u8, tls.PskKeyExchangeMode, .{ |
| 228 | 229 | .psk_dhe_ke, |
| ... | ... | @@ -233,6 +234,8 @@ pub fn init(stream: anytype, options: Options) InitError(@TypeOf(stream))!Client |
| 233 | 234 | array(u16, u8, key_share.ml_kem768_kp.public_key.toBytes() ++ key_share.x25519_kp.public_key) ++ |
| 234 | 235 | int(u16, @intFromEnum(tls.NamedGroup.secp256r1)) ++ |
| 235 | 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 | 239 | int(u16, @intFromEnum(tls.NamedGroup.x25519)) ++ |
| 237 | 240 | array(u16, u8, key_share.x25519_kp.public_key), |
| 238 | 241 | )); |
| ... | ... | @@ -1630,23 +1633,26 @@ inline fn big(x: anytype) @TypeOf(x) { |
| 1630 | 1633 | } |
| 1631 | 1634 | |
| 1632 | 1635 | const KeyShare = struct { |
| 1633 | | x25519_kp: crypto.dh.X25519.KeyPair, |
| 1634 | | secp256r1_kp: crypto.sign.ecdsa.EcdsaP256Sha256.KeyPair, |
| 1635 | 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 | 1640 | sk_buf: [sk_max_len]u8, |
| 1637 | 1641 | sk_len: std.math.IntFittingRange(0, sk_max_len), |
| 1638 | 1642 | |
| 1639 | 1643 | const sk_max_len = @max( |
| 1640 | 1644 | crypto.dh.X25519.shared_length + crypto.kem.ml_kem.MLKem768.shared_length, |
| 1641 | | crypto.dh.X25519.shared_length, |
| 1642 | 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 | 1651 | return .{ |
| 1647 | | .x25519_kp = try .create(seed[0..32].*), |
| 1648 | | .secp256r1_kp = try .create(seed[32..64].*), |
| 1649 | 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 | 1656 | .sk_buf = undefined, |
| 1651 | 1657 | .sk_len = 0, |
| 1652 | 1658 | }; |
| ... | ... | @@ -1680,6 +1686,15 @@ const KeyShare = struct { |
| 1680 | 1686 | @memcpy(ks.sk_buf[0..sk.len], &sk); |
| 1681 | 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 | 1698 | .x25519 => { |
| 1684 | 1699 | const ksl = crypto.dh.X25519.public_length; |
| 1685 | 1700 | if (server_pub_key.len != ksl) return error.TlsIllegalParameter; |