Skip to content

Commit b8b69c8

Browse files
committed
Tests: test for loading "store:..." keys.
1 parent c747dfa commit b8b69c8

File tree

2 files changed

+362
-0
lines changed

2 files changed

+362
-0
lines changed

ssl_provider_keys.t

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Sergey Kandaurov
4+
# (C) Aleksei Bavshin
5+
# (C) Nginx, Inc.
6+
7+
# Tests for http ssl module, loading "store:..." keys from OpenSSL providers.
8+
9+
# Test prerequisites:
10+
# * OpenSSL >= 3
11+
# * softhsm2
12+
# * opensc
13+
# * pkcs11-provider (https://github.com/latchset/pkcs11-provider)
14+
15+
###############################################################################
16+
17+
use warnings;
18+
use strict;
19+
20+
use Test::More;
21+
22+
BEGIN { use FindBin; chdir($FindBin::Bin); }
23+
24+
use lib 'lib';
25+
use Test::Nginx;
26+
27+
###############################################################################
28+
29+
select STDERR; $| = 1;
30+
select STDOUT; $| = 1;
31+
32+
plan(skip_all => 'win32') if $^O eq 'MSWin32';
33+
34+
plan(skip_all => 'may not work, leaves coredump')
35+
unless $ENV{TEST_NGINX_UNSAFE};
36+
37+
my $t = Test::Nginx->new()->has(qw/http proxy http_ssl openssl:3/)
38+
->has_daemon('openssl')->has_daemon('softhsm2-util')
39+
->has_daemon('pkcs11-tool');
40+
41+
plan(skip_all => "not yet") unless $t->has_version('1.29.0');
42+
43+
$t->write_file_expand('nginx.conf', <<'EOF');
44+
45+
%%TEST_GLOBALS%%
46+
47+
daemon off;
48+
49+
events {
50+
}
51+
52+
env SOFTHSM2_CONF;
53+
env OPENSSL_CONF;
54+
55+
http {
56+
%%TEST_GLOBALS_HTTP%%
57+
58+
server {
59+
listen 127.0.0.1:8081 ssl;
60+
listen 127.0.0.1:8080;
61+
server_name localhost;
62+
63+
ssl_certificate localhost.crt;
64+
ssl_certificate_key "store:pkcs11:token=NginxZero;object=nx_key_0";
65+
66+
location / {
67+
# index index.html by default
68+
}
69+
70+
location /proxy {
71+
proxy_pass https://127.0.0.1:8081/;
72+
}
73+
74+
location /var {
75+
proxy_pass https://127.0.0.1:8082/;
76+
proxy_ssl_name localhost;
77+
proxy_ssl_server_name on;
78+
}
79+
}
80+
81+
server {
82+
listen 127.0.0.1:8082 ssl;
83+
server_name localhost;
84+
85+
ssl_certificate $ssl_server_name.crt;
86+
ssl_certificate_key "store:pkcs11:token=NginxZero;object=nx_key_0";
87+
88+
location / {
89+
# index index.html by default
90+
}
91+
}
92+
}
93+
94+
EOF
95+
96+
# Create a SoftHSM token with a secret key, and configure OpenSSL
97+
# to access it using the pkcs11 provider.
98+
#
99+
# Note that library paths vary on different systems,
100+
# and may need to be adjusted.
101+
102+
my $libsofthsm2_path;
103+
my @so_paths = (
104+
'/usr/lib/softhsm', # Debian-based
105+
'/usr/local/lib/softhsm', # FreeBSD
106+
'/opt/local/lib/softhsm', # MacPorts
107+
'/lib64', # RHEL-based
108+
split /:/, $ENV{TEST_NGINX_SOFTHSM} || ''
109+
);
110+
111+
for my $so_path (@so_paths) {
112+
$so_path .= '/libsofthsm2.so';
113+
if (-e $so_path) {
114+
$libsofthsm2_path = $so_path;
115+
last;
116+
}
117+
};
118+
119+
plan(skip_all => "libsofthsm2.so not found") unless $libsofthsm2_path;
120+
121+
my $d = $t->testdir();
122+
123+
$t->write_file('openssl.conf', <<EOF);
124+
openssl_conf = openssl_def
125+
126+
[openssl_def]
127+
providers = provider_sect
128+
129+
[provider_sect]
130+
default = default_sect
131+
pkcs11 = pkcs11_sect
132+
133+
[default_sect]
134+
activate = 1
135+
136+
[pkcs11_sect]
137+
pkcs11-module-path = $libsofthsm2_path
138+
pkcs11-module-token-pin = file:$d/pin.txt
139+
# https://github.com/latchset/pkcs11-provider/commit/ab6370fd
140+
pkcs11-module-quirks = no-deinit no-operation-state
141+
activate = 1
142+
143+
[ req ]
144+
default_bits = 2048
145+
encrypt_key = no
146+
distinguished_name = req_distinguished_name
147+
[ req_distinguished_name ]
148+
EOF
149+
150+
$t->write_file('pin.txt', '1234');
151+
152+
$t->write_file('softhsm2.conf', <<EOF);
153+
directories.tokendir = $d/tokens/
154+
objectstore.backend = file
155+
EOF
156+
157+
mkdir($d . '/tokens');
158+
159+
$ENV{SOFTHSM2_CONF} = "$d/softhsm2.conf";
160+
$ENV{OPENSSL_CONF} = "$d/openssl.conf";
161+
162+
foreach my $name ('localhost') {
163+
system('softhsm2-util --init-token --slot 0 --label NginxZero '
164+
. '--pin 1234 --so-pin 1234 '
165+
. ">>$d/openssl.out 2>&1");
166+
167+
system("pkcs11-tool --module=$libsofthsm2_path "
168+
. '-p 1234 -l -k -d 0 -a nx_key_0 --key-type rsa:2048 '
169+
. ">>$d/openssl.out 2>&1");
170+
171+
system('openssl req -x509 -new '
172+
. "-subj /CN=$name/ -out $d/$name.crt -text "
173+
. "-key 'pkcs11:token=NginxZero;object=nx_key_0' "
174+
. ">>$d/openssl.out 2>&1") == 0
175+
or plan(skip_all => "missing pkcs11-provider");
176+
}
177+
178+
$t->run()->plan(2);
179+
180+
$t->write_file('index.html', '');
181+
182+
###############################################################################
183+
184+
like(http_get('/proxy'), qr/200 OK/, 'ssl provider keys');
185+
like(http_get('/var'), qr/200 OK/, 'ssl_certificate with variable');
186+
187+
###############################################################################

ssl_store_keys.t

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
2+
#!/usr/bin/perl
3+
4+
# (C) Aleksei Bavshin
5+
# (C) Nginx, Inc.
6+
7+
# Tests for http ssl module, loading "store:..." keys.
8+
9+
###############################################################################
10+
11+
use warnings;
12+
use strict;
13+
14+
use Test::More;
15+
16+
BEGIN { use FindBin; chdir($FindBin::Bin); }
17+
18+
use lib 'lib';
19+
use Test::Nginx qw/ :DEFAULT http_end /;
20+
21+
###############################################################################
22+
23+
select STDERR; $| = 1;
24+
select STDOUT; $| = 1;
25+
26+
my $t = Test::Nginx->new()
27+
->has(qw/http http_ssl geo openssl:1.1.1 socket_ssl_sni/)
28+
->has_daemon('openssl');
29+
30+
plan(skip_all => 'BoringSSL') if $t->has_module('BoringSSL|AWS-LC');
31+
plan(skip_all => 'not yet') unless $t->has_version('1.29.0');
32+
33+
$t->write_file_expand('nginx.conf', <<'EOF');
34+
35+
%%TEST_GLOBALS%%
36+
37+
daemon off;
38+
39+
events {
40+
}
41+
42+
http {
43+
%%TEST_GLOBALS_HTTP%%
44+
45+
geo $localhost {
46+
default localhost;
47+
}
48+
49+
geo $pass {
50+
default pass;
51+
}
52+
53+
add_header X-SSL $ssl_server_name;
54+
55+
server {
56+
listen 127.0.0.1:8080 ssl;
57+
server_name default;
58+
59+
ssl_certificate localhost.crt;
60+
ssl_certificate_key store:file:%%TESTDIR%%/localhost.key;
61+
}
62+
63+
server {
64+
listen 127.0.0.1:8080 ssl;
65+
server_name variable;
66+
67+
ssl_certificate localhost.crt;
68+
ssl_certificate_key store:file:%%TESTDIR%%/$localhost.key;
69+
}
70+
71+
server {
72+
listen 127.0.0.1:8080 ssl;
73+
server_name pass;
74+
75+
ssl_certificate pass.crt;
76+
ssl_certificate_key store:file:%%TESTDIR%%/pass.key;
77+
78+
ssl_password_file password;
79+
}
80+
81+
server {
82+
listen 127.0.0.1:8080 ssl;
83+
server_name variable-pass;
84+
85+
ssl_certificate pass.crt;
86+
ssl_certificate_key store:file:%%TESTDIR%%/$pass.key;
87+
88+
ssl_password_file password;
89+
}
90+
91+
server {
92+
listen 127.0.0.1:8080 ssl;
93+
server_name variable-no-pass;
94+
95+
ssl_certificate pass.crt;
96+
ssl_certificate_key store:file:%%TESTDIR%%/$pass.key;
97+
}
98+
}
99+
100+
EOF
101+
102+
$t->write_file('openssl.conf', <<EOF);
103+
[ req ]
104+
default_bits = 2048
105+
encrypt_key = no
106+
distinguished_name = req_distinguished_name
107+
[ req_distinguished_name ]
108+
EOF
109+
110+
my $d = $t->testdir();
111+
112+
foreach my $name ('localhost') {
113+
system('openssl req -x509 -new '
114+
. "-config $d/openssl.conf -subj /CN=$name/ "
115+
. "-out $d/$name.crt -keyout $d/$name.key "
116+
. ">>$d/openssl.out 2>&1") == 0
117+
or die "Can't create certificate for $name: $!\n";
118+
}
119+
120+
foreach my $name ('pass') {
121+
system("openssl genrsa -out $d/$name.key -passout pass:$name "
122+
. "-aes128 2048 >>$d/openssl.out 2>&1") == 0
123+
or die "Can't create private key: $!\n";
124+
system('openssl req -x509 -new '
125+
. "-config $d/openssl.conf -subj /CN=$name/ "
126+
. "-out $d/$name.crt "
127+
. "-key $d/$name.key -passin pass:$name"
128+
. ">>$d/openssl.out 2>&1") == 0
129+
or die "Can't create certificate for $name: $!\n";
130+
}
131+
132+
133+
$t->write_file('password', 'pass');
134+
$t->write_file('index.html', '');
135+
136+
$t->run()->plan(9);
137+
138+
###############################################################################
139+
140+
like(cert('default'), qr/CN=localhost/, 'default key');
141+
like(get('default'), qr/default/, 'default context');
142+
143+
like(cert('variable'), qr/CN=localhost/, 'key with vars');
144+
like(get('variable'), qr/variable/, 'context with vars');
145+
146+
like(cert('pass'), qr/CN=pass/, 'encrypted key');
147+
like(get('pass'), qr/pass/, 'encrypted context');
148+
149+
like(cert('variable-pass'), qr/CN=pass/, 'encrypted key - vars');
150+
like(get('variable-pass'), qr/variable-pass/, 'encrypted context - vars');
151+
152+
is(cert('variable-no-pass'), undef, 'encrypted key - no pass');
153+
154+
###############################################################################
155+
156+
sub get {
157+
my $s = get_socket(@_) || return;
158+
return http_end($s);
159+
}
160+
161+
sub cert {
162+
my $s = get_socket(@_) || return;
163+
return $s->dump_peer_certificate();
164+
}
165+
166+
sub get_socket {
167+
my ($host) = @_;
168+
return http_get(
169+
'/', start => 1, PeerAddr => '127.0.0.1:' . port(8080),
170+
SSL => 1,
171+
SSL_hostname => $host,
172+
);
173+
}
174+
175+
###############################################################################

0 commit comments

Comments
 (0)