| ... | @@ -257,6 +257,7 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -257,6 +257,7 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 257 | .client_handshake_iv = undefined, | 257 | .client_handshake_iv = undefined, |
| 258 | .server_handshake_iv = undefined, | 258 | .server_handshake_iv = undefined, |
| 259 | .transcript_hash = P.Hash.init(.{}), | 259 | .transcript_hash = P.Hash.init(.{}), |
| | 260 | .finished_digest = undefined, |
| 260 | }); | 261 | }); |
| 261 | const p = &@field(cipher_params, @tagName(tag)); | 262 | const p = &@field(cipher_params, @tagName(tag)); |
| 262 | p.transcript_hash.update(client_hello_bytes1); // Client Hello part 1 | 263 | p.transcript_hash.update(client_hello_bytes1); // Client Hello part 1 |
| ... | @@ -391,6 +392,11 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -391,6 +392,11 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 391 | }, | 392 | }, |
| 392 | @enumToInt(HandshakeType.certificate_verify) => { | 393 | @enumToInt(HandshakeType.certificate_verify) => { |
| 393 | std.debug.print("the certificate came with a fancy signature\n", .{}); | 394 | std.debug.print("the certificate came with a fancy signature\n", .{}); |
| | 395 | switch (cipher_params) { |
| | 396 | inline else => |*p| { |
| | 397 | p.finished_digest = p.transcript_hash.peek(); |
| | 398 | }, |
| | 399 | } |
| 394 | }, | 400 | }, |
| 395 | @enumToInt(HandshakeType.finished) => { | 401 | @enumToInt(HandshakeType.finished) => { |
| 396 | // This message is to trick buggy proxies into behaving correctly. | 402 | // This message is to trick buggy proxies into behaving correctly. |
| ... | @@ -403,7 +409,10 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -403,7 +409,10 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 403 | const app_cipher = switch (cipher_params) { | 409 | const app_cipher = switch (cipher_params) { |
| 404 | inline else => |*p, tag| c: { | 410 | inline else => |*p, tag| c: { |
| 405 | const P = @TypeOf(p.*); | 411 | const P = @TypeOf(p.*); |
| 406 | // TODO verify the server's data | 412 | const expected_server_verify_data = tls.hmac(P.Hmac, &p.finished_digest, p.server_finished_key); |
| | 413 | const actual_server_verify_data = cleartext[ct_i..][0..handshake_len]; |
| | 414 | if (!mem.eql(u8, &expected_server_verify_data, actual_server_verify_data)) |
| | 415 | return error.TlsDecryptError; |
| 407 | const handshake_hash = p.transcript_hash.finalResult(); | 416 | const handshake_hash = p.transcript_hash.finalResult(); |
| 408 | const verify_data = tls.hmac(P.Hmac, &handshake_hash, p.client_finished_key); | 417 | const verify_data = tls.hmac(P.Hmac, &handshake_hash, p.client_finished_key); |
| 409 | const out_cleartext = [_]u8{ | 418 | const out_cleartext = [_]u8{ |
| ... | @@ -454,7 +463,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { | ... | @@ -454,7 +463,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client { |
| 454 | }; | 463 | }; |
| 455 | }, | 464 | }, |
| 456 | else => { | 465 | else => { |
| 457 | std.debug.print("handshake type: {d}\n", .{cleartext[0]}); | | |
| 458 | return error.TlsUnexpectedMessage; | 466 | return error.TlsUnexpectedMessage; |
| 459 | }, | 467 | }, |
| 460 | } | 468 | } |