1#! /usr/bin/env perl
2# Copyright 2015-2021 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
9
10use strict;
11use warnings;
12
13use File::Compare qw/compare_text/;
14use File::Copy;
15use OpenSSL::Test qw/:DEFAULT/;
16
17my %conversionforms = (
18    # Default conversion forms.  Other series may be added with
19    # specific test types as key.
20    "*"		=> [ "d", "p" ],
21    "msb"	=> [ "d", "p", "msblob" ],
22    "pvk"	=> [ "d", "p", "pvk" ],
23    );
24sub tconversion {
25    my %opts = @_;
26
27    die "Missing option -type" unless $opts{-type};
28    die "Missing option -in" unless $opts{-in};
29    my $testtype = $opts{-type};
30    my $t = $opts{-in};
31    my $prefix = $opts{-prefix} // $testtype;
32    my @conversionforms =
33	defined($conversionforms{$testtype}) ?
34	@{$conversionforms{$testtype}} :
35	@{$conversionforms{"*"}};
36    my @openssl_args;
37    if (defined $opts{-args}) {
38        @openssl_args = @{$opts{-args}} if ref $opts{-args} eq 'ARRAY';
39        @openssl_args = ($opts{-args}) if ref $opts{-args} eq '';
40    }
41    @openssl_args = ($testtype) unless @openssl_args;
42
43    my $n = scalar @conversionforms;
44    my $totaltests =
45	1			# for initializing
46	+ $n			# initial conversions from p to all forms (A)
47	+ $n*$n			# conversion from result of A to all forms (B)
48	+ 1			# comparing original test file to p form of A
49	+ $n*($n-1);		# comparing first conversion to each form in A with B
50    $totaltests-- if ($testtype eq "p7d"); # no comparison of original test file
51    $totaltests -= $n if ($testtype eq "pvk"); # no comparisons of the pvk form
52    plan tests => $totaltests;
53
54    my @cmd = ("openssl", @openssl_args);
55
56    my $init;
57    if (scalar @openssl_args > 0 && $openssl_args[0] eq "pkey") {
58	$init = ok(run(app([@cmd, "-in", $t, "-out", "$prefix-fff.p"])),
59		   'initializing');
60    } else {
61	$init = ok(copy($t, "$prefix-fff.p"), 'initializing');
62    }
63    if (!$init) {
64	diag("Trying to copy $t to $prefix-fff.p : $!");
65    }
66
67  SKIP: {
68      skip "Not initialized, skipping...", 22 unless $init;
69
70      foreach my $to (@conversionforms) {
71	  ok(run(app([@cmd,
72		      "-in", "$prefix-fff.p",
73		      "-inform", "p",
74		      "-out", "$prefix-f.$to",
75		      "-outform", $to])),
76	     "p -> $to");
77      }
78
79      foreach my $to (@conversionforms) {
80	  foreach my $from (@conversionforms) {
81	      ok(run(app([@cmd,
82			  "-in", "$prefix-f.$from",
83			  "-inform", $from,
84			  "-out", "$prefix-ff.$from$to",
85			  "-outform", $to])),
86		 "$from -> $to");
87	  }
88      }
89
90      if ($testtype ne "p7d") {
91	  is(cmp_text("$prefix-fff.p", "$prefix-f.p"), 0,
92	     'comparing orig to p');
93      }
94
95      foreach my $to (@conversionforms) {
96	  next if $to eq "d" or $to eq "pvk";
97	  foreach my $from (@conversionforms) {
98	      is(cmp_text("$prefix-f.$to", "$prefix-ff.$from$to"), 0,
99		 "comparing $to to $from$to");
100	  }
101      }
102    }
103}
104
105sub cmp_text {
106    return compare_text(@_, sub {
107        $_[0] =~ s/\R//g;
108        $_[1] =~ s/\R//g;
109        return $_[0] ne $_[1];
110    });
111}
112
113sub file_contains {
114    $_ = shift @_;
115    my $pattern = shift @_;
116    open(DATA, $_) or return 0;
117    $_= join('', <DATA>);
118    close(DATA);
119    return m/$pattern/ ? 1 : 0;
120}
121
122sub cert_contains {
123    my $cert = shift @_;
124    my $pattern = shift @_;
125    my $expected = shift @_;
126    my $name = shift @_;
127    my $out = "cert_contains.out";
128    run(app(["openssl", "x509", "-noout", "-text", "-in", $cert, "-out", $out]));
129    is(file_contains($out, $pattern), $expected, ($name ? "$name: " : "").
130       "$cert should ".($expected ? "" : "not ")."contain $pattern");
131    # not unlinking $out
132}
133
134sub uniq (@) {
135    my %seen = ();
136    grep { not $seen{$_}++ } @_;
137}
138
139sub file_n_different_lines {
140    my $filename = shift @_;
141    open(DATA, $filename) or return 0;
142    chomp(my @lines = <DATA>);
143    close(DATA);
144    return scalar(uniq @lines);
145}
146
147sub cert_ext_has_n_different_lines {
148    my $cert = shift @_;
149    my $expected = shift @_;
150    my $exts = shift @_;
151    my $name = shift @_;
152    my $out = "cert_n_different_exts.out";
153    run(app(["openssl", "x509", "-noout", "-ext", $exts,
154             "-in", $cert, "-out", $out]));
155    is(file_n_different_lines($out), $expected, ($name ? "$name: " : "").
156       "$cert '$exts' output should contain $expected different lines");
157    # not unlinking $out
158}
159
1601;
161