| ... | ... | @@ -24,7 +24,7 @@ read_seq: u64, |
| 24 | 24 | write_seq: u64, |
| 25 | 25 | /// The size is enough to contain exactly one TLSCiphertext record. |
| 26 | 26 | partially_read_buffer: [tls.max_ciphertext_record_len]u8, |
| 27 | | /// The number of partially read bytes inside `partiall_read_buffer`. |
| 27 | /// The number of partially read bytes inside `partially_read_buffer`. |
| 28 | 28 | partially_read_len: u15, |
| 29 | 29 | eof: bool, |
| 30 | 30 | |
| ... | ... | @@ -584,6 +584,8 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8) |
| 584 | 584 | // std.fmt.fmtSliceHexLower(&server_secret), |
| 585 | 585 | //}); |
| 586 | 586 | break :c @unionInit(ApplicationCipher, @tagName(tag), .{ |
| 587 | .client_secret = client_secret, |
| 588 | .server_secret = server_secret, |
| 587 | 589 | .client_key = hkdfExpandLabel(P.Hkdf, client_secret, "key", "", P.AEAD.key_length), |
| 588 | 590 | .server_key = hkdfExpandLabel(P.Hkdf, server_secret, "key", "", P.AEAD.key_length), |
| 589 | 591 | .client_iv = hkdfExpandLabel(P.Hkdf, client_secret, "iv", "", P.AEAD.nonce_length), |
| ... | ... | @@ -669,7 +671,7 @@ pub fn write(c: *Client, stream: net.Stream, bytes: []const u8) !usize { |
| 669 | 671 | ciphertext_end += auth_tag.len; |
| 670 | 672 | const pad = [1]u8{0} ** (P.AEAD.nonce_length - 8); |
| 671 | 673 | const operand: V = pad ++ @bitCast([8]u8, big(c.write_seq)); |
| 672 | | c.write_seq += 1; |
| 674 | c.write_seq += 1; // TODO send key_update on overflow |
| 673 | 675 | const nonce = @as(V, p.client_iv) ^ operand; |
| 674 | 676 | P.AEAD.encrypt(ciphertext, auth_tag, cleartext, ad, nonce, p.client_key); |
| 675 | 677 | //std.debug.print("seq: {d} nonce: {} client_key: {} client_iv: {} ad: {} auth_tag: {}\nserver_key: {} server_iv: {}\n", .{ |
| ... | ... | @@ -789,7 +791,8 @@ pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize { |
| 789 | 791 | }, |
| 790 | 792 | }; |
| 791 | 793 | |
| 792 | | const inner_ct = @intToEnum(ContentType, buffer[out + cleartext_len - 1]); |
| 794 | const cleartext = buffer[out..][0..cleartext_len]; |
| 795 | const inner_ct = @intToEnum(ContentType, cleartext[cleartext.len - 1]); |
| 793 | 796 | switch (inner_ct) { |
| 794 | 797 | .alert => { |
| 795 | 798 | const level = @intToEnum(tls.AlertLevel, buffer[out]); |
| ... | ... | @@ -802,7 +805,56 @@ pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize { |
| 802 | 805 | return error.TlsAlert; |
| 803 | 806 | }, |
| 804 | 807 | .handshake => { |
| 805 | | std.debug.print("the server wants to keep shaking hands\n", .{}); |
| 808 | var ct_i: usize = 0; |
| 809 | while (true) { |
| 810 | const handshake_type = cleartext[ct_i]; |
| 811 | ct_i += 1; |
| 812 | const handshake_len = mem.readIntBig(u24, cleartext[ct_i..][0..3]); |
| 813 | ct_i += 3; |
| 814 | const next_handshake_i = ct_i + handshake_len; |
| 815 | if (next_handshake_i > cleartext.len - 1) |
| 816 | return error.TlsBadLength; |
| 817 | const handshake = cleartext[ct_i..next_handshake_i]; |
| 818 | switch (handshake_type) { |
| 819 | @enumToInt(HandshakeType.new_session_ticket) => { |
| 820 | std.debug.print("server sent a new session ticket\n", .{}); |
| 821 | }, |
| 822 | @enumToInt(HandshakeType.key_update) => { |
| 823 | switch (c.application_cipher) { |
| 824 | inline else => |*p| { |
| 825 | const P = @TypeOf(p.*); |
| 826 | const server_secret = hkdfExpandLabel(P.Hkdf, p.server_secret, "traffic upd", "", P.Hash.digest_length); |
| 827 | p.server_secret = server_secret; |
| 828 | p.server_key = hkdfExpandLabel(P.Hkdf, server_secret, "key", "", P.AEAD.key_length); |
| 829 | p.server_iv = hkdfExpandLabel(P.Hkdf, server_secret, "iv", "", P.AEAD.nonce_length); |
| 830 | }, |
| 831 | } |
| 832 | c.read_seq = 0; |
| 833 | |
| 834 | switch (@intToEnum(tls.KeyUpdateRequest, handshake[0])) { |
| 835 | .update_requested => { |
| 836 | switch (c.application_cipher) { |
| 837 | inline else => |*p| { |
| 838 | const P = @TypeOf(p.*); |
| 839 | const client_secret = hkdfExpandLabel(P.Hkdf, p.client_secret, "traffic upd", "", P.Hash.digest_length); |
| 840 | p.client_secret = client_secret; |
| 841 | p.client_key = hkdfExpandLabel(P.Hkdf, client_secret, "key", "", P.AEAD.key_length); |
| 842 | p.client_iv = hkdfExpandLabel(P.Hkdf, client_secret, "iv", "", P.AEAD.nonce_length); |
| 843 | }, |
| 844 | } |
| 845 | c.write_seq = 0; |
| 846 | }, |
| 847 | .update_not_requested => {}, |
| 848 | _ => return error.TlsIllegalParameter, |
| 849 | } |
| 850 | }, |
| 851 | else => { |
| 852 | return error.TlsUnexpectedMessage; |
| 853 | }, |
| 854 | } |
| 855 | ct_i = next_handshake_i; |
| 856 | if (ct_i >= cleartext.len - 1) break; |
| 857 | } |
| 806 | 858 | }, |
| 807 | 859 | .application_data => { |
| 808 | 860 | out += cleartext_len - 1; |