xref: /openssl/test/recipes/80-test_cms.t (revision ed686232)
1#! /usr/bin/env perl
2# Copyright 2015-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
9
10use strict;
11use warnings;
12
13use POSIX;
14use File::Spec::Functions qw/catfile/;
15use File::Compare qw/compare_text compare/;
16use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file with data_file/;
17
18use OpenSSL::Test::Utils;
19
20BEGIN {
21    setup("test_cms");
22}
23
24use lib srctop_dir('Configurations');
25use lib bldtop_dir('.');
26
27my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
28my $old_fips = 0;
29
30plan skip_all => "CMS is not supported by this OpenSSL build"
31    if disabled("cms");
32
33my $provpath = bldtop_dir("providers");
34
35# Some tests require legacy algorithms to be included.
36my @legacyprov = ("-provider-path", $provpath,
37                  "-provider", "default",
38                  "-provider", "legacy" );
39my @defaultprov = ("-provider-path", $provpath,
40                   "-provider", "default");
41
42my @config = ( );
43my $provname = 'default';
44my $dsaallow = '1';
45
46my $datadir = srctop_dir("test", "recipes", "80-test_cms_data");
47my $smdir    = srctop_dir("test", "smime-certs");
48my $smcont   = srctop_file("test", "smcont.txt");
49my $smcont_zero = srctop_file("test", "smcont_zero.txt");
50my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
51    = disabled qw/des dh dsa ec ec2m rc2 zlib/;
52
53$no_rc2 = 1 if disabled("legacy");
54
55plan tests => 25;
56
57ok(run(test(["pkcs7_test"])), "test pkcs7");
58
59unless ($no_fips) {
60    my $provconf = srctop_file("test", "fips-and-base.cnf");
61    @config = ( "-config", $provconf );
62    $provname = 'fips';
63
64    run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]),
65    capture => 1, statusvar => \$dsaallow);
66    $no_dsa = 1 if $dsaallow == '0';
67    $old_fips = 1 if $dsaallow != '0';
68}
69
70$ENV{OPENSSL_TEST_LIBCTX} = "1";
71my @prov = ("-provider-path", $provpath,
72            @config,
73            "-provider", $provname);
74
75my $smrsa1024 = catfile($smdir, "smrsa1024.pem");
76my $smrsa1 = catfile($smdir, "smrsa1.pem");
77my $smroot = catfile($smdir, "smroot.pem");
78
79my @smime_pkcs7_tests = (
80
81    [ "signed content DER format, RSA key",
82      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
83        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
84      [ "{cmd2}",  @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
85        "-CAfile", $smroot, "-out", "{output}.txt" ],
86      \&final_compare
87    ],
88
89    [ "signed detached content DER format, RSA key",
90      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
91        "-signer", $smrsa1, "-out", "{output}.cms" ],
92      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
93        "-CAfile", $smroot, "-out", "{output}.txt",
94        "-content", $smcont ],
95      \&final_compare
96    ],
97
98    [ "signed content test streaming BER format, RSA",
99      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
100        "-stream",
101        "-signer", $smrsa1, "-out", "{output}.cms" ],
102      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
103        "-CAfile", $smroot, "-out", "{output}.txt" ],
104      \&final_compare
105    ],
106
107    [ "signed content DER format, DSA key",
108      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
109        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
110      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
111        "-CAfile", $smroot, "-out", "{output}.txt" ],
112      \&final_compare
113    ],
114
115    [ "signed detached content DER format, DSA key",
116      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
117        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
118      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
119        "-CAfile", $smroot, "-out", "{output}.txt",
120        "-content", $smcont ],
121      \&final_compare
122    ],
123
124    [ "signed detached content DER format, add RSA signer (with DSA existing)",
125      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
126        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
127      [ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
128        "-signer", $smrsa1, "-out", "{output}2.cms" ],
129      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
130        "-CAfile", $smroot, "-out", "{output}.txt",
131        "-content", $smcont ],
132      \&final_compare
133    ],
134
135    [ "signed content test streaming BER format, DSA key",
136      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
137        "-nodetach", "-stream",
138        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
139      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
140        "-CAfile", $smroot, "-out", "{output}.txt" ],
141      \&final_compare
142    ],
143
144    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
145      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
146        "-nodetach", "-stream",
147        "-signer", $smrsa1,
148        "-signer", catfile($smdir, "smrsa2.pem"),
149        "-signer", catfile($smdir, "smdsa1.pem"),
150        "-signer", catfile($smdir, "smdsa2.pem"),
151        "-out", "{output}.cms" ],
152      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
153        "-CAfile", $smroot, "-out", "{output}.txt" ],
154      \&final_compare
155    ],
156
157    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
158      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
159        "-noattr", "-nodetach", "-stream",
160        "-signer", $smrsa1,
161        "-signer", catfile($smdir, "smrsa2.pem"),
162        "-signer", catfile($smdir, "smdsa1.pem"),
163        "-signer", catfile($smdir, "smdsa2.pem"),
164        "-out", "{output}.cms" ],
165      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
166        "-CAfile", $smroot, "-out", "{output}.txt" ],
167      \&final_compare
168    ],
169
170    [ "signed content S/MIME format, RSA key SHA1",
171      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-md", "sha1",
172        "-certfile", $smroot,
173        "-signer", $smrsa1, "-out", "{output}.cms" ],
174      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
175        "-CAfile", $smroot, "-out", "{output}.txt" ],
176      \&final_compare
177    ],
178
179    [ "signed zero-length content S/MIME format, RSA key SHA1",
180      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont_zero, "-md", "sha1",
181        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
182      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
183        "-CAfile", $smroot, "-out", "{output}.txt" ],
184      \&zero_compare
185    ],
186
187    [ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
188      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
189        "-signer", $smrsa1,
190        "-signer", catfile($smdir, "smrsa2.pem"),
191        "-signer", catfile($smdir, "smdsa1.pem"),
192        "-signer", catfile($smdir, "smdsa2.pem"),
193        "-stream", "-out", "{output}.cms" ],
194      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
195        "-CAfile", $smroot, "-out", "{output}.txt" ],
196      \&final_compare
197    ],
198
199    [ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
200      [ "{cmd1}", @prov, "-sign", "-in", $smcont,
201        "-signer", $smrsa1,
202        "-signer", catfile($smdir, "smrsa2.pem"),
203        "-signer", catfile($smdir, "smdsa1.pem"),
204        "-signer", catfile($smdir, "smdsa2.pem"),
205        "-stream", "-out", "{output}.cms" ],
206      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
207        "-CAfile", $smroot, "-out", "{output}.txt" ],
208      \&final_compare
209    ],
210
211    [ "enveloped content test streaming S/MIME format, DES, 3 recipients",
212      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
213        "-stream", "-out", "{output}.cms",
214        $smrsa1,
215        catfile($smdir, "smrsa2.pem"),
216        catfile($smdir, "smrsa3.pem") ],
217      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
218        "-in", "{output}.cms", "-out", "{output}.txt" ],
219      \&final_compare
220    ],
221
222    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, 3rd used",
223      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
224        "-stream", "-out", "{output}.cms",
225        $smrsa1,
226        catfile($smdir, "smrsa2.pem"),
227        catfile($smdir, "smrsa3.pem") ],
228      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
229        "-in", "{output}.cms", "-out", "{output}.txt" ],
230      \&final_compare
231    ],
232
233    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, cert and key files used",
234      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
235        "-stream", "-out", "{output}.cms",
236        $smrsa1,
237        catfile($smdir, "smrsa2.pem"),
238        catfile($smdir, "smrsa3-cert.pem") ],
239      [ "{cmd2}", @defaultprov, "-decrypt",
240	"-recip", catfile($smdir, "smrsa3-cert.pem"),
241	"-inkey", catfile($smdir, "smrsa3-key.pem"),
242        "-in", "{output}.cms", "-out", "{output}.txt" ],
243      \&final_compare
244    ],
245
246);
247
248if ($no_fips || $old_fips) {
249    push(@smime_pkcs7_tests,
250         [ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
251           [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
252             "-aes256", "-stream", "-out", "{output}.cms",
253             $smrsa1,
254             catfile($smdir, "smrsa2.pem"),
255             catfile($smdir, "smrsa3.pem") ],
256           [ "{cmd2}", @prov, "-decrypt", "-recip", $smrsa1,
257             "-in", "{output}.cms", "-out", "{output}.txt" ],
258           \&final_compare
259         ]
260    );
261}
262
263my @smime_cms_tests = (
264
265    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
266      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
267        "-nodetach", "-keyid",
268        "-signer", $smrsa1,
269        "-signer", catfile($smdir, "smrsa2.pem"),
270        "-signer", catfile($smdir, "smdsa1.pem"),
271        "-signer", catfile($smdir, "smdsa2.pem"),
272        "-stream", "-out", "{output}.cms" ],
273      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
274        "-CAfile", $smroot, "-out", "{output}.txt" ],
275      \&final_compare
276    ],
277
278    [ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
279      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
280        "-signer", $smrsa1,
281        "-signer", catfile($smdir, "smrsa2.pem"),
282        "-signer", catfile($smdir, "smdsa1.pem"),
283        "-signer", catfile($smdir, "smdsa2.pem"),
284        "-stream", "-out", "{output}.cms" ],
285      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
286        "-CAfile", $smroot, "-out", "{output}.txt" ],
287      \&final_compare
288    ],
289
290    [ "signed content MIME format, RSA key, signed receipt request",
291      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
292        "-signer", $smrsa1,
293        "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
294        "-out", "{output}.cms" ],
295      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
296        "-CAfile", $smroot, "-out", "{output}.txt" ],
297      \&final_compare
298    ],
299
300    [ "signed receipt MIME format, RSA key",
301      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
302        "-signer", $smrsa1,
303        "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
304        "-out", "{output}.cms" ],
305      [ "{cmd1}", @prov, "-sign_receipt", "-in", "{output}.cms",
306        "-signer", catfile($smdir, "smrsa2.pem"), "-out", "{output}2.cms" ],
307      [ "{cmd2}", @prov, "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
308        "-CAfile", $smroot ]
309    ],
310
311    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
312      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
313        "-stream", "-out", "{output}.cms", "-keyid",
314        $smrsa1,
315        catfile($smdir, "smrsa2.pem"),
316        catfile($smdir, "smrsa3.pem") ],
317      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
318        "-in", "{output}.cms", "-out", "{output}.txt" ],
319      \&final_compare
320    ],
321
322    [ "enveloped content test streaming PEM format, AES-256-CBC cipher, KEK",
323      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
324        "-stream", "-out", "{output}.cms",
325        "-secretkey", "000102030405060708090A0B0C0D0E0F",
326        "-secretkeyid", "C0FEE0" ],
327      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
328        "-inform", "PEM",
329        "-secretkey", "000102030405060708090A0B0C0D0E0F",
330        "-secretkeyid", "C0FEE0" ],
331      \&final_compare
332    ],
333
334    [ "enveloped content test streaming PEM format, AES-256-GCM cipher, KEK",
335      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes-128-gcm",
336        "-stream", "-out", "{output}.cms",
337        "-secretkey", "000102030405060708090A0B0C0D0E0F",
338        "-secretkeyid", "C0FEE0" ],
339      [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
340        "-inform", "PEM",
341        "-secretkey", "000102030405060708090A0B0C0D0E0F",
342        "-secretkeyid", "C0FEE0" ],
343      \&final_compare
344    ],
345
346    [ "enveloped content test streaming PEM format, KEK, key only",
347      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
348        "-stream", "-out", "{output}.cms",
349        "-secretkey", "000102030405060708090A0B0C0D0E0F",
350        "-secretkeyid", "C0FEE0" ],
351      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
352        "-inform", "PEM",
353        "-secretkey", "000102030405060708090A0B0C0D0E0F" ],
354      \&final_compare
355    ],
356
357    [ "data content test streaming PEM format",
358      [ "{cmd1}", @prov, "-data_create", "-in", $smcont, "-outform", "PEM",
359        "-nodetach", "-stream", "-out", "{output}.cms" ],
360      [ "{cmd2}", @prov, "-data_out", "-in", "{output}.cms", "-inform", "PEM",
361        "-out", "{output}.txt" ],
362      \&final_compare
363    ],
364
365    [ "encrypted content test streaming PEM format, 128 bit RC2 key",
366      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
367        "-in", $smcont, "-outform", "PEM",
368        "-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
369        "-stream", "-out", "{output}.cms" ],
370      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
371        "-inform", "PEM",
372        "-secretkey", "000102030405060708090A0B0C0D0E0F",
373        "-out", "{output}.txt" ],
374      \&final_compare
375    ],
376
377    [ "encrypted content test streaming PEM format, 40 bit RC2 key",
378      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
379        "-in", $smcont, "-outform", "PEM",
380        "-rc2", "-secretkey", "0001020304",
381        "-stream", "-out", "{output}.cms" ],
382      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
383        "-inform", "PEM",
384        "-secretkey", "0001020304", "-out", "{output}.txt" ],
385      \&final_compare
386    ],
387
388    [ "encrypted content test streaming PEM format, triple DES key",
389      [ "{cmd1}", @defaultprov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
390        "-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
391        "-stream", "-out", "{output}.cms" ],
392      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
393        "-inform", "PEM",
394        "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
395        "-out", "{output}.txt" ],
396      \&final_compare
397    ],
398
399    [ "encrypted content test streaming PEM format, 128 bit AES key",
400      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
401        "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
402        "-stream", "-out", "{output}.cms" ],
403      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
404        "-inform", "PEM",
405        "-secretkey", "000102030405060708090A0B0C0D0E0F",
406        "-out", "{output}.txt" ],
407      \&final_compare
408    ],
409
410    [ "encrypted content test streaming PEM format -noout, 128 bit AES key",
411      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
412	"-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
413	"-stream", "-noout" ],
414      [ "{cmd2}", @prov, "-help" ]
415    ],
416);
417
418my @smime_cms_cades_tests = (
419
420    [ "signed content DER format, RSA key, CAdES-BES compatible",
421      [ "{cmd1}", @prov, "-sign", "-cades", "-in", $smcont, "-outform", "DER",
422         "-nodetach",
423        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
424      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
425        "-CAfile", $smroot, "-out", "{output}.txt" ],
426      \&final_compare
427    ],
428
429    [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
430      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
431        "DER", "-nodetach", "-certfile", $smroot,
432        "-signer", $smrsa1, "-out", "{output}.cms" ],
433      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
434        "-CAfile", $smroot, "-out", "{output}.txt" ],
435      \&final_compare
436    ],
437
438    [ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
439      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
440        "DER", "-nodetach", "-certfile", $smroot,
441        "-signer", $smrsa1, "-out", "{output}.cms" ],
442      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
443        "-CAfile", $smroot, "-out", "{output}.txt" ],
444      \&final_compare
445    ],
446
447    [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
448      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
449        "-in", $smcont, "-outform", "DER",
450        "-certfile", $smroot, "-signer", $smrsa1,
451        "-outform", "DER", "-out", "{output}.cms"  ],
452      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
453        "-CAfile", $smroot, "-out", "{output}.txt" ],
454      \&final_compare
455    ],
456
457    [ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
458      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
459        "-in", $smcont, "-outform", "DER",
460        "-certfile", $smroot, "-signer", $smrsa1,
461        "-outform", "DER", "-out", "{output}.cms"  ],
462      [ "{cmd1}", @prov, "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
463        "-inform", "DER", "-in", "{output}.cms",
464        "-certfile", $smroot, "-signer", catfile($smdir, "smrsa2.pem"),
465        "-outform", "DER", "-out", "{output}2.cms" ],
466
467      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
468        "-CAfile", $smroot, "-out", "{output}.txt" ],
469      \&final_compare
470    ],
471);
472
473my @smime_cms_cades_ko_tests = (
474    [ "sign content DER format, RSA key, not CAdES-BES compatible",
475      [ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
476        "-certfile", $smroot, "-signer", $smrsa1, "-out", "cades-ko.cms" ],
477      "fail to verify token since requiring CAdES-BES compatibility",
478      [ @prov, "-verify", "-cades", "-in", "cades-ko.cms", "-inform", "DER",
479        "-CAfile", $smroot, "-out", "cades-ko.txt" ],
480      \&final_compare
481    ]
482);
483
484# cades options test - check that some combinations are rejected
485my @smime_cms_cades_invalid_option_tests = (
486    [
487        [ "-cades", "-noattr" ],
488    ],[
489        [ "-verify", "-cades", "-noattr" ],
490    ],[
491        [ "-verify", "-cades", "-noverify" ],
492    ],
493);
494
495my @smime_cms_comp_tests = (
496
497    [ "compressed content test streaming PEM format",
498      [ "{cmd1}", @prov, "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
499        "-stream", "-out", "{output}.cms" ],
500      [ "{cmd2}", @prov, "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
501        "-out", "{output}.txt" ],
502      \&final_compare
503    ]
504
505);
506
507my @smime_cms_param_tests = (
508    [ "signed content test streaming PEM format, RSA keys, PSS signature",
509      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
510        "-signer", $smrsa1,
511        "-keyopt", "rsa_padding_mode:pss",
512        "-out", "{output}.cms" ],
513      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
514        "-CAfile", $smroot, "-out", "{output}.txt" ],
515      \&final_compare
516    ],
517
518    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=max",
519      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
520        "-signer", $smrsa1,
521        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:max",
522        "-out", "{output}.cms" ],
523      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 222; },
524      [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
525        "-CAfile", $smroot, "-out", "{output}.txt" ],
526      \&final_compare
527    ],
528
529    [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
530      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
531        "-noattr", "-signer", $smrsa1,
532        "-keyopt", "rsa_padding_mode:pss",
533        "-out", "{output}.cms" ],
534      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
535        "-CAfile", $smroot, "-out", "{output}.txt" ],
536      \&final_compare
537    ],
538
539    [ "signed content test streaming PEM format, RSA keys, PSS signature, SHA384 MGF1",
540      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
541        "-signer", $smrsa1,
542        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_mgf1_md:sha384",
543        "-out", "{output}.cms" ],
544      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
545        "-CAfile", $smroot, "-out", "{output}.txt" ],
546      \&final_compare
547    ],
548
549    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=16",
550      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
551        "-signer", $smrsa1, "-md", "sha256",
552        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:16",
553        "-out", "{output}.cms" ],
554      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 16; },
555      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
556        "-CAfile", $smroot, "-out", "{output}.txt" ],
557      \&final_compare
558    ],
559
560    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=digest",
561      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
562        "-signer", $smrsa1, "-md", "sha256",
563        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:digest",
564        "-out", "{output}.cms" ],
565      # digest is SHA-256, which produces 32 bytes of output
566      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 32; },
567      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
568        "-CAfile", $smroot, "-out", "{output}.txt" ],
569      \&final_compare
570    ],
571
572    [ "enveloped content test streaming S/MIME format, DES, OAEP default parameters",
573      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
574        "-stream", "-out", "{output}.cms",
575        "-recip", $smrsa1,
576        "-keyopt", "rsa_padding_mode:oaep" ],
577      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
578        "-in", "{output}.cms", "-out", "{output}.txt" ],
579      \&final_compare
580    ],
581
582    [ "enveloped content test streaming S/MIME format, DES, OAEP SHA256",
583      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
584        "-stream", "-out", "{output}.cms",
585        "-recip", $smrsa1,
586        "-keyopt", "rsa_padding_mode:oaep",
587        "-keyopt", "rsa_oaep_md:sha256" ],
588      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
589        "-in", "{output}.cms", "-out", "{output}.txt" ],
590      \&final_compare
591    ],
592
593    [ "enveloped content test streaming S/MIME format, DES, ECDH",
594      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
595        "-stream", "-out", "{output}.cms",
596        "-recip", catfile($smdir, "smec1.pem") ],
597      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
598        "-in", "{output}.cms", "-out", "{output}.txt" ],
599      \&final_compare
600    ],
601
602    [ "enveloped content test streaming S/MIME format, DES, ECDH, 2 recipients, key only used",
603      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
604        "-stream", "-out", "{output}.cms",
605        catfile($smdir, "smec1.pem"),
606        catfile($smdir, "smec3.pem") ],
607      [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
608        "-in", "{output}.cms", "-out", "{output}.txt" ],
609      \&final_compare
610    ],
611
612    [ "enveloped content test streaming S/MIME format, ECDH, DES, key identifier",
613      [ "{cmd1}", @defaultprov, "-encrypt", "-keyid", "-in", $smcont,
614        "-stream", "-out", "{output}.cms",
615        "-recip", catfile($smdir, "smec1.pem") ],
616      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
617        "-in", "{output}.cms", "-out", "{output}.txt" ],
618      \&final_compare
619    ],
620
621    [ "enveloped content test streaming S/MIME format, ECDH, AES-128-CBC, SHA256 KDF",
622      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
623        "-stream", "-out", "{output}.cms",
624        "-recip", catfile($smdir, "smec1.pem"), "-aes128",
625        "-keyopt", "ecdh_kdf_md:sha256" ],
626      sub { my %opts = @_; smimeType_matches("$opts{output}.cms", "enveloped-data"); },
627      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
628        "-in", "{output}.cms", "-out", "{output}.txt" ],
629      \&final_compare
630    ],
631
632    [ "enveloped content test streaming S/MIME format, ECDH, AES-128-GCM cipher, SHA256 KDF",
633      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
634        "-stream", "-out", "{output}.cms",
635        "-recip", catfile($smdir, "smec1.pem"), "-aes-128-gcm", "-keyopt", "ecdh_kdf_md:sha256" ],
636      sub { my %opts = @_; smimeType_matches("$opts{output}.cms", "authEnveloped-data"); },
637      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
638        "-in", "{output}.cms", "-out", "{output}.txt" ],
639      \&final_compare
640    ],
641
642    [ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
643      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
644        "-stream", "-out", "{output}.cms",
645        "-recip", catfile($smdir, "smec2.pem"), "-aes128",
646        "-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
647      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
648        "-in", "{output}.cms", "-out", "{output}.txt" ],
649      \&final_compare
650    ]
651);
652
653if ($no_fips || $old_fips) {
654    # Only SHA1 supported in dh_cms_encrypt()
655    push(@smime_cms_param_tests,
656
657	 [ "enveloped content test streaming S/MIME format, X9.42 DH",
658	   [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
659	     "-stream", "-out", "{output}.cms",
660	     "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
661	   [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
662	     "-in", "{output}.cms", "-out", "{output}.txt" ],
663	   \&final_compare
664	 ]
665    );
666}
667
668my @smime_cms_param_tests_autodigestmax = (
669    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=auto-digestmax, digestsize < maximum salt length",
670      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
671        "-signer", $smrsa1, "-md", "sha256",
672        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:auto-digestmax",
673        "-out", "{output}.cms" ],
674      # digest is SHA-256, which produces 32, bytes of output
675      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 32; },
676      [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
677        "-CAfile", $smroot, "-out", "{output}.txt" ],
678      \&final_compare
679    ],
680
681    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=auto-digestmax, digestsize > maximum salt length",
682      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
683        "-signer", $smrsa1024, "-md", "sha512",
684        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:auto-digestmax",
685        "-out", "{output}.cms" ],
686      # digest is SHA-512, which produces 64, bytes of output, but an RSA-PSS
687      # signature with a 1024 bit RSA key can only accommodate 62
688      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 62; },
689      [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
690        "-CAfile", $smroot, "-out", "{output}.txt" ],
691      \&final_compare
692    ]
693);
694
695
696my @contenttype_cms_test = (
697    [ "signed content test - check that content type is added to additional signerinfo, RSA keys",
698      [ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
699        "-outform", "DER", "-signer", $smrsa1, "-md", "SHA256",
700        "-out", "{output}.cms" ],
701      [ "{cmd1}", @prov, "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
702        "-inform", "DER", "-outform", "DER",
703        "-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256",
704        "-out", "{output}2.cms" ],
705      sub { my %opts = @_; contentType_matches("$opts{output}2.cms") == 2; },
706      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
707        "-CAfile", $smroot, "-out", "{output}.txt" ]
708    ],
709);
710
711my @incorrect_attribute_cms_test = (
712    "bad_signtime_attr.cms",
713    "no_ct_attr.cms",
714    "no_md_attr.cms",
715    "ct_multiple_attr.cms"
716);
717
718# Runs a standard loop on the input array
719sub runner_loop {
720    my %opts = ( @_ );
721    my $cnt1 = 0;
722
723    foreach (@{$opts{tests}}) {
724        $cnt1++;
725        $opts{output} = "$opts{prefix}-$cnt1";
726      SKIP: {
727          my $skip_reason = check_availability($$_[0]);
728          skip $skip_reason, 1 if $skip_reason;
729          my $ok = 1;
730          1 while unlink "$opts{output}.txt";
731
732          foreach (@$_[1..$#$_]) {
733              if (ref $_ eq 'CODE') {
734                  $ok &&= $_->(%opts);
735              } else {
736                  my @cmd = map {
737                      my $x = $_;
738                      while ($x =~ /\{([^\}]+)\}/) {
739                          $x = $`.$opts{$1}.$' if exists $opts{$1};
740                      }
741                      $x;
742                  } @$_;
743
744                  diag "CMD: openssl ", join(" ", @cmd);
745                  $ok &&= run(app(["openssl", @cmd]));
746                  $opts{input} = $opts{output};
747              }
748          }
749
750          ok($ok, $$_[0]);
751        }
752    }
753}
754
755sub final_compare {
756    my %opts = @_;
757
758    diag "Comparing $smcont with $opts{output}.txt";
759    return compare_text($smcont, "$opts{output}.txt") == 0;
760}
761
762sub zero_compare {
763    my %opts = @_;
764
765    diag "Checking for zero-length file";
766    return (-e "$opts{output}.txt" && -z "$opts{output}.txt");
767}
768
769subtest "CMS => PKCS#7 compatibility tests\n" => sub {
770    plan tests => scalar @smime_pkcs7_tests;
771
772    runner_loop(prefix => 'cms2pkcs7', cmd1 => 'cms', cmd2 => 'smime',
773                tests => [ @smime_pkcs7_tests ]);
774};
775subtest "CMS <= PKCS#7 compatibility tests\n" => sub {
776    plan tests => scalar @smime_pkcs7_tests;
777
778    runner_loop(prefix => 'pkcs72cms', cmd1 => 'smime', cmd2 => 'cms',
779                tests => [ @smime_pkcs7_tests ]);
780};
781
782subtest "CMS <=> CMS consistency tests\n" => sub {
783    plan tests => (scalar @smime_pkcs7_tests) + (scalar @smime_cms_tests);
784
785    runner_loop(prefix => 'cms2cms-1', cmd1 => 'cms', cmd2 => 'cms',
786                tests => [ @smime_pkcs7_tests ]);
787    runner_loop(prefix => 'cms2cms-2', cmd1 => 'cms', cmd2 => 'cms',
788                tests => [ @smime_cms_tests ]);
789};
790
791subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
792    plan tests =>
793        (scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests) +
794        (scalar @smime_cms_param_tests_autodigestmax) + 1;
795
796    ok(run(app(["openssl", "cms", @prov,
797                "-sign", "-in", $smcont,
798                "-outform", "PEM",
799                "-nodetach",
800                "-signer", $smrsa1,
801                "-keyopt", "rsa_padding_mode:pss",
802                "-keyopt", "rsa_pss_saltlen:auto-digestmax",
803                "-out", "digestmaxtest.cms"])));
804    # Providers that do not support rsa_pss_saltlen:auto-digestmax will parse
805    # it as 0
806    my $no_autodigestmax = rsapssSaltlen("digestmaxtest.cms") == 0;
807    1 while unlink "digestmaxtest.cms";
808
809    runner_loop(prefix => 'cms2cms-mod', cmd1 => 'cms', cmd2 => 'cms',
810                tests => [ @smime_cms_param_tests ]);
811  SKIP: {
812      skip("Zlib not supported: compression tests skipped",
813           scalar @smime_cms_comp_tests)
814          if $no_zlib;
815
816      runner_loop(prefix => 'cms2cms-comp', cmd1 => 'cms', cmd2 => 'cms',
817                  tests => [ @smime_cms_comp_tests ]);
818    }
819
820  SKIP: {
821    skip("rsa_pss_saltlen:auto-digestmax not supported",
822         scalar @smime_cms_param_tests_autodigestmax)
823       if $no_autodigestmax;
824
825       runner_loop(prefix => 'cms2cms-comp', 'cmd1' => 'cms', cmd2 => 'cms',
826                   tests => [ @smime_cms_param_tests_autodigestmax ]);
827  }
828};
829
830# Returns the number of matches of a Content Type Attribute in a binary file.
831sub contentType_matches {
832  # Read in a binary file
833  my ($in) = @_;
834  open (HEX_IN, "$in") or die("open failed for $in : $!");
835  binmode(HEX_IN);
836  local $/;
837  my $str = <HEX_IN>;
838
839  # Find ASN1 data for a Content Type Attribute (with a OID of PKCS7 data)
840  my @c = $str =~ /\x30\x18\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x03\x31\x0B\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01/gs;
841
842  close(HEX_IN);
843  return scalar(@c);
844}
845
846# Returns 1 if the smime-type matches the passed parameter, otherwise 0.
847sub smimeType_matches {
848  my ($in, $expected_smime_type) = @_;
849
850  # Read the text file
851  open(my $fh, '<', $in) or die("open failed for $in : $!");
852  local $/;
853  my $content = <$fh>;
854  close($fh);
855
856  # Extract the Content-Type line with the smime-type attribute
857  if ($content =~ /Content-Type:\s*application\/pkcs7-mime.*smime-type=([^\s;]+)/) {
858    my $smime_type = $1;
859
860    # Compare the extracted smime-type with the expected value
861    return ($smime_type eq $expected_smime_type) ? 1 : 0;
862  }
863
864  # If no smime-type is found, return 0
865  return 0;
866}
867
868sub rsapssSaltlen {
869  my ($in) = @_;
870  my $exit = 0;
871
872  my @asn1parse = run(app(["openssl", "asn1parse", "-in", $in, "-dump"]),
873                      capture => 1,
874                      statusvar => $exit);
875  return -1 if $exit != 0;
876
877  my $pssparam_offset = -1;
878  while ($_ = shift @asn1parse) {
879    chomp;
880    next unless /:rsassaPss/;
881    # This line contains :rsassaPss, the next line contains a raw dump of the
882    # RSA_PSS_PARAMS sequence; obtain its offset
883    $_ = shift @asn1parse;
884    if (/^\s*(\d+):/) {
885      $pssparam_offset = int($1);
886    }
887  }
888
889  if ($pssparam_offset == -1) {
890    note "Failed to determine RSA_PSS_PARAM offset in CMS. " +
891         "Was the file correctly signed with RSASSA-PSS?";
892    return -1;
893  }
894
895  my @pssparam = run(app(["openssl", "asn1parse", "-in", $in,
896                          "-strparse", $pssparam_offset]),
897                     capture => 1,
898                     statusvar => $exit);
899  return -1 if $exit != 0;
900
901  my $saltlen = -1;
902  # Can't use asn1parse -item RSA_PSS_PARAMS here, because that's deprecated.
903  # This assumes the salt length is the last field, which may possibly be
904  # incorrect if there is a non-standard trailer field, but there almost never
905  # is in PSS.
906  if ($pssparam[-1] =~ /prim:\s+INTEGER\s+:([A-Fa-f0-9]+)/) {
907    $saltlen = hex($1);
908  }
909
910  if ($saltlen == -1) {
911    note "Failed to determine salt length from RSA_PSS_PARAM struct. " +
912         "Was the file correctly signed with RSASSA-PSS?";
913    return -1;
914  }
915
916  return $saltlen;
917}
918
919subtest "CMS Check the content type attribute is added for additional signers\n" => sub {
920    plan tests => (scalar @contenttype_cms_test);
921
922    runner_loop(prefix => 'cms2cms-added', cmd1 => 'cms', cmd2 => 'cms',
923                tests => [ @contenttype_cms_test ]);
924};
925
926subtest "CMS Check that bad attributes fail when verifying signers\n" => sub {
927    plan tests =>
928        (scalar @incorrect_attribute_cms_test);
929
930    my $cnt = 0;
931    foreach my $name (@incorrect_attribute_cms_test) {
932        my $out = "incorrect-$cnt.txt";
933
934        ok(!run(app(["openssl", "cms", @prov, "-verify", "-in",
935                     catfile($datadir, $name), "-inform", "DER", "-CAfile",
936                     $smroot, "-out", $out ])),
937            $name);
938    }
939};
940
941subtest "CMS Check that bad encryption algorithm fails\n" => sub {
942    plan tests => 1;
943
944    SKIP: {
945        skip "DES or Legacy isn't supported in this build", 1
946            if disabled("des") || disabled("legacy");
947
948        my $out = "smtst.txt";
949
950        ok(!run(app(["openssl", "cms", @legacyprov, "-encrypt",
951                    "-in", $smcont,
952                    "-stream", "-recip", $smrsa1,
953                    "-des-ede3",
954                    "-out", $out ])),
955           "Decrypt message from OpenSSL 1.1.1");
956    }
957};
958
959subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
960    plan tests => 1;
961
962    SKIP: {
963        skip "EC or DES isn't supported in this build", 1
964            if disabled("ec") || disabled("des");
965
966        my $out = "smtst.txt";
967
968        ok(run(app(["openssl", "cms", @defaultprov, "-decrypt",
969                    "-inkey", catfile($smdir, "smec3.pem"),
970                    "-in", catfile($datadir, "ciphertext_from_1_1_1.cms"),
971                    "-out", $out ]))
972           && compare_text($smcont, $out) == 0,
973           "Decrypt message from OpenSSL 1.1.1");
974    }
975};
976
977subtest "CAdES <=> CAdES consistency tests\n" => sub {
978    plan tests => (scalar @smime_cms_cades_tests);
979
980    runner_loop(prefix => 'cms-cades', cmd1 => 'cms', cmd2 => 'cms',
981                tests => [ @smime_cms_cades_tests ]);
982};
983
984subtest "CAdES; cms incompatible arguments tests\n" => sub {
985    plan tests => (scalar @smime_cms_cades_invalid_option_tests);
986
987    foreach (@smime_cms_cades_invalid_option_tests) {
988        ok(!run(app(["openssl", "cms", @{$$_[0]} ] )));
989    }
990};
991
992subtest "CAdES ko tests\n" => sub {
993    plan tests => 2 * scalar @smime_cms_cades_ko_tests;
994
995    foreach (@smime_cms_cades_ko_tests) {
996      SKIP: {
997        my $skip_reason = check_availability($$_[0]);
998        skip $skip_reason, 1 if $skip_reason;
999        1 while unlink "cades-ko.txt";
1000
1001        ok(run(app(["openssl", "cms", @{$$_[1]}])), $$_[0]);
1002        ok(!run(app(["openssl", "cms", @{$$_[3]}])), $$_[2]);
1003        }
1004    }
1005};
1006
1007subtest "CMS binary input tests\n" => sub {
1008    my $input = srctop_file("test", "smcont.bin");
1009    my $signed = "smcont.signed";
1010    my $verified = "smcont.verified";
1011
1012    plan tests => 11;
1013
1014    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
1015                "-binary", "-in", $input, "-out", $signed])),
1016       "sign binary input with -binary");
1017    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
1018                "-binary", "-in", $signed, "-out", $verified])),
1019       "verify binary input with -binary");
1020    is(compare($input, $verified), 0, "binary input retained with -binary");
1021
1022    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
1023                "-in", $input, "-out", $signed.".nobin"])),
1024       "sign binary input without -binary");
1025    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
1026                "-in", $signed.".nobin", "-out", $verified.".nobin"])),
1027       "verify binary input without -binary");
1028    is(compare($input, $verified.".nobin"), 1, "binary input not retained without -binary");
1029    ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
1030                "-binary", "-in", $signed, "-out", $verified.".crlfeol"])),
1031       "verify binary input wrong crlfeol");
1032
1033    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
1034                "-crlfeol",
1035                "-binary", "-in", $input, "-out", $signed.".crlf"])),
1036       "sign binary input with -binary -crlfeol");
1037    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
1038                "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf"])),
1039       "verify binary input with -binary -crlfeol");
1040    is(compare($input, $verified.".crlf"), 0,
1041       "binary input retained with -binary -crlfeol");
1042    ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
1043                "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf2"])),
1044       "verify binary input with -binary missing -crlfeol");
1045};
1046
1047subtest "CMS signed digest, DER format" => sub {
1048    plan tests => 2;
1049
1050    # Pre-computed SHA256 digest of $smcont in hexadecimal form
1051    my $digest = "ff236ef61b396355f75a4cc6e1c306d4c309084ae271a9e2ad6888f10a101b32";
1052
1053    my $sig_file = "signature.der";
1054    ok(run(app(["openssl", "cms", @prov, "-sign", "-digest", $digest,
1055                    "-outform", "DER",
1056                    "-certfile", catfile($smdir, "smroot.pem"),
1057                    "-signer", catfile($smdir, "smrsa1.pem"),
1058                    "-out", $sig_file])),
1059        "CMS sign pre-computed digest, DER format");
1060
1061    ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1062                    "-inform", "DER",
1063                    "-CAfile", catfile($smdir, "smroot.pem"),
1064                    "-content", $smcont])),
1065       "Verify CMS signed digest, DER format");
1066};
1067
1068subtest "CMS signed digest, S/MIME format" => sub {
1069    plan tests => 2;
1070
1071    # Pre-computed SHA256 digest of $smcont in hexadecimal form
1072    my $digest = "ff236ef61b396355f75a4cc6e1c306d4c309084ae271a9e2ad6888f10a101b32";
1073
1074    my $sig_file = "signature.smime";
1075    ok(run(app(["openssl", "cms", @prov, "-sign", "-digest", $digest,
1076                    "-outform", "SMIME",
1077                    "-certfile", catfile($smdir, "smroot.pem"),
1078                    "-signer", catfile($smdir, "smrsa1.pem"),
1079                    "-out", $sig_file])),
1080        "CMS sign pre-computed digest, S/MIME format");
1081
1082    ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1083                    "-inform", "SMIME",
1084                    "-CAfile", catfile($smdir, "smroot.pem"),
1085                    "-content", $smcont])),
1086       "Verify CMS signed digest, S/MIME format");
1087};
1088
1089sub path_tests {
1090    our $app = shift;
1091    our @path = qw(test certs);
1092    our $key = srctop_file(@path, "ee-key.pem");
1093    our $ee = srctop_file(@path, "ee-cert.pem");
1094    our $ca = srctop_file(@path, "ca-cert.pem");
1095    our $root = srctop_file(@path, "root-cert.pem");
1096    our $sig_file = "signature.p7s";
1097
1098    sub sign {
1099        my $inter = shift;
1100        my @inter = $inter ? ("-certfile", $inter) : ();
1101        my $msg = shift;
1102        ok(run(app(["openssl", $app, @prov, "-sign", "-in", $smcont,
1103                    "-inkey", $key, "-signer", $ee, @inter,
1104                    "-out", $sig_file],
1105                   "accept $app sign with EE $msg".
1106                   " intermediate CA certificates")));
1107    }
1108    sub verify {
1109        my $inter = shift;
1110        my @inter = $inter ? ("-certfile", $inter) : ();
1111        my $msg = shift;
1112        my $res = shift;
1113        ok($res == run(app(["openssl", $app, @prov, "-verify", "-in", $sig_file,
1114                            "-purpose", "sslserver", "-CAfile", $root, @inter,
1115                            "-content", $smcont],
1116                           "accept $app verify with EE ".
1117                           "$msg intermediate CA certificates")));
1118    }
1119    sign($ca, "and");
1120    verify(0, "with included", 1);
1121    sign(0, "without");
1122    verify(0, "without", 0);
1123    verify($ca, "with added", 1);
1124};
1125subtest "CMS sign+verify cert path tests" => sub {
1126    plan tests => 5;
1127
1128    path_tests("cms");
1129};
1130subtest "PKCS7 sign+verify cert path tests" => sub {
1131    plan tests => 5;
1132
1133    path_tests("smime");
1134};
1135
1136subtest "CMS code signing test" => sub {
1137    plan tests => 7;
1138    my $sig_file = "signature.p7s";
1139    ok(run(app(["openssl", "cms", @prov, "-sign", "-in", $smcont,
1140                   "-certfile", catfile($smdir, "smroot.pem"),
1141                   "-signer", catfile($smdir, "smrsa1.pem"),
1142                   "-out", $sig_file])),
1143       "accept perform CMS signature with smime certificate");
1144
1145    ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1146                    "-CAfile", catfile($smdir, "smroot.pem"),
1147                    "-content", $smcont])),
1148       "accept verify CMS signature with smime certificate");
1149
1150    ok(!run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1151                    "-CAfile", catfile($smdir, "smroot.pem"),
1152                    "-purpose", "codesign",
1153                    "-content", $smcont])),
1154       "fail verify CMS signature with smime certificate for purpose code signing");
1155
1156    ok(!run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1157                    "-CAfile", catfile($smdir, "smroot.pem"),
1158                    "-purpose", "football",
1159                    "-content", $smcont])),
1160       "fail verify CMS signature with invalid purpose argument");
1161
1162    ok(run(app(["openssl", "cms", @prov, "-sign", "-in", $smcont,
1163                   "-certfile", catfile($smdir, "smroot.pem"),
1164                   "-signer", catfile($smdir, "csrsa1.pem"),
1165                   "-out", $sig_file])),
1166        "accept perform CMS signature with code signing certificate");
1167
1168    ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1169                    "-CAfile", catfile($smdir, "smroot.pem"),
1170                    "-purpose", "codesign",
1171                    "-content", $smcont])),
1172       "accept verify CMS signature with code signing certificate for purpose code signing");
1173
1174    ok(!run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
1175                    "-CAfile", catfile($smdir, "smroot.pem"),
1176                    "-content", $smcont])),
1177       "fail verify CMS signature with code signing certificate for purpose smime_sign");
1178};
1179
1180# Test case for missing MD algorithm (must not segfault)
1181
1182with({ exit_checker => sub { return shift == 4; } },
1183    sub {
1184        ok(run(app(['openssl', 'smime', '-verify', '-noverify',
1185                    '-inform', 'PEM',
1186                    '-in', data_file("pkcs7-md4.pem"),
1187                   ])),
1188            "Check failure of EVP_DigestInit in PKCS7 signed is handled");
1189
1190        ok(run(app(['openssl', 'smime', '-decrypt',
1191                    '-inform', 'PEM',
1192                    '-in', data_file("pkcs7-md4-encrypted.pem"),
1193                    '-recip', srctop_file("test", "certs", "ee-cert.pem"),
1194                    '-inkey', srctop_file("test", "certs", "ee-key.pem")
1195                   ])),
1196            "Check failure of EVP_DigestInit in PKCS7 signedAndEnveloped is handled");
1197    });
1198
1199sub check_availability {
1200    my $tnam = shift;
1201
1202    return "$tnam: skipped, EC disabled\n"
1203        if ($no_ec && $tnam =~ /ECDH/);
1204    return "$tnam: skipped, ECDH disabled\n"
1205        if ($no_ec && $tnam =~ /ECDH/);
1206    return "$tnam: skipped, EC2M disabled\n"
1207        if ($no_ec2m && $tnam =~ /K-283/);
1208    return "$tnam: skipped, DH disabled\n"
1209        if ($no_dh && $tnam =~ /X9\.42/);
1210    return "$tnam: skipped, RC2 disabled\n"
1211        if ($no_rc2 && $tnam =~ /RC2/);
1212    return "$tnam: skipped, DES disabled\n"
1213        if ($no_des && $tnam =~ /DES/);
1214    return "$tnam: skipped, DSA disabled\n"
1215        if ($no_dsa && $tnam =~ / DSA/);
1216
1217    return "";
1218}
1219
1220# Test case for the locking problem reported in #19643.
1221# This will fail if the fix is in and deadlock on Windows (and possibly
1222# other platforms) if not.
1223ok(!run(app(['openssl', 'cms', '-verify',
1224             '-CAfile', srctop_file("test/certs", "pkitsta.pem"),
1225             '-policy', 'anyPolicy',
1226             '-in', srctop_file("test/smime-eml",
1227                                "SignedInvalidMappingFromanyPolicyTest7.eml")
1228            ])),
1229   "issue#19643");
1230
1231# Check that we get the expected failure return code
1232with({ exit_checker => sub { return shift == 6; } },
1233    sub {
1234        ok(run(app(['openssl', 'cms', '-encrypt',
1235                    '-in', srctop_file("test", "smcont.txt"),
1236                    '-aes128', '-stream', '-recip',
1237                    srctop_file("test/smime-certs", "badrsa.pem"),
1238                   ])),
1239            "Check failure during BIO setup with -stream is handled correctly");
1240    });
1241
1242# Test case for return value mis-check reported in #21986
1243with({ exit_checker => sub { return shift == 3; } },
1244    sub {
1245        SKIP: {
1246          skip "DSA is not supported in this build", 1 if $no_dsa;
1247
1248          ok(run(app(['openssl', 'cms', '-sign',
1249                      '-in', srctop_file("test", "smcont.txt"),
1250                      '-signer', srctop_file("test/smime-certs", "smdsa1.pem"),
1251                      '-md', 'SHAKE256'])),
1252            "issue#21986");
1253        }
1254    });
1255
1256# Test for problem reported in #22225
1257with({ exit_checker => sub { return shift == 3; } },
1258    sub {
1259	ok(run(app(['openssl', 'cms', '-encrypt',
1260		    '-in', srctop_file("test", "smcont.txt"),
1261		    '-aes-256-ctr', '-recip',
1262		    catfile($smdir, "smec1.pem"),
1263		   ])),
1264	   "Check for failure when cipher does not have an assigned OID (issue#22225)");
1265     });
1266
1267# Test encrypt to three recipients, and decrypt using key-only;
1268# i.e. do not follow the recommended practice of providing the
1269# recipient cert in the decrypt op.
1270#
1271# Use RSAES-OAEP for key-transport, not RSAES-PKCS-v1_5.
1272#
1273# Because the cert is not provided during decrypt, all RSA ciphertexts
1274# are decrypted in turn, and when/if there is a valid decryption, it
1275# is assumed the correct content-key has been recovered.
1276#
1277# That process may fail with RSAES-PKCS-v1_5 b/c there is a
1278# non-negligible chance that decrypting a random input using
1279# RSAES-PKCS-v1_5 can result in a valid plaintext (so two content-keys
1280# could be recovered and the wrong one might be used).
1281#
1282# See https://github.com/openssl/project/issues/380
1283subtest "encrypt to three recipients with RSA-OAEP, key only decrypt" => sub {
1284    plan tests => 3;
1285
1286    my $pt = srctop_file("test", "smcont.txt");
1287    my $ct = "smtst.cms";
1288    my $ptpt = "smtst.txt";
1289
1290    ok(run(app(['openssl', 'cms',
1291		@defaultprov,
1292		'-encrypt', '-aes128',
1293		'-in', $pt,
1294		'-out', $ct,
1295		'-stream',
1296		'-recip', catfile($smdir, "smrsa1.pem"),
1297		'-keyopt', 'rsa_padding_mode:oaep',
1298		'-recip', catfile($smdir, "smrsa2.pem"),
1299		'-keyopt', 'rsa_padding_mode:oaep',
1300		'-recip', catfile($smdir, "smrsa3-cert.pem"),
1301		'-keyopt', 'rsa_padding_mode:oaep',
1302	       ])),
1303       "encrypt to three recipients with RSA-OAEP (avoid openssl/project issue#380)");
1304    ok(run(app(['openssl', 'cms',
1305		@defaultprov,
1306		'-decrypt', '-aes128',
1307		'-in', $ct,
1308		'-out', $ptpt,
1309		'-inkey', catfile($smdir, "smrsa3-key.pem"),
1310	       ])),
1311       "decrypt with key only");
1312    is(compare($pt, $ptpt), 0, "compare original message with decrypted ciphertext");
1313};
1314