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