90-test_store.t revision 1.1.1.1
1#! /usr/bin/env perl 2# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. 3# 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 8 9use File::Spec::Functions; 10use File::Copy; 11use MIME::Base64; 12use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file data_file); 13use OpenSSL::Test::Utils; 14 15my $test_name = "test_store"; 16setup($test_name); 17 18my $mingw = config('target') =~ m|^mingw|; 19 20my @noexist_files = 21 ( "test/blahdiblah.pem", 22 "test/blahdibleh.der" ); 23my @src_files = 24 ( "test/testx509.pem", 25 "test/testrsa.pem", 26 "test/testrsapub.pem", 27 "test/testcrl.pem", 28 "apps/server.pem" ); 29my @generated_files = 30 ( 31 ### generated from the source files 32 33 "testx509.der", 34 "testrsa.der", 35 "testrsapub.der", 36 "testcrl.der", 37 38 ### generated locally 39 40 "rsa-key-pkcs1.pem", "rsa-key-pkcs1.der", 41 "rsa-key-pkcs1-aes128.pem", 42 "rsa-key-pkcs8.pem", "rsa-key-pkcs8.der", 43 "rsa-key-pkcs8-pbes1-sha1-3des.pem", "rsa-key-pkcs8-pbes1-sha1-3des.der", 44 "rsa-key-pkcs8-pbes2-sha1.pem", "rsa-key-pkcs8-pbes2-sha1.der", 45 "rsa-key-sha1-3des-sha1.p12", "rsa-key-sha1-3des-sha256.p12", 46 "rsa-key-aes256-cbc-sha256.p12", 47 "rsa-key-md5-des-sha1.p12", 48 "rsa-key-aes256-cbc-md5-des-sha256.p12", 49 "rsa-key-pkcs8-pbes2-sha256.pem", "rsa-key-pkcs8-pbes2-sha256.der", 50 "rsa-key-pkcs8-pbes1-md5-des.pem", "rsa-key-pkcs8-pbes1-md5-des.der", 51 "dsa-key-pkcs1.pem", "dsa-key-pkcs1.der", 52 "dsa-key-pkcs1-aes128.pem", 53 "dsa-key-pkcs8.pem", "dsa-key-pkcs8.der", 54 "dsa-key-pkcs8-pbes2-sha1.pem", "dsa-key-pkcs8-pbes2-sha1.der", 55 "dsa-key-aes256-cbc-sha256.p12", 56 "ec-key-pkcs1.pem", "ec-key-pkcs1.der", 57 "ec-key-pkcs1-aes128.pem", 58 "ec-key-pkcs8.pem", "ec-key-pkcs8.der", 59 "ec-key-pkcs8-pbes2-sha1.pem", "ec-key-pkcs8-pbes2-sha1.der", 60 "ec-key-aes256-cbc-sha256.p12", 61 ); 62my %generated_file_files = 63 $^O eq 'linux' 64 ? ( "test/testx509.pem" => "file:testx509.pem", 65 "test/testrsa.pem" => "file:testrsa.pem", 66 "test/testrsapub.pem" => "file:testrsapub.pem", 67 "test/testcrl.pem" => "file:testcrl.pem", 68 "apps/server.pem" => "file:server.pem" ) 69 : (); 70my @noexist_file_files = 71 ( "file:blahdiblah.pem", 72 "file:test/blahdibleh.der" ); 73 74my $n = (3 * scalar @noexist_files) 75 + (6 * scalar @src_files) 76 + (4 * scalar @generated_files) 77 + (scalar keys %generated_file_files) 78 + (scalar @noexist_file_files) 79 + 3 80 + 11; 81 82plan tests => $n; 83 84indir "store_$$" => sub { 85 SKIP: 86 { 87 skip "failed initialisation", $n unless init(); 88 89 my $rehash = init_rehash(); 90 91 foreach (@noexist_files) { 92 my $file = srctop_file($_); 93 94 ok(!run(app(["openssl", "storeutl", "-noout", $file]))); 95 ok(!run(app(["openssl", "storeutl", "-noout", 96 to_abs_file($file)]))); 97 { 98 local $ENV{MSYS2_ARG_CONV_EXCL} = "file:"; 99 100 ok(!run(app(["openssl", "storeutl", "-noout", 101 to_abs_file_uri($file)]))); 102 } 103 } 104 foreach (@src_files) { 105 my $file = srctop_file($_); 106 107 ok(run(app(["openssl", "storeutl", "-noout", $file]))); 108 ok(run(app(["openssl", "storeutl", "-noout", to_abs_file($file)]))); 109 SKIP: 110 { 111 skip "file: tests disabled on MingW", 4 if $mingw; 112 113 ok(run(app(["openssl", "storeutl", "-noout", 114 to_abs_file_uri($file)]))); 115 ok(run(app(["openssl", "storeutl", "-noout", 116 to_abs_file_uri($file, 0, "")]))); 117 ok(run(app(["openssl", "storeutl", "-noout", 118 to_abs_file_uri($file, 0, "localhost")]))); 119 ok(!run(app(["openssl", "storeutl", "-noout", 120 to_abs_file_uri($file, 0, "dummy")]))); 121 } 122 } 123 foreach (@generated_files) { 124 ok(run(app(["openssl", "storeutl", "-noout", "-passin", 125 "pass:password", $_]))); 126 ok(run(app(["openssl", "storeutl", "-noout", "-passin", 127 "pass:password", to_abs_file($_)]))); 128 129 SKIP: 130 { 131 skip "file: tests disabled on MingW", 2 if $mingw; 132 133 ok(run(app(["openssl", "storeutl", "-noout", "-passin", 134 "pass:password", to_abs_file_uri($_)]))); 135 ok(!run(app(["openssl", "storeutl", "-noout", "-passin", 136 "pass:password", to_file_uri($_)]))); 137 } 138 } 139 foreach (values %generated_file_files) { 140 SKIP: 141 { 142 skip "file: tests disabled on MingW", 1 if $mingw; 143 144 ok(run(app(["openssl", "storeutl", "-noout", $_]))); 145 } 146 } 147 foreach (@noexist_file_files) { 148 SKIP: 149 { 150 skip "file: tests disabled on MingW", 1 if $mingw; 151 152 ok(!run(app(["openssl", "storeutl", "-noout", $_]))); 153 } 154 } 155 { 156 my $dir = srctop_dir("test", "certs"); 157 158 ok(run(app(["openssl", "storeutl", "-noout", $dir]))); 159 ok(run(app(["openssl", "storeutl", "-noout", 160 to_abs_file($dir, 1)]))); 161 SKIP: 162 { 163 skip "file: tests disabled on MingW", 1 if $mingw; 164 165 ok(run(app(["openssl", "storeutl", "-noout", 166 to_abs_file_uri($dir, 1)]))); 167 } 168 } 169 170 ok(!run(app(['openssl', 'storeutl', '-noout', 171 '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert', 172 srctop_file('test', 'testx509.pem')])), 173 "Checking that -subject can't be used with a single file"); 174 175 ok(run(app(['openssl', 'storeutl', '-certs', '-noout', 176 srctop_file('test', 'testx509.pem')])), 177 "Checking that -certs returns 1 object on a certificate file"); 178 ok(run(app(['openssl', 'storeutl', '-certs', '-noout', 179 srctop_file('test', 'testcrl.pem')])), 180 "Checking that -certs returns 0 objects on a CRL file"); 181 182 ok(run(app(['openssl', 'storeutl', '-crls', '-noout', 183 srctop_file('test', 'testx509.pem')])), 184 "Checking that -crls returns 0 objects on a certificate file"); 185 ok(run(app(['openssl', 'storeutl', '-crls', '-noout', 186 srctop_file('test', 'testcrl.pem')])), 187 "Checking that -crls returns 1 object on a CRL file"); 188 189 SKIP: { 190 skip "failed rehash initialisation", 6 unless $rehash; 191 192 # subject from testx509.pem: 193 # '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert' 194 # issuer from testcrl.pem: 195 # '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority' 196 ok(run(app(['openssl', 'storeutl', '-noout', 197 '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert', 198 catdir(curdir(), 'rehash')]))); 199 ok(run(app(['openssl', 'storeutl', '-noout', 200 '-subject', 201 '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority', 202 catdir(curdir(), 'rehash')]))); 203 ok(run(app(['openssl', 'storeutl', '-noout', '-certs', 204 '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert', 205 catdir(curdir(), 'rehash')]))); 206 ok(run(app(['openssl', 'storeutl', '-noout', '-crls', 207 '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert', 208 catdir(curdir(), 'rehash')]))); 209 ok(run(app(['openssl', 'storeutl', '-noout', '-certs', 210 '-subject', 211 '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority', 212 catdir(curdir(), 'rehash')]))); 213 ok(run(app(['openssl', 'storeutl', '-noout', '-crls', 214 '-subject', 215 '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority', 216 catdir(curdir(), 'rehash')]))); 217 } 218 } 219}, create => 1, cleanup => 1; 220 221sub init { 222 return ( 223 # rsa-key-pkcs1.pem 224 run(app(["openssl", "genrsa", 225 "-out", "rsa-key-pkcs1.pem", "2432"])) 226 # dsa-key-pkcs1.pem 227 && run(app(["openssl", "dsaparam", "-genkey", 228 "-out", "dsa-key-pkcs1.pem", "1024"])) 229 # ec-key-pkcs1.pem (one might think that 'genec' would be practical) 230 && run(app(["openssl", "ecparam", "-genkey", "-name", "prime256v1", 231 "-out", "ec-key-pkcs1.pem"])) 232 # rsa-key-pkcs1-aes128.pem 233 && run(app(["openssl", "rsa", "-passout", "pass:password", "-aes128", 234 "-in", "rsa-key-pkcs1.pem", 235 "-out", "rsa-key-pkcs1-aes128.pem"])) 236 # dsa-key-pkcs1-aes128.pem 237 && run(app(["openssl", "dsa", "-passout", "pass:password", "-aes128", 238 "-in", "dsa-key-pkcs1.pem", 239 "-out", "dsa-key-pkcs1-aes128.pem"])) 240 # ec-key-pkcs1-aes128.pem 241 && run(app(["openssl", "ec", "-passout", "pass:password", "-aes128", 242 "-in", "ec-key-pkcs1.pem", 243 "-out", "ec-key-pkcs1-aes128.pem"])) 244 # *-key-pkcs8.pem 245 && runall(sub { 246 my $dstfile = shift; 247 (my $srcfile = $dstfile) 248 =~ s/-key-pkcs8\.pem$/-key-pkcs1.pem/i; 249 run(app(["openssl", "pkcs8", "-topk8", "-nocrypt", 250 "-in", $srcfile, "-out", $dstfile])); 251 }, grep(/-key-pkcs8\.pem$/, @generated_files)) 252 # *-key-pkcs8-pbes1-sha1-3des.pem 253 && runall(sub { 254 my $dstfile = shift; 255 (my $srcfile = $dstfile) 256 =~ s/-key-pkcs8-pbes1-sha1-3des\.pem$ 257 /-key-pkcs8.pem/ix; 258 run(app(["openssl", "pkcs8", "-topk8", 259 "-passout", "pass:password", 260 "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC", 261 "-in", $srcfile, "-out", $dstfile])); 262 }, grep(/-key-pkcs8-pbes1-sha1-3des\.pem$/, @generated_files)) 263 # *-key-pkcs8-pbes1-md5-des.pem 264 && runall(sub { 265 my $dstfile = shift; 266 (my $srcfile = $dstfile) 267 =~ s/-key-pkcs8-pbes1-md5-des\.pem$ 268 /-key-pkcs8.pem/ix; 269 run(app(["openssl", "pkcs8", "-topk8", 270 "-passout", "pass:password", 271 "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC", 272 "-in", $srcfile, "-out", $dstfile])); 273 }, grep(/-key-pkcs8-pbes1-md5-des\.pem$/, @generated_files)) 274 # *-key-pkcs8-pbes2-sha1.pem 275 && runall(sub { 276 my $dstfile = shift; 277 (my $srcfile = $dstfile) 278 =~ s/-key-pkcs8-pbes2-sha1\.pem$ 279 /-key-pkcs8.pem/ix; 280 run(app(["openssl", "pkcs8", "-topk8", 281 "-passout", "pass:password", 282 "-v2", "aes256", "-v2prf", "hmacWithSHA1", 283 "-in", $srcfile, "-out", $dstfile])); 284 }, grep(/-key-pkcs8-pbes2-sha1\.pem$/, @generated_files)) 285 # *-key-pkcs8-pbes2-sha1.pem 286 && runall(sub { 287 my $dstfile = shift; 288 (my $srcfile = $dstfile) 289 =~ s/-key-pkcs8-pbes2-sha256\.pem$ 290 /-key-pkcs8.pem/ix; 291 run(app(["openssl", "pkcs8", "-topk8", 292 "-passout", "pass:password", 293 "-v2", "aes256", "-v2prf", "hmacWithSHA256", 294 "-in", $srcfile, "-out", $dstfile])); 295 }, grep(/-key-pkcs8-pbes2-sha256\.pem$/, @generated_files)) 296 # *-cert.pem (intermediary for the .p12 inits) 297 && run(app(["openssl", "req", "-x509", 298 "-config", data_file("ca.cnf"), "-nodes", 299 "-out", "cacert.pem", "-keyout", "cakey.pem"])) 300 && runall(sub { 301 my $srckey = shift; 302 (my $dstfile = $srckey) =~ s|-key-pkcs8\.|-cert.|; 303 (my $csr = $dstfile) =~ s|\.pem|.csr|; 304 305 (run(app(["openssl", "req", "-new", 306 "-config", data_file("user.cnf"), 307 "-key", $srckey, "-out", $csr])) 308 && 309 run(app(["openssl", "x509", "-days", "3650", 310 "-CA", "cacert.pem", 311 "-CAkey", "cakey.pem", 312 "-set_serial", time(), "-req", 313 "-in", $csr, "-out", $dstfile]))); 314 }, grep(/-key-pkcs8\.pem$/, @generated_files)) 315 # *.p12 316 && runall(sub { 317 my $dstfile = shift; 318 my ($type, $certpbe_index, $keypbe_index, 319 $macalg_index) = 320 $dstfile =~ m{^(.*)-key-(?| 321 # cert and key PBE are same 322 () # 323 ([^-]*-[^-]*)- # key & cert PBE 324 ([^-]*) # MACalg 325 | 326 # cert and key PBE are not same 327 ([^-]*-[^-]*)- # cert PBE 328 ([^-]*-[^-]*)- # key PBE 329 ([^-]*) # MACalg 330 )\.}x; 331 if (!$certpbe_index) { 332 $certpbe_index = $keypbe_index; 333 } 334 my $srckey = "$type-key-pkcs8.pem"; 335 my $srccert = "$type-cert.pem"; 336 my %pbes = 337 ( 338 "sha1-3des" => "pbeWithSHA1And3-KeyTripleDES-CBC", 339 "md5-des" => "pbeWithMD5AndDES-CBC", 340 "aes256-cbc" => "AES-256-CBC", 341 ); 342 my %macalgs = 343 ( 344 "sha1" => "SHA1", 345 "sha256" => "SHA256", 346 ); 347 my $certpbe = $pbes{$certpbe_index}; 348 my $keypbe = $pbes{$keypbe_index}; 349 my $macalg = $macalgs{$macalg_index}; 350 if (!defined($certpbe) || !defined($keypbe) 351 || !defined($macalg)) { 352 print STDERR "Cert PBE for $pbe_index not defined\n" 353 unless defined $certpbe; 354 print STDERR "Key PBE for $pbe_index not defined\n" 355 unless defined $keypbe; 356 print STDERR "MACALG for $macalg_index not defined\n" 357 unless defined $macalg; 358 print STDERR "(destination file was $dstfile)\n"; 359 return 0; 360 } 361 run(app(["openssl", "pkcs12", "-inkey", $srckey, 362 "-in", $srccert, "-passout", "pass:password", 363 "-export", "-macalg", $macalg, 364 "-certpbe", $certpbe, "-keypbe", $keypbe, 365 "-out", $dstfile])); 366 }, grep(/\.p12/, @generated_files)) 367 # *.der (the end all init) 368 && runall(sub { 369 my $dstfile = shift; 370 (my $srcfile = $dstfile) =~ s/\.der$/.pem/i; 371 if (! -f $srcfile) { 372 $srcfile = srctop_file("test", $srcfile); 373 } 374 my $infh; 375 unless (open $infh, $srcfile) { 376 return 0; 377 } 378 my $l; 379 while (($l = <$infh>) !~ /^-----BEGIN\s/ 380 || $l =~ /^-----BEGIN.*PARAMETERS-----/) { 381 } 382 my $b64 = ""; 383 while (($l = <$infh>) !~ /^-----END\s/) { 384 $l =~ s|\R$||; 385 $b64 .= $l unless $l =~ /:/; 386 } 387 close $infh; 388 my $der = decode_base64($b64); 389 unless (length($b64) / 4 * 3 - length($der) < 3) { 390 print STDERR "Length error, ",length($b64), 391 " bytes of base64 became ",length($der), 392 " bytes of der? ($srcfile => $dstfile)\n"; 393 return 0; 394 } 395 my $outfh; 396 unless (open $outfh, ">:raw", $dstfile) { 397 return 0; 398 } 399 print $outfh $der; 400 close $outfh; 401 return 1; 402 }, grep(/\.der$/, @generated_files)) 403 && runall(sub { 404 my $srcfile = shift; 405 my $dstfile = $generated_file_files{$srcfile}; 406 407 unless (copy srctop_file($srcfile), $dstfile) { 408 warn "$!\n"; 409 return 0; 410 } 411 return 1; 412 }, keys %generated_file_files) 413 ); 414} 415 416sub init_rehash { 417 return ( 418 mkdir(catdir(curdir(), 'rehash')) 419 && copy(srctop_file('test', 'testx509.pem'), 420 catdir(curdir(), 'rehash')) 421 && copy(srctop_file('test', 'testcrl.pem'), 422 catdir(curdir(), 'rehash')) 423 && run(app(['openssl', 'rehash', catdir(curdir(), 'rehash')])) 424 ); 425} 426 427sub runall { 428 my ($function, @items) = @_; 429 430 foreach (@items) { 431 return 0 unless $function->($_); 432 } 433 return 1; 434} 435 436# According to RFC8089, a relative file: path is invalid. We still produce 437# them for testing purposes. 438sub to_file_uri { 439 my ($file, $isdir, $authority) = @_; 440 my $vol; 441 my $dir; 442 443 die "to_file_uri: No file given\n" if !defined($file) || $file eq ''; 444 445 ($vol, $dir, $file) = File::Spec->splitpath($file, $isdir // 0); 446 447 # Make sure we have a Unix style directory. 448 $dir = join('/', File::Spec->splitdir($dir)); 449 # Canonicalise it (note: it seems to be only needed on Unix) 450 while (1) { 451 my $newdir = $dir; 452 $newdir =~ s|/[^/]*[^/\.]+[^/]*/\.\./|/|g; 453 last if $newdir eq $dir; 454 $dir = $newdir; 455 } 456 # Take care of the corner cases the loop can't handle, and that $dir 457 # ends with a / unless it's empty 458 $dir =~ s|/[^/]*[^/\.]+[^/]*/\.\.$|/|; 459 $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\./|/|; 460 $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\.$||; 461 if ($isdir // 0) { 462 $dir =~ s|/$|| if $dir ne '/'; 463 } else { 464 $dir .= '/' if $dir ne '' && $dir !~ m|/$|; 465 } 466 467 # If the file system has separate volumes (at present, Windows and VMS) 468 # we need to handle them. In URIs, they are invariably the first 469 # component of the path, which is always absolute. 470 # On VMS, user:[foo.bar] translates to /user/foo/bar 471 # On Windows, c:\Users\Foo translates to /c:/Users/Foo 472 if ($vol ne '') { 473 $vol =~ s|:||g if ($^O eq "VMS"); 474 $dir = '/' . $dir if $dir ne '' && $dir !~ m|^/|; 475 $dir = '/' . $vol . $dir; 476 } 477 $file = $dir . $file; 478 479 return "file://$authority$file" if defined $authority; 480 return "file:$file"; 481} 482 483sub to_abs_file { 484 my ($file) = @_; 485 486 return File::Spec->rel2abs($file); 487} 488 489sub to_abs_file_uri { 490 my ($file, $isdir, $authority) = @_; 491 492 die "to_abs_file_uri: No file given\n" if !defined($file) || $file eq ''; 493 return to_file_uri(to_abs_file($file), $isdir, $authority); 494} 495