xref: /freebsd/crypto/openssl/test/cmsapitest.c (revision 8f9aabbdbcd55b25b698bd762e8693d43f295bbd)
1 /*
2  * Copyright 2018-2026 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 #include <string.h>
11 
12 #include <openssl/pem.h>
13 #include <openssl/cms.h>
14 #include <openssl/bio.h>
15 #include <openssl/x509.h>
16 #include "../crypto/cms/cms_local.h" /* for d.signedData and d.envelopedData */
17 
18 #include "testutil.h"
19 
20 static X509 *cert = NULL;
21 static EVP_PKEY *privkey = NULL;
22 static char *derin = NULL;
23 static char *too_long_iv_cms_in = NULL;
24 static char *pwri_kek_oob_der_in = NULL;
25 
26 static int test_encrypt_decrypt(const EVP_CIPHER *cipher)
27 {
28     int testresult = 0;
29     STACK_OF(X509) *certstack = sk_X509_new_null();
30     const char *msg = "Hello world";
31     BIO *msgbio = BIO_new_mem_buf(msg, strlen(msg));
32     BIO *outmsgbio = BIO_new(BIO_s_mem());
33     CMS_ContentInfo *content = NULL;
34     BIO *contentbio = NULL;
35     char buf[80];
36 
37     if (!TEST_ptr(certstack) || !TEST_ptr(msgbio) || !TEST_ptr(outmsgbio))
38         goto end;
39 
40     if (!TEST_int_gt(sk_X509_push(certstack, cert), 0))
41         goto end;
42 
43     content = CMS_encrypt(certstack, msgbio, cipher, CMS_TEXT);
44     if (!TEST_ptr(content))
45         goto end;
46 
47     if (!TEST_true(CMS_decrypt(content, privkey, cert, NULL, outmsgbio,
48             CMS_TEXT)))
49         goto end;
50 
51     if (!(EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
52         && !TEST_ptr(contentbio = CMS_EnvelopedData_decrypt(content->d.envelopedData,
53                          NULL, privkey, cert, NULL,
54                          CMS_TEXT, NULL, NULL)))
55         goto end;
56 
57     /* Check we got the message we first started with */
58     if (!TEST_int_eq(BIO_gets(outmsgbio, buf, sizeof(buf)), strlen(msg))
59         || !TEST_int_eq(strcmp(buf, msg), 0))
60         goto end;
61 
62     testresult = 1;
63 end:
64     BIO_free(contentbio);
65     sk_X509_free(certstack);
66     BIO_free(msgbio);
67     BIO_free(outmsgbio);
68     CMS_ContentInfo_free(content);
69 
70     return testresult && TEST_int_eq(ERR_peek_error(), 0);
71 }
72 
73 static int test_encrypt_decrypt_aes_cbc(void)
74 {
75     return test_encrypt_decrypt(EVP_aes_128_cbc());
76 }
77 
78 static int test_encrypt_decrypt_aes_128_gcm(void)
79 {
80     return test_encrypt_decrypt(EVP_aes_128_gcm());
81 }
82 
83 static int test_encrypt_decrypt_aes_192_gcm(void)
84 {
85     return test_encrypt_decrypt(EVP_aes_192_gcm());
86 }
87 
88 static int test_encrypt_decrypt_aes_256_gcm(void)
89 {
90     return test_encrypt_decrypt(EVP_aes_256_gcm());
91 }
92 
93 static int test_CMS_add1_cert(void)
94 {
95     CMS_ContentInfo *cms = NULL;
96     int ret = 0;
97 
98     ret = TEST_ptr(cms = CMS_ContentInfo_new())
99         && TEST_ptr(CMS_add1_signer(cms, cert, privkey, NULL, 0))
100         && TEST_true(CMS_add1_cert(cms, cert)); /* add cert again */
101 
102     CMS_ContentInfo_free(cms);
103     return ret;
104 }
105 
106 static int test_d2i_CMS_bio_NULL(void)
107 {
108     BIO *bio, *content = NULL;
109     CMS_ContentInfo *cms = NULL;
110     unsigned int flags = CMS_NO_SIGNER_CERT_VERIFY;
111     int ret = 0;
112 
113     /*
114      * Test data generated using:
115      * openssl cms -sign -md sha256 -signer ./test/certs/rootCA.pem -inkey \
116      * ./test/certs/rootCA.key -nodetach -outform DER -in ./in.txt -out out.der \
117      * -nosmimecap
118      */
119     static const unsigned char cms_data[] = {
120         0x30, 0x82, 0x05, 0xc5, 0x06, 0x09, 0x2a, 0x86,
121         0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0,
122         0x82, 0x05, 0xb6, 0x30, 0x82, 0x05, 0xb2, 0x02,
123         0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09,
124         0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
125         0x01, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48,
126         0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x0f,
127         0x04, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
128         0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0d, 0x0a, 0xa0,
129         0x82, 0x03, 0x83, 0x30, 0x82, 0x03, 0x7f, 0x30,
130         0x82, 0x02, 0x67, 0xa0, 0x03, 0x02, 0x01, 0x02,
131         0x02, 0x09, 0x00, 0x88, 0x43, 0x29, 0xcb, 0xc2,
132         0xeb, 0x15, 0x9a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
133         0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
134         0x05, 0x00, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09,
135         0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
136         0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
137         0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
138         0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
139         0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
140         0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
141         0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
142         0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
143         0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55,
144         0x04, 0x03, 0x0c, 0x06, 0x72, 0x6f, 0x6f, 0x74,
145         0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35,
146         0x30, 0x37, 0x30, 0x32, 0x31, 0x33, 0x31, 0x35,
147         0x31, 0x31, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30,
148         0x37, 0x30, 0x32, 0x31, 0x33, 0x31, 0x35, 0x31,
149         0x31, 0x5a, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09,
150         0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
151         0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
152         0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
153         0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
154         0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
155         0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
156         0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
157         0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
158         0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55,
159         0x04, 0x03, 0x0c, 0x06, 0x72, 0x6f, 0x6f, 0x74,
160         0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
161         0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
162         0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
163         0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
164         0x01, 0x01, 0x00, 0xc0, 0xf1, 0x6b, 0x77, 0x88,
165         0xac, 0x35, 0xdf, 0xfb, 0x73, 0x53, 0x2f, 0x92,
166         0x80, 0x2f, 0x74, 0x16, 0x32, 0x4d, 0xf5, 0x10,
167         0x20, 0x6f, 0x6c, 0x3a, 0x8e, 0xd1, 0xdc, 0x6b,
168         0xe1, 0x2e, 0x3e, 0xc3, 0x04, 0x0f, 0xbf, 0x9b,
169         0xc4, 0xc9, 0x12, 0xd1, 0xe4, 0x0b, 0x45, 0x97,
170         0xe5, 0x06, 0xcd, 0x66, 0x3a, 0xe1, 0xe0, 0xe2,
171         0x2b, 0xdf, 0xa2, 0xc4, 0xec, 0x7b, 0xd3, 0x3d,
172         0x3c, 0x8a, 0xff, 0x5e, 0x74, 0xa0, 0xab, 0xa7,
173         0x03, 0x6a, 0x16, 0x5b, 0x5e, 0x92, 0xc4, 0x7e,
174         0x5b, 0x79, 0x8a, 0x69, 0xd4, 0xbc, 0x83, 0x5e,
175         0xae, 0x42, 0x92, 0x74, 0xa5, 0x2b, 0xe7, 0x00,
176         0xc1, 0xa9, 0xdc, 0xd5, 0xb1, 0x53, 0x07, 0x0f,
177         0x73, 0xf7, 0x8e, 0xad, 0x14, 0x3e, 0x25, 0x9e,
178         0xe5, 0x1e, 0xe6, 0xcc, 0x91, 0xcd, 0x95, 0x0c,
179         0x80, 0x44, 0x20, 0xc3, 0xfd, 0x17, 0xcf, 0x91,
180         0x3d, 0x63, 0x10, 0x1c, 0x14, 0x5b, 0xfb, 0xc3,
181         0xa8, 0xc1, 0x88, 0xb2, 0x77, 0xff, 0x9c, 0xdb,
182         0xfc, 0x6a, 0x44, 0x44, 0x44, 0xf7, 0x85, 0xec,
183         0x08, 0x2c, 0xd4, 0xdf, 0x81, 0xa3, 0x79, 0xc9,
184         0xfe, 0x1e, 0x9b, 0x93, 0x16, 0x53, 0xb7, 0x97,
185         0xab, 0xbe, 0x4f, 0x1a, 0xa5, 0xe2, 0xfa, 0x46,
186         0x05, 0xe4, 0x0d, 0x9c, 0x2a, 0xa4, 0xcc, 0xb9,
187         0x1e, 0x21, 0xa0, 0x6c, 0xc4, 0xab, 0x59, 0xb0,
188         0x40, 0x39, 0xbb, 0xf9, 0x88, 0xad, 0xfd, 0xdf,
189         0x8d, 0xb4, 0x0b, 0xaf, 0x7e, 0x41, 0xe0, 0x21,
190         0x3c, 0xc8, 0x33, 0x45, 0x49, 0x84, 0x2f, 0x93,
191         0x06, 0xee, 0xfd, 0x4f, 0xed, 0x4f, 0xf3, 0xbc,
192         0x9b, 0xde, 0xfc, 0x25, 0x5e, 0x55, 0xd5, 0x75,
193         0xd4, 0xc5, 0x7b, 0x3a, 0x40, 0x35, 0x06, 0x9f,
194         0xc4, 0x84, 0xb4, 0x6c, 0x93, 0x0c, 0xaf, 0x37,
195         0x5a, 0xaf, 0xb6, 0x41, 0x4d, 0x26, 0x23, 0x1c,
196         0xb8, 0x02, 0xb3, 0x02, 0x03, 0x01, 0x00, 0x01,
197         0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03,
198         0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01,
199         0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
200         0x0e, 0x04, 0x16, 0x04, 0x14, 0x85, 0x56, 0x89,
201         0x35, 0xe2, 0x9f, 0x00, 0x1a, 0xe1, 0x86, 0x03,
202         0x0b, 0x4b, 0xaf, 0x76, 0x12, 0x6b, 0x33, 0x6d,
203         0xfd, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
204         0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x85, 0x56,
205         0x89, 0x35, 0xe2, 0x9f, 0x00, 0x1a, 0xe1, 0x86,
206         0x03, 0x0b, 0x4b, 0xaf, 0x76, 0x12, 0x6b, 0x33,
207         0x6d, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
208         0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
209         0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x32, 0x0a,
210         0xbf, 0x2a, 0x0a, 0xe2, 0xbb, 0x4f, 0x43, 0xce,
211         0x88, 0xda, 0x5a, 0x39, 0x10, 0x37, 0x80, 0xbb,
212         0x37, 0x2d, 0x5e, 0x2d, 0x88, 0xdd, 0x26, 0x69,
213         0x9c, 0xe7, 0xb4, 0x98, 0x20, 0xb1, 0x25, 0xe6,
214         0x61, 0x59, 0x6d, 0x12, 0xec, 0x9b, 0x87, 0xbe,
215         0x57, 0xe1, 0x12, 0x05, 0xc5, 0x04, 0xf1, 0x17,
216         0xce, 0x14, 0xb8, 0x1c, 0x92, 0xd4, 0x95, 0x95,
217         0x2c, 0x5b, 0x28, 0x89, 0xfb, 0x72, 0x9c, 0x20,
218         0xd3, 0x32, 0x81, 0xa8, 0x85, 0xec, 0xc8, 0x08,
219         0x7b, 0xa8, 0x59, 0x5b, 0x3a, 0x6c, 0x31, 0xab,
220         0x52, 0xe2, 0x66, 0xcd, 0x14, 0x49, 0x5c, 0xf3,
221         0xd3, 0x3e, 0x62, 0xbc, 0x91, 0x16, 0xb4, 0x1c,
222         0xf5, 0xdd, 0x54, 0xaa, 0x3c, 0x61, 0x97, 0x79,
223         0xac, 0xe4, 0xc8, 0x43, 0x35, 0xc3, 0x0f, 0xfc,
224         0xf3, 0x70, 0x1d, 0xaf, 0xf0, 0x9c, 0x8a, 0x2a,
225         0x92, 0x93, 0x48, 0xaa, 0xd0, 0xe8, 0x47, 0xbe,
226         0x35, 0xc1, 0xc6, 0x7b, 0x6d, 0xda, 0xfa, 0x5d,
227         0x57, 0x45, 0xf3, 0xea, 0x41, 0x8f, 0x36, 0xc1,
228         0x3c, 0xf4, 0x52, 0x7f, 0x6e, 0x31, 0xdd, 0xba,
229         0x9a, 0xbc, 0x70, 0x56, 0x71, 0x38, 0xdc, 0x49,
230         0x57, 0x0c, 0xfd, 0x91, 0x17, 0xc5, 0xea, 0x87,
231         0xe5, 0x23, 0x74, 0x19, 0xb2, 0xb6, 0x99, 0x0c,
232         0x6b, 0xa2, 0x05, 0xf8, 0x51, 0x68, 0xed, 0x97,
233         0xe0, 0xdf, 0x62, 0xf9, 0x7e, 0x7a, 0x3a, 0x44,
234         0x71, 0x83, 0x57, 0x28, 0x49, 0x88, 0x69, 0xb5,
235         0x14, 0x1e, 0xda, 0x46, 0xe3, 0x6e, 0x78, 0xe1,
236         0xcb, 0x8f, 0xb5, 0x98, 0xb3, 0x2d, 0x6e, 0x5b,
237         0xb7, 0xf6, 0x93, 0x24, 0x14, 0x1f, 0xa4, 0xf6,
238         0x69, 0xbd, 0xff, 0x4c, 0x52, 0x50, 0x02, 0xc5,
239         0x43, 0x8d, 0x14, 0xe2, 0xd0, 0x75, 0x9f, 0x12,
240         0x5e, 0x94, 0x89, 0xd1, 0xef, 0x77, 0x89, 0x7d,
241         0x89, 0xd9, 0x9e, 0x76, 0x99, 0x24, 0x31, 0x82,
242         0x01, 0xf7, 0x30, 0x82, 0x01, 0xf3, 0x02, 0x01,
243         0x01, 0x30, 0x63, 0x30, 0x56, 0x31, 0x0b, 0x30,
244         0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
245         0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
246         0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d,
247         0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
248         0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
249         0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
250         0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
251         0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
252         0x74, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03,
253         0x55, 0x04, 0x03, 0x0c, 0x06, 0x72, 0x6f, 0x6f,
254         0x74, 0x43, 0x41, 0x02, 0x09, 0x00, 0x88, 0x43,
255         0x29, 0xcb, 0xc2, 0xeb, 0x15, 0x9a, 0x30, 0x0b,
256         0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
257         0x04, 0x02, 0x01, 0xa0, 0x69, 0x30, 0x18, 0x06,
258         0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
259         0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86,
260         0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30,
261         0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
262         0x0d, 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d,
263         0x32, 0x30, 0x31, 0x32, 0x31, 0x31, 0x30, 0x39,
264         0x30, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x2f, 0x06,
265         0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
266         0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0xb0, 0x80,
267         0x22, 0xd3, 0x15, 0xcf, 0x1e, 0xb1, 0x2d, 0x26,
268         0x65, 0xbd, 0xed, 0x0e, 0x6a, 0xf4, 0x06, 0x53,
269         0xc0, 0xa0, 0xbe, 0x97, 0x52, 0x32, 0xfb, 0x49,
270         0xbc, 0xbd, 0x02, 0x1c, 0xfc, 0x36, 0x30, 0x0d,
271         0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
272         0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01,
273         0x00, 0x37, 0x44, 0x39, 0x08, 0xb2, 0x19, 0x52,
274         0x35, 0x9c, 0xd0, 0x67, 0x87, 0xae, 0xb8, 0x1c,
275         0x80, 0xf4, 0x03, 0x29, 0x2e, 0xe3, 0x76, 0x4a,
276         0xb0, 0x98, 0x10, 0x00, 0x9a, 0x30, 0xdb, 0x05,
277         0x28, 0x53, 0x34, 0x31, 0x14, 0xbd, 0x87, 0xb9,
278         0x4d, 0x45, 0x07, 0x97, 0xa3, 0x57, 0x0b, 0x7e,
279         0xd1, 0x67, 0xfb, 0x4e, 0x0f, 0x5b, 0x90, 0xb2,
280         0x6f, 0xe6, 0xce, 0x49, 0xdd, 0x72, 0x46, 0x71,
281         0x26, 0xa1, 0x1b, 0x98, 0x23, 0x7d, 0x69, 0x73,
282         0x84, 0xdc, 0xf9, 0xd2, 0x1c, 0x6d, 0xf6, 0xf5,
283         0x17, 0x49, 0x6e, 0x9d, 0x4d, 0xf1, 0xe2, 0x43,
284         0x29, 0x53, 0x55, 0xa5, 0x22, 0x1e, 0x89, 0x2c,
285         0xaf, 0xf2, 0x43, 0x47, 0xd5, 0xfa, 0xad, 0xe7,
286         0x89, 0x60, 0xbf, 0x96, 0x35, 0x6f, 0xc2, 0x99,
287         0xb7, 0x55, 0xc5, 0xe3, 0x04, 0x25, 0x1b, 0xf6,
288         0x7e, 0xf2, 0x2b, 0x14, 0xa9, 0x57, 0x96, 0xbe,
289         0xbd, 0x6e, 0x95, 0x44, 0x94, 0xbd, 0xaf, 0x9a,
290         0x6d, 0x77, 0x55, 0x5e, 0x6c, 0xf6, 0x32, 0x37,
291         0xec, 0xef, 0xe5, 0x81, 0xb0, 0xe3, 0x35, 0xc7,
292         0x86, 0xea, 0x47, 0x59, 0x38, 0xb6, 0x16, 0xfb,
293         0x1d, 0x10, 0x55, 0x48, 0xb1, 0x44, 0x33, 0xde,
294         0xf6, 0x29, 0xbe, 0xbf, 0xbc, 0x71, 0x3e, 0x49,
295         0xba, 0xe7, 0x9f, 0x4d, 0x6c, 0xfb, 0xec, 0xd2,
296         0xe0, 0x12, 0xa9, 0x7c, 0xc9, 0x9a, 0x7b, 0x85,
297         0x83, 0xb8, 0xca, 0xdd, 0xf6, 0xb7, 0x15, 0x75,
298         0x7b, 0x4a, 0x69, 0xcf, 0x0a, 0xc7, 0x80, 0x01,
299         0xe7, 0x94, 0x16, 0x7f, 0x8d, 0x3c, 0xfa, 0x1f,
300         0x05, 0x71, 0x76, 0x15, 0xb0, 0xf6, 0x61, 0x30,
301         0x58, 0x16, 0xbe, 0x1b, 0xd1, 0x93, 0xc4, 0x1a,
302         0x91, 0x0c, 0x48, 0xe2, 0x1c, 0x8e, 0xa5, 0xc5,
303         0xa7, 0x81, 0x44, 0x48, 0x3b, 0x10, 0xc2, 0x74,
304         0x07, 0xdf, 0xa8, 0xae, 0x57, 0xee, 0x7f, 0xe3,
305         0x6a
306     };
307 
308     ret = TEST_ptr(bio = BIO_new_mem_buf(cms_data, sizeof(cms_data)))
309         && TEST_ptr(cms = d2i_CMS_bio(bio, NULL))
310         && TEST_true(CMS_verify(cms, NULL, NULL, NULL, NULL, flags))
311         && TEST_ptr(content = CMS_SignedData_verify(cms->d.signedData, NULL, NULL, NULL,
312                         NULL, NULL, flags, NULL, NULL));
313     BIO_free(content);
314     CMS_ContentInfo_free(cms);
315     BIO_free(bio);
316     return ret && TEST_int_eq(ERR_peek_error(), 0);
317 }
318 
319 static unsigned char *read_all(BIO *bio, long *p_len)
320 {
321     const int step = 256;
322     unsigned char *buf = NULL;
323     unsigned char *tmp = NULL;
324     int ret;
325 
326     *p_len = 0;
327     for (;;) {
328         tmp = OPENSSL_realloc(buf, *p_len + step);
329         if (tmp == NULL)
330             break;
331         buf = tmp;
332         ret = BIO_read(bio, buf + *p_len, step);
333         if (ret < 0)
334             break;
335 
336         if (LONG_MAX - ret < *p_len)
337             break;
338 
339         *p_len += ret;
340 
341         if (ret < step)
342             return buf;
343     }
344 
345     /* Error */
346     OPENSSL_free(buf);
347     *p_len = 0;
348     return NULL;
349 }
350 
351 static int test_d2i_CMS_decode(const int idx)
352 {
353     BIO *bio = NULL;
354     CMS_ContentInfo *cms = NULL;
355     unsigned char *buf = NULL;
356     const unsigned char *tmp = NULL;
357     long buf_len = 0;
358     int ret = 0;
359 
360     if (!TEST_ptr(bio = BIO_new_file(derin, "r")))
361         goto end;
362 
363     switch (idx) {
364     case 0:
365         if (!TEST_ptr(cms = d2i_CMS_bio(bio, NULL)))
366             goto end;
367         break;
368     case 1:
369         if (!TEST_ptr(buf = read_all(bio, &buf_len)))
370             goto end;
371         tmp = buf;
372         if (!TEST_ptr(cms = d2i_CMS_ContentInfo(NULL, &tmp, buf_len)))
373             goto end;
374         break;
375     }
376 
377     if (!TEST_int_eq(ERR_peek_error(), 0))
378         goto end;
379 
380     ret = 1;
381 end:
382     CMS_ContentInfo_free(cms);
383     BIO_free(bio);
384     OPENSSL_free(buf);
385 
386     return ret;
387 }
388 
389 static int test_CMS_set1_key_mem_leak(void)
390 {
391     CMS_ContentInfo *cms;
392     unsigned char key[32] = { 0 };
393     int ret = 0;
394 
395     if (!TEST_ptr(cms = CMS_ContentInfo_new()))
396         return 0;
397 
398     if (!TEST_true(CMS_EncryptedData_set1_key(cms, EVP_aes_256_cbc(),
399             key, 32)))
400         goto end;
401 
402     if (!TEST_true(CMS_EncryptedData_set1_key(cms, EVP_aes_128_cbc(),
403             key, 16)))
404         goto end;
405 
406     ret = 1;
407 end:
408     CMS_ContentInfo_free(cms);
409     return ret;
410 }
411 
412 static int test_encrypted_data(void)
413 {
414     const char *msg = "Hello world";
415     BIO *msgbio = BIO_new_mem_buf(msg, (int)strlen(msg));
416     uint8_t key[16] = { 0 };
417     size_t keylen = 16;
418     CMS_ContentInfo *cms;
419     BIO *decryptbio = BIO_new(BIO_s_mem());
420     char buf[80];
421     int ret = 0;
422 
423     cms = CMS_EncryptedData_encrypt(msgbio, EVP_aes_128_cbc(), key, keylen, SMIME_BINARY);
424     if (!TEST_ptr(cms))
425         goto end;
426 
427     if (!TEST_true(CMS_EncryptedData_decrypt(cms, key, keylen, NULL, decryptbio, SMIME_BINARY)))
428         goto end;
429 
430     /* Check we got the message we first started with */
431     if (!TEST_int_eq(BIO_gets(decryptbio, buf, sizeof(buf)), (int)strlen(msg))
432         || !TEST_int_eq(strcmp(buf, msg), 0))
433         goto end;
434 
435     ret = 1;
436 end:
437     CMS_ContentInfo_free(cms);
438     BIO_free(msgbio);
439     BIO_free(decryptbio);
440     return ret;
441 }
442 
443 static int test_encrypted_data_aead(void)
444 {
445     const char *msg = "Hello world";
446     BIO *msgbio = BIO_new_mem_buf(msg, (int)strlen(msg));
447     uint8_t key[16] = { 0 };
448     size_t keylen = 16;
449     CMS_ContentInfo *cms;
450     BIO *decryptbio = BIO_new(BIO_s_mem());
451     int ret = 0;
452 
453     cms = CMS_ContentInfo_new();
454     if (!TEST_ptr(cms))
455         goto end;
456 
457     /*
458      * AEAD algorithms are not supported by the CMS EncryptedData so setting
459      * the cipher to AES GCM 128 will result in a failure
460      */
461     if (!TEST_false(CMS_EncryptedData_set1_key(cms, EVP_aes_128_gcm(), key, keylen)))
462         goto end;
463 
464     CMS_ContentInfo_free(cms);
465     cms = NULL;
466 
467     /*
468      * AEAD algorithms are not supported by the CMS EncryptedData so setting
469      * the cipher to AES GCM 128 will result in a failure
470      */
471     cms = CMS_EncryptedData_encrypt(msgbio, EVP_aes_128_gcm(), key, keylen, SMIME_BINARY);
472     if (!TEST_ptr_null(cms))
473         goto end;
474 
475     ret = 1;
476 
477 end:
478     CMS_ContentInfo_free(cms);
479     BIO_free(msgbio);
480     BIO_free(decryptbio);
481     return ret;
482 }
483 
484 static int test_cms_aesgcm_iv_too_long(void)
485 {
486     int ret = 0;
487     BIO *cmsbio = NULL, *out = NULL;
488     CMS_ContentInfo *cms = NULL;
489     unsigned long err = 0;
490 
491     if (!TEST_ptr(cmsbio = BIO_new_file(too_long_iv_cms_in, "r")))
492         goto end;
493 
494     if (!TEST_ptr(cms = PEM_read_bio_CMS(cmsbio, NULL, NULL, NULL)))
495         goto end;
496 
497     /* Must fail cleanly (no crash) */
498     if (!TEST_false(CMS_decrypt(cms, privkey, cert, NULL, out, 0)))
499         goto end;
500     err = ERR_peek_last_error();
501     if (!TEST_ulong_ne(err, 0))
502         goto end;
503     if (!TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_CMS))
504         goto end;
505     if (!TEST_int_eq(ERR_GET_REASON(err), CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR))
506         goto end;
507 
508     ret = 1;
509 end:
510     CMS_ContentInfo_free(cms);
511     BIO_free(cmsbio);
512     BIO_free(out);
513     return ret;
514 }
515 
516 /*
517  * CMS EnvelopedData with a single PasswordRecipientInfo using
518  * id-alg-PWRI-KEK and an AES-128-CFB key encryption cipher
519  * (1-byte effective block size).  The encryptedKey OCTET STRING is
520  * only two bytes long, so the wrapped key buffer is shorter than
521  * the seven octets read by the check-byte test in kek_unwrap_key().
522  * Prior to CVE-2026-9076 this triggered an out-of-bounds heap read;
523  * CMS_decrypt() must now fail cleanly.
524  */
525 static int test_pwri_kek_unwrap_short_encrypted_key(void)
526 {
527     BIO *in = NULL;
528     CMS_ContentInfo *cms = NULL;
529     unsigned long err = 0;
530     int ret = 0;
531 
532     if (!TEST_ptr(in = BIO_new_file(pwri_kek_oob_der_in, "rb"))
533         || !TEST_ptr(cms = d2i_CMS_bio(in, NULL)))
534         goto end;
535 
536     /*
537      * The unwrap is attempted eagerly inside CMS_decrypt_set1_password().
538      * It must fail cleanly (no OOB read) and report CMS_R_UNWRAP_FAILURE.
539      */
540     if (!TEST_false(CMS_decrypt_set1_password(cms,
541             (unsigned char *)"password", -1)))
542         goto end;
543 
544     err = ERR_peek_last_error();
545     if (!TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_CMS)
546         || !TEST_int_eq(ERR_GET_REASON(err), CMS_R_UNWRAP_FAILURE))
547         goto end;
548 
549     ERR_clear_error();
550     ret = 1;
551 end:
552     CMS_ContentInfo_free(cms);
553     BIO_free(in);
554     return ret;
555 }
556 
557 OPT_TEST_DECLARE_USAGE("certfile privkeyfile derfile tooLongIVpem pwriKekOobDer\n")
558 
559 int setup_tests(void)
560 {
561     char *certin = NULL, *privkeyin = NULL;
562     BIO *certbio = NULL, *privkeybio = NULL;
563 
564     if (!test_skip_common_options()) {
565         TEST_error("Error parsing test options\n");
566         return 0;
567     }
568 
569     if (!TEST_ptr(certin = test_get_argument(0))
570         || !TEST_ptr(privkeyin = test_get_argument(1))
571         || !TEST_ptr(derin = test_get_argument(2))
572         || !TEST_ptr(too_long_iv_cms_in = test_get_argument(3))
573         || !TEST_ptr(pwri_kek_oob_der_in = test_get_argument(4)))
574         return 0;
575 
576     certbio = BIO_new_file(certin, "r");
577     if (!TEST_ptr(certbio))
578         return 0;
579     if (!TEST_true(PEM_read_bio_X509(certbio, &cert, NULL, NULL))) {
580         BIO_free(certbio);
581         return 0;
582     }
583     BIO_free(certbio);
584 
585     privkeybio = BIO_new_file(privkeyin, "r");
586     if (!TEST_ptr(privkeybio)) {
587         X509_free(cert);
588         cert = NULL;
589         return 0;
590     }
591     if (!TEST_true(PEM_read_bio_PrivateKey(privkeybio, &privkey, NULL, NULL))) {
592         BIO_free(privkeybio);
593         X509_free(cert);
594         cert = NULL;
595         return 0;
596     }
597     BIO_free(privkeybio);
598 
599     ADD_TEST(test_encrypt_decrypt_aes_cbc);
600     ADD_TEST(test_encrypt_decrypt_aes_128_gcm);
601     ADD_TEST(test_encrypt_decrypt_aes_192_gcm);
602     ADD_TEST(test_encrypt_decrypt_aes_256_gcm);
603     ADD_TEST(test_CMS_add1_cert);
604     ADD_TEST(test_d2i_CMS_bio_NULL);
605     ADD_TEST(test_CMS_set1_key_mem_leak);
606     ADD_TEST(test_encrypted_data);
607     ADD_TEST(test_encrypted_data_aead);
608     ADD_ALL_TESTS(test_d2i_CMS_decode, 2);
609     ADD_TEST(test_cms_aesgcm_iv_too_long);
610     ADD_TEST(test_pwri_kek_unwrap_short_encrypted_key);
611     return 1;
612 }
613 
614 void cleanup_tests(void)
615 {
616     X509_free(cert);
617     EVP_PKEY_free(privkey);
618 }
619