Tests for processing zero-length content in SMIME format
[openssl.git] / test / recipes / 80-test_cms.t
1 #! /usr/bin/env perl
2 # Copyright 2015-2020 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
10 use strict;
11 use warnings;
12
13 use POSIX;
14 use File::Spec::Functions qw/catfile/;
15 use File::Compare qw/compare_text/;
16 use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
17
18 use OpenSSL::Test::Utils;
19
20 BEGIN {
21     setup("test_cms");
22 }
23
24 use lib srctop_dir('Configurations');
25 use lib bldtop_dir('.');
26 use platform;
27
28 my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
29
30 plan skip_all => "CMS is not supported by this OpenSSL build"
31     if disabled("cms");
32
33 my $provpath = bldtop_dir("providers");
34
35 # Some tests require legacy algorithms to be included.
36 my @legacyprov = ("-provider-path", $provpath,
37                   "-provider", "default",
38                   "-provider", "legacy" );
39 my @defaultprov = ("-provider-path", $provpath,
40                    "-provider", "default");
41
42 my @config = ( );
43 my $provname = 'default';
44
45 my $datadir = srctop_dir("test", "recipes", "80-test_cms_data");
46 my $smdir    = srctop_dir("test", "smime-certs");
47 my $smcont   = srctop_file("test", "smcont.txt");
48 my $smcont_zero = srctop_file("test", "smcont_zero.txt");
49 my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
50     = disabled qw/des dh dsa ec ec2m rc2 zlib/;
51
52 plan tests =>
53     ($no_fips ? 0 : 1)          # FIPS install test
54     + 10;
55
56 unless ($no_fips) {
57     my $infile = bldtop_file('providers', platform->dso('fips'));
58
59     ok(run(app(['openssl', 'fipsinstall',
60                 '-out', bldtop_file('providers', 'fipsmodule.cnf'),
61                 '-module', $infile])),
62        "fipsinstall");
63     @config = ( "-config", srctop_file("test", "fips-and-base.cnf") );
64     $provname = 'fips';
65 }
66
67 $ENV{OPENSSL_TEST_LIBCTX} = "1";
68 my @prov = ("-provider-path", $provpath,
69             @config,
70             "-provider", $provname);
71
72 my @smime_pkcs7_tests = (
73
74     [ "signed content DER format, RSA key",
75       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
76         "-certfile", catfile($smdir, "smroot.pem"),
77         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
78       [ "{cmd2}",  @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
79         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
80       \&final_compare
81     ],
82
83     [ "signed detached content DER format, RSA key",
84       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
85         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
86       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
87         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
88         "-content", $smcont ],
89       \&final_compare
90     ],
91
92     [ "signed content test streaming BER format, RSA",
93       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
94         "-stream",
95         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
96       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
97         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
98       \&final_compare
99     ],
100
101     [ "signed content DER format, DSA key",
102       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
103         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
104       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
105         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
106       \&final_compare
107     ],
108
109     [ "signed detached content DER format, DSA key",
110       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
111         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
112       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
113         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
114         "-content", $smcont ],
115       \&final_compare
116     ],
117
118     [ "signed detached content DER format, add RSA signer (with DSA existing)",
119       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
120         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
121       [ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
122         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}2.cms" ],
123       [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
124         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
125         "-content", $smcont ],
126       \&final_compare
127     ],
128
129     [ "signed content test streaming BER format, DSA key",
130       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
131         "-nodetach", "-stream",
132         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
133       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
134         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
135       \&final_compare
136     ],
137
138     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
139       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
140         "-nodetach", "-stream",
141         "-signer", catfile($smdir, "smrsa1.pem"),
142         "-signer", catfile($smdir, "smrsa2.pem"),
143         "-signer", catfile($smdir, "smdsa1.pem"),
144         "-signer", catfile($smdir, "smdsa2.pem"),
145         "-out", "{output}.cms" ],
146       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
147         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
148       \&final_compare
149     ],
150
151     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
152       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
153         "-noattr", "-nodetach", "-stream",
154         "-signer", catfile($smdir, "smrsa1.pem"),
155         "-signer", catfile($smdir, "smrsa2.pem"),
156         "-signer", catfile($smdir, "smdsa1.pem"),
157         "-signer", catfile($smdir, "smdsa2.pem"),
158         "-out", "{output}.cms" ],
159       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
160         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
161       \&final_compare
162     ],
163
164     [ "signed content S/MIME format, RSA key SHA1",
165       [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-md", "sha1",
166         "-certfile", catfile($smdir, "smroot.pem"),
167         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
168       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
169         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
170       \&final_compare
171     ],
172
173     [ "signed zero-length content S/MIME format, RSA key SHA1",
174       [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont_zero, "-md", "sha1",
175         "-certfile", catfile($smdir, "smroot.pem"),
176         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
177       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
178         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
179       \&zero_compare
180     ],
181
182     [ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
183       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
184         "-signer", catfile($smdir, "smrsa1.pem"),
185         "-signer", catfile($smdir, "smrsa2.pem"),
186         "-signer", catfile($smdir, "smdsa1.pem"),
187         "-signer", catfile($smdir, "smdsa2.pem"),
188         "-stream", "-out", "{output}.cms" ],
189       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
190         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
191       \&final_compare
192     ],
193
194     [ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
195       [ "{cmd1}", @prov, "-sign", "-in", $smcont,
196         "-signer", catfile($smdir, "smrsa1.pem"),
197         "-signer", catfile($smdir, "smrsa2.pem"),
198         "-signer", catfile($smdir, "smdsa1.pem"),
199         "-signer", catfile($smdir, "smdsa2.pem"),
200         "-stream", "-out", "{output}.cms" ],
201       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
202         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
203       \&final_compare
204     ],
205
206     [ "enveloped content test streaming S/MIME format, DES, 3 recipients",
207       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
208         "-stream", "-out", "{output}.cms",
209         catfile($smdir, "smrsa1.pem"),
210         catfile($smdir, "smrsa2.pem"),
211         catfile($smdir, "smrsa3.pem") ],
212       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
213         "-in", "{output}.cms", "-out", "{output}.txt" ],
214       \&final_compare
215     ],
216
217     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, 3rd used",
218       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
219         "-stream", "-out", "{output}.cms",
220         catfile($smdir, "smrsa1.pem"),
221         catfile($smdir, "smrsa2.pem"),
222         catfile($smdir, "smrsa3.pem") ],
223       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
224         "-in", "{output}.cms", "-out", "{output}.txt" ],
225       \&final_compare
226     ],
227
228     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, key only used",
229       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
230         "-stream", "-out", "{output}.cms",
231         catfile($smdir, "smrsa1.pem"),
232         catfile($smdir, "smrsa2.pem"),
233         catfile($smdir, "smrsa3.pem") ],
234       [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"),
235         "-in", "{output}.cms", "-out", "{output}.txt" ],
236       \&final_compare
237     ],
238
239     [ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
240       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
241         "-aes256", "-stream", "-out", "{output}.cms",
242         catfile($smdir, "smrsa1.pem"),
243         catfile($smdir, "smrsa2.pem"),
244         catfile($smdir, "smrsa3.pem") ],
245       [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
246         "-in", "{output}.cms", "-out", "{output}.txt" ],
247       \&final_compare
248     ],
249
250 );
251
252 my @smime_cms_tests = (
253
254     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
255       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
256         "-nodetach", "-keyid",
257         "-signer", catfile($smdir, "smrsa1.pem"),
258         "-signer", catfile($smdir, "smrsa2.pem"),
259         "-signer", catfile($smdir, "smdsa1.pem"),
260         "-signer", catfile($smdir, "smdsa2.pem"),
261         "-stream", "-out", "{output}.cms" ],
262       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
263         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
264       \&final_compare
265     ],
266
267     [ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
268       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
269         "-signer", catfile($smdir, "smrsa1.pem"),
270         "-signer", catfile($smdir, "smrsa2.pem"),
271         "-signer", catfile($smdir, "smdsa1.pem"),
272         "-signer", catfile($smdir, "smdsa2.pem"),
273         "-stream", "-out", "{output}.cms" ],
274       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
275         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
276       \&final_compare
277     ],
278
279     [ "signed content MIME format, RSA key, signed receipt request",
280       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
281         "-signer", catfile($smdir, "smrsa1.pem"),
282         "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
283         "-out", "{output}.cms" ],
284       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
285         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
286       \&final_compare
287     ],
288
289     [ "signed receipt MIME format, RSA key",
290       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
291         "-signer", catfile($smdir, "smrsa1.pem"),
292         "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
293         "-out", "{output}.cms" ],
294       [ "{cmd1}", @prov, "-sign_receipt", "-in", "{output}.cms",
295         "-signer", catfile($smdir, "smrsa2.pem"), "-out", "{output}2.cms" ],
296       [ "{cmd2}", @prov, "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
297         "-CAfile", catfile($smdir, "smroot.pem") ]
298     ],
299
300     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
301       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
302         "-stream", "-out", "{output}.cms", "-keyid",
303         catfile($smdir, "smrsa1.pem"),
304         catfile($smdir, "smrsa2.pem"),
305         catfile($smdir, "smrsa3.pem") ],
306       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
307         "-in", "{output}.cms", "-out", "{output}.txt" ],
308       \&final_compare
309     ],
310
311     [ "enveloped content test streaming PEM format, AES-256-CBC cipher, KEK",
312       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
313         "-stream", "-out", "{output}.cms",
314         "-secretkey", "000102030405060708090A0B0C0D0E0F",
315         "-secretkeyid", "C0FEE0" ],
316       [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
317         "-inform", "PEM",
318         "-secretkey", "000102030405060708090A0B0C0D0E0F",
319         "-secretkeyid", "C0FEE0" ],
320       \&final_compare
321     ],
322
323     [ "enveloped content test streaming PEM format, AES-256-GCM cipher, KEK",
324       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes-128-gcm",
325         "-stream", "-out", "{output}.cms",
326         "-secretkey", "000102030405060708090A0B0C0D0E0F",
327         "-secretkeyid", "C0FEE0" ],
328       [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
329         "-inform", "PEM",
330         "-secretkey", "000102030405060708090A0B0C0D0E0F",
331         "-secretkeyid", "C0FEE0" ],
332       \&final_compare
333     ],
334
335     [ "enveloped content test streaming PEM format, KEK, key only",
336       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
337         "-stream", "-out", "{output}.cms",
338         "-secretkey", "000102030405060708090A0B0C0D0E0F",
339         "-secretkeyid", "C0FEE0" ],
340       [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
341         "-inform", "PEM",
342         "-secretkey", "000102030405060708090A0B0C0D0E0F" ],
343       \&final_compare
344     ],
345
346     [ "data content test streaming PEM format",
347       [ "{cmd1}", @prov, "-data_create", "-in", $smcont, "-outform", "PEM",
348         "-nodetach", "-stream", "-out", "{output}.cms" ],
349       [ "{cmd2}", @prov, "-data_out", "-in", "{output}.cms", "-inform", "PEM",
350         "-out", "{output}.txt" ],
351       \&final_compare
352     ],
353
354     [ "encrypted content test streaming PEM format, 128 bit RC2 key",
355       [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
356         "-in", $smcont, "-outform", "PEM",
357         "-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
358         "-stream", "-out", "{output}.cms" ],
359       [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
360         "-inform", "PEM",
361         "-secretkey", "000102030405060708090A0B0C0D0E0F",
362         "-out", "{output}.txt" ],
363       \&final_compare
364     ],
365
366     [ "encrypted content test streaming PEM format, 40 bit RC2 key",
367       [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
368         "-in", $smcont, "-outform", "PEM",
369         "-rc2", "-secretkey", "0001020304",
370         "-stream", "-out", "{output}.cms" ],
371       [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
372         "-inform", "PEM",
373         "-secretkey", "0001020304", "-out", "{output}.txt" ],
374       \&final_compare
375     ],
376
377     [ "encrypted content test streaming PEM format, triple DES key",
378       [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
379         "-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
380         "-stream", "-out", "{output}.cms" ],
381       [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
382         "-inform", "PEM",
383         "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
384         "-out", "{output}.txt" ],
385       \&final_compare
386     ],
387
388     [ "encrypted content test streaming PEM format, 128 bit AES key",
389       [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
390         "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
391         "-stream", "-out", "{output}.cms" ],
392       [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
393         "-inform", "PEM",
394         "-secretkey", "000102030405060708090A0B0C0D0E0F",
395         "-out", "{output}.txt" ],
396       \&final_compare
397     ],
398 );
399
400 my @smime_cms_cades_tests = (
401
402     [ "signed content DER format, RSA key, CAdES-BES compatible",
403       [ "{cmd1}", @prov, "-sign", "-cades", "-in", $smcont, "-outform", "DER",
404          "-nodetach",
405         "-certfile", catfile($smdir, "smroot.pem"),
406         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
407       [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
408         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
409       \&final_compare
410     ],
411
412     [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
413       [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
414         "DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
415         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
416       [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
417         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
418       \&final_compare
419     ],
420
421     [ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
422       [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
423         "DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
424         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
425       [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
426         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
427       \&final_compare
428     ],
429
430     [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
431       [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
432         "-in", $smcont, "-outform", "DER", 
433         "-certfile", catfile($smdir, "smroot.pem"),
434         "-signer", catfile($smdir, "smrsa1.pem"),
435         "-outform", "DER", "-out", "{output}.cms"  ],
436       [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
437         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
438       \&final_compare
439     ],
440
441     [ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
442       [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
443         "-in", $smcont, "-outform", "DER", 
444         "-certfile", catfile($smdir, "smroot.pem"),
445         "-signer", catfile($smdir, "smrsa1.pem"),
446         "-outform", "DER", "-out", "{output}.cms"  ],
447       [ "{cmd1}", @prov, "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
448         "-inform", "DER", "-in", "{output}.cms",
449         "-certfile", catfile($smdir, "smroot.pem"),
450         "-signer", catfile($smdir, "smrsa2.pem"),
451         "-outform", "DER", "-out", "{output}2.cms" ],
452
453       [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
454         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
455       \&final_compare
456     ],
457 );
458
459 my @smime_cms_cades_ko_tests = (
460     [ "signed content DER format, RSA key, but verified as CAdES-BES compatible",
461       [ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
462         "-certfile", catfile($smdir, "smroot.pem"),
463         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
464       [ @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
465         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
466       \&final_compare
467     ]
468 );
469
470 # cades options test - check that some combinations are rejected
471 my @smime_cms_cades_invalid_option_tests = (
472     [
473         [ "-cades", "-noattr" ],
474     ],[
475         [ "-verify", "-cades", "-noattr" ],
476     ],[
477         [ "-verify", "-cades", "-noverify" ],
478     ],
479 );
480
481 my @smime_cms_comp_tests = (
482
483     [ "compressed content test streaming PEM format",
484       [ "{cmd1}", @prov, "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
485         "-stream", "-out", "{output}.cms" ],
486       [ "{cmd2}", @prov, "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
487         "-out", "{output}.txt" ],
488       \&final_compare
489     ]
490
491 );
492
493 my @smime_cms_param_tests = (
494     [ "signed content test streaming PEM format, RSA keys, PSS signature",
495       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
496         "-signer", catfile($smdir, "smrsa1.pem"),
497         "-keyopt", "rsa_padding_mode:pss",
498         "-out", "{output}.cms" ],
499       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
500         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
501       \&final_compare
502     ],
503
504     [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=max",
505       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
506         "-signer", catfile($smdir, "smrsa1.pem"),
507         "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:max",
508         "-out", "{output}.cms" ],
509       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
510         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
511       \&final_compare
512     ],
513
514     [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
515       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
516         "-noattr",
517         "-signer", catfile($smdir, "smrsa1.pem"),
518         "-keyopt", "rsa_padding_mode:pss",
519         "-out", "{output}.cms" ],
520       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
521         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
522       \&final_compare
523     ],
524
525     [ "signed content test streaming PEM format, RSA keys, PSS signature, SHA384 MGF1",
526       [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
527         "-signer", catfile($smdir, "smrsa1.pem"),
528         "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_mgf1_md:sha384",
529         "-out", "{output}.cms" ],
530       [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
531         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
532       \&final_compare
533     ],
534
535     [ "enveloped content test streaming S/MIME format, DES, OAEP default parameters",
536       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
537         "-stream", "-out", "{output}.cms",
538         "-recip", catfile($smdir, "smrsa1.pem"),
539         "-keyopt", "rsa_padding_mode:oaep" ],
540       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
541         "-in", "{output}.cms", "-out", "{output}.txt" ],
542       \&final_compare
543     ],
544
545     [ "enveloped content test streaming S/MIME format, DES, OAEP SHA256",
546       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
547         "-stream", "-out", "{output}.cms",
548         "-recip", catfile($smdir, "smrsa1.pem"),
549         "-keyopt", "rsa_padding_mode:oaep",
550         "-keyopt", "rsa_oaep_md:sha256" ],
551       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
552         "-in", "{output}.cms", "-out", "{output}.txt" ],
553       \&final_compare
554     ],
555
556     [ "enveloped content test streaming S/MIME format, DES, ECDH",
557       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
558         "-stream", "-out", "{output}.cms",
559         "-recip", catfile($smdir, "smec1.pem") ],
560       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
561         "-in", "{output}.cms", "-out", "{output}.txt" ],
562       \&final_compare
563     ],
564
565     [ "enveloped content test streaming S/MIME format, DES, ECDH, 2 recipients, key only used",
566       [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
567         "-stream", "-out", "{output}.cms",
568         catfile($smdir, "smec1.pem"),
569         catfile($smdir, "smec3.pem") ],
570       [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
571         "-in", "{output}.cms", "-out", "{output}.txt" ],
572       \&final_compare
573     ],
574
575     [ "enveloped content test streaming S/MIME format, ECDH, DES, key identifier",
576       [ "{cmd1}", @defaultprov, "-encrypt", "-keyid", "-in", $smcont,
577         "-stream", "-out", "{output}.cms",
578         "-recip", catfile($smdir, "smec1.pem") ],
579       [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
580         "-in", "{output}.cms", "-out", "{output}.txt" ],
581       \&final_compare
582     ],
583
584     [ "enveloped content test streaming S/MIME format, ECDH, AES-128-CBC, SHA256 KDF",
585       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
586         "-stream", "-out", "{output}.cms",
587         "-recip", catfile($smdir, "smec1.pem"), "-aes128",
588         "-keyopt", "ecdh_kdf_md:sha256" ],
589       [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
590         "-in", "{output}.cms", "-out", "{output}.txt" ],
591       \&final_compare
592     ],
593
594     [ "enveloped content test streaming S/MIME format, ECDH, AES-128-GCM cipher, SHA256 KDF",
595       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
596         "-stream", "-out", "{output}.cms",
597         "-recip", catfile($smdir, "smec1.pem"), "-aes-128-gcm", "-keyopt", "ecdh_kdf_md:sha256" ],
598       [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
599               "-in", "{output}.cms", "-out", "{output}.txt" ],
600       \&final_compare
601     ],
602
603     [ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
604       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
605         "-stream", "-out", "{output}.cms",
606         "-recip", catfile($smdir, "smec2.pem"), "-aes128",
607         "-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
608       [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
609         "-in", "{output}.cms", "-out", "{output}.txt" ],
610       \&final_compare
611     ]
612
613     # TODO(3.0) Add this test back in when "dhpublicnumber" is supported
614     # in the keymanger.
615     #[ "enveloped content test streaming S/MIME format, X9.42 DH",
616     #  [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
617     #    "-stream", "-out", "{output}.cms",
618     #    "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
619     #  [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
620     #    "-in", "{output}.cms", "-out", "{output}.txt" ],
621     #  \&final_compare
622     #]
623 );
624
625 my @contenttype_cms_test = (
626     [ "signed content test - check that content type is added to additional signerinfo, RSA keys",
627       [ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
628         "-outform", "DER",
629         "-signer", catfile($smdir, "smrsa1.pem"), "-md", "SHA256",
630         "-out", "{output}.cms" ],
631       [ "{cmd1}", @prov, "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
632         "-inform", "DER", "-outform", "DER",
633         "-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256",
634         "-out", "{output}2.cms" ],
635       sub { my %opts = @_; contentType_matches("$opts{output}2.cms") == 2; },
636       [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
637         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ]
638     ],
639 );
640
641 my @incorrect_attribute_cms_test = (
642     "bad_signtime_attr.cms",
643     "no_ct_attr.cms",
644     "no_md_attr.cms",
645     "ct_multiple_attr.cms"
646 );
647
648 # Runs a standard loop on the input array
649 sub runner_loop {
650     my %opts = ( @_ );
651     my $cnt1 = 0;
652
653     foreach (@{$opts{tests}}) {
654         $cnt1++;
655         $opts{output} = "$opts{prefix}-$cnt1";
656       SKIP: {
657           my $skip_reason = check_availability($$_[0]);
658           skip $skip_reason, 1 if $skip_reason;
659           my $ok = 1;
660           1 while unlink "$opts{output}.txt";
661
662           foreach (@$_[1..$#$_]) {
663               if (ref $_ eq 'CODE') {
664                   $ok &&= $_->(%opts);
665               } else {
666                   my @cmd = map {
667                       my $x = $_;
668                       while ($x =~ /\{([^\}]+)\}/) {
669                           $x = $`.$opts{$1}.$' if exists $opts{$1};
670                       }
671                       $x;
672                   } @$_;
673
674                   diag "CMD: openssl ", join(" ", @cmd);
675                   $ok &&= run(app(["openssl", @cmd]));
676                   $opts{input} = $opts{output};
677               }
678           }
679
680           ok($ok, $$_[0]);
681         }
682     }
683 }
684
685 sub final_compare {
686     my %opts = @_;
687
688     diag "Comparing $smcont with $opts{output}.txt";
689     return compare_text($smcont, "$opts{output}.txt") == 0;
690 }
691
692 sub zero_compare {
693     my %opts = @_;
694
695     diag "Checking for zero-length file";
696     return (-e "$opts{output}.txt" && -z "$opts{output}.txt");
697 }
698
699 subtest "CMS => PKCS#7 compatibility tests\n" => sub {
700     plan tests => scalar @smime_pkcs7_tests;
701
702     runner_loop(prefix => 'cms2pkcs7', cmd1 => 'cms', cmd2 => 'smime',
703                 tests => [ @smime_pkcs7_tests ]);
704 };
705 subtest "CMS <= PKCS#7 compatibility tests\n" => sub {
706     plan tests => scalar @smime_pkcs7_tests;
707
708     runner_loop(prefix => 'pkcs72cms', cmd1 => 'smime', cmd2 => 'cms',
709                 tests => [ @smime_pkcs7_tests ]);
710 };
711
712 subtest "CMS <=> CMS consistency tests\n" => sub {
713     plan tests => (scalar @smime_pkcs7_tests) + (scalar @smime_cms_tests);
714
715     runner_loop(prefix => 'cms2cms-1', cmd1 => 'cms', cmd2 => 'cms',
716                 tests => [ @smime_pkcs7_tests ]);
717     runner_loop(prefix => 'cms2cms-2', cmd1 => 'cms', cmd2 => 'cms',
718                 tests => [ @smime_cms_tests ]);
719 };
720
721 subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
722     plan tests =>
723         (scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests);
724
725     runner_loop(prefix => 'cms2cms-mod', cmd1 => 'cms', cmd2 => 'cms',
726                 tests => [ @smime_cms_param_tests ]);
727   SKIP: {
728       skip("Zlib not supported: compression tests skipped",
729            scalar @smime_cms_comp_tests)
730           if $no_zlib;
731
732       runner_loop(prefix => 'cms2cms-comp', cmd1 => 'cms', cmd2 => 'cms',
733                   tests => [ @smime_cms_comp_tests ]);
734     }
735 };
736
737 # Returns the number of matches of a Content Type Attribute in a binary file.
738 sub contentType_matches {
739   # Read in a binary file
740   my ($in) = @_;
741   open (HEX_IN, "$in") or die("open failed for $in : $!");
742   binmode(HEX_IN);
743   local $/;
744   my $str = <HEX_IN>;
745
746   # Find ASN1 data for a Content Type Attribute (with a OID of PKCS7 data)
747   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;
748
749   close(HEX_IN);
750   return scalar(@c);
751 }
752
753 subtest "CMS Check the content type attribute is added for additional signers\n" => sub {
754     plan tests => (scalar @contenttype_cms_test);
755
756     runner_loop(prefix => 'cms2cms-added', cmd1 => 'cms', cmd2 => 'cms',
757                 tests => [ @contenttype_cms_test ]);
758 };
759
760 subtest "CMS Check that bad attributes fail when verifying signers\n" => sub {
761     plan tests =>
762         (scalar @incorrect_attribute_cms_test);
763
764     my $cnt = 0;
765     foreach my $name (@incorrect_attribute_cms_test) {
766         my $out = "incorrect-$cnt.txt";
767
768         ok(!run(app(["openssl", "cms", @prov, "-verify", "-in",
769                      catfile($datadir, $name), "-inform", "DER", "-CAfile",
770                      catfile($smdir, "smroot.pem"), "-out", $out ])),
771             $name);
772     }
773 };
774
775 subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
776     plan tests => 1;
777
778     SKIP: {
779         skip "EC or DES isn't supported in this build", 1
780             if disabled("ec") || disabled("des");
781
782         my $out = "smtst.txt";
783
784         ok(run(app(["openssl", "cms", @defaultprov, "-decrypt",
785                     "-inkey", catfile($smdir, "smec3.pem"),
786                     "-in", catfile($datadir, "ciphertext_from_1_1_1.cms"),
787                     "-out", $out ]))
788            && compare_text($smcont, $out) == 0,
789            "Decrypt message from OpenSSL 1.1.1");
790     }
791 };
792
793 subtest "CAdES <=> CAdES consistency tests\n" => sub {
794     plan tests => (scalar @smime_cms_cades_tests);
795
796     runner_loop(prefix => 'cms-cades', cmd1 => 'cms', cmd2 => 'cms',
797                 tests => [ @smime_cms_cades_tests ]);
798 };
799
800 subtest "CAdES; cms incompatible arguments tests\n" => sub {
801     plan tests => (scalar @smime_cms_cades_invalid_option_tests);
802
803     foreach (@smime_cms_cades_invalid_option_tests) {
804         ok(!run(app(["openssl", "cms", @{$$_[0]} ] )));
805     }
806 };
807
808 subtest "CAdES ko tests\n" => sub {
809     plan tests => (scalar @smime_cms_cades_ko_tests);
810
811     foreach (@smime_cms_cades_ko_tests) {
812       SKIP: {
813         my $skip_reason = check_availability($$_[0]);
814         skip $skip_reason, 1 if $skip_reason;
815
816         ok(run(app(["openssl", "cms", @{$$_[1]}]))
817             && !run(app(["openssl", "cms", @{$$_[2]}])),
818             $$_[0]);
819         }
820     }
821 };
822
823 sub check_availability {
824     my $tnam = shift;
825
826     return "$tnam: skipped, EC disabled\n"
827         if ($no_ec && $tnam =~ /ECDH/);
828     return "$tnam: skipped, ECDH disabled\n"
829         if ($no_ec && $tnam =~ /ECDH/);
830     return "$tnam: skipped, EC2M disabled\n"
831         if ($no_ec2m && $tnam =~ /K-283/);
832     return "$tnam: skipped, DH disabled\n"
833         if ($no_dh && $tnam =~ /X9\.42/);
834     return "$tnam: skipped, RC2 disabled\n"
835         if ($no_rc2 && $tnam =~ /RC2/);
836     return "$tnam: skipped, DES disabled\n"
837         if ($no_des && $tnam =~ /DES/);
838     return "$tnam: skipped, DSA disabled\n"
839         if ($no_dsa && $tnam =~ / DSA/);
840
841     return "";
842 }