2 # Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
4 # Licensed under the OpenSSL license (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
12 use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file data_file);
13 use OpenSSL::Test::Utils;
15 my $test_name = "test_store";
18 # The MSYS2 run-time convert arguments that look like paths when executing
19 # a program unless that application is linked with the MSYS run-time. The
20 # exact conversion rules are listed here:
22 # http://www.mingw.org/wiki/Posix_path_conversion
24 # With the built-in configurations (all having names starting with "mingw"),
25 # the openssl application is not linked with the MSYS2 run-time, and therefore,
26 # it will receive possibly converted arguments from the process that executes
27 # it. This conversion is fine for normal path arguments, but when those
28 # arguments are URIs, they sometimes aren't converted right (typically for
29 # URIs without an authority component, 'cause the conversion mechanism doesn't
30 # recognise them as URIs) or aren't converted at all (which gives perfectly
31 # normal absolute paths from the MSYS viewpoint, but don't work for the
32 # Windows run-time we're linked with).
34 # It's also possible to avoid conversion by defining MSYS2_ARG_CONV_EXCL with
35 # some suitable pattern ("*" to avoid conversions entirely), but that will
36 # again give us unconverted paths that don't work with the Windows run-time
39 # Checking for both msys perl operating environment and that the target name
40 # starts with "mingw", we're doing what we can to assure that other configs
41 # that might link openssl.exe with the MSYS run-time are not disturbed.
42 my $msys_mingw = ($^O eq 'msys') && (config('target') =~ m|^mingw|);
45 ( "test/blahdiblah.pem",
46 "test/blahdibleh.der" );
48 ( "test/testx509.pem",
50 "test/testrsapub.pem",
55 ### generated from the source files
64 "rsa-key-pkcs1.pem", "rsa-key-pkcs1.der",
65 "rsa-key-pkcs1-aes128.pem",
66 "rsa-key-pkcs8.pem", "rsa-key-pkcs8.der",
67 "rsa-key-pkcs8-pbes1-sha1-3des.pem", "rsa-key-pkcs8-pbes1-sha1-3des.der",
68 "rsa-key-pkcs8-pbes2-sha1.pem", "rsa-key-pkcs8-pbes2-sha1.der",
69 "rsa-key-sha1-3des-sha1.p12", "rsa-key-sha1-3des-sha256.p12",
70 "rsa-key-aes256-cbc-sha256.p12",
71 "rsa-key-md5-des-sha1.p12",
72 "rsa-key-aes256-cbc-md5-des-sha256.p12",
73 "rsa-key-pkcs8-pbes2-sha256.pem", "rsa-key-pkcs8-pbes2-sha256.der",
74 "rsa-key-pkcs8-pbes1-md5-des.pem", "rsa-key-pkcs8-pbes1-md5-des.der",
75 "dsa-key-pkcs1.pem", "dsa-key-pkcs1.der",
76 "dsa-key-pkcs1-aes128.pem",
77 "dsa-key-pkcs8.pem", "dsa-key-pkcs8.der",
78 "dsa-key-pkcs8-pbes2-sha1.pem", "dsa-key-pkcs8-pbes2-sha1.der",
79 "dsa-key-aes256-cbc-sha256.p12",
80 "ec-key-pkcs1.pem", "ec-key-pkcs1.der",
81 "ec-key-pkcs1-aes128.pem",
82 "ec-key-pkcs8.pem", "ec-key-pkcs8.der",
83 "ec-key-pkcs8-pbes2-sha1.pem", "ec-key-pkcs8-pbes2-sha1.der",
84 "ec-key-aes256-cbc-sha256.p12",
86 my %generated_file_files =
88 ? ( "test/testx509.pem" => "file:testx509.pem",
89 "test/testrsa.pem" => "file:testrsa.pem",
90 "test/testrsapub.pem" => "file:testrsapub.pem",
91 "test/testcrl.pem" => "file:testcrl.pem",
92 "apps/server.pem" => "file:server.pem" )
94 my @noexist_file_files =
95 ( "file:blahdiblah.pem",
96 "file:test/blahdibleh.der" );
99 my $n = (3 * scalar @noexist_files)
100 + (6 * scalar @src_files)
101 + (4 * scalar @generated_files)
102 + (scalar keys %generated_file_files)
103 + (scalar @noexist_file_files)
108 indir "store_$$" => sub {
111 skip "failed initialisation", $n unless init();
113 # test PEM_read_bio_PrivateKey
114 ok(run(app(["openssl", "rsa", "-in", "rsa-key-pkcs8-pbes2-sha256.pem",
115 "-passin", "pass:password"])));
117 foreach (@noexist_files) {
118 my $file = srctop_file($_);
120 ok(!run(app(["openssl", "storeutl", $file])));
121 ok(!run(app(["openssl", "storeutl", to_abs_file($file)])));
123 skip "No test of URI form of $file for mingw", 1 if $msys_mingw;
125 ok(!run(app(["openssl", "storeutl", to_abs_file_uri($file)])));
128 foreach (@src_files) {
129 my $file = srctop_file($_);
131 ok(run(app(["openssl", "storeutl", $file])));
132 ok(run(app(["openssl", "storeutl", to_abs_file($file)])));
134 skip "No test of URI form of $file for mingw", 4 if $msys_mingw;
136 ok(run(app(["openssl", "storeutl", to_abs_file_uri($file)])));
137 ok(run(app(["openssl", "storeutl",
138 to_abs_file_uri($file, 0, "")])));
139 ok(run(app(["openssl", "storeutl",
140 to_abs_file_uri($file, 0, "localhost")])));
141 ok(!run(app(["openssl", "storeutl",
142 to_abs_file_uri($file, 0, "dummy")])));
145 foreach (@generated_files) {
147 ok(run(app(["openssl", "storeutl", "-passin", "pass:password",
149 ok(run(app(["openssl", "storeutl", "-passin", "pass:password",
152 skip "No test of URI form of $_ for mingw", 2 if $msys_mingw;
154 ok(run(app(["openssl", "storeutl", "-passin", "pass:password",
155 to_abs_file_uri($_)])));
156 ok(!run(app(["openssl", "storeutl", "-passin", "pass:password",
160 foreach (values %generated_file_files) {
162 skip "No test of $_ for mingw", 1 if $msys_mingw;
164 ok(run(app(["openssl", "storeutl", $_])));
167 foreach (@noexist_file_files) {
169 skip "No test of $_ for mingw", 1 if $msys_mingw;
171 ok(!run(app(["openssl", "storeutl", $_])));
175 my $dir = srctop_dir("test", "certs");
177 ok(run(app(["openssl", "storeutl", $dir])));
178 ok(run(app(["openssl", "storeutl", to_abs_file($dir, 1)])));
180 skip "No test of URI form of $dir for mingw", 1 if $msys_mingw;
182 ok(run(app(["openssl", "storeutl", to_abs_file_uri($dir, 1)])));
186 }, create => 1, cleanup => 1;
191 run(app(["openssl", "genrsa",
192 "-out", "rsa-key-pkcs1.pem", "2432"]))
194 && run(app(["openssl", "dsaparam", "-genkey",
195 "-out", "dsa-key-pkcs1.pem", "1024"]))
196 # ec-key-pkcs1.pem (one might think that 'genec' would be practical)
197 && run(app(["openssl", "ecparam", "-genkey", "-name", "prime256v1",
198 "-out", "ec-key-pkcs1.pem"]))
199 # rsa-key-pkcs1-aes128.pem
200 && run(app(["openssl", "rsa", "-passout", "pass:password", "-aes128",
201 "-in", "rsa-key-pkcs1.pem",
202 "-out", "rsa-key-pkcs1-aes128.pem"]))
203 # dsa-key-pkcs1-aes128.pem
204 && run(app(["openssl", "dsa", "-passout", "pass:password", "-aes128",
205 "-in", "dsa-key-pkcs1.pem",
206 "-out", "dsa-key-pkcs1-aes128.pem"]))
207 # ec-key-pkcs1-aes128.pem
208 && run(app(["openssl", "ec", "-passout", "pass:password", "-aes128",
209 "-in", "ec-key-pkcs1.pem",
210 "-out", "ec-key-pkcs1-aes128.pem"]))
214 (my $srcfile = $dstfile)
215 =~ s/-key-pkcs8\.pem$/-key-pkcs1.pem/i;
216 run(app(["openssl", "pkcs8", "-topk8", "-nocrypt",
217 "-in", $srcfile, "-out", $dstfile]));
218 }, grep(/-key-pkcs8\.pem$/, @generated_files))
219 # *-key-pkcs8-pbes1-sha1-3des.pem
222 (my $srcfile = $dstfile)
223 =~ s/-key-pkcs8-pbes1-sha1-3des\.pem$
225 run(app(["openssl", "pkcs8", "-topk8",
226 "-passout", "pass:password",
227 "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC",
228 "-in", $srcfile, "-out", $dstfile]));
229 }, grep(/-key-pkcs8-pbes1-sha1-3des\.pem$/, @generated_files))
230 # *-key-pkcs8-pbes1-md5-des.pem
233 (my $srcfile = $dstfile)
234 =~ s/-key-pkcs8-pbes1-md5-des\.pem$
236 run(app(["openssl", "pkcs8", "-topk8",
237 "-passout", "pass:password",
238 "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC",
239 "-in", $srcfile, "-out", $dstfile]));
240 }, grep(/-key-pkcs8-pbes1-md5-des\.pem$/, @generated_files))
241 # *-key-pkcs8-pbes2-sha1.pem
244 (my $srcfile = $dstfile)
245 =~ s/-key-pkcs8-pbes2-sha1\.pem$
247 run(app(["openssl", "pkcs8", "-topk8",
248 "-passout", "pass:password",
249 "-v2", "aes256", "-v2prf", "hmacWithSHA1",
250 "-in", $srcfile, "-out", $dstfile]));
251 }, grep(/-key-pkcs8-pbes2-sha1\.pem$/, @generated_files))
252 # *-key-pkcs8-pbes2-sha1.pem
255 (my $srcfile = $dstfile)
256 =~ s/-key-pkcs8-pbes2-sha256\.pem$
258 run(app(["openssl", "pkcs8", "-topk8",
259 "-passout", "pass:password",
260 "-v2", "aes256", "-v2prf", "hmacWithSHA256",
261 "-in", $srcfile, "-out", $dstfile]));
262 }, grep(/-key-pkcs8-pbes2-sha256\.pem$/, @generated_files))
263 # *-cert.pem (intermediary for the .p12 inits)
264 && run(app(["openssl", "req", "-x509",
265 "-config", data_file("ca.cnf"), "-nodes",
266 "-out", "cacert.pem", "-keyout", "cakey.pem"]))
269 (my $dstfile = $srckey) =~ s|-key-pkcs8\.|-cert.|;
270 (my $csr = $dstfile) =~ s|\.pem|.csr|;
272 (run(app(["openssl", "req", "-new",
273 "-config", data_file("user.cnf"),
274 "-key", $srckey, "-out", $csr]))
276 run(app(["openssl", "x509", "-days", "3650",
278 "-CAkey", "cakey.pem",
279 "-set_serial", time(), "-req",
280 "-in", $csr, "-out", $dstfile])));
281 }, grep(/-key-pkcs8\.pem$/, @generated_files))
285 my ($type, $certpbe_index, $keypbe_index,
287 $dstfile =~ m{^(.*)-key-(?|
288 # cert and key PBE are same
290 ([^-]*-[^-]*)- # key & cert PBE
293 # cert and key PBE are not same
294 ([^-]*-[^-]*)- # cert PBE
295 ([^-]*-[^-]*)- # key PBE
298 if (!$certpbe_index) {
299 $certpbe_index = $keypbe_index;
301 my $srckey = "$type-key-pkcs8.pem";
302 my $srccert = "$type-cert.pem";
305 "sha1-3des" => "pbeWithSHA1And3-KeyTripleDES-CBC",
306 "md5-des" => "pbeWithMD5AndDES-CBC",
307 "aes256-cbc" => "AES-256-CBC",
312 "sha256" => "SHA256",
314 my $certpbe = $pbes{$certpbe_index};
315 my $keypbe = $pbes{$keypbe_index};
316 my $macalg = $macalgs{$macalg_index};
317 if (!defined($certpbe) || !defined($keypbe)
318 || !defined($macalg)) {
319 print STDERR "Cert PBE for $pbe_index not defined\n"
320 unless defined $certpbe;
321 print STDERR "Key PBE for $pbe_index not defined\n"
322 unless defined $keypbe;
323 print STDERR "MACALG for $macalg_index not defined\n"
324 unless defined $macalg;
325 print STDERR "(destination file was $dstfile)\n";
328 run(app(["openssl", "pkcs12", "-inkey", $srckey,
329 "-in", $srccert, "-passout", "pass:password",
330 "-export", "-macalg", $macalg,
331 "-certpbe", $certpbe, "-keypbe", $keypbe,
333 }, grep(/\.p12/, @generated_files))
334 # *.der (the end all init)
337 (my $srcfile = $dstfile) =~ s/\.der$/.pem/i;
339 $srcfile = srctop_file("test", $srcfile);
342 unless (open $infh, $srcfile) {
346 while (($l = <$infh>) !~ /^-----BEGIN\s/
347 || $l =~ /^-----BEGIN.*PARAMETERS-----/) {
350 while (($l = <$infh>) !~ /^-----END\s/) {
352 $b64 .= $l unless $l =~ /:/;
355 my $der = decode_base64($b64);
356 unless (length($b64) / 4 * 3 - length($der) < 3) {
357 print STDERR "Length error, ",length($b64),
358 " bytes of base64 became ",length($der),
359 " bytes of der? ($srcfile => $dstfile)\n";
363 unless (open $outfh, ">:raw", $dstfile) {
369 }, grep(/\.der$/, @generated_files))
372 my $dstfile = $generated_file_files{$srcfile};
374 unless (copy srctop_file($srcfile), $dstfile) {
379 }, keys %generated_file_files)
384 my ($function, @items) = @_;
387 return 0 unless $function->($_);
392 # According to RFC8089, a relative file: path is invalid. We still produce
393 # them for testing purposes.
395 my ($file, $isdir, $authority) = @_;
399 die "to_file_uri: No file given\n" if !defined($file) || $file eq '';
401 ($vol, $dir, $file) = File::Spec->splitpath($file, $isdir // 0);
403 # Make sure we have a Unix style directory.
404 $dir = join('/', File::Spec->splitdir($dir));
405 # Canonicalise it (note: it seems to be only needed on Unix)
408 $newdir =~ s|/[^/]*[^/\.]+[^/]*/\.\./|/|g;
409 last if $newdir eq $dir;
412 # Take care of the corner cases the loop can't handle, and that $dir
413 # ends with a / unless it's empty
414 $dir =~ s|/[^/]*[^/\.]+[^/]*/\.\.$|/|;
415 $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\./|/|;
416 $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\.$||;
418 $dir =~ s|/$|| if $dir ne '/';
420 $dir .= '/' if $dir ne '' && $dir !~ m|/$|;
423 # If the file system has separate volumes (at present, Windows and VMS)
424 # we need to handle them. In URIs, they are invariably the first
425 # component of the path, which is always absolute.
426 # On VMS, user:[foo.bar] translates to /user/foo/bar
427 # On Windows, c:\Users\Foo translates to /c:/Users/Foo
429 $vol =~ s|:||g if ($^O eq "VMS");
430 $dir = '/' . $dir if $dir ne '' && $dir !~ m|^/|;
431 $dir = '/' . $vol . $dir;
433 $file = $dir . $file;
435 return "file://$authority$file" if defined $authority;
442 return File::Spec->rel2abs($file);
445 sub to_abs_file_uri {
446 my ($file, $isdir, $authority) = @_;
448 die "to_abs_file_uri: No file given\n" if !defined($file) || $file eq '';
449 return to_file_uri(to_abs_file($file), $isdir, $authority);