comparison lib/Test/Nginx/HTTP3.pm @ 1934:4d13c9e74d04

Tests: added ability to setup QUIC TLS named group.
author Sergey Kandaurov <pluknet@nginx.com>
date Tue, 22 Aug 2023 14:29:16 +0400
parents 9bafe7cddd3c
children e1059682aeef
comparison
equal deleted inserted replaced
1933:9bafe7cddd3c 1934:4d13c9e74d04
21 bless $self, shift @_; 21 bless $self, shift @_;
22 22
23 my ($port, %extra) = @_; 23 my ($port, %extra) = @_;
24 24
25 require Crypt::KeyDerivation; 25 require Crypt::KeyDerivation;
26 require Crypt::PK::ECC;
26 require Crypt::PK::X25519; 27 require Crypt::PK::X25519;
27 require Crypt::PRNG; 28 require Crypt::PRNG;
28 require Crypt::AuthEnc::GCM; 29 require Crypt::AuthEnc::GCM;
29 require Crypt::AuthEnc::CCM; 30 require Crypt::AuthEnc::CCM;
30 require Crypt::AuthEnc::ChaCha20Poly1305; 31 require Crypt::AuthEnc::ChaCha20Poly1305;
44 $self->{early_data} = $extra{early_data}; 45 $self->{early_data} = $extra{early_data};
45 46
46 $self->{sni} = exists $extra{sni} ? $extra{sni} : 'localhost'; 47 $self->{sni} = exists $extra{sni} ? $extra{sni} : 'localhost';
47 $self->{cipher} = 0x1301; 48 $self->{cipher} = 0x1301;
48 $self->{ciphers} = $extra{ciphers} || "\x13\x01"; 49 $self->{ciphers} = $extra{ciphers} || "\x13\x01";
50 $self->{group} = $extra{group} || 'x25519';
49 $self->{opts} = $extra{opts}; 51 $self->{opts} = $extra{opts};
50 52
51 $self->{zero} = pack("x5"); 53 $self->{zero} = pack("x5");
52 54
53 $self->{static_encode} = [ static_table() ]; 55 $self->{static_encode} = [ static_table() ];
124 ('SHA384', 48) : ('SHA256', 32); 126 ('SHA384', 48) : ('SHA256', 32);
125 $self->{es_prk} = Crypt::KeyDerivation::hkdf_extract( 127 $self->{es_prk} = Crypt::KeyDerivation::hkdf_extract(
126 $self->{psk}->{secret} || pack("x$hlen"), pack("x$hlen"), 128 $self->{psk}->{secret} || pack("x$hlen"), pack("x$hlen"),
127 $hash); 129 $hash);
128 Test::Nginx::log_core('||', "es = " . unpack("H*", $self->{es_prk})); 130 Test::Nginx::log_core('||', "es = " . unpack("H*", $self->{es_prk}));
129 $self->{sk} = Crypt::PK::X25519->new->generate_key; 131
132 $self->tls_generate_key();
130 } 133 }
131 134
132 sub initial { 135 sub initial {
133 my ($self) = @_; 136 my ($self) = @_;
134 $self->{tlsm}{ch} = $self->build_tls_client_hello(); 137 $self->{tlsm}{ch} = $self->build_tls_client_hello();
169 + unpack("C*", substr($sh, 6 + 32 + 5, 1)); 172 + unpack("C*", substr($sh, 6 + 32 + 5, 1));
170 my $extens = substr($sh, 6 + 32 + 4 + 2, $extens_len); 173 my $extens = substr($sh, 6 + 32 + 4 + 2, $extens_len);
171 my $pub = key_share($extens); 174 my $pub = key_share($extens);
172 Test::Nginx::log_core('||', "pub = " . unpack("H*", $pub)); 175 Test::Nginx::log_core('||', "pub = " . unpack("H*", $pub));
173 176
174 my $pk = Crypt::PK::X25519->new; 177 my $shared_secret = $self->tls_shared_secret($pub);
175 $pk->import_key_raw($pub, "public");
176 my $shared_secret = $self->{sk}->shared_secret($pk);
177 Test::Nginx::log_core('||', "shared = " . unpack("H*", $shared_secret)); 178 Test::Nginx::log_core('||', "shared = " . unpack("H*", $shared_secret));
178 179
179 # tls13_advance_key_schedule 180 # tls13_advance_key_schedule
180 181
181 my ($hash, $hlen) = $self->{cipher} == 0x1302 ? 182 my ($hash, $hlen) = $self->{cipher} == 0x1302 ?
2305 } 2306 }
2306 } 2307 }
2307 2308
2308 sub build_tls_client_hello { 2309 sub build_tls_client_hello {
2309 my ($self) = @_; 2310 my ($self) = @_;
2310 my $key_share = $self->{sk}->export_key_raw('public'); 2311 my $named_group = $self->tls_named_group();
2312 my $key_share = $self->tls_public_key();
2311 2313
2312 my $version = "\x03\x03"; 2314 my $version = "\x03\x03";
2313 my $random = Crypt::PRNG::random_bytes(32); 2315 my $random = Crypt::PRNG::random_bytes(32);
2314 my $session = "\x00"; 2316 my $session = "\x00";
2315 my $cipher = pack('n', length($self->{ciphers})) . $self->{ciphers}; 2317 my $cipher = pack('n', length($self->{ciphers})) . $self->{ciphers};
2316 my $compr = "\x01\x00"; 2318 my $compr = "\x01\x00";
2317 my $ext = build_tlsext_server_name($self->{sni}) 2319 my $ext = build_tlsext_server_name($self->{sni})
2318 . build_tlsext_supported_groups(29) 2320 . build_tlsext_supported_groups($named_group)
2319 . build_tlsext_alpn("h3", "hq-interop") 2321 . build_tlsext_alpn("h3", "hq-interop")
2320 . build_tlsext_sigalgs(0x0804, 0x0805, 0x0806) 2322 . build_tlsext_sigalgs(0x0804, 0x0805, 0x0806)
2321 . build_tlsext_supported_versions(0x0304) 2323 . build_tlsext_supported_versions(0x0304)
2322 . build_tlsext_ke_modes(1) 2324 . build_tlsext_ke_modes(1)
2323 . build_tlsext_key_share(29, $key_share) 2325 . build_tlsext_key_share($named_group, $key_share)
2324 . build_tlsext_quic_tp($self->{scid}, $self->{opts}); 2326 . build_tlsext_quic_tp($self->{scid}, $self->{opts});
2325 2327
2326 $ext .= build_tlsext_early_data($self->{psk}) 2328 $ext .= build_tlsext_early_data($self->{psk})
2327 . build_tlsext_psk($self->{psk}) if keys %{$self->{psk}}; 2329 . build_tlsext_psk($self->{psk}) if keys %{$self->{psk}};
2328 2330
2418 my $truncated = substr($ch, 0, -3 - $hlen); 2420 my $truncated = substr($ch, 0, -3 - $hlen);
2419 my $context = Crypt::Digest::digest_data($hash, $truncated); 2421 my $context = Crypt::Digest::digest_data($hash, $truncated);
2420 $truncated . binders($hash, $hlen, $key, $context); 2422 $truncated . binders($hash, $hlen, $key, $context);
2421 } 2423 }
2422 2424
2425 sub tls_generate_key {
2426 my ($self) = @_;
2427 $self->{sk} = $self->{group} eq 'x25519'
2428 ? Crypt::PK::X25519->new->generate_key
2429 : Crypt::PK::ECC->new->generate_key($self->{group});
2430 }
2431
2432 sub tls_public_key {
2433 my ($self) = @_;
2434 $self->{sk}->export_key_raw('public');
2435 }
2436
2437 sub tls_shared_secret {
2438 my ($self, $pub) = @_;
2439 my $pk = $self->{group} eq 'x25519'
2440 ? Crypt::PK::X25519->new : Crypt::PK::ECC->new;
2441 $pk->import_key_raw($pub, $self->{group} eq 'x25519'
2442 ? 'public' : $self->{group});
2443 $self->{sk}->shared_secret($pk);
2444 }
2445
2446 sub tls_named_group {
2447 my ($self) = @_;
2448 my $name = $self->{group};
2449 return 0x17 if $name eq 'secp256r1';
2450 return 0x18 if $name eq 'secp384r1';
2451 return 0x19 if $name eq 'secp521r1';
2452 return 0x1d if $name eq 'x25519';
2453 }
2454
2423 ############################################################################### 2455 ###############################################################################
2424 2456
2425 1; 2457 1;
2426 2458
2427 ############################################################################### 2459 ###############################################################################