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