| ... | @@ -158,6 +158,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -158,6 +158,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 158 | // Only possible to happen if the private key is all zeroes. | 158 | // Only possible to happen if the private key is all zeroes. |
| 159 | error.IdentityElement => return error.InsufficientEntropy, | 159 | error.IdentityElement => return error.InsufficientEntropy, |
| 160 | }; | 160 | }; |
| | 161 | const kyber768_kp = crypto.kem.kyber_d00.Kyber768.KeyPair.create(null) catch {}; |
| 161 | | 162 | |
| 162 | const extensions_payload = | 163 | const extensions_payload = |
| 163 | tls.extension(.supported_versions, [_]u8{ | 164 | tls.extension(.supported_versions, [_]u8{ |
| ... | @@ -175,6 +176,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -175,6 +176,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 175 | .rsa_pkcs1_sha512, | 176 | .rsa_pkcs1_sha512, |
| 176 | .ed25519, | 177 | .ed25519, |
| 177 | })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{ | 178 | })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{ |
| | 179 | .x25519_kyber768d00, |
| 178 | .secp256r1, | 180 | .secp256r1, |
| 179 | .x25519, | 181 | .x25519, |
| 180 | })) ++ tls.extension( | 182 | })) ++ tls.extension( |
| ... | @@ -182,7 +184,9 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -182,7 +184,9 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 182 | array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++ | 184 | array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++ |
| 183 | array(1, x25519_kp.public_key) ++ | 185 | array(1, x25519_kp.public_key) ++ |
| 184 | int2(@enumToInt(tls.NamedGroup.secp256r1)) ++ | 186 | int2(@enumToInt(tls.NamedGroup.secp256r1)) ++ |
| 185 | array(1, secp256r1_kp.public_key.toUncompressedSec1())), | 187 | array(1, secp256r1_kp.public_key.toUncompressedSec1()) ++ |
| | 188 | int2(@enumToInt(tls.NamedGroup.x25519_kyber768d00)) ++ |
| | 189 | array(1, x25519_kp.public_key ++ kyber768_kp.public_key.toBytes())), |
| 186 | ) ++ | 190 | ) ++ |
| 187 | int2(@enumToInt(tls.ExtensionType.server_name)) ++ | 191 | int2(@enumToInt(tls.ExtensionType.server_name)) ++ |
| 188 | int2(host_len + 5) ++ // byte length of this extension payload | 192 | int2(host_len + 5) ++ // byte length of this extension payload |
| ... | @@ -274,7 +278,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -274,7 +278,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 274 | const extensions_size = hsd.decode(u16); | 278 | const extensions_size = hsd.decode(u16); |
| 275 | var all_extd = try hsd.sub(extensions_size); | 279 | var all_extd = try hsd.sub(extensions_size); |
| 276 | var supported_version: u16 = 0; | 280 | var supported_version: u16 = 0; |
| 277 | var shared_key: [32]u8 = undefined; | 281 | var shared_key: []const u8 = undefined; |
| 278 | var have_shared_key = false; | 282 | var have_shared_key = false; |
| 279 | while (!all_extd.eof()) { | 283 | while (!all_extd.eof()) { |
| 280 | try all_extd.ensure(2 + 2); | 284 | try all_extd.ensure(2 + 2); |
| ... | @@ -295,14 +299,29 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -295,14 +299,29 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 295 | const key_size = extd.decode(u16); | 299 | const key_size = extd.decode(u16); |
| 296 | try extd.ensure(key_size); | 300 | try extd.ensure(key_size); |
| 297 | switch (named_group) { | 301 | switch (named_group) { |
| | 302 | .x25519_kyber768d00 => { |
| | 303 | const xksl = crypto.dh.X25519.public_length; |
| | 304 | const hksl = xksl + crypto.kem.kyber_d00.Kyber768.ciphertext_length; |
| | 305 | if (key_size != hksl) |
| | 306 | return error.TlsIllegalParameter; |
| | 307 | const server_ks = extd.array(hksl); |
| | 308 | |
| | 309 | shared_key = &((crypto.dh.X25519.scalarmult( |
| | 310 | x25519_kp.secret_key, |
| | 311 | server_ks[0..xksl].*, |
| | 312 | ) catch return error.TlsDecryptFailure) ++ (kyber768_kp.secret_key.decaps( |
| | 313 | server_ks[xksl..hksl], |
| | 314 | ) catch return error.TlsDecryptFailure)); |
| | 315 | }, |
| 298 | .x25519 => { | 316 | .x25519 => { |
| 299 | if (key_size != 32) return error.TlsIllegalParameter; | 317 | const ksl = crypto.dh.X25519.public_length; |
| 300 | const server_pub_key = extd.array(32); | 318 | if (key_size != ksl) return error.TlsIllegalParameter; |
| | 319 | const server_pub_key = extd.array(ksl); |
| 301 | | 320 | |
| 302 | shared_key = crypto.dh.X25519.scalarmult( | 321 | shared_key = &(crypto.dh.X25519.scalarmult( |
| 303 | x25519_kp.secret_key, | 322 | x25519_kp.secret_key, |
| 304 | server_pub_key.*, | 323 | server_pub_key.*, |
| 305 | ) catch return error.TlsDecryptFailure; | 324 | ) catch return error.TlsDecryptFailure); |
| 306 | }, | 325 | }, |
| 307 | .secp256r1 => { | 326 | .secp256r1 => { |
| 308 | const server_pub_key = extd.slice(key_size); | 327 | const server_pub_key = extd.slice(key_size); |
| ... | @@ -314,7 +333,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -314,7 +333,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 314 | const mul = pk.p.mulPublic(secp256r1_kp.secret_key.bytes, .Big) catch { | 333 | const mul = pk.p.mulPublic(secp256r1_kp.secret_key.bytes, .Big) catch { |
| 315 | return error.TlsDecryptFailure; | 334 | return error.TlsDecryptFailure; |
| 316 | }; | 335 | }; |
| 317 | shared_key = mul.affineCoordinates().x.toBytes(.Big); | 336 | shared_key = &mul.affineCoordinates().x.toBytes(.Big); |
| 318 | }, | 337 | }, |
| 319 | else => { | 338 | else => { |
| 320 | return error.TlsIllegalParameter; | 339 | return error.TlsIllegalParameter; |
| ... | @@ -358,7 +377,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In | ... | @@ -358,7 +377,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In |
| 358 | const early_secret = P.Hkdf.extract(&[1]u8{0}, &zeroes); | 377 | const early_secret = P.Hkdf.extract(&[1]u8{0}, &zeroes); |
| 359 | const empty_hash = tls.emptyHash(P.Hash); | 378 | const empty_hash = tls.emptyHash(P.Hash); |
| 360 | const hs_derived_secret = hkdfExpandLabel(P.Hkdf, early_secret, "derived", &empty_hash, P.Hash.digest_length); | 379 | const hs_derived_secret = hkdfExpandLabel(P.Hkdf, early_secret, "derived", &empty_hash, P.Hash.digest_length); |
| 361 | p.handshake_secret = P.Hkdf.extract(&hs_derived_secret, &shared_key); | 380 | p.handshake_secret = P.Hkdf.extract(&hs_derived_secret, shared_key); |
| 362 | const ap_derived_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "derived", &empty_hash, P.Hash.digest_length); | 381 | const ap_derived_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "derived", &empty_hash, P.Hash.digest_length); |
| 363 | p.master_secret = P.Hkdf.extract(&ap_derived_secret, &zeroes); | 382 | p.master_secret = P.Hkdf.extract(&ap_derived_secret, &zeroes); |
| 364 | const client_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "c hs traffic", &hello_hash, P.Hash.digest_length); | 383 | const client_secret = hkdfExpandLabel(P.Hkdf, p.handshake_secret, "c hs traffic", &hello_hash, P.Hash.digest_length); |