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;