90-test_store.t 21 KB

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