| ... | @@ -36,9 +36,11 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -36,9 +36,11 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 36 | error.IdentityElement => return error.InsufficientEntropy, | 36 | error.IdentityElement => return error.InsufficientEntropy, |
| 37 | }; | 37 | }; |
| 38 | | 38 | |
| 39 | // random (u32) | 39 | // This is used both for the random bytes and for the legacy session id. |
| 40 | var rand_buf: [32]u8 = undefined; | 40 | var random_buffer: [64]u8 = undefined; |
| 41 | crypto.random.bytes(&rand_buf); | 41 | crypto.random.bytes(&random_buffer); |
| | 42 | const hello_rand = random_buffer[0..32].*; |
| | 43 | const legacy_session_id = random_buffer[32..64].*; |
| 42 | | 44 | |
| 43 | const extensions_payload = | 45 | const extensions_payload = |
| 44 | tls.extension(.supported_versions, [_]u8{ | 46 | tls.extension(.supported_versions, [_]u8{ |
| ... | @@ -86,8 +88,8 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -86,8 +88,8 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 86 | | 88 | |
| 87 | const client_hello = | 89 | const client_hello = |
| 88 | int2(@enumToInt(tls.ProtocolVersion.tls_1_2)) ++ | 90 | int2(@enumToInt(tls.ProtocolVersion.tls_1_2)) ++ |
| 89 | rand_buf ++ | 91 | hello_rand ++ |
| 90 | [1]u8{0} ++ | 92 | [1]u8{32} ++ legacy_session_id ++ |
| 91 | cipher_suites ++ | 93 | cipher_suites ++ |
| 92 | int2(legacy_compression_methods) ++ | 94 | int2(legacy_compression_methods) ++ |
| 93 | extensions_header; | 95 | extensions_header; |
| ... | @@ -152,46 +154,55 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -152,46 +154,55 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 152 | } | 154 | } |
| 153 | const length = mem.readIntBig(u24, frag[1..4]); | 155 | const length = mem.readIntBig(u24, frag[1..4]); |
| 154 | if (4 + length != frag.len) return error.TlsBadLength; | 156 | if (4 + length != frag.len) return error.TlsBadLength; |
| 155 | const hello = frag[4..]; | 157 | var i: usize = 4; |
| 156 | const legacy_version = mem.readIntBig(u16, hello[0..2]); | 158 | const legacy_version = mem.readIntBig(u16, frag[i..][0..2]); |
| 157 | const random = hello[2..34].*; | 159 | i += 2; |
| | 160 | const random = frag[i..][0..32].*; |
| | 161 | i += 32; |
| 158 | if (mem.eql(u8, &random, &tls.hello_retry_request_sequence)) { | 162 | if (mem.eql(u8, &random, &tls.hello_retry_request_sequence)) { |
| 159 | @panic("TODO handle HelloRetryRequest"); | 163 | @panic("TODO handle HelloRetryRequest"); |
| 160 | } | 164 | } |
| 161 | const legacy_session_id_echo_len = hello[34]; | 165 | const legacy_session_id_echo_len = frag[i]; |
| 162 | if (legacy_session_id_echo_len != 0) return error.TlsIllegalParameter; | 166 | i += 1; |
| 163 | const cipher_suite_int = mem.readIntBig(u16, hello[35..37]); | 167 | if (legacy_session_id_echo_len != 32) return error.TlsIllegalParameter; |
| | 168 | const legacy_session_id_echo = frag[i..][0..32]; |
| | 169 | if (!mem.eql(u8, legacy_session_id_echo, &legacy_session_id)) |
| | 170 | return error.TlsIllegalParameter; |
| | 171 | i += 32; |
| | 172 | const cipher_suite_int = mem.readIntBig(u16, frag[i..][0..2]); |
| | 173 | i += 2; |
| 164 | const cipher_suite_tag = @intToEnum(CipherSuite, cipher_suite_int); | 174 | const cipher_suite_tag = @intToEnum(CipherSuite, cipher_suite_int); |
| 165 | std.debug.print("server wants cipher suite {any}\n", .{cipher_suite_tag}); | 175 | std.debug.print("server wants cipher suite {any}\n", .{cipher_suite_tag}); |
| 166 | const legacy_compression_method = hello[37]; | 176 | const legacy_compression_method = frag[i]; |
| | 177 | i += 1; |
| 167 | _ = legacy_compression_method; | 178 | _ = legacy_compression_method; |
| 168 | const extensions_size = mem.readIntBig(u16, hello[38..40]); | 179 | const extensions_size = mem.readIntBig(u16, frag[i..][0..2]); |
| 169 | if (40 + extensions_size != hello.len) return error.TlsBadLength; | 180 | i += 2; |
| 170 | var i: usize = 40; | 181 | if (i + extensions_size != frag.len) return error.TlsBadLength; |
| 171 | var supported_version: u16 = 0; | 182 | var supported_version: u16 = 0; |
| 172 | var opt_x25519_server_pub_key: ?*[32]u8 = null; | 183 | var opt_x25519_server_pub_key: ?*[32]u8 = null; |
| 173 | while (i < hello.len) { | 184 | while (i < frag.len) { |
| 174 | const et = mem.readIntBig(u16, hello[i..][0..2]); | 185 | const et = mem.readIntBig(u16, frag[i..][0..2]); |
| 175 | i += 2; | 186 | i += 2; |
| 176 | const ext_size = mem.readIntBig(u16, hello[i..][0..2]); | 187 | const ext_size = mem.readIntBig(u16, frag[i..][0..2]); |
| 177 | i += 2; | 188 | i += 2; |
| 178 | const next_i = i + ext_size; | 189 | const next_i = i + ext_size; |
| 179 | if (next_i > hello.len) return error.TlsBadLength; | 190 | if (next_i > frag.len) return error.TlsBadLength; |
| 180 | switch (et) { | 191 | switch (et) { |
| 181 | @enumToInt(tls.ExtensionType.supported_versions) => { | 192 | @enumToInt(tls.ExtensionType.supported_versions) => { |
| 182 | if (supported_version != 0) return error.TlsIllegalParameter; | 193 | if (supported_version != 0) return error.TlsIllegalParameter; |
| 183 | supported_version = mem.readIntBig(u16, hello[i..][0..2]); | 194 | supported_version = mem.readIntBig(u16, frag[i..][0..2]); |
| 184 | }, | 195 | }, |
| 185 | @enumToInt(tls.ExtensionType.key_share) => { | 196 | @enumToInt(tls.ExtensionType.key_share) => { |
| 186 | if (opt_x25519_server_pub_key != null) return error.TlsIllegalParameter; | 197 | if (opt_x25519_server_pub_key != null) return error.TlsIllegalParameter; |
| 187 | const named_group = mem.readIntBig(u16, hello[i..][0..2]); | 198 | const named_group = mem.readIntBig(u16, frag[i..][0..2]); |
| 188 | i += 2; | 199 | i += 2; |
| 189 | switch (named_group) { | 200 | switch (named_group) { |
| 190 | @enumToInt(tls.NamedGroup.x25519) => { | 201 | @enumToInt(tls.NamedGroup.x25519) => { |
| 191 | const key_size = mem.readIntBig(u16, hello[i..][0..2]); | 202 | const key_size = mem.readIntBig(u16, frag[i..][0..2]); |
| 192 | i += 2; | 203 | i += 2; |
| 193 | if (key_size != 32) return error.TlsBadLength; | 204 | if (key_size != 32) return error.TlsBadLength; |
| 194 | opt_x25519_server_pub_key = hello[i..][0..32]; | 205 | opt_x25519_server_pub_key = frag[i..][0..32]; |
| 195 | }, | 206 | }, |
| 196 | else => { | 207 | else => { |
| 197 | std.debug.print("named group: {x}\n", .{named_group}); | 208 | std.debug.print("named group: {x}\n", .{named_group}); |