Home | History | Annotate | Line # | Download | only in recipes
      1  1.1  christos #! /usr/bin/env perl
      2  1.1  christos # Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
      3  1.1  christos #
      4  1.1  christos # Licensed under the Apache License 2.0 (the "License").  You may not use
      5  1.1  christos # this file except in compliance with the License.  You can obtain a copy
      6  1.1  christos # in the file LICENSE in the source distribution or at
      7  1.1  christos # https://www.openssl.org/source/license.html
      8  1.1  christos 
      9  1.1  christos use File::Spec::Functions;
     10  1.1  christos use File::Copy;
     11  1.1  christos use MIME::Base64;
     12  1.1  christos use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file bldtop_dir
     13  1.1  christos                      data_file);
     14  1.1  christos use OpenSSL::Test::Utils;
     15  1.1  christos 
     16  1.1  christos my $test_name = "test_store";
     17  1.1  christos setup($test_name);
     18  1.1  christos 
     19  1.1  christos require(srctop_file("test", "recipes", "tconversion.pl")); # for test_file_contains()
     20  1.1  christos 
     21  1.1  christos my $use_md5 = !disabled("md5");
     22  1.1  christos my $use_des = !(disabled("des") || disabled("legacy")); # also affects 3des and pkcs12 app
     23  1.1  christos my $use_dsa = !disabled("dsa");
     24  1.1  christos my $use_ecc = !disabled("ec");
     25  1.1  christos 
     26  1.1  christos my @noexist_files =
     27  1.1  christos     ( "test/blahdiblah.pem",
     28  1.1  christos       "test/blahdibleh.der" );
     29  1.1  christos my @src_files =
     30  1.1  christos     ( "test/testx509.pem",
     31  1.1  christos       "test/testrsa.pem",
     32  1.1  christos       "test/testrsapub.pem",
     33  1.1  christos       "test/testcrl.pem",
     34  1.1  christos       "apps/server.pem" );
     35  1.1  christos my @data_files =
     36  1.1  christos     ( "testrsa.msb" );
     37  1.1  christos push(@data_files,
     38  1.1  christos      ( "testrsa.pvk" ))
     39  1.1  christos     unless disabled("legacy") || disabled("rc4");
     40  1.1  christos my @src_rsa_files =
     41  1.1  christos     ( "test/testrsa.pem",
     42  1.1  christos       "test/testrsapub.pem" );
     43  1.1  christos my @generated_files =
     44  1.1  christos     (
     45  1.1  christos      ### generated from the source files
     46  1.1  christos 
     47  1.1  christos      "testx509.der",
     48  1.1  christos      "testrsa.der",
     49  1.1  christos      "testrsapub.der",
     50  1.1  christos      "testcrl.der",
     51  1.1  christos 
     52  1.1  christos      ### generated locally
     53  1.1  christos 
     54  1.1  christos      "rsa-key-pkcs1.pem", "rsa-key-pkcs1.der",
     55  1.1  christos      "rsa-key-pkcs1-aes128.pem",
     56  1.1  christos      "rsa-key-pkcs8.pem", "rsa-key-pkcs8.der",
     57  1.1  christos      "rsa-key-pkcs8-pbes2-sha1.pem", "rsa-key-pkcs8-pbes2-sha1.der",
     58  1.1  christos      "rsa-key-pkcs8-pbes2-sha256.pem", "rsa-key-pkcs8-pbes2-sha256.der",
     59  1.1  christos     );
     60  1.1  christos push(@generated_files, (
     61  1.1  christos      "rsa-key-pkcs8-pbes1-sha1-3des.pem", "rsa-key-pkcs8-pbes1-sha1-3des.der",
     62  1.1  christos     )) if $use_des;
     63  1.1  christos push(@generated_files, (
     64  1.1  christos      "rsa-key-sha1-3des-sha1.p12", "rsa-key-sha1-3des-sha256.p12",
     65  1.1  christos      "rsa-key-aes256-cbc-sha256.p12",
     66  1.1  christos      "rsa-key-md5-des-sha1.p12",
     67  1.1  christos      "rsa-key-aes256-cbc-md5-des-sha256.p12"
     68  1.1  christos      )) if $use_des;
     69  1.1  christos push(@generated_files, (
     70  1.1  christos      "rsa-key-pkcs8-pbes1-md5-des.pem", "rsa-key-pkcs8-pbes1-md5-des.der"
     71  1.1  christos      )) if $use_md5 && $use_des;
     72  1.1  christos push(@generated_files, (
     73  1.1  christos      "dsa-key-pkcs1.pem", "dsa-key-pkcs1.der",
     74  1.1  christos      "dsa-key-pkcs1-aes128.pem",
     75  1.1  christos      "dsa-key-pkcs8.pem", "dsa-key-pkcs8.der",
     76  1.1  christos      "dsa-key-pkcs8-pbes2-sha1.pem", "dsa-key-pkcs8-pbes2-sha1.der",
     77  1.1  christos      )) if $use_dsa;
     78  1.1  christos push(@generated_files, "dsa-key-aes256-cbc-sha256.p12") if $use_dsa && $use_des;
     79  1.1  christos push(@generated_files, (
     80  1.1  christos      "ec-key-pkcs1.pem", "ec-key-pkcs1.der",
     81  1.1  christos      "ec-key-pkcs1-aes128.pem",
     82  1.1  christos      "ec-key-pkcs8.pem", "ec-key-pkcs8.der",
     83  1.1  christos      "ec-key-pkcs8-pbes2-sha1.pem", "ec-key-pkcs8-pbes2-sha1.der",
     84  1.1  christos      )) if $use_ecc;
     85  1.1  christos push(@generated_files, "ec-key-aes256-cbc-sha256.p12") if $use_ecc && $use_des;
     86  1.1  christos my %generated_file_files =
     87  1.1  christos     $^O eq 'linux'
     88  1.1  christos     ? ( "test/testx509.pem" => "file:testx509.pem",
     89  1.1  christos         "test/testrsa.pem" => "file:testrsa.pem",
     90  1.1  christos         "test/testrsapub.pem" => "file:testrsapub.pem",
     91  1.1  christos         "test/testcrl.pem" => "file:testcrl.pem",
     92  1.1  christos         "apps/server.pem" => "file:server.pem" )
     93  1.1  christos     : ();
     94  1.1  christos my @noexist_file_files =
     95  1.1  christos     ( "file:blahdiblah.pem",
     96  1.1  christos       "file:test/blahdibleh.der" );
     97  1.1  christos 
     98  1.1  christos # There is more than one method to get a 'file:' loader.
     99  1.1  christos # The default is a built-in provider implementation.
    100  1.1  christos # However, there is also an engine, specially for testing purposes.
    101  1.1  christos #
    102  1.1  christos # @methods is a collection of extra 'openssl storeutl' arguments used to
    103  1.1  christos # try the different methods.
    104  1.1  christos my @methods;
    105  1.1  christos my @prov_method = qw(-provider default);
    106  1.1  christos push @prov_method, qw(-provider legacy) unless disabled('legacy');
    107  1.1  christos push @methods, [ @prov_method ];
    108  1.1  christos push @methods, [qw(-engine loader_attic)]
    109  1.1  christos     unless disabled('loadereng');
    110  1.1  christos 
    111  1.1  christos my $n = 4 + scalar @methods
    112  1.1  christos     * ( (3 * scalar @noexist_files)
    113  1.1  christos         + (6 * scalar @src_files)
    114  1.1  christos         + (2 * scalar @data_files)
    115  1.1  christos         + (4 * scalar @generated_files)
    116  1.1  christos         + (scalar keys %generated_file_files)
    117  1.1  christos         + (scalar @noexist_file_files)
    118  1.1  christos         + 3
    119  1.1  christos         + 11 );
    120  1.1  christos 
    121  1.1  christos # Test doesn't work under msys because the file name munging doesn't work
    122  1.1  christos # correctly with the "ot:" prefix
    123  1.1  christos my $do_test_ossltest_store =
    124  1.1  christos     !(disabled("engine") || disabled("dynamic-engine") || $^O =~ /^msys$/);
    125  1.1  christos 
    126  1.1  christos if ($do_test_ossltest_store) {
    127  1.1  christos     # test loading with apps 'org.openssl.engine:' loader, using the
    128  1.1  christos     # ossltest engine.
    129  1.1  christos     $n += 4 * scalar @src_rsa_files;
    130  1.1  christos }
    131  1.1  christos 
    132  1.1  christos plan skip_all => "No plan" if $n == 0;
    133  1.1  christos 
    134  1.1  christos plan tests => $n;
    135  1.1  christos 
    136  1.1  christos my $test_x509 = srctop_file('test', 'testx509.pem');
    137  1.1  christos 
    138  1.1  christos ok(run(app(["openssl", "storeutl",  "-crls", $test_x509])),
    139  1.1  christos    "storeutil with -crls option");
    140  1.1  christos 
    141  1.1  christos ok(!run(app(["openssl", "storeutl", $test_x509, "-crls"])),
    142  1.1  christos    "storeutil with extra parameter (at end) should fail");
    143  1.1  christos 
    144  1.1  christos indir "store_$$" => sub {
    145  1.1  christos     if ($do_test_ossltest_store) {
    146  1.1  christos         # ossltest loads PEM files, with names prefixed with 'ot:'.
    147  1.1  christos         # This prefix ensures that the files are, in fact, loaded through
    148  1.1  christos         # that engine and not mistakenly going through the 'file:' loader.
    149  1.1  christos 
    150  1.1  christos         my $engine_scheme = 'org.openssl.engine:';
    151  1.1  christos         $ENV{OPENSSL_ENGINES} = bldtop_dir("engines");
    152  1.1  christos 
    153  1.1  christos         foreach (@src_rsa_files) {
    154  1.1  christos             my $file = srctop_file($_);
    155  1.1  christos             my $file_abs = to_abs_file($file);
    156  1.1  christos             my @pubin = $_ =~ m|pub\.pem$| ? ("-pubin") : ();
    157  1.1  christos 
    158  1.1  christos             ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
    159  1.1  christos                         "-engine", "ossltest", "-inform", "engine",
    160  1.1  christos                         "-in", "ot:$file"])));
    161  1.1  christos             ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
    162  1.1  christos                         "-engine", "ossltest", "-inform", "engine",
    163  1.1  christos                         "-in", "ot:$file_abs"])));
    164  1.1  christos             ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
    165  1.1  christos                         "-in", "${engine_scheme}ossltest:ot:$file"])));
    166  1.1  christos             ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
    167  1.1  christos                         "-in", "${engine_scheme}ossltest:ot:$file_abs"])));
    168  1.1  christos         }
    169  1.1  christos     }
    170  1.1  christos 
    171  1.1  christos  SKIP:
    172  1.1  christos     {
    173  1.1  christos         init() or die "init failed";
    174  1.1  christos 
    175  1.1  christos         my $rehash = init_rehash();
    176  1.1  christos 
    177  1.1  christos         ok(run(app(["openssl", "storeutl", "-out", "cacert.pem", "cacert.pem"])),
    178  1.1  christos             "identical infile and outfile");
    179  1.1  christos         test_file_contains("storeutl output on same input",
    180  1.1  christos                            "cacert.pem", "Total found: 1");
    181  1.1  christos 
    182  1.1  christos         foreach my $method (@methods) {
    183  1.1  christos             my @storeutl = ( qw(openssl storeutl), @$method );
    184  1.1  christos 
    185  1.1  christos             foreach (@noexist_files) {
    186  1.1  christos                 my $file = srctop_file($_);
    187  1.1  christos 
    188  1.1  christos                 ok(!run(app([@storeutl, "-noout", $file])));
    189  1.1  christos                 ok(!run(app([@storeutl, "-noout", to_abs_file($file)])));
    190  1.1  christos                 {
    191  1.1  christos                     local $ENV{MSYS2_ARG_CONV_EXCL} = "file:";
    192  1.1  christos 
    193  1.1  christos                     ok(!run(app([@storeutl, "-noout",
    194  1.1  christos                                  to_abs_file_uri($file)])));
    195  1.1  christos                 }
    196  1.1  christos             }
    197  1.1  christos             foreach (@src_files) {
    198  1.1  christos                 my $file = srctop_file($_);
    199  1.1  christos 
    200  1.1  christos                 ok(run(app([@storeutl, "-noout", $file])));
    201  1.1  christos                 ok(run(app([@storeutl, "-noout", to_abs_file($file)])));
    202  1.1  christos               SKIP:
    203  1.1  christos                 {
    204  1.1  christos                     skip "file: tests disabled on MingW", 4  if $^O =~ /^msys$/;
    205  1.1  christos 
    206  1.1  christos                     ok(run(app([@storeutl, "-noout",
    207  1.1  christos                                 to_abs_file_uri($file)])));
    208  1.1  christos                     ok(run(app([@storeutl, "-noout",
    209  1.1  christos                                 to_abs_file_uri($file, 0, "")])));
    210  1.1  christos                     ok(run(app([@storeutl, "-noout",
    211  1.1  christos                                 to_abs_file_uri($file, 0, "localhost")])));
    212  1.1  christos                     ok(!run(app([@storeutl, "-noout",
    213  1.1  christos                                  to_abs_file_uri($file, 0, "dummy")])));
    214  1.1  christos                 }
    215  1.1  christos             }
    216  1.1  christos             foreach (@data_files) {
    217  1.1  christos                 my $file = data_file($_);
    218  1.1  christos 
    219  1.1  christos                 ok(run(app([@storeutl, "-noout", "-passin", "pass:password",
    220  1.1  christos                             $file])));
    221  1.1  christos                 ok(run(app([@storeutl, "-noout", "-passin", "pass:password",
    222  1.1  christos                             to_abs_file($file)])));
    223  1.1  christos             }
    224  1.1  christos             foreach (@generated_files) {
    225  1.1  christos                 ok(run(app([@storeutl, "-noout", "-passin", "pass:password",
    226  1.1  christos                             $_])));
    227  1.1  christos                 ok(run(app([@storeutl,  "-noout", "-passin", "pass:password",
    228  1.1  christos                             to_abs_file($_)])));
    229  1.1  christos 
    230  1.1  christos               SKIP:
    231  1.1  christos                 {
    232  1.1  christos                     skip "file: tests disabled on MingW", 2  if $^O =~ /^msys$/;
    233  1.1  christos 
    234  1.1  christos                     ok(run(app([@storeutl, "-noout", "-passin",
    235  1.1  christos                                 "pass:password", to_abs_file_uri($_)])));
    236  1.1  christos                     ok(!run(app([@storeutl, "-noout", "-passin",
    237  1.1  christos                                  "pass:password", to_file_uri($_)])));
    238  1.1  christos                 }
    239  1.1  christos             }
    240  1.1  christos             foreach (values %generated_file_files) {
    241  1.1  christos               SKIP:
    242  1.1  christos                 {
    243  1.1  christos                     skip "file: tests disabled on MingW", 1  if $^O =~ /^msys$/;
    244  1.1  christos 
    245  1.1  christos                     ok(run(app([@storeutl,  "-noout", $_])));
    246  1.1  christos                 }
    247  1.1  christos             }
    248  1.1  christos             foreach (@noexist_file_files) {
    249  1.1  christos               SKIP:
    250  1.1  christos                 {
    251  1.1  christos                     skip "file: tests disabled on MingW", 1  if $^O =~ /^msys$/;
    252  1.1  christos 
    253  1.1  christos                     ok(!run(app([@storeutl,  "-noout", $_])));
    254  1.1  christos                 }
    255  1.1  christos             }
    256  1.1  christos             {
    257  1.1  christos                 my $dir = srctop_dir("test", "certs");
    258  1.1  christos 
    259  1.1  christos                 ok(run(app([@storeutl,  "-noout", $dir])));
    260  1.1  christos                 ok(run(app([@storeutl,  "-noout", to_abs_file($dir, 1)])));
    261  1.1  christos               SKIP:
    262  1.1  christos                 {
    263  1.1  christos                     skip "file: tests disabled on MingW", 1  if $^O =~ /^msys$/;
    264  1.1  christos 
    265  1.1  christos                     ok(run(app([@storeutl,  "-noout",
    266  1.1  christos                                 to_abs_file_uri($dir, 1)])));
    267  1.1  christos                 }
    268  1.1  christos             }
    269  1.1  christos 
    270  1.1  christos             ok(!run(app([@storeutl, '-noout',
    271  1.1  christos                          '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
    272  1.1  christos                          srctop_file('test', 'testx509.pem')])),
    273  1.1  christos                "Checking that -subject can't be used with a single file");
    274  1.1  christos 
    275  1.1  christos             ok(run(app([@storeutl, '-certs', '-noout',
    276  1.1  christos                         srctop_file('test', 'testx509.pem')])),
    277  1.1  christos                "Checking that -certs returns 1 object on a certificate file");
    278  1.1  christos             ok(run(app([@storeutl, '-certs', '-noout',
    279  1.1  christos                         srctop_file('test', 'testcrl.pem')])),
    280  1.1  christos                "Checking that -certs returns 0 objects on a CRL file");
    281  1.1  christos 
    282  1.1  christos             ok(run(app([@storeutl, '-crls', '-noout',
    283  1.1  christos                         srctop_file('test', 'testx509.pem')])),
    284  1.1  christos                "Checking that -crls returns 0 objects on a certificate file");
    285  1.1  christos             ok(run(app([@storeutl, '-crls', '-noout',
    286  1.1  christos                         srctop_file('test', 'testcrl.pem')])),
    287  1.1  christos                "Checking that -crls returns 1 object on a CRL file");
    288  1.1  christos 
    289  1.1  christos           SKIP: {
    290  1.1  christos               skip "failed rehash initialisation", 6 unless $rehash;
    291  1.1  christos 
    292  1.1  christos               # subject from testx509.pem:
    293  1.1  christos               # '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert'
    294  1.1  christos               # issuer from testcrl.pem:
    295  1.1  christos               # '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority'
    296  1.1  christos               ok(run(app([@storeutl, '-noout',
    297  1.1  christos                           '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
    298  1.1  christos                           catdir(curdir(), 'rehash')])));
    299  1.1  christos               ok(run(app([@storeutl, '-noout',
    300  1.1  christos                           '-subject',
    301  1.1  christos                           '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
    302  1.1  christos                           catdir(curdir(), 'rehash')])));
    303  1.1  christos               ok(run(app([@storeutl, '-noout', '-certs',
    304  1.1  christos                           '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
    305  1.1  christos                           catdir(curdir(), 'rehash')])));
    306  1.1  christos               ok(run(app([@storeutl, '-noout', '-crls',
    307  1.1  christos                           '-subject', '/C=AU/ST=QLD/CN=SSLeay\/rsa test cert',
    308  1.1  christos                           catdir(curdir(), 'rehash')])));
    309  1.1  christos               ok(run(app([@storeutl, '-noout', '-certs',
    310  1.1  christos                           '-subject',
    311  1.1  christos                           '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
    312  1.1  christos                           catdir(curdir(), 'rehash')])));
    313  1.1  christos               ok(run(app([@storeutl, '-noout', '-crls',
    314  1.1  christos                           '-subject',
    315  1.1  christos                           '/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority',
    316  1.1  christos                           catdir(curdir(), 'rehash')])));
    317  1.1  christos             }
    318  1.1  christos         }
    319  1.1  christos     }
    320  1.1  christos }, create => 1, cleanup => 1;
    321  1.1  christos 
    322  1.1  christos sub init {
    323  1.1  christos     my $cnf = srctop_file('test', 'ca-and-certs.cnf');
    324  1.1  christos     my $cakey = srctop_file('test', 'certs', 'ca-key.pem');
    325  1.1  christos     my @std_args = qw(-provider default);
    326  1.1  christos     push @std_args, qw(-provider legacy)
    327  1.1  christos         unless disabled('legacy');
    328  1.1  christos     return (
    329  1.1  christos             # rsa-key-pkcs1.pem
    330  1.1  christos             run(app(["openssl", "pkey", @std_args,
    331  1.1  christos                      "-in", data_file("rsa-key-2432.pem"),
    332  1.1  christos                      "-out", "rsa-key-pkcs1.pem"]))
    333  1.1  christos             # rsa-key-pkcs1-aes128.pem
    334  1.1  christos             && run(app(["openssl", "rsa", @std_args,
    335  1.1  christos                         "-passout", "pass:password", "-aes128",
    336  1.1  christos                         "-in", "rsa-key-pkcs1.pem",
    337  1.1  christos                         "-out", "rsa-key-pkcs1-aes128.pem"]))
    338  1.1  christos             # dsa-key-pkcs1.pem
    339  1.1  christos             && (!$use_dsa
    340  1.1  christos                 || run(app(["openssl", "gendsa", @std_args,
    341  1.1  christos                             "-out", "dsa-key-pkcs1.pem",
    342  1.1  christos                             data_file("dsaparam.pem")])))
    343  1.1  christos             # dsa-key-pkcs1-aes128.pem
    344  1.1  christos             && (!$use_dsa
    345  1.1  christos                 || run(app(["openssl", "dsa", @std_args,
    346  1.1  christos                             "-passout", "pass:password", "-aes128",
    347  1.1  christos                             "-in", "dsa-key-pkcs1.pem",
    348  1.1  christos                             "-out", "dsa-key-pkcs1-aes128.pem"])))
    349  1.1  christos             # ec-key-pkcs1.pem (one might think that 'genec' would be practical)
    350  1.1  christos             && (!$use_ecc
    351  1.1  christos                 || run(app(["openssl", "ecparam", @std_args,
    352  1.1  christos                             "-genkey",
    353  1.1  christos                             "-name", "prime256v1",
    354  1.1  christos                             "-out", "ec-key-pkcs1.pem"])))
    355  1.1  christos             # ec-key-pkcs1-aes128.pem
    356  1.1  christos             && (!$use_ecc
    357  1.1  christos                 || run(app(["openssl", "ec", @std_args,
    358  1.1  christos                             "-passout", "pass:password", "-aes128",
    359  1.1  christos                             "-in", "ec-key-pkcs1.pem",
    360  1.1  christos                             "-out", "ec-key-pkcs1-aes128.pem"])))
    361  1.1  christos             # *-key-pkcs8.pem
    362  1.1  christos             && runall(sub {
    363  1.1  christos                           my $dstfile = shift;
    364  1.1  christos                           (my $srcfile = $dstfile)
    365  1.1  christos                               =~ s/-key-pkcs8\.pem$/-key-pkcs1.pem/i;
    366  1.1  christos                           run(app(["openssl", "pkcs8", @std_args,
    367  1.1  christos                                    "-topk8", "-nocrypt",
    368  1.1  christos                                    "-in", $srcfile, "-out", $dstfile]));
    369  1.1  christos                       }, grep(/-key-pkcs8\.pem$/, @generated_files))
    370  1.1  christos             # *-key-pkcs8-pbes1-sha1-3des.pem
    371  1.1  christos             && runall(sub {
    372  1.1  christos                           my $dstfile = shift;
    373  1.1  christos                           (my $srcfile = $dstfile)
    374  1.1  christos                               =~ s/-key-pkcs8-pbes1-sha1-3des\.pem$
    375  1.1  christos                                   /-key-pkcs8.pem/ix;
    376  1.1  christos                           run(app(["openssl", "pkcs8", @std_args,
    377  1.1  christos                                    "-topk8",
    378  1.1  christos                                    "-passout", "pass:password",
    379  1.1  christos                                    "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC",
    380  1.1  christos                                    "-in", $srcfile, "-out", $dstfile]));
    381  1.1  christos                       }, grep(/-key-pkcs8-pbes1-sha1-3des\.pem$/, @generated_files))
    382  1.1  christos             # *-key-pkcs8-pbes1-md5-des.pem
    383  1.1  christos             && runall(sub {
    384  1.1  christos                           my $dstfile = shift;
    385  1.1  christos                           (my $srcfile = $dstfile)
    386  1.1  christos                               =~ s/-key-pkcs8-pbes1-md5-des\.pem$
    387  1.1  christos                                   /-key-pkcs8.pem/ix;
    388  1.1  christos                           run(app(["openssl", "pkcs8", @std_args,
    389  1.1  christos                                    "-topk8",
    390  1.1  christos                                    "-passout", "pass:password",
    391  1.1  christos                                    "-v1", "pbeWithSHA1And3-KeyTripleDES-CBC",
    392  1.1  christos                                    "-in", $srcfile, "-out", $dstfile]));
    393  1.1  christos                       }, grep(/-key-pkcs8-pbes1-md5-des\.pem$/, @generated_files))
    394  1.1  christos             # *-key-pkcs8-pbes2-sha1.pem
    395  1.1  christos             && runall(sub {
    396  1.1  christos                           my $dstfile = shift;
    397  1.1  christos                           (my $srcfile = $dstfile)
    398  1.1  christos                               =~ s/-key-pkcs8-pbes2-sha1\.pem$
    399  1.1  christos                                   /-key-pkcs8.pem/ix;
    400  1.1  christos                           run(app(["openssl", "pkcs8", @std_args,
    401  1.1  christos                                    "-topk8",
    402  1.1  christos                                    "-passout", "pass:password",
    403  1.1  christos                                    "-v2", "aes256", "-v2prf", "hmacWithSHA1",
    404  1.1  christos                                    "-in", $srcfile, "-out", $dstfile]));
    405  1.1  christos                       }, grep(/-key-pkcs8-pbes2-sha1\.pem$/, @generated_files))
    406  1.1  christos             # *-key-pkcs8-pbes2-sha1.pem
    407  1.1  christos             && runall(sub {
    408  1.1  christos                           my $dstfile = shift;
    409  1.1  christos                           (my $srcfile = $dstfile)
    410  1.1  christos                               =~ s/-key-pkcs8-pbes2-sha256\.pem$
    411  1.1  christos                                   /-key-pkcs8.pem/ix;
    412  1.1  christos                           run(app(["openssl", "pkcs8", @std_args,
    413  1.1  christos                                    "-topk8",
    414  1.1  christos                                    "-passout", "pass:password",
    415  1.1  christos                                    "-v2", "aes256", "-v2prf", "hmacWithSHA256",
    416  1.1  christos                                    "-in", $srcfile, "-out", $dstfile]));
    417  1.1  christos                       }, grep(/-key-pkcs8-pbes2-sha256\.pem$/, @generated_files))
    418  1.1  christos             # *-cert.pem (intermediary for the .p12 inits)
    419  1.1  christos             && run(app(["openssl", "req", "-x509", @std_args,
    420  1.1  christos                         "-config", $cnf, "-reqexts", "v3_ca", "-noenc",
    421  1.1  christos                         "-key", $cakey, "-out", "cacert.pem"]))
    422  1.1  christos             && runall(sub {
    423  1.1  christos                           my $srckey = shift;
    424  1.1  christos                           (my $dstfile = $srckey) =~ s|-key-pkcs8\.|-cert.|;
    425  1.1  christos                           (my $csr = $dstfile) =~ s|\.pem|.csr|;
    426  1.1  christos 
    427  1.1  christos                           (run(app(["openssl", "req", "-new", @std_args,
    428  1.1  christos                                     "-config", $cnf, "-section", "userreq",
    429  1.1  christos                                     "-key", $srckey, "-out", $csr]))
    430  1.1  christos                            &&
    431  1.1  christos                            run(app(["openssl", "x509", @std_args,
    432  1.1  christos                                     "-days", "3650",
    433  1.1  christos                                     "-CA", "cacert.pem",
    434  1.1  christos                                     "-CAkey", $cakey,
    435  1.1  christos                                     "-set_serial", time(), "-req",
    436  1.1  christos                                     "-in", $csr, "-out", $dstfile])));
    437  1.1  christos                       }, grep(/-key-pkcs8\.pem$/, @generated_files))
    438  1.1  christos             # *.p12
    439  1.1  christos             && runall(sub {
    440  1.1  christos                           my $dstfile = shift;
    441  1.1  christos                           my ($type, $certpbe_index, $keypbe_index,
    442  1.1  christos                               $macalg_index) =
    443  1.1  christos                               $dstfile =~ m{^(.*)-key-(?|
    444  1.1  christos                                                 # cert and key PBE are same
    445  1.1  christos                                                 ()             #
    446  1.1  christos                                                 ([^-]*-[^-]*)- # key & cert PBE
    447  1.1  christos                                                 ([^-]*)        # MACalg
    448  1.1  christos                                             |
    449  1.1  christos                                                 # cert and key PBE are not same
    450  1.1  christos                                                 ([^-]*-[^-]*)- # cert PBE
    451  1.1  christos                                                 ([^-]*-[^-]*)- # key PBE
    452  1.1  christos                                                 ([^-]*)        # MACalg
    453  1.1  christos                                             )\.}x;
    454  1.1  christos                           if (!$certpbe_index) {
    455  1.1  christos                               $certpbe_index = $keypbe_index;
    456  1.1  christos                           }
    457  1.1  christos                           my $srckey = "$type-key-pkcs8.pem";
    458  1.1  christos                           my $srccert = "$type-cert.pem";
    459  1.1  christos                           my %pbes =
    460  1.1  christos                               (
    461  1.1  christos                                "sha1-3des" => "pbeWithSHA1And3-KeyTripleDES-CBC",
    462  1.1  christos                                "md5-des" => "pbeWithMD5AndDES-CBC",
    463  1.1  christos                                "aes256-cbc" => "AES-256-CBC",
    464  1.1  christos                               );
    465  1.1  christos                           my %macalgs =
    466  1.1  christos                               (
    467  1.1  christos                                "sha1" => "SHA1",
    468  1.1  christos                                "sha256" => "SHA256",
    469  1.1  christos                               );
    470  1.1  christos                           my $certpbe = $pbes{$certpbe_index};
    471  1.1  christos                           my $keypbe = $pbes{$keypbe_index};
    472  1.1  christos                           my $macalg = $macalgs{$macalg_index};
    473  1.1  christos                           if (!defined($certpbe) || !defined($keypbe)
    474  1.1  christos                               || !defined($macalg)) {
    475  1.1  christos                               print STDERR "Cert PBE for $certpbe_index not defined\n"
    476  1.1  christos                                   unless defined $certpbe;
    477  1.1  christos                               print STDERR "Key PBE for $keypbe_index not defined\n"
    478  1.1  christos                                   unless defined $keypbe;
    479  1.1  christos                               print STDERR "MACALG for $macalg_index not defined\n"
    480  1.1  christos                                   unless defined $macalg;
    481  1.1  christos                               print STDERR "(destination file was $dstfile)\n";
    482  1.1  christos                               return 0;
    483  1.1  christos                           }
    484  1.1  christos                           run(app(["openssl", "pkcs12", @std_args,
    485  1.1  christos                                    "-inkey", $srckey,
    486  1.1  christos                                    "-in", $srccert, "-passout", "pass:password",
    487  1.1  christos                                    "-chain", "-CAfile", "cacert.pem",
    488  1.1  christos                                    "-export", "-macalg", $macalg,
    489  1.1  christos                                    "-certpbe", $certpbe, "-keypbe", $keypbe,
    490  1.1  christos                                    "-out", $dstfile]));
    491  1.1  christos                       }, grep(/\.p12/, @generated_files))
    492  1.1  christos             # *.der (the end all init)
    493  1.1  christos             && runall(sub {
    494  1.1  christos                           my $dstfile = shift;
    495  1.1  christos                           (my $srcfile = $dstfile) =~ s/\.der$/.pem/i;
    496  1.1  christos                           if (! -f $srcfile) {
    497  1.1  christos                               $srcfile = srctop_file("test", $srcfile);
    498  1.1  christos                           }
    499  1.1  christos                           my $infh;
    500  1.1  christos                           unless (open $infh, $srcfile) {
    501  1.1  christos                               return 0;
    502  1.1  christos                           }
    503  1.1  christos                           my $l;
    504  1.1  christos                           while (($l = <$infh>) !~ /^-----BEGIN\s/
    505  1.1  christos                                  || $l =~ /^-----BEGIN.*PARAMETERS-----/) {
    506  1.1  christos                           }
    507  1.1  christos                           my $b64 = "";
    508  1.1  christos                           while (($l = <$infh>) !~ /^-----END\s/) {
    509  1.1  christos                               $l =~ s|\R$||;
    510  1.1  christos                               $b64 .= $l unless $l =~ /:/;
    511  1.1  christos                           }
    512  1.1  christos                           close $infh;
    513  1.1  christos                           my $der = decode_base64($b64);
    514  1.1  christos                           unless (length($b64) / 4 * 3 - length($der) < 3) {
    515  1.1  christos                               print STDERR "Length error, ",length($b64),
    516  1.1  christos                                   " bytes of base64 became ",length($der),
    517  1.1  christos                                   " bytes of der? ($srcfile => $dstfile)\n";
    518  1.1  christos                               return 0;
    519  1.1  christos                           }
    520  1.1  christos                           my $outfh;
    521  1.1  christos                           unless (open $outfh, ">:raw", $dstfile) {
    522  1.1  christos                               return 0;
    523  1.1  christos                           }
    524  1.1  christos                           print $outfh $der;
    525  1.1  christos                           close $outfh;
    526  1.1  christos                           return 1;
    527  1.1  christos                       }, grep(/\.der$/, @generated_files))
    528  1.1  christos             && runall(sub {
    529  1.1  christos                           my $srcfile = shift;
    530  1.1  christos                           my $dstfile = $generated_file_files{$srcfile};
    531  1.1  christos 
    532  1.1  christos                           unless (copy srctop_file($srcfile), $dstfile) {
    533  1.1  christos                               warn "$!\n";
    534  1.1  christos                               return 0;
    535  1.1  christos                           }
    536  1.1  christos                           return 1;
    537  1.1  christos                       }, keys %generated_file_files)
    538  1.1  christos            );
    539  1.1  christos }
    540  1.1  christos 
    541  1.1  christos sub init_rehash {
    542  1.1  christos     return (
    543  1.1  christos             mkdir(catdir(curdir(), 'rehash'))
    544  1.1  christos             && copy(srctop_file('test', 'testx509.pem'),
    545  1.1  christos                     catdir(curdir(), 'rehash'))
    546  1.1  christos             && copy(srctop_file('test', 'testcrl.pem'),
    547  1.1  christos                     catdir(curdir(), 'rehash'))
    548  1.1  christos             && run(app(['openssl', 'rehash', catdir(curdir(), 'rehash')]))
    549  1.1  christos            );
    550  1.1  christos }
    551  1.1  christos 
    552  1.1  christos sub runall {
    553  1.1  christos     my ($function, @items) = @_;
    554  1.1  christos 
    555  1.1  christos     foreach (@items) {
    556  1.1  christos         return 0 unless $function->($_);
    557  1.1  christos     }
    558  1.1  christos     return 1;
    559  1.1  christos }
    560  1.1  christos 
    561  1.1  christos # According to RFC8089, a relative file: path is invalid.  We still produce
    562  1.1  christos # them for testing purposes.
    563  1.1  christos sub to_file_uri {
    564  1.1  christos     my ($file, $isdir, $authority) = @_;
    565  1.1  christos     my $vol;
    566  1.1  christos     my $dir;
    567  1.1  christos 
    568  1.1  christos     die "to_file_uri: No file given\n" if !defined($file) || $file eq '';
    569  1.1  christos 
    570  1.1  christos     ($vol, $dir, $file) = File::Spec->splitpath($file, $isdir // 0);
    571  1.1  christos 
    572  1.1  christos     # Make sure we have a Unix style directory.
    573  1.1  christos     $dir = join('/', File::Spec->splitdir($dir));
    574  1.1  christos     # Canonicalise it (note: it seems to be only needed on Unix)
    575  1.1  christos     while (1) {
    576  1.1  christos         my $newdir = $dir;
    577  1.1  christos         $newdir =~ s|/[^/]*[^/\.]+[^/]*/\.\./|/|g;
    578  1.1  christos         last if $newdir eq $dir;
    579  1.1  christos         $dir = $newdir;
    580  1.1  christos     }
    581  1.1  christos     # Take care of the corner cases the loop can't handle, and that $dir
    582  1.1  christos     # ends with a / unless it's empty
    583  1.1  christos     $dir =~ s|/[^/]*[^/\.]+[^/]*/\.\.$|/|;
    584  1.1  christos     $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\./|/|;
    585  1.1  christos     $dir =~ s|^[^/]*[^/\.]+[^/]*/\.\.$||;
    586  1.1  christos     if ($isdir // 0) {
    587  1.1  christos         $dir =~ s|/$|| if $dir ne '/';
    588  1.1  christos     } else {
    589  1.1  christos         $dir .= '/' if $dir ne '' && $dir !~ m|/$|;
    590  1.1  christos     }
    591  1.1  christos 
    592  1.1  christos     # If the file system has separate volumes (at present, Windows and VMS)
    593  1.1  christos     # we need to handle them.  In URIs, they are invariably the first
    594  1.1  christos     # component of the path, which is always absolute.
    595  1.1  christos     # On VMS, user:[foo.bar] translates to /user/foo/bar
    596  1.1  christos     # On Windows, c:\Users\Foo translates to /c:/Users/Foo
    597  1.1  christos     if ($vol ne '') {
    598  1.1  christos         $vol =~ s|:||g if ($^O eq "VMS");
    599  1.1  christos         $dir = '/' . $dir if $dir ne '' && $dir !~ m|^/|;
    600  1.1  christos         $dir = '/' . $vol . $dir;
    601  1.1  christos     }
    602  1.1  christos     $file = $dir . $file;
    603  1.1  christos 
    604  1.1  christos     return "file://$authority$file" if defined $authority;
    605  1.1  christos     return "file:$file";
    606  1.1  christos }
    607  1.1  christos 
    608  1.1  christos sub to_abs_file {
    609  1.1  christos     my ($file) = @_;
    610  1.1  christos 
    611  1.1  christos     return File::Spec->rel2abs($file);
    612  1.1  christos }
    613  1.1  christos 
    614  1.1  christos sub to_abs_file_uri {
    615  1.1  christos     my ($file, $isdir, $authority) = @_;
    616  1.1  christos 
    617  1.1  christos     die "to_abs_file_uri: No file given\n" if !defined($file) || $file eq '';
    618  1.1  christos     return to_file_uri(to_abs_file($file), $isdir, $authority);
    619  1.1  christos }
    620