90-test_store.t 21 KB

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