Mercurial > hg > nginx-tests
comparison lib/Test/Nginx/HTTP3.pm @ 1915:15131dd931a0
Tests: QUIC address validation tests.
While here, fixed establishing connection after receiving a Retry packet,
broken after conversion to HTTP3 package.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 20 Jun 2023 20:01:20 +0400 |
parents | afbf4c06c014 |
children | 24fea64f233f |
comparison
equal
deleted
inserted
replaced
1914:afbf4c06c014 | 1915:15131dd931a0 |
---|---|
37 Proto => "udp", | 37 Proto => "udp", |
38 PeerAddr => '127.0.0.1:' . port($port || 8980), | 38 PeerAddr => '127.0.0.1:' . port($port || 8980), |
39 ); | 39 ); |
40 | 40 |
41 $self->{repeat} = 0; | 41 $self->{repeat} = 0; |
42 $self->{token} = ''; | 42 $self->{token} = $extra{token} || ''; |
43 $self->{psk_list} = $extra{psk_list} || []; | 43 $self->{psk_list} = $extra{psk_list} || []; |
44 | 44 |
45 $self->{sni} = exists $extra{sni} ? $extra{sni} : 'localhost'; | 45 $self->{sni} = exists $extra{sni} ? $extra{sni} : 'localhost'; |
46 $self->{cipher} = 0x1301; | 46 $self->{cipher} = 0x1301; |
47 $self->{ciphers} = $extra{ciphers} || "\x13\x01"; | 47 $self->{ciphers} = $extra{ciphers} || "\x13\x01"; |
54 $self->{dynamic_encode} = []; | 54 $self->{dynamic_encode} = []; |
55 $self->{last_stream} = -4; | 55 $self->{last_stream} = -4; |
56 $self->{buf} = ''; | 56 $self->{buf} = ''; |
57 | 57 |
58 $self->init(); | 58 $self->init(); |
59 $self->init_key_schedule(); | 59 $self->retry(%extra) or return; |
60 $self->initial(); | |
61 return $self if $extra{probe}; | |
62 $self->handshake() or return; | |
63 | |
64 # RFC 9204, 4.3.1. Set Dynamic Table Capacity | |
65 | |
66 my $buf = pack("B*", '001' . ipack(5, $extra{capacity} || 400)); | |
67 $self->{encoder_offset} = length($buf) + 1; | |
68 $buf = "\x08\x02\x02" . $buf; | |
69 | |
70 # RFC 9114, 6.2.1. Control Streams | |
71 | |
72 $buf = "\x0a\x06\x03\x00\x04\x00" . $buf; | |
73 $self->{control_offset} = 3; | |
74 | |
75 $self->raw_write($buf); | |
76 | 60 |
77 return $self; | 61 return $self; |
78 } | 62 } |
79 | 63 |
80 sub init { | 64 sub init { |
97 $self->{dcid} = Crypt::PRNG::random_bytes(18); | 81 $self->{dcid} = Crypt::PRNG::random_bytes(18); |
98 $self->{salt} = "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" | 82 $self->{salt} = "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" |
99 . "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; | 83 . "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; |
100 $self->{ncid} = []; | 84 $self->{ncid} = []; |
101 $self->{early_data} = $early_data; | 85 $self->{early_data} = $early_data; |
102 | |
103 $self->retry(); | |
104 } | 86 } |
105 | 87 |
106 sub retry { | 88 sub retry { |
107 my ($self) = @_; | 89 my ($self, %extra) = @_; |
108 my $prk = Crypt::KeyDerivation::hkdf_extract($self->{dcid}, | 90 my $prk = Crypt::KeyDerivation::hkdf_extract($self->{dcid}, |
109 $self->{salt}, 'SHA256'); | 91 $self->{salt}, 'SHA256'); |
110 | 92 |
111 Test::Nginx::log_core('||', "scid = " . unpack("H*", $self->{scid})); | 93 Test::Nginx::log_core('||', "scid = " . unpack("H*", $self->{scid})); |
112 Test::Nginx::log_core('||', "dcid = " . unpack("H*", $self->{dcid})); | 94 Test::Nginx::log_core('||', "dcid = " . unpack("H*", $self->{dcid})); |
113 Test::Nginx::log_core('||', "prk = " . unpack("H*", $prk)); | 95 Test::Nginx::log_core('||', "prk = " . unpack("H*", $prk)); |
114 | 96 |
115 $self->set_traffic_keys('tls13 client in', 'SHA256', 32, 0, 'w', $prk); | 97 $self->set_traffic_keys('tls13 client in', 'SHA256', 32, 0, 'w', $prk); |
116 $self->set_traffic_keys('tls13 server in', 'SHA256', 32, 0, 'r', $prk); | 98 $self->set_traffic_keys('tls13 server in', 'SHA256', 32, 0, 'r', $prk); |
99 | |
100 $self->init_key_schedule(); | |
101 $self->initial(); | |
102 return $self if $extra{probe}; | |
103 $self->handshake() or return; | |
104 | |
105 # RFC 9204, 4.3.1. Set Dynamic Table Capacity | |
106 | |
107 my $buf = pack("B*", '001' . ipack(5, $extra{capacity} || 400)); | |
108 $self->{encoder_offset} = length($buf) + 1; | |
109 $buf = "\x08\x02\x02" . $buf; | |
110 | |
111 # RFC 9114, 6.2.1. Control Streams | |
112 | |
113 $buf = "\x0a\x06\x03\x00\x04\x00" . $buf; | |
114 $self->{control_offset} = 3; | |
115 | |
116 $self->raw_write($buf); | |
117 } | 117 } |
118 | 118 |
119 sub init_key_schedule { | 119 sub init_key_schedule { |
120 my ($self) = @_; | 120 my ($self) = @_; |
121 $self->{psk} = $self->{psk_list}[0]; | 121 $self->{psk} = $self->{psk_list}[0]; |
1801 $self->{dcid} = substr($buf, 6 + $off + 1, $self->{dcid}); | 1801 $self->{dcid} = substr($buf, 6 + $off + 1, $self->{dcid}); |
1802 my $token = substr($buf, 6 + $off + 1 + length($self->{dcid}), -16); | 1802 my $token = substr($buf, 6 + $off + 1 + length($self->{dcid}), -16); |
1803 my $tag = substr($buf, -16); | 1803 my $tag = substr($buf, -16); |
1804 my $pseudo = pack("C", length($self->{odcid})) . $self->{odcid} | 1804 my $pseudo = pack("C", length($self->{odcid})) . $self->{odcid} |
1805 . substr($buf, 0, -16); | 1805 . substr($buf, 0, -16); |
1806 return ($tag, retry_verify_tag($pseudo), $token); | 1806 $self->{retry} = { token => $token, tag => $tag, pseudo => $pseudo }; |
1807 return $tag, '', $token; | |
1808 } | |
1809 | |
1810 sub retry_token { | |
1811 my ($self) = @_; | |
1812 return $self->{retry}{token}; | |
1813 } | |
1814 | |
1815 sub retry_tag { | |
1816 my ($self) = @_; | |
1817 return $self->{retry}{tag}; | |
1807 } | 1818 } |
1808 | 1819 |
1809 sub retry_verify_tag { | 1820 sub retry_verify_tag { |
1821 my ($self) = @_; | |
1810 my $key = "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a" | 1822 my $key = "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a" |
1811 . "\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"; | 1823 . "\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"; |
1812 my $nonce = "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; | 1824 my $nonce = "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; |
1813 my (undef, $tag) = Crypt::AuthEnc::GCM::gcm_encrypt_authenticate('AES', | 1825 my (undef, $tag) = Crypt::AuthEnc::GCM::gcm_encrypt_authenticate('AES', |
1814 $key, $nonce, shift, ''); | 1826 $key, $nonce, $self->{retry}{pseudo}, ''); |
1815 return $tag; | 1827 return $tag; |
1816 } | 1828 } |
1817 | 1829 |
1818 sub set_traffic_keys { | 1830 sub set_traffic_keys { |
1819 my ($self, $label, $hash, $hlen, $level, $direction, $secret, $digest) | 1831 my ($self, $label, $hash, $hlen, $level, $direction, $secret, $digest) |
2038 = $self->decrypt_aead($self->{buf}); | 2050 = $self->decrypt_aead($self->{buf}); |
2039 if (!defined $plaintext) { | 2051 if (!defined $plaintext) { |
2040 $self->{buf} = ''; | 2052 $self->{buf} = ''; |
2041 goto again; | 2053 goto again; |
2042 } | 2054 } |
2043 goto retry if $self->{token}; | 2055 $self->retry(), return if $self->{token}; |
2044 $self->handle_frames(parse_frames($plaintext), $level); | 2056 $self->handle_frames(parse_frames($plaintext), $level); |
2045 @data = $self->parse_stream(); | 2057 @data = $self->parse_stream(); |
2046 return @data if @data; | 2058 return @data if @data; |
2047 return if scalar @{$self->{frames_in}}; | 2059 return if scalar @{$self->{frames_in}}; |
2048 } | 2060 } |
2099 | 2111 |
2100 while ($$buf) { | 2112 while ($$buf) { |
2101 (my $level, my $plaintext, $$buf, $self->{token}) | 2113 (my $level, my $plaintext, $$buf, $self->{token}) |
2102 = $self->decrypt_aead($$buf); | 2114 = $self->decrypt_aead($$buf); |
2103 return if !defined $plaintext; | 2115 return if !defined $plaintext; |
2104 goto retry if $self->{token}; | 2116 $self->retry(), return 1 if $self->{token}; |
2105 $self->handle_frames(parse_frames($plaintext), $level); | 2117 $self->handle_frames(parse_frames($plaintext), $level); |
2106 return 1 if $type->($self); | 2118 return 1 if $type->($self); |
2107 } | 2119 } |
2108 } | 2120 } |
2109 return; | 2121 return; |