| ... | @@ -46,7 +46,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -46,7 +46,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 46 | // Only possible to happen if the private key is all zeroes. | 46 | // Only possible to happen if the private key is all zeroes. |
| 47 | error.IdentityElement => return error.InsufficientEntropy, | 47 | error.IdentityElement => return error.InsufficientEntropy, |
| 48 | }; | 48 | }; |
| 49 | _ = secp256r1_kp; | | |
| 50 | | 49 | |
| 51 | const extensions_payload = | 50 | const extensions_payload = |
| 52 | tls.extension(.supported_versions, [_]u8{ | 51 | tls.extension(.supported_versions, [_]u8{ |
| ... | @@ -70,11 +69,14 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -70,11 +69,14 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 70 | .rsa_pkcs1_sha1, | 69 | .rsa_pkcs1_sha1, |
| 71 | .ecdsa_sha1, | 70 | .ecdsa_sha1, |
| 72 | })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{ | 71 | })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{ |
| 73 | //.secp256r1, | 72 | .secp256r1, |
| 74 | .x25519, | 73 | .x25519, |
| 75 | })) ++ tls.extension( | 74 | })) ++ tls.extension( |
| 76 | .key_share, | 75 | .key_share, |
| 77 | array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++ array(1, x25519_kp.public_key)), | 76 | array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++ |
| | 77 | array(1, x25519_kp.public_key) ++ |
| | 78 | int2(@enumToInt(tls.NamedGroup.secp256r1)) ++ |
| | 79 | array(1, secp256r1_kp.public_key.toUncompressedSec1())), |
| 78 | ) ++ | 80 | ) ++ |
| 79 | int2(@enumToInt(tls.ExtensionType.server_name)) ++ | 81 | int2(@enumToInt(tls.ExtensionType.server_name)) ++ |
| 80 | int2(host_len + 5) ++ // byte length of this extension payload | 82 | int2(host_len + 5) ++ // byte length of this extension payload |
| ... | @@ -182,7 +184,8 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -182,7 +184,8 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 182 | i += 2; | 184 | i += 2; |
| 183 | if (i + extensions_size != frag.len) return error.TlsBadLength; | 185 | if (i + extensions_size != frag.len) return error.TlsBadLength; |
| 184 | var supported_version: u16 = 0; | 186 | var supported_version: u16 = 0; |
| 185 | var opt_x25519_server_pub_key: ?*[32]u8 = null; | 187 | var shared_key: [32]u8 = undefined; |
| | 188 | var have_shared_key = false; |
| 186 | while (i < frag.len) { | 189 | while (i < frag.len) { |
| 187 | const et = mem.readIntBig(u16, frag[i..][0..2]); | 190 | const et = mem.readIntBig(u16, frag[i..][0..2]); |
| 188 | i += 2; | 191 | i += 2; |
| ... | @@ -196,15 +199,34 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -196,15 +199,34 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 196 | supported_version = mem.readIntBig(u16, frag[i..][0..2]); | 199 | supported_version = mem.readIntBig(u16, frag[i..][0..2]); |
| 197 | }, | 200 | }, |
| 198 | @enumToInt(tls.ExtensionType.key_share) => { | 201 | @enumToInt(tls.ExtensionType.key_share) => { |
| 199 | if (opt_x25519_server_pub_key != null) return error.TlsIllegalParameter; | 202 | if (have_shared_key) return error.TlsIllegalParameter; |
| | 203 | have_shared_key = true; |
| 200 | const named_group = mem.readIntBig(u16, frag[i..][0..2]); | 204 | const named_group = mem.readIntBig(u16, frag[i..][0..2]); |
| 201 | i += 2; | 205 | i += 2; |
| | 206 | const key_size = mem.readIntBig(u16, frag[i..][0..2]); |
| | 207 | i += 2; |
| | 208 | |
| 202 | switch (named_group) { | 209 | switch (named_group) { |
| 203 | @enumToInt(tls.NamedGroup.x25519) => { | 210 | @enumToInt(tls.NamedGroup.x25519) => { |
| 204 | const key_size = mem.readIntBig(u16, frag[i..][0..2]); | | |
| 205 | i += 2; | | |
| 206 | if (key_size != 32) return error.TlsBadLength; | 211 | if (key_size != 32) return error.TlsBadLength; |
| 207 | opt_x25519_server_pub_key = frag[i..][0..32]; | 212 | const server_pub_key = frag[i..][0..32]; |
| | 213 | |
| | 214 | shared_key = crypto.dh.X25519.scalarmult( |
| | 215 | x25519_kp.secret_key, |
| | 216 | server_pub_key.*, |
| | 217 | ) catch return error.TlsDecryptFailure; |
| | 218 | }, |
| | 219 | @enumToInt(tls.NamedGroup.secp256r1) => { |
| | 220 | const server_pub_key = frag[i..][0..key_size]; |
| | 221 | |
| | 222 | const PublicKey = crypto.sign.ecdsa.EcdsaP256Sha256.PublicKey; |
| | 223 | const pk = PublicKey.fromSec1(server_pub_key) catch { |
| | 224 | return error.TlsDecryptFailure; |
| | 225 | }; |
| | 226 | const mul = pk.p.mulPublic(secp256r1_kp.secret_key.bytes, .Big) catch { |
| | 227 | return error.TlsDecryptFailure; |
| | 228 | }; |
| | 229 | shared_key = mul.affineCoordinates().x.toBytes(.Big); |
| 208 | }, | 230 | }, |
| 209 | else => { | 231 | else => { |
| 210 | std.debug.print("named group: {x}\n", .{named_group}); | 232 | std.debug.print("named group: {x}\n", .{named_group}); |
| ... | @@ -218,8 +240,7 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -218,8 +240,7 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 218 | } | 240 | } |
| 219 | i = next_i; | 241 | i = next_i; |
| 220 | } | 242 | } |
| 221 | const x25519_server_pub_key = opt_x25519_server_pub_key orelse | 243 | if (!have_shared_key) return error.TlsIllegalParameter; |
| 222 | return error.TlsIllegalParameter; | | |
| 223 | const tls_version = if (supported_version == 0) legacy_version else supported_version; | 244 | const tls_version = if (supported_version == 0) legacy_version else supported_version; |
| 224 | switch (tls_version) { | 245 | switch (tls_version) { |
| 225 | @enumToInt(tls.ProtocolVersion.tls_1_2) => { | 246 | @enumToInt(tls.ProtocolVersion.tls_1_2) => { |
| ... | @@ -231,11 +252,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -231,11 +252,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 231 | else => return error.TlsIllegalParameter, | 252 | else => return error.TlsIllegalParameter, |
| 232 | } | 253 | } |
| 233 | | 254 | |
| 234 | const shared_key = crypto.dh.X25519.scalarmult( | | |
| 235 | x25519_kp.secret_key, | | |
| 236 | x25519_server_pub_key.*, | | |
| 237 | ) catch return error.TlsDecryptFailure; | | |
| 238 | | | |
| 239 | switch (cipher_suite_tag) { | 255 | switch (cipher_suite_tag) { |
| 240 | inline .AES_128_GCM_SHA256, | 256 | inline .AES_128_GCM_SHA256, |
| 241 | .AES_256_GCM_SHA384, | 257 | .AES_256_GCM_SHA384, |