tconversion.pl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #! /usr/bin/env perl
  2. # Copyright 2015-2023 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. use strict;
  9. use warnings;
  10. use File::Compare qw/compare_text/;
  11. use File::Copy;
  12. use OpenSSL::Test qw/:DEFAULT/;
  13. use Time::Piece;
  14. use POSIX qw(strftime);
  15. my %conversionforms = (
  16. # Default conversion forms. Other series may be added with
  17. # specific test types as key.
  18. "*" => [ "d", "p" ],
  19. "msb" => [ "d", "p", "msblob" ],
  20. "pvk" => [ "d", "p", "pvk" ],
  21. );
  22. sub tconversion {
  23. my %opts = @_;
  24. die "Missing option -type" unless $opts{-type};
  25. die "Missing option -in" unless $opts{-in};
  26. my $testtype = $opts{-type};
  27. my $t = $opts{-in};
  28. my $prefix = $opts{-prefix} // $testtype;
  29. my @conversionforms =
  30. defined($conversionforms{$testtype}) ?
  31. @{$conversionforms{$testtype}} :
  32. @{$conversionforms{"*"}};
  33. my @openssl_args;
  34. if (defined $opts{-args}) {
  35. @openssl_args = @{$opts{-args}} if ref $opts{-args} eq 'ARRAY';
  36. @openssl_args = ($opts{-args}) if ref $opts{-args} eq '';
  37. }
  38. @openssl_args = ($testtype) unless @openssl_args;
  39. my $n = scalar @conversionforms;
  40. my $totaltests =
  41. 1 # for initializing
  42. + $n # initial conversions from p to all forms (A)
  43. + $n*$n # conversion from result of A to all forms (B)
  44. + 1 # comparing original test file to p form of A
  45. + $n*($n-1); # comparing first conversion to each form in A with B
  46. $totaltests-- if ($testtype eq "p7d"); # no comparison of original test file
  47. $totaltests -= $n if ($testtype eq "pvk"); # no comparisons of the pvk form
  48. plan tests => $totaltests;
  49. my @cmd = ("openssl", @openssl_args);
  50. my $init;
  51. if (scalar @openssl_args > 0 && $openssl_args[0] eq "pkey") {
  52. $init = ok(run(app([@cmd, "-in", $t, "-out", "$prefix-fff.p"])),
  53. 'initializing');
  54. } else {
  55. $init = ok(copy($t, "$prefix-fff.p"), 'initializing');
  56. }
  57. if (!$init) {
  58. diag("Trying to copy $t to $prefix-fff.p : $!");
  59. }
  60. SKIP: {
  61. skip "Not initialized, skipping...", 22 unless $init;
  62. foreach my $to (@conversionforms) {
  63. ok(run(app([@cmd,
  64. "-in", "$prefix-fff.p",
  65. "-inform", "p",
  66. "-out", "$prefix-f.$to",
  67. "-outform", $to])),
  68. "p -> $to");
  69. }
  70. foreach my $to (@conversionforms) {
  71. foreach my $from (@conversionforms) {
  72. ok(run(app([@cmd,
  73. "-in", "$prefix-f.$from",
  74. "-inform", $from,
  75. "-out", "$prefix-ff.$from$to",
  76. "-outform", $to])),
  77. "$from -> $to");
  78. }
  79. }
  80. if ($testtype ne "p7d") {
  81. is(cmp_text("$prefix-fff.p", "$prefix-f.p"), 0,
  82. 'comparing orig to p');
  83. }
  84. foreach my $to (@conversionforms) {
  85. next if $to eq "d" or $to eq "pvk";
  86. foreach my $from (@conversionforms) {
  87. is(cmp_text("$prefix-f.$to", "$prefix-ff.$from$to"), 0,
  88. "comparing $to to $from$to");
  89. }
  90. }
  91. }
  92. }
  93. sub cmp_text {
  94. return compare_text(@_, sub {
  95. $_[0] =~ s/\R//g;
  96. $_[1] =~ s/\R//g;
  97. return $_[0] ne $_[1];
  98. });
  99. }
  100. sub file_contains {
  101. $_ = shift @_;
  102. my $pattern = shift @_;
  103. open(DATA, $_) or return 0;
  104. $_= join('', <DATA>);
  105. close(DATA);
  106. s/\s+/ /g; # take multiple whitespace (including newline) as single space
  107. return m/$pattern/ ? 1 : 0;
  108. }
  109. sub cert_contains {
  110. my $cert = shift @_;
  111. my $pattern = shift @_;
  112. my $expected = shift @_;
  113. my $name = shift @_;
  114. my $out = "cert_contains.out";
  115. run(app(["openssl", "x509", "-noout", "-text", "-in", $cert, "-out", $out]));
  116. is(file_contains($out, $pattern), $expected, ($name ? "$name: " : "").
  117. "$cert should ".($expected ? "" : "not ")."contain: \"$pattern\"");
  118. # not unlinking $out
  119. }
  120. sub has_version {
  121. my $cert = shift @_;
  122. my $expect = shift @_;
  123. cert_contains($cert, "Version: $expect", 1);
  124. }
  125. sub has_SKID {
  126. my $cert = shift @_;
  127. my $expect = shift @_;
  128. cert_contains($cert, "Subject Key Identifier", $expect);
  129. }
  130. sub has_AKID {
  131. my $cert = shift @_;
  132. my $expect = shift @_;
  133. cert_contains($cert, "Authority Key Identifier", $expect);
  134. }
  135. sub uniq (@) {
  136. my %seen = ();
  137. grep { not $seen{$_}++ } @_;
  138. }
  139. sub 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. sub cert_ext_has_n_different_lines {
  147. my $cert = shift @_;
  148. my $expected = shift @_;
  149. my $exts = shift @_;
  150. my $name = shift @_;
  151. my $out = "cert_n_different_exts.out";
  152. run(app(["openssl", "x509", "-noout", "-ext", $exts,
  153. "-in", $cert, "-out", $out]));
  154. is(file_n_different_lines($out), $expected, ($name ? "$name: " : "").
  155. "$cert '$exts' output should contain $expected different lines");
  156. # not unlinking $out
  157. }
  158. # extracts string value of certificate field from a -text formatted-output
  159. sub get_field {
  160. my ($f, $field) = @_;
  161. my $string = "";
  162. open my $fh, $f or die;
  163. while (my $line = <$fh>) {
  164. if ($line =~ /$field:\s+(.*)/) {
  165. $string = $1;
  166. }
  167. }
  168. close $fh;
  169. return $string;
  170. }
  171. sub get_issuer {
  172. return get_field(@_, "Issuer");
  173. }
  174. sub get_not_before {
  175. return get_field(@_, "Not Before");
  176. }
  177. # Date as yyyy-mm-dd
  178. sub get_not_before_date {
  179. return Time::Piece->strptime(
  180. get_not_before(@_),
  181. "%b %d %T %Y %Z")->date;
  182. }
  183. sub get_not_after {
  184. return get_field(@_, "Not After ");
  185. }
  186. # Date as yyyy-mm-dd
  187. sub get_not_after_date {
  188. return Time::Piece->strptime(
  189. get_not_after(@_),
  190. "%b %d %T %Y %Z")->date;
  191. }
  192. 1;