• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#! /usr/bin/env perl
2# Copyright 2015-2023 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);
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 => 16;
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 $smrsa1024 = catfile($smdir, "smrsa1024.pem");
68my $smrsa1 = catfile($smdir, "smrsa1.pem");
69my $smroot = catfile($smdir, "smroot.pem");
70
71my @smime_pkcs7_tests = (
72
73    [ "signed content DER format, RSA key",
74      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
75        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
76      [ "{cmd2}",  @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
77        "-CAfile", $smroot, "-out", "{output}.txt" ],
78      \&final_compare
79    ],
80
81    [ "signed detached content DER format, RSA key",
82      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
83        "-signer", $smrsa1, "-out", "{output}.cms" ],
84      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
85        "-CAfile", $smroot, "-out", "{output}.txt",
86        "-content", $smcont ],
87      \&final_compare
88    ],
89
90    [ "signed content test streaming BER format, RSA",
91      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
92        "-stream",
93        "-signer", $smrsa1, "-out", "{output}.cms" ],
94      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
95        "-CAfile", $smroot, "-out", "{output}.txt" ],
96      \&final_compare
97    ],
98
99    [ "signed content DER format, DSA key",
100      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
101        "-signer", catfile($smdir, "smdsa1.pem"), "-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 detached content DER format, DSA key",
108      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
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        "-content", $smcont ],
113      \&final_compare
114    ],
115
116    [ "signed detached content DER format, add RSA signer (with DSA existing)",
117      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
118        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
119      [ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
120        "-signer", $smrsa1, "-out", "{output}2.cms" ],
121      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
122        "-CAfile", $smroot, "-out", "{output}.txt",
123        "-content", $smcont ],
124      \&final_compare
125    ],
126
127    [ "signed content test streaming BER format, DSA key",
128      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
129        "-nodetach", "-stream",
130        "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
131      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
132        "-CAfile", $smroot, "-out", "{output}.txt" ],
133      \&final_compare
134    ],
135
136    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
137      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
138        "-nodetach", "-stream",
139        "-signer", $smrsa1,
140        "-signer", catfile($smdir, "smrsa2.pem"),
141        "-signer", catfile($smdir, "smdsa1.pem"),
142        "-signer", catfile($smdir, "smdsa2.pem"),
143        "-out", "{output}.cms" ],
144      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
145        "-CAfile", $smroot, "-out", "{output}.txt" ],
146      \&final_compare
147    ],
148
149    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
150      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
151        "-noattr", "-nodetach", "-stream",
152        "-signer", $smrsa1,
153        "-signer", catfile($smdir, "smrsa2.pem"),
154        "-signer", catfile($smdir, "smdsa1.pem"),
155        "-signer", catfile($smdir, "smdsa2.pem"),
156        "-out", "{output}.cms" ],
157      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
158        "-CAfile", $smroot, "-out", "{output}.txt" ],
159      \&final_compare
160    ],
161
162    [ "signed content S/MIME format, RSA key SHA1",
163      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-md", "sha1",
164        "-certfile", $smroot,
165        "-signer", $smrsa1, "-out", "{output}.cms" ],
166      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
167        "-CAfile", $smroot, "-out", "{output}.txt" ],
168      \&final_compare
169    ],
170
171    [ "signed zero-length content S/MIME format, RSA key SHA1",
172      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont_zero, "-md", "sha1",
173        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
174      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
175        "-CAfile", $smroot, "-out", "{output}.txt" ],
176      \&zero_compare
177    ],
178
179    [ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
180      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
181        "-signer", $smrsa1,
182        "-signer", catfile($smdir, "smrsa2.pem"),
183        "-signer", catfile($smdir, "smdsa1.pem"),
184        "-signer", catfile($smdir, "smdsa2.pem"),
185        "-stream", "-out", "{output}.cms" ],
186      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
187        "-CAfile", $smroot, "-out", "{output}.txt" ],
188      \&final_compare
189    ],
190
191    [ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
192      [ "{cmd1}", @prov, "-sign", "-in", $smcont,
193        "-signer", $smrsa1,
194        "-signer", catfile($smdir, "smrsa2.pem"),
195        "-signer", catfile($smdir, "smdsa1.pem"),
196        "-signer", catfile($smdir, "smdsa2.pem"),
197        "-stream", "-out", "{output}.cms" ],
198      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
199        "-CAfile", $smroot, "-out", "{output}.txt" ],
200      \&final_compare
201    ],
202
203    [ "enveloped content test streaming S/MIME format, DES, 3 recipients",
204      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
205        "-stream", "-out", "{output}.cms",
206        $smrsa1,
207        catfile($smdir, "smrsa2.pem"),
208        catfile($smdir, "smrsa3.pem") ],
209      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
210        "-in", "{output}.cms", "-out", "{output}.txt" ],
211      \&final_compare
212    ],
213
214    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, 3rd used",
215      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
216        "-stream", "-out", "{output}.cms",
217        $smrsa1,
218        catfile($smdir, "smrsa2.pem"),
219        catfile($smdir, "smrsa3.pem") ],
220      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
221        "-in", "{output}.cms", "-out", "{output}.txt" ],
222      \&final_compare
223    ],
224
225    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, key only used",
226      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
227        "-stream", "-out", "{output}.cms",
228        $smrsa1,
229        catfile($smdir, "smrsa2.pem"),
230        catfile($smdir, "smrsa3.pem") ],
231      [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"),
232        "-in", "{output}.cms", "-out", "{output}.txt" ],
233      \&final_compare
234    ],
235
236    [ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
237      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
238        "-aes256", "-stream", "-out", "{output}.cms",
239        $smrsa1,
240        catfile($smdir, "smrsa2.pem"),
241        catfile($smdir, "smrsa3.pem") ],
242      [ "{cmd2}", @prov, "-decrypt", "-recip", $smrsa1,
243        "-in", "{output}.cms", "-out", "{output}.txt" ],
244      \&final_compare
245    ],
246
247);
248
249my @smime_cms_tests = (
250
251    [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
252      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
253        "-nodetach", "-keyid",
254        "-signer", $smrsa1,
255        "-signer", catfile($smdir, "smrsa2.pem"),
256        "-signer", catfile($smdir, "smdsa1.pem"),
257        "-signer", catfile($smdir, "smdsa2.pem"),
258        "-stream", "-out", "{output}.cms" ],
259      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
260        "-CAfile", $smroot, "-out", "{output}.txt" ],
261      \&final_compare
262    ],
263
264    [ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
265      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
266        "-signer", $smrsa1,
267        "-signer", catfile($smdir, "smrsa2.pem"),
268        "-signer", catfile($smdir, "smdsa1.pem"),
269        "-signer", catfile($smdir, "smdsa2.pem"),
270        "-stream", "-out", "{output}.cms" ],
271      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
272        "-CAfile", $smroot, "-out", "{output}.txt" ],
273      \&final_compare
274    ],
275
276    [ "signed content MIME format, RSA key, signed receipt request",
277      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
278        "-signer", $smrsa1,
279        "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
280        "-out", "{output}.cms" ],
281      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
282        "-CAfile", $smroot, "-out", "{output}.txt" ],
283      \&final_compare
284    ],
285
286    [ "signed receipt MIME format, RSA key",
287      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
288        "-signer", $smrsa1,
289        "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
290        "-out", "{output}.cms" ],
291      [ "{cmd1}", @prov, "-sign_receipt", "-in", "{output}.cms",
292        "-signer", catfile($smdir, "smrsa2.pem"), "-out", "{output}2.cms" ],
293      [ "{cmd2}", @prov, "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
294        "-CAfile", $smroot ]
295    ],
296
297    [ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
298      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
299        "-stream", "-out", "{output}.cms", "-keyid",
300        $smrsa1,
301        catfile($smdir, "smrsa2.pem"),
302        catfile($smdir, "smrsa3.pem") ],
303      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
304        "-in", "{output}.cms", "-out", "{output}.txt" ],
305      \&final_compare
306    ],
307
308    [ "enveloped content test streaming PEM format, AES-256-CBC cipher, KEK",
309      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
310        "-stream", "-out", "{output}.cms",
311        "-secretkey", "000102030405060708090A0B0C0D0E0F",
312        "-secretkeyid", "C0FEE0" ],
313      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
314        "-inform", "PEM",
315        "-secretkey", "000102030405060708090A0B0C0D0E0F",
316        "-secretkeyid", "C0FEE0" ],
317      \&final_compare
318    ],
319
320    [ "enveloped content test streaming PEM format, AES-256-GCM cipher, KEK",
321      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes-128-gcm",
322        "-stream", "-out", "{output}.cms",
323        "-secretkey", "000102030405060708090A0B0C0D0E0F",
324        "-secretkeyid", "C0FEE0" ],
325      [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
326        "-inform", "PEM",
327        "-secretkey", "000102030405060708090A0B0C0D0E0F",
328        "-secretkeyid", "C0FEE0" ],
329      \&final_compare
330    ],
331
332    [ "enveloped content test streaming PEM format, KEK, key only",
333      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
334        "-stream", "-out", "{output}.cms",
335        "-secretkey", "000102030405060708090A0B0C0D0E0F",
336        "-secretkeyid", "C0FEE0" ],
337      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
338        "-inform", "PEM",
339        "-secretkey", "000102030405060708090A0B0C0D0E0F" ],
340      \&final_compare
341    ],
342
343    [ "data content test streaming PEM format",
344      [ "{cmd1}", @prov, "-data_create", "-in", $smcont, "-outform", "PEM",
345        "-nodetach", "-stream", "-out", "{output}.cms" ],
346      [ "{cmd2}", @prov, "-data_out", "-in", "{output}.cms", "-inform", "PEM",
347        "-out", "{output}.txt" ],
348      \&final_compare
349    ],
350
351    [ "encrypted content test streaming PEM format, 128 bit RC2 key",
352      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
353        "-in", $smcont, "-outform", "PEM",
354        "-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
355        "-stream", "-out", "{output}.cms" ],
356      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
357        "-inform", "PEM",
358        "-secretkey", "000102030405060708090A0B0C0D0E0F",
359        "-out", "{output}.txt" ],
360      \&final_compare
361    ],
362
363    [ "encrypted content test streaming PEM format, 40 bit RC2 key",
364      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
365        "-in", $smcont, "-outform", "PEM",
366        "-rc2", "-secretkey", "0001020304",
367        "-stream", "-out", "{output}.cms" ],
368      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
369        "-inform", "PEM",
370        "-secretkey", "0001020304", "-out", "{output}.txt" ],
371      \&final_compare
372    ],
373
374    [ "encrypted content test streaming PEM format, triple DES key",
375      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
376        "-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
377        "-stream", "-out", "{output}.cms" ],
378      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
379        "-inform", "PEM",
380        "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
381        "-out", "{output}.txt" ],
382      \&final_compare
383    ],
384
385    [ "encrypted content test streaming PEM format, 128 bit AES key",
386      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
387        "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
388        "-stream", "-out", "{output}.cms" ],
389      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
390        "-inform", "PEM",
391        "-secretkey", "000102030405060708090A0B0C0D0E0F",
392        "-out", "{output}.txt" ],
393      \&final_compare
394    ],
395);
396
397my @smime_cms_cades_tests = (
398
399    [ "signed content DER format, RSA key, CAdES-BES compatible",
400      [ "{cmd1}", @prov, "-sign", "-cades", "-in", $smcont, "-outform", "DER",
401         "-nodetach",
402        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
403      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
404        "-CAfile", $smroot, "-out", "{output}.txt" ],
405      \&final_compare
406    ],
407
408    [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
409      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
410        "DER", "-nodetach", "-certfile", $smroot,
411        "-signer", $smrsa1, "-out", "{output}.cms" ],
412      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
413        "-CAfile", $smroot, "-out", "{output}.txt" ],
414      \&final_compare
415    ],
416
417    [ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
418      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
419        "DER", "-nodetach", "-certfile", $smroot,
420        "-signer", $smrsa1, "-out", "{output}.cms" ],
421      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
422        "-CAfile", $smroot, "-out", "{output}.txt" ],
423      \&final_compare
424    ],
425
426    [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
427      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
428        "-in", $smcont, "-outform", "DER",
429        "-certfile", $smroot, "-signer", $smrsa1,
430        "-outform", "DER", "-out", "{output}.cms"  ],
431      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
432        "-CAfile", $smroot, "-out", "{output}.txt" ],
433      \&final_compare
434    ],
435
436    [ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
437      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
438        "-in", $smcont, "-outform", "DER",
439        "-certfile", $smroot, "-signer", $smrsa1,
440        "-outform", "DER", "-out", "{output}.cms"  ],
441      [ "{cmd1}", @prov, "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
442        "-inform", "DER", "-in", "{output}.cms",
443        "-certfile", $smroot, "-signer", catfile($smdir, "smrsa2.pem"),
444        "-outform", "DER", "-out", "{output}2.cms" ],
445
446      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
447        "-CAfile", $smroot, "-out", "{output}.txt" ],
448      \&final_compare
449    ],
450);
451
452my @smime_cms_cades_ko_tests = (
453    [ "sign content DER format, RSA key, not CAdES-BES compatible",
454      [ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
455        "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ],
456      "fail to verify token since requiring CAdES-BES compatibility",
457      [ @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
458        "-CAfile", $smroot, "-out", "{output}.txt" ],
459      \&final_compare
460    ]
461);
462
463# cades options test - check that some combinations are rejected
464my @smime_cms_cades_invalid_option_tests = (
465    [
466        [ "-cades", "-noattr" ],
467    ],[
468        [ "-verify", "-cades", "-noattr" ],
469    ],[
470        [ "-verify", "-cades", "-noverify" ],
471    ],
472);
473
474my @smime_cms_comp_tests = (
475
476    [ "compressed content test streaming PEM format",
477      [ "{cmd1}", @prov, "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
478        "-stream", "-out", "{output}.cms" ],
479      [ "{cmd2}", @prov, "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
480        "-out", "{output}.txt" ],
481      \&final_compare
482    ]
483
484);
485
486my @smime_cms_param_tests = (
487    [ "signed content test streaming PEM format, RSA keys, PSS signature",
488      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
489        "-signer", $smrsa1,
490        "-keyopt", "rsa_padding_mode:pss",
491        "-out", "{output}.cms" ],
492      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
493        "-CAfile", $smroot, "-out", "{output}.txt" ],
494      \&final_compare
495    ],
496
497    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=max",
498      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
499        "-signer", $smrsa1,
500        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:max",
501        "-out", "{output}.cms" ],
502      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 222; },
503      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
504        "-CAfile", $smroot, "-out", "{output}.txt" ],
505      \&final_compare
506    ],
507
508    [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
509      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
510        "-noattr", "-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, SHA384 MGF1",
519      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
520        "-signer", $smrsa1,
521        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_mgf1_md:sha384",
522        "-out", "{output}.cms" ],
523      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
524        "-CAfile", $smroot, "-out", "{output}.txt" ],
525      \&final_compare
526    ],
527
528    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=16",
529      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
530        "-signer", $smrsa1, "-md", "sha256",
531        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:16",
532        "-out", "{output}.cms" ],
533      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 16; },
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, saltlen=digest",
540      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
541        "-signer", $smrsa1, "-md", "sha256",
542        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:digest",
543        "-out", "{output}.cms" ],
544      # digest is SHA-256, which produces 32 bytes of output
545      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 32; },
546      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
547        "-CAfile", $smroot, "-out", "{output}.txt" ],
548      \&final_compare
549    ],
550
551    [ "enveloped content test streaming S/MIME format, DES, OAEP default parameters",
552      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
553        "-stream", "-out", "{output}.cms",
554        "-recip", $smrsa1,
555        "-keyopt", "rsa_padding_mode:oaep" ],
556      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
557        "-in", "{output}.cms", "-out", "{output}.txt" ],
558      \&final_compare
559    ],
560
561    [ "enveloped content test streaming S/MIME format, DES, OAEP SHA256",
562      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
563        "-stream", "-out", "{output}.cms",
564        "-recip", $smrsa1,
565        "-keyopt", "rsa_padding_mode:oaep",
566        "-keyopt", "rsa_oaep_md:sha256" ],
567      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", $smrsa1,
568        "-in", "{output}.cms", "-out", "{output}.txt" ],
569      \&final_compare
570    ],
571
572    [ "enveloped content test streaming S/MIME format, DES, ECDH",
573      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
574        "-stream", "-out", "{output}.cms",
575        "-recip", catfile($smdir, "smec1.pem") ],
576      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
577        "-in", "{output}.cms", "-out", "{output}.txt" ],
578      \&final_compare
579    ],
580
581    [ "enveloped content test streaming S/MIME format, DES, ECDH, 2 recipients, key only used",
582      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
583        "-stream", "-out", "{output}.cms",
584        catfile($smdir, "smec1.pem"),
585        catfile($smdir, "smec3.pem") ],
586      [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
587        "-in", "{output}.cms", "-out", "{output}.txt" ],
588      \&final_compare
589    ],
590
591    [ "enveloped content test streaming S/MIME format, ECDH, DES, key identifier",
592      [ "{cmd1}", @defaultprov, "-encrypt", "-keyid", "-in", $smcont,
593        "-stream", "-out", "{output}.cms",
594        "-recip", catfile($smdir, "smec1.pem") ],
595      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
596        "-in", "{output}.cms", "-out", "{output}.txt" ],
597      \&final_compare
598    ],
599
600    [ "enveloped content test streaming S/MIME format, ECDH, AES-128-CBC, SHA256 KDF",
601      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
602        "-stream", "-out", "{output}.cms",
603        "-recip", catfile($smdir, "smec1.pem"), "-aes128",
604        "-keyopt", "ecdh_kdf_md:sha256" ],
605      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
606        "-in", "{output}.cms", "-out", "{output}.txt" ],
607      \&final_compare
608    ],
609
610    [ "enveloped content test streaming S/MIME format, ECDH, AES-128-GCM cipher, SHA256 KDF",
611      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
612        "-stream", "-out", "{output}.cms",
613        "-recip", catfile($smdir, "smec1.pem"), "-aes-128-gcm", "-keyopt", "ecdh_kdf_md:sha256" ],
614      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
615        "-in", "{output}.cms", "-out", "{output}.txt" ],
616      \&final_compare
617    ],
618
619    [ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
620      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
621        "-stream", "-out", "{output}.cms",
622        "-recip", catfile($smdir, "smec2.pem"), "-aes128",
623        "-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
624      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
625        "-in", "{output}.cms", "-out", "{output}.txt" ],
626      \&final_compare
627    ],
628
629    [ "enveloped content test streaming S/MIME format, X9.42 DH",
630      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
631        "-stream", "-out", "{output}.cms",
632        "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
633      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
634        "-in", "{output}.cms", "-out", "{output}.txt" ],
635      \&final_compare
636    ]
637);
638
639my @contenttype_cms_test = (
640    [ "signed content test - check that content type is added to additional signerinfo, RSA keys",
641      [ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
642        "-outform", "DER", "-signer", $smrsa1, "-md", "SHA256",
643        "-out", "{output}.cms" ],
644      [ "{cmd1}", @prov, "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
645        "-inform", "DER", "-outform", "DER",
646        "-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256",
647        "-out", "{output}2.cms" ],
648      sub { my %opts = @_; contentType_matches("$opts{output}2.cms") == 2; },
649      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
650        "-CAfile", $smroot, "-out", "{output}.txt" ]
651    ],
652);
653
654my @incorrect_attribute_cms_test = (
655    "bad_signtime_attr.cms",
656    "no_ct_attr.cms",
657    "no_md_attr.cms",
658    "ct_multiple_attr.cms"
659);
660
661# Runs a standard loop on the input array
662sub runner_loop {
663    my %opts = ( @_ );
664    my $cnt1 = 0;
665
666    foreach (@{$opts{tests}}) {
667        $cnt1++;
668        $opts{output} = "$opts{prefix}-$cnt1";
669      SKIP: {
670          my $skip_reason = check_availability($$_[0]);
671          skip $skip_reason, 1 if $skip_reason;
672          my $ok = 1;
673          1 while unlink "$opts{output}.txt";
674
675          foreach (@$_[1..$#$_]) {
676              if (ref $_ eq 'CODE') {
677                  $ok &&= $_->(%opts);
678              } else {
679                  my @cmd = map {
680                      my $x = $_;
681                      while ($x =~ /\{([^\}]+)\}/) {
682                          $x = $`.$opts{$1}.$' if exists $opts{$1};
683                      }
684                      $x;
685                  } @$_;
686
687                  diag "CMD: openssl ", join(" ", @cmd);
688                  $ok &&= run(app(["openssl", @cmd]));
689                  $opts{input} = $opts{output};
690              }
691          }
692
693          ok($ok, $$_[0]);
694        }
695    }
696}
697
698sub final_compare {
699    my %opts = @_;
700
701    diag "Comparing $smcont with $opts{output}.txt";
702    return compare_text($smcont, "$opts{output}.txt") == 0;
703}
704
705sub zero_compare {
706    my %opts = @_;
707
708    diag "Checking for zero-length file";
709    return (-e "$opts{output}.txt" && -z "$opts{output}.txt");
710}
711
712subtest "CMS => PKCS#7 compatibility tests\n" => sub {
713    plan tests => scalar @smime_pkcs7_tests;
714
715    runner_loop(prefix => 'cms2pkcs7', cmd1 => 'cms', cmd2 => 'smime',
716                tests => [ @smime_pkcs7_tests ]);
717};
718subtest "CMS <= PKCS#7 compatibility tests\n" => sub {
719    plan tests => scalar @smime_pkcs7_tests;
720
721    runner_loop(prefix => 'pkcs72cms', cmd1 => 'smime', cmd2 => 'cms',
722                tests => [ @smime_pkcs7_tests ]);
723};
724
725subtest "CMS <=> CMS consistency tests\n" => sub {
726    plan tests => (scalar @smime_pkcs7_tests) + (scalar @smime_cms_tests);
727
728    runner_loop(prefix => 'cms2cms-1', cmd1 => 'cms', cmd2 => 'cms',
729                tests => [ @smime_pkcs7_tests ]);
730    runner_loop(prefix => 'cms2cms-2', cmd1 => 'cms', cmd2 => 'cms',
731                tests => [ @smime_cms_tests ]);
732};
733
734subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
735    plan tests =>
736        (scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests);
737
738    runner_loop(prefix => 'cms2cms-mod', cmd1 => 'cms', cmd2 => 'cms',
739                tests => [ @smime_cms_param_tests ]);
740  SKIP: {
741      skip("Zlib not supported: compression tests skipped",
742           scalar @smime_cms_comp_tests)
743          if $no_zlib;
744
745      runner_loop(prefix => 'cms2cms-comp', cmd1 => 'cms', cmd2 => 'cms',
746                  tests => [ @smime_cms_comp_tests ]);
747    }
748};
749
750# Returns the number of matches of a Content Type Attribute in a binary file.
751sub contentType_matches {
752  # Read in a binary file
753  my ($in) = @_;
754  open (HEX_IN, "$in") or die("open failed for $in : $!");
755  binmode(HEX_IN);
756  local $/;
757  my $str = <HEX_IN>;
758
759  # Find ASN1 data for a Content Type Attribute (with a OID of PKCS7 data)
760  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;
761
762  close(HEX_IN);
763  return scalar(@c);
764}
765
766sub rsapssSaltlen {
767  my ($in) = @_;
768  my $exit = 0;
769
770  my @asn1parse = run(app(["openssl", "asn1parse", "-in", $in, "-dump"]),
771                      capture => 1,
772                      statusvar => $exit);
773  return -1 if $exit != 0;
774
775  my $pssparam_offset = -1;
776  while ($_ = shift @asn1parse) {
777    chomp;
778    next unless /:rsassaPss/;
779    # This line contains :rsassaPss, the next line contains a raw dump of the
780    # RSA_PSS_PARAMS sequence; obtain its offset
781    $_ = shift @asn1parse;
782    if (/^\s*(\d+):/) {
783      $pssparam_offset = int($1);
784    }
785  }
786
787  if ($pssparam_offset == -1) {
788    note "Failed to determine RSA_PSS_PARAM offset in CMS. " +
789         "Was the file correctly signed with RSASSA-PSS?";
790    return -1;
791  }
792
793  my @pssparam = run(app(["openssl", "asn1parse", "-in", $in,
794                          "-strparse", $pssparam_offset]),
795                     capture => 1,
796                     statusvar => $exit);
797  return -1 if $exit != 0;
798
799  my $saltlen = -1;
800  # Can't use asn1parse -item RSA_PSS_PARAMS here, because that's deprecated.
801  # This assumes the salt length is the last field, which may possibly be
802  # incorrect if there is a non-standard trailer field, but there almost never
803  # is in PSS.
804  if ($pssparam[-1] =~ /prim:\s+INTEGER\s+:([A-Fa-f0-9]+)/) {
805    $saltlen = hex($1);
806  }
807
808  if ($saltlen == -1) {
809    note "Failed to determine salt length from RSA_PSS_PARAM struct. " +
810         "Was the file correctly signed with RSASSA-PSS?";
811    return -1;
812  }
813
814  return $saltlen;
815}
816
817subtest "CMS Check the content type attribute is added for additional signers\n" => sub {
818    plan tests => (scalar @contenttype_cms_test);
819
820    runner_loop(prefix => 'cms2cms-added', cmd1 => 'cms', cmd2 => 'cms',
821                tests => [ @contenttype_cms_test ]);
822};
823
824subtest "CMS Check that bad attributes fail when verifying signers\n" => sub {
825    plan tests =>
826        (scalar @incorrect_attribute_cms_test);
827
828    my $cnt = 0;
829    foreach my $name (@incorrect_attribute_cms_test) {
830        my $out = "incorrect-$cnt.txt";
831
832        ok(!run(app(["openssl", "cms", @prov, "-verify", "-in",
833                     catfile($datadir, $name), "-inform", "DER", "-CAfile",
834                     $smroot, "-out", $out ])),
835            $name);
836    }
837};
838
839subtest "CMS Check that bad encryption algorithm fails\n" => sub {
840    plan tests => 1;
841
842    SKIP: {
843        skip "DES or Legacy isn't supported in this build", 1
844            if disabled("des") || disabled("legacy");
845
846        my $out = "smtst.txt";
847
848        ok(!run(app(["openssl", "cms", @legacyprov, "-encrypt",
849                    "-in", $smcont,
850                    "-stream", "-recip", $smrsa1,
851                    "-des-ede3",
852                    "-out", $out ])),
853           "Decrypt message from OpenSSL 1.1.1");
854    }
855};
856
857subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
858    plan tests => 1;
859
860    SKIP: {
861        skip "EC or DES isn't supported in this build", 1
862            if disabled("ec") || disabled("des");
863
864        my $out = "smtst.txt";
865
866        ok(run(app(["openssl", "cms", @defaultprov, "-decrypt",
867                    "-inkey", catfile($smdir, "smec3.pem"),
868                    "-in", catfile($datadir, "ciphertext_from_1_1_1.cms"),
869                    "-out", $out ]))
870           && compare_text($smcont, $out) == 0,
871           "Decrypt message from OpenSSL 1.1.1");
872    }
873};
874
875subtest "CAdES <=> CAdES consistency tests\n" => sub {
876    plan tests => (scalar @smime_cms_cades_tests);
877
878    runner_loop(prefix => 'cms-cades', cmd1 => 'cms', cmd2 => 'cms',
879                tests => [ @smime_cms_cades_tests ]);
880};
881
882subtest "CAdES; cms incompatible arguments tests\n" => sub {
883    plan tests => (scalar @smime_cms_cades_invalid_option_tests);
884
885    foreach (@smime_cms_cades_invalid_option_tests) {
886        ok(!run(app(["openssl", "cms", @{$$_[0]} ] )));
887    }
888};
889
890subtest "CAdES ko tests\n" => sub {
891    plan tests => 2 * scalar @smime_cms_cades_ko_tests;
892
893    foreach (@smime_cms_cades_ko_tests) {
894      SKIP: {
895        my $skip_reason = check_availability($$_[0]);
896        skip $skip_reason, 1 if $skip_reason;
897
898        ok(run(app(["openssl", "cms", @{$$_[1]}])), $$_[0]);
899        ok(!run(app(["openssl", "cms", @{$$_[3]}])), $$_[2]);
900        }
901    }
902};
903
904subtest "CMS binary input tests\n" => sub {
905    my $input = srctop_file("test", "smcont.bin");
906    my $signed = "smcont.signed";
907    my $verified = "smcont.verified";
908
909    plan tests => 11;
910
911    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
912                "-binary", "-in", $input, "-out", $signed])),
913       "sign binary input with -binary");
914    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
915                "-binary", "-in", $signed, "-out", $verified])),
916       "verify binary input with -binary");
917    is(compare($input, $verified), 0, "binary input retained with -binary");
918
919    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
920                "-in", $input, "-out", $signed.".nobin"])),
921       "sign binary input without -binary");
922    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
923                "-in", $signed.".nobin", "-out", $verified.".nobin"])),
924       "verify binary input without -binary");
925    is(compare($input, $verified.".nobin"), 1, "binary input not retained without -binary");
926    ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
927                "-binary", "-in", $signed, "-out", $verified.".crlfeol"])),
928       "verify binary input wrong crlfeol");
929
930    ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-signer", $smrsa1,
931                "-crlfeol",
932                "-binary", "-in", $input, "-out", $signed.".crlf"])),
933       "sign binary input with -binary -crlfeol");
934    ok(run(app(["openssl", "cms", "-verify", "-CAfile", $smroot, "-crlfeol",
935                "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf"])),
936       "verify binary input with -binary -crlfeol");
937    is(compare($input, $verified.".crlf"), 0,
938       "binary input retained with -binary -crlfeol");
939    ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $smroot,
940                "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf2"])),
941       "verify binary input with -binary missing -crlfeol");
942};
943
944# Test case for missing MD algorithm (must not segfault)
945
946with({ exit_checker => sub { return shift == 4; } },
947    sub {
948        ok(run(app(['openssl', 'smime', '-verify', '-noverify',
949                    '-inform', 'PEM',
950                    '-in', data_file("pkcs7-md4.pem"),
951                   ])),
952            "Check failure of EVP_DigestInit is handled correctly");
953    });
954
955sub check_availability {
956    my $tnam = shift;
957
958    return "$tnam: skipped, EC disabled\n"
959        if ($no_ec && $tnam =~ /ECDH/);
960    return "$tnam: skipped, ECDH disabled\n"
961        if ($no_ec && $tnam =~ /ECDH/);
962    return "$tnam: skipped, EC2M disabled\n"
963        if ($no_ec2m && $tnam =~ /K-283/);
964    return "$tnam: skipped, DH disabled\n"
965        if ($no_dh && $tnam =~ /X9\.42/);
966    return "$tnam: skipped, RC2 disabled\n"
967        if ($no_rc2 && $tnam =~ /RC2/);
968    return "$tnam: skipped, DES disabled\n"
969        if ($no_des && $tnam =~ /DES/);
970    return "$tnam: skipped, DSA disabled\n"
971        if ($no_dsa && $tnam =~ / DSA/);
972
973    return "";
974}
975
976# Test case for the locking problem reported in #19643.
977# This will fail if the fix is in and deadlock on Windows (and possibly
978# other platforms) if not.
979ok(!run(app(['openssl', 'cms', '-verify',
980             '-CAfile', srctop_file("test/certs", "pkitsta.pem"),
981             '-policy', 'anyPolicy',
982             '-in', srctop_file("test/smime-eml",
983                                "SignedInvalidMappingFromanyPolicyTest7.eml")
984            ])),
985   "issue#19643");
986
987# Check that we get the expected failure return code
988with({ exit_checker => sub { return shift == 6; } },
989    sub {
990        ok(run(app(['openssl', 'cms', '-encrypt',
991                    '-in', srctop_file("test", "smcont.txt"),
992                    '-aes128', '-stream', '-recip',
993                    srctop_file("test/smime-certs", "badrsa.pem"),
994                   ])),
995            "Check failure during BIO setup with -stream is handled correctly");
996    });
997