|
Packit |
b893dc |
#!/usr/bin/perl
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# Various TLS exporter related tests.
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
use strict;
|
|
Packit |
b893dc |
use warnings;
|
|
Packit |
b893dc |
use Test::More;
|
|
Packit |
b893dc |
use Socket;
|
|
Packit |
b893dc |
use File::Spec;
|
|
Packit |
b893dc |
use Net::SSLeay;
|
|
Packit |
b893dc |
use Config;
|
|
Packit |
b893dc |
use IO::Socket::INET;
|
|
Packit |
b893dc |
use Storable;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
BEGIN {
|
|
Packit |
b893dc |
plan skip_all => "fork() not supported on $^O" unless $Config{d_fork};
|
|
Packit |
b893dc |
plan skip_all => "No export_keying_material()" unless defined &Net::SSLeay::export_keying_material;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my $tests = 36;
|
|
Packit |
b893dc |
plan tests => $tests;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my $pid;
|
|
Packit |
b893dc |
alarm(30);
|
|
Packit |
b893dc |
END { kill 9,$pid if $pid }
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my @rounds = qw(TLSv1 TLSv1.1 TLSv1.2 TLSv1.3);
|
|
Packit |
b893dc |
my (%server_stats, %client_stats);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my ($server, $server_ctx, $client_ctx, $server_ssl, $client_ssl);
|
|
Packit |
b893dc |
Net::SSLeay::initialize();
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# Helper for client and server
|
|
Packit |
b893dc |
sub make_ctx
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
my ($round) = @_;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my $ctx;
|
|
Packit |
b893dc |
if ($round =~ /^TLSv1\.3/) {
|
|
Packit |
b893dc |
return undef unless eval { Net::SSLeay::TLS1_3_VERSION(); };
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# Use API introduced in OpenSSL 1.1.0
|
|
Packit |
b893dc |
$ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_method());
|
|
Packit |
b893dc |
Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION());
|
|
Packit |
b893dc |
Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION());
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
elsif ($round =~ /^TLSv1\.2/) {
|
|
Packit |
b893dc |
return undef unless exists &Net::SSLeay::TLSv1_2_method;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_2_method());
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
elsif ($round =~ /^TLSv1\.1/) {
|
|
Packit |
b893dc |
return undef unless exists &Net::SSLeay::TLSv1_1_method;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_1_method());
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
else
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
$ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_method());
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
return $ctx;
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
sub server
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
# SSL server - just handle connections, write, wait for read and repeat
|
|
Packit |
b893dc |
my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem');
|
|
Packit |
b893dc |
my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem');
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3)
|
|
Packit |
b893dc |
or BAIL_OUT("failed to create server socket: $!");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
defined($pid = fork()) or BAIL_OUT("failed to fork: $!");
|
|
Packit |
b893dc |
if ($pid == 0) {
|
|
Packit |
b893dc |
my ($ctx, $ssl, $ret, $cl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
foreach my $round (@rounds)
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
$cl = $server->accept or BAIL_OUT("accept failed: $!");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$ctx = make_ctx($round);
|
|
Packit |
b893dc |
next unless $ctx;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem);
|
|
Packit |
b893dc |
$ssl = Net::SSLeay::new($ctx);
|
|
Packit |
b893dc |
Net::SSLeay::set_fd($ssl, fileno($cl));
|
|
Packit |
b893dc |
Net::SSLeay::accept($ssl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
Net::SSLeay::write($ssl, $round);
|
|
Packit |
b893dc |
my $msg = Net::SSLeay::read($ssl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
Net::SSLeay::shutdown($ssl);
|
|
Packit |
b893dc |
Net::SSLeay::free($ssl);
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
exit(0);
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
sub client {
|
|
Packit |
b893dc |
# SSL client - connect to server, read, test and repeat
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my $saddr = $server->sockhost.':'.$server->sockport;
|
|
Packit |
b893dc |
my ($ctx, $ssl, $ret, $cl);
|
|
Packit |
b893dc |
my $end = "end";
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
foreach my $round (@rounds)
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
$cl = IO::Socket::INET->new($saddr)
|
|
Packit |
b893dc |
or BAIL_OUT("failed to connect to server: $!");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$ctx = make_ctx($round);
|
|
Packit |
b893dc |
unless($ctx) {
|
|
Packit |
b893dc |
SKIP: {
|
|
Packit |
b893dc |
skip("Skipping round $round", 9);
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
next;
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$ssl = Net::SSLeay::new($ctx);
|
|
Packit |
b893dc |
Net::SSLeay::set_fd($ssl, $cl);
|
|
Packit |
b893dc |
Net::SSLeay::connect($ssl);
|
|
Packit |
b893dc |
my $msg = Net::SSLeay::read($ssl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
test_export($ssl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
Net::SSLeay::write($ssl, $msg);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
Net::SSLeay::shutdown($ssl);
|
|
Packit |
b893dc |
Net::SSLeay::free($ssl);
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
return;
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
sub test_export
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
my ($ssl) = @_;
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my ($bytes1_0, $bytes1_1, $bytes1_2, $bytes1_3, $bytes2_0, $bytes2_2_64);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
my $tls_version = Net::SSLeay::get_version($ssl);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$bytes1_0 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1');
|
|
Packit |
b893dc |
$bytes1_1 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', undef);
|
|
Packit |
b893dc |
$bytes1_2 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', '');
|
|
Packit |
b893dc |
$bytes1_3 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', 'context');
|
|
Packit |
b893dc |
$bytes2_0 = Net::SSLeay::export_keying_material($ssl, 128, 'label 1', '');
|
|
Packit |
b893dc |
$bytes2_2_64 = substr($bytes2_0, 0, 64);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
is(length($bytes1_0), 64, "$tls_version: Got enough for bytes1_0");
|
|
Packit |
b893dc |
is(length($bytes1_1), 64, "$tls_version: Got enough for bytes1_1");
|
|
Packit |
b893dc |
is(length($bytes1_2), 64, "$tls_version: Got enough for bytes1_2");
|
|
Packit |
b893dc |
is(length($bytes1_3), 64, "$tls_version: Got enough for bytes1_3");
|
|
Packit |
b893dc |
is(length($bytes2_0), 128, "$tls_version: Got enough for bytes2_0");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
$bytes1_0 = unpack('H*', $bytes1_0);
|
|
Packit |
b893dc |
$bytes1_1 = unpack('H*', $bytes1_1);
|
|
Packit |
b893dc |
$bytes1_2 = unpack('H*', $bytes1_2);
|
|
Packit |
b893dc |
$bytes1_3 = unpack('H*', $bytes1_3);
|
|
Packit |
b893dc |
$bytes2_0 = unpack('H*', $bytes2_0);
|
|
Packit |
b893dc |
$bytes2_2_64 = unpack('H*', $bytes2_2_64);
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# Last argument should default to undef
|
|
Packit |
b893dc |
is($bytes1_0, $bytes1_1, "$tls_version: context default param is undef");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# Empty and undefined context are the same for TLSv1.3.
|
|
Packit |
b893dc |
# Different length export changes the whole values for TLSv1.3.
|
|
Packit |
b893dc |
if ($tls_version eq 'TLSv1.3') {
|
|
Packit |
b893dc |
is($bytes1_0, $bytes1_2, "$tls_version: empty and undefined context yields equal values");
|
|
Packit |
b893dc |
isnt($bytes2_2_64, $bytes1_2, "$tls_version: export length does matter");
|
|
Packit |
b893dc |
} else {
|
|
Packit |
b893dc |
isnt($bytes1_0, $bytes1_2, "$tls_version: empty and undefined context yields different values");
|
|
Packit |
b893dc |
is($bytes2_2_64, $bytes1_2, "$tls_version: export length does not matter");
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
isnt($bytes1_3, $bytes1_0, "$tls_version: different context");
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
return;
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
# For SSL_export_keying_material_early available with TLSv1.3
|
|
Packit |
b893dc |
sub test_export_early
|
|
Packit |
b893dc |
{
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
return;
|
|
Packit |
b893dc |
}
|
|
Packit |
b893dc |
|
|
Packit |
b893dc |
server();
|
|
Packit |
b893dc |
client();
|
|
Packit |
b893dc |
waitpid $pid, 0;
|
|
Packit |
b893dc |
exit(0);
|