1#! /usr/bin/env perl 2# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (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 strict; 10use warnings; 11 12use OpenSSL::Test qw/:DEFAULT srctop_file with/; 13use OpenSSL::Test::Utils; 14 15use Encode; 16 17setup("test_pkcs12"); 18 19my $pass = "σύνθημα γνώρισμα"; 20 21my $savedcp; 22if (eval { require Win32::API; 1; }) { 23 # Trouble is that Win32 perl uses CreateProcessA, which 24 # makes it problematic to pass non-ASCII arguments, from perl[!] 25 # that is. This is because CreateProcessA is just a wrapper for 26 # CreateProcessW and will call MultiByteToWideChar and use 27 # system default locale. Since we attempt Greek pass-phrase 28 # conversion can be done only with Greek locale. 29 30 Win32::API->Import("kernel32","UINT GetSystemDefaultLCID()"); 31 if (GetSystemDefaultLCID() != 0x408) { 32 plan skip_all => "Non-Greek system locale"; 33 } else { 34 # Ensure correct code page so that VERBOSE output is right. 35 Win32::API->Import("kernel32","UINT GetConsoleOutputCP()"); 36 Win32::API->Import("kernel32","BOOL SetConsoleOutputCP(UINT cp)"); 37 $savedcp = GetConsoleOutputCP(); 38 SetConsoleOutputCP(1253); 39 $pass = Encode::encode("cp1253",Encode::decode("utf-8",$pass)); 40 } 41} elsif ($^O eq "MSWin32") { 42 plan skip_all => "Win32::API unavailable"; 43} elsif ($^O ne "VMS") { 44 # Running MinGW tests transparently under Wine apparently requires 45 # UTF-8 locale... 46 47 foreach(`locale -a`) { 48 s/\R$//; 49 if ($_ =~ m/^C\.UTF\-?8/i) { 50 $ENV{LC_ALL} = $_; 51 last; 52 } 53 } 54} 55$ENV{OPENSSL_WIN32_UTF8}=1; 56 57plan tests => 20; 58 59# Test different PKCS#12 formats 60ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats"); 61# Test with legacy APIs 62ok(run(test(["pkcs12_format_test", "-legacy"])), "test pkcs12 formats using legacy APIs"); 63# Test with a non-default library context (and no loaded providers in the default context) 64ok(run(test(["pkcs12_format_test", "-context"])), "test pkcs12 formats using a non-default library context"); 65 66SKIP: { 67 skip "VMS doesn't have command line UTF-8 support yet in DCL", 1 68 if $^O eq "VMS"; 69 70 # just see that we can read shibboleth.pfx protected with $pass 71 ok(run(app(["openssl", "pkcs12", "-noout", 72 "-password", "pass:$pass", 73 "-in", srctop_file("test", "shibboleth.pfx")])), 74 "test_load_cert_pkcs12"); 75} 76 77my @path = qw(test certs); 78my $outfile1 = "out1.p12"; 79my $outfile2 = "out2.p12"; 80my $outfile3 = "out3.p12"; 81my $outfile4 = "out4.p12"; 82my $outfile5 = "out5.p12"; 83 84# Test the -chain option with -untrusted 85ok(run(app(["openssl", "pkcs12", "-export", "-chain", 86 "-CAfile", srctop_file(@path, "sroot-cert.pem"), 87 "-untrusted", srctop_file(@path, "ca-cert.pem"), 88 "-in", srctop_file(@path, "ee-cert.pem"), 89 "-nokeys", "-passout", "pass:", "-out", $outfile1])), 90 "test_pkcs12_chain_untrusted"); 91 92# Test the -passcerts option 93SKIP: { 94 skip "Skipping PKCS#12 test because DES is disabled in this build", 1 95 if disabled("des"); 96 ok(run(app(["openssl", "pkcs12", "-export", 97 "-in", srctop_file(@path, "ee-cert.pem"), 98 "-certfile", srctop_file(@path, "v3-certs-TDES.p12"), 99 "-passcerts", "pass:v3-certs", 100 "-nokeys", "-passout", "pass:v3-certs", "-descert", 101 "-out", $outfile2])), 102 "test_pkcs12_passcerts"); 103} 104 105SKIP: { 106 skip "Skipping legacy PKCS#12 test because the required algorithms are disabled", 1 107 if disabled("des") || disabled("rc2") || disabled("legacy"); 108 # Test reading legacy PKCS#12 file 109 ok(run(app(["openssl", "pkcs12", "-export", 110 "-in", srctop_file(@path, "v3-certs-RC2.p12"), 111 "-passin", "pass:v3-certs", 112 "-provider", "default", "-provider", "legacy", 113 "-nokeys", "-passout", "pass:v3-certs", "-descert", 114 "-out", $outfile3])), 115 "test_pkcs12_passcerts_legacy"); 116} 117 118# Test export of PEM file with both cert and key 119# -nomac necessary to avoid legacy provider requirement 120ok(run(app(["openssl", "pkcs12", "-export", 121 "-inkey", srctop_file(@path, "cert-key-cert.pem"), 122 "-in", srctop_file(@path, "cert-key-cert.pem"), 123 "-passout", "pass:v3-certs", 124 "-nomac", "-out", $outfile4], stderr => "outerr.txt")), 125 "test_export_pkcs12_cert_key_cert"); 126open DATA, "outerr.txt"; 127my @match = grep /:error:/, <DATA>; 128close DATA; 129ok(scalar @match > 0 ? 0 : 1, "test_export_pkcs12_outerr_empty"); 130 131ok(run(app(["openssl", "pkcs12", 132 "-in", $outfile4, 133 "-passin", "pass:v3-certs", 134 "-nomacver", "-nodes"])), 135 "test_import_pkcs12_cert_key_cert"); 136 137ok(run(app(["openssl", "pkcs12", "-export", "-out", $outfile5, 138 "-in", srctop_file(@path, "ee-cert.pem"), "-caname", "testname", 139 "-nokeys", "-passout", "pass:", "-certpbe", "NONE"])), 140 "test nokeys single cert"); 141 142my @pkcs12info = run(app(["openssl", "pkcs12", "-info", "-in", $outfile5, 143 "-passin", "pass:"]), capture => 1); 144 145# Test that with one input certificate, we get one output certificate 146ok(grep(/subject=CN = server.example/, @pkcs12info) == 1, 147 "test one cert in output"); 148# Test that the expected friendly name is present in the output 149ok(grep(/testname/, @pkcs12info) == 1, "test friendly name in output"); 150 151# Test some bad pkcs12 files 152my $bad1 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad1.p12"); 153my $bad2 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad2.p12"); 154my $bad3 = srctop_file("test", "recipes", "80-test_pkcs12_data", "bad3.p12"); 155 156with({ exit_checker => sub { return shift == 1; } }, 157 sub { 158 ok(run(app(["openssl", "pkcs12", "-in", $bad1, "-password", "pass:"])), 159 "test bad pkcs12 file 1"); 160 161 ok(run(app(["openssl", "pkcs12", "-in", $bad1, "-password", "pass:", 162 "-nomacver"])), 163 "test bad pkcs12 file 1 (nomacver)"); 164 165 ok(run(app(["openssl", "pkcs12", "-in", $bad1, "-password", "pass:", 166 "-info"])), 167 "test bad pkcs12 file 1 (info)"); 168 169 ok(run(app(["openssl", "pkcs12", "-in", $bad2, "-password", "pass:"])), 170 "test bad pkcs12 file 2"); 171 172 ok(run(app(["openssl", "pkcs12", "-in", $bad2, "-password", "pass:", 173 "-info"])), 174 "test bad pkcs12 file 2 (info)"); 175 176 ok(run(app(["openssl", "pkcs12", "-in", $bad3, "-password", "pass:"])), 177 "test bad pkcs12 file 3"); 178 179 ok(run(app(["openssl", "pkcs12", "-in", $bad3, "-password", "pass:", 180 "-info"])), 181 "test bad pkcs12 file 3 (info)"); 182 }); 183 184SetConsoleOutputCP($savedcp) if (defined($savedcp)); 185