1 | /*
|
---|
2 | * Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include "internal/cryptlib.h"
|
---|
11 | #include <openssl/asn1t.h>
|
---|
12 | #include <openssl/x509.h>
|
---|
13 | #include <openssl/x509v3.h>
|
---|
14 | #include <openssl/err.h>
|
---|
15 | #include <openssl/cms.h>
|
---|
16 | #include "cms_local.h"
|
---|
17 | #include "crypto/asn1.h"
|
---|
18 |
|
---|
19 | static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
|
---|
20 | {
|
---|
21 | BIO *rbio;
|
---|
22 |
|
---|
23 | if (out == NULL)
|
---|
24 | rbio = BIO_new(BIO_s_null());
|
---|
25 | else if (flags & CMS_TEXT) {
|
---|
26 | rbio = BIO_new(BIO_s_mem());
|
---|
27 | BIO_set_mem_eof_return(rbio, 0);
|
---|
28 | } else
|
---|
29 | rbio = out;
|
---|
30 | return rbio;
|
---|
31 | }
|
---|
32 |
|
---|
33 | static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
|
---|
34 | {
|
---|
35 | unsigned char buf[4096];
|
---|
36 | int r = 0, i;
|
---|
37 | BIO *tmpout;
|
---|
38 |
|
---|
39 | tmpout = cms_get_text_bio(out, flags);
|
---|
40 |
|
---|
41 | if (tmpout == NULL) {
|
---|
42 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
43 | goto err;
|
---|
44 | }
|
---|
45 |
|
---|
46 | /* Read all content through chain to process digest, decrypt etc */
|
---|
47 | for (;;) {
|
---|
48 | i = BIO_read(in, buf, sizeof(buf));
|
---|
49 | if (i <= 0) {
|
---|
50 | if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
|
---|
51 | if (BIO_get_cipher_status(in) <= 0)
|
---|
52 | goto err;
|
---|
53 | }
|
---|
54 | if (i < 0)
|
---|
55 | goto err;
|
---|
56 | break;
|
---|
57 | }
|
---|
58 |
|
---|
59 | if (tmpout != NULL && (BIO_write(tmpout, buf, i) != i))
|
---|
60 | goto err;
|
---|
61 | }
|
---|
62 |
|
---|
63 | if (flags & CMS_TEXT) {
|
---|
64 | if (!SMIME_text(tmpout, out)) {
|
---|
65 | ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
|
---|
66 | goto err;
|
---|
67 | }
|
---|
68 | }
|
---|
69 |
|
---|
70 | r = 1;
|
---|
71 | err:
|
---|
72 | if (tmpout != out)
|
---|
73 | BIO_free(tmpout);
|
---|
74 | return r;
|
---|
75 |
|
---|
76 | }
|
---|
77 |
|
---|
78 | static int check_content(CMS_ContentInfo *cms)
|
---|
79 | {
|
---|
80 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
---|
81 |
|
---|
82 | if (pos == NULL || *pos == NULL) {
|
---|
83 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
|
---|
84 | return 0;
|
---|
85 | }
|
---|
86 | return 1;
|
---|
87 | }
|
---|
88 |
|
---|
89 | static void do_free_upto(BIO *f, BIO *upto)
|
---|
90 | {
|
---|
91 | if (upto != NULL) {
|
---|
92 | BIO *tbio;
|
---|
93 |
|
---|
94 | do {
|
---|
95 | tbio = BIO_pop(f);
|
---|
96 | BIO_free(f);
|
---|
97 | f = tbio;
|
---|
98 | } while (f != NULL && f != upto);
|
---|
99 | } else {
|
---|
100 | BIO_free_all(f);
|
---|
101 | }
|
---|
102 | }
|
---|
103 |
|
---|
104 | int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
|
---|
105 | {
|
---|
106 | BIO *cont;
|
---|
107 | int r;
|
---|
108 |
|
---|
109 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
|
---|
110 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA);
|
---|
111 | return 0;
|
---|
112 | }
|
---|
113 | cont = CMS_dataInit(cms, NULL);
|
---|
114 | if (cont == NULL)
|
---|
115 | return 0;
|
---|
116 | r = cms_copy_content(out, cont, flags);
|
---|
117 | BIO_free_all(cont);
|
---|
118 | return r;
|
---|
119 | }
|
---|
120 |
|
---|
121 | CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
|
---|
122 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
123 | {
|
---|
124 | CMS_ContentInfo *cms = ossl_cms_Data_create(libctx, propq);
|
---|
125 |
|
---|
126 | if (cms == NULL)
|
---|
127 | return NULL;
|
---|
128 |
|
---|
129 | if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
---|
130 | return cms;
|
---|
131 |
|
---|
132 | CMS_ContentInfo_free(cms);
|
---|
133 | return NULL;
|
---|
134 | }
|
---|
135 |
|
---|
136 | CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
|
---|
137 | {
|
---|
138 | return CMS_data_create_ex(in, flags, NULL, NULL);
|
---|
139 | }
|
---|
140 |
|
---|
141 | int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
---|
142 | unsigned int flags)
|
---|
143 | {
|
---|
144 | BIO *cont;
|
---|
145 | int r;
|
---|
146 |
|
---|
147 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
|
---|
148 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA);
|
---|
149 | return 0;
|
---|
150 | }
|
---|
151 |
|
---|
152 | if (dcont == NULL && !check_content(cms))
|
---|
153 | return 0;
|
---|
154 |
|
---|
155 | cont = CMS_dataInit(cms, dcont);
|
---|
156 | if (cont == NULL)
|
---|
157 | return 0;
|
---|
158 |
|
---|
159 | r = cms_copy_content(out, cont, flags);
|
---|
160 | if (r)
|
---|
161 | r = ossl_cms_DigestedData_do_final(cms, cont, 1);
|
---|
162 | do_free_upto(cont, dcont);
|
---|
163 | return r;
|
---|
164 | }
|
---|
165 |
|
---|
166 | CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
|
---|
167 | unsigned int flags, OSSL_LIB_CTX *ctx,
|
---|
168 | const char *propq)
|
---|
169 | {
|
---|
170 | CMS_ContentInfo *cms;
|
---|
171 |
|
---|
172 | /*
|
---|
173 | * Because the EVP_MD is cached and can be a legacy algorithm, we
|
---|
174 | * cannot fetch the algorithm if it isn't supplied.
|
---|
175 | */
|
---|
176 | if (md == NULL)
|
---|
177 | md = EVP_sha1();
|
---|
178 | cms = ossl_cms_DigestedData_create(md, ctx, propq);
|
---|
179 | if (cms == NULL)
|
---|
180 | return NULL;
|
---|
181 |
|
---|
182 | if (!(flags & CMS_DETACHED))
|
---|
183 | CMS_set_detached(cms, 0);
|
---|
184 |
|
---|
185 | if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
---|
186 | return cms;
|
---|
187 |
|
---|
188 | CMS_ContentInfo_free(cms);
|
---|
189 | return NULL;
|
---|
190 | }
|
---|
191 |
|
---|
192 | CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
|
---|
193 | unsigned int flags)
|
---|
194 | {
|
---|
195 | return CMS_digest_create_ex(in, md, flags, NULL, NULL);
|
---|
196 | }
|
---|
197 |
|
---|
198 | int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
|
---|
199 | const unsigned char *key, size_t keylen,
|
---|
200 | BIO *dcont, BIO *out, unsigned int flags)
|
---|
201 | {
|
---|
202 | BIO *cont;
|
---|
203 | int r;
|
---|
204 |
|
---|
205 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
|
---|
206 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA);
|
---|
207 | return 0;
|
---|
208 | }
|
---|
209 |
|
---|
210 | if (dcont == NULL && !check_content(cms))
|
---|
211 | return 0;
|
---|
212 |
|
---|
213 | if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
|
---|
214 | return 0;
|
---|
215 | cont = CMS_dataInit(cms, dcont);
|
---|
216 | if (cont == NULL)
|
---|
217 | return 0;
|
---|
218 | r = cms_copy_content(out, cont, flags);
|
---|
219 | do_free_upto(cont, dcont);
|
---|
220 | return r;
|
---|
221 | }
|
---|
222 |
|
---|
223 | CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
|
---|
224 | const unsigned char *key,
|
---|
225 | size_t keylen, unsigned int flags,
|
---|
226 | OSSL_LIB_CTX *libctx,
|
---|
227 | const char *propq)
|
---|
228 | {
|
---|
229 | CMS_ContentInfo *cms;
|
---|
230 |
|
---|
231 | if (cipher == NULL) {
|
---|
232 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
|
---|
233 | return NULL;
|
---|
234 | }
|
---|
235 | cms = CMS_ContentInfo_new_ex(libctx, propq);
|
---|
236 | if (cms == NULL)
|
---|
237 | return NULL;
|
---|
238 | if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
|
---|
239 | goto err;
|
---|
240 |
|
---|
241 | if (!(flags & CMS_DETACHED))
|
---|
242 | CMS_set_detached(cms, 0);
|
---|
243 |
|
---|
244 | if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
---|
245 | || CMS_final(cms, in, NULL, flags))
|
---|
246 | return cms;
|
---|
247 |
|
---|
248 | err:
|
---|
249 | CMS_ContentInfo_free(cms);
|
---|
250 | return NULL;
|
---|
251 | }
|
---|
252 |
|
---|
253 | CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|
---|
254 | const unsigned char *key,
|
---|
255 | size_t keylen, unsigned int flags)
|
---|
256 | {
|
---|
257 | return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
|
---|
258 | NULL);
|
---|
259 | }
|
---|
260 |
|
---|
261 | static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
|
---|
262 | X509_STORE *store,
|
---|
263 | STACK_OF(X509) *untrusted,
|
---|
264 | STACK_OF(X509_CRL) *crls,
|
---|
265 | STACK_OF(X509) **chain,
|
---|
266 | const CMS_CTX *cms_ctx)
|
---|
267 | {
|
---|
268 | X509_STORE_CTX *ctx;
|
---|
269 | X509 *signer;
|
---|
270 | int i, j, r = 0;
|
---|
271 |
|
---|
272 | ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
|
---|
273 | ossl_cms_ctx_get0_propq(cms_ctx));
|
---|
274 | if (ctx == NULL) {
|
---|
275 | ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB);
|
---|
276 | goto err;
|
---|
277 | }
|
---|
278 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
---|
279 | if (!X509_STORE_CTX_init(ctx, store, signer, untrusted)) {
|
---|
280 | ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
|
---|
281 | goto err;
|
---|
282 | }
|
---|
283 | X509_STORE_CTX_set_default(ctx, "smime_sign");
|
---|
284 | if (crls != NULL)
|
---|
285 | X509_STORE_CTX_set0_crls(ctx, crls);
|
---|
286 |
|
---|
287 | i = X509_verify_cert(ctx);
|
---|
288 | if (i <= 0) {
|
---|
289 | j = X509_STORE_CTX_get_error(ctx);
|
---|
290 | ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
|
---|
291 | "Verify error: %s", X509_verify_cert_error_string(j));
|
---|
292 | goto err;
|
---|
293 | }
|
---|
294 | r = 1;
|
---|
295 |
|
---|
296 | /* also send back the trust chain when required */
|
---|
297 | if (chain != NULL)
|
---|
298 | *chain = X509_STORE_CTX_get1_chain(ctx);
|
---|
299 | err:
|
---|
300 | X509_STORE_CTX_free(ctx);
|
---|
301 | return r;
|
---|
302 |
|
---|
303 | }
|
---|
304 |
|
---|
305 | /* This strongly overlaps with PKCS7_verify() */
|
---|
306 | int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
---|
307 | X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
|
---|
308 | {
|
---|
309 | CMS_SignerInfo *si;
|
---|
310 | STACK_OF(CMS_SignerInfo) *sinfos;
|
---|
311 | STACK_OF(X509) *cms_certs = NULL;
|
---|
312 | STACK_OF(X509_CRL) *crls = NULL;
|
---|
313 | STACK_OF(X509) **si_chains = NULL;
|
---|
314 | X509 *signer;
|
---|
315 | int i, scount = 0, ret = 0;
|
---|
316 | BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
|
---|
317 | int cadesVerify = (flags & CMS_CADES) != 0;
|
---|
318 | const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
|
---|
319 |
|
---|
320 | if (dcont == NULL && !check_content(cms))
|
---|
321 | return 0;
|
---|
322 | if (dcont != NULL && !(flags & CMS_BINARY)) {
|
---|
323 | const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
|
---|
324 |
|
---|
325 | if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
|
---|
326 | flags |= CMS_ASCIICRLF;
|
---|
327 | }
|
---|
328 |
|
---|
329 | /* Attempt to find all signer certificates */
|
---|
330 |
|
---|
331 | sinfos = CMS_get0_SignerInfos(cms);
|
---|
332 |
|
---|
333 | if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
|
---|
334 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
|
---|
335 | goto err;
|
---|
336 | }
|
---|
337 |
|
---|
338 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
---|
339 | si = sk_CMS_SignerInfo_value(sinfos, i);
|
---|
340 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
---|
341 | if (signer != NULL)
|
---|
342 | scount++;
|
---|
343 | }
|
---|
344 |
|
---|
345 | if (scount != sk_CMS_SignerInfo_num(sinfos))
|
---|
346 | scount += CMS_set1_signers_certs(cms, certs, flags);
|
---|
347 |
|
---|
348 | if (scount != sk_CMS_SignerInfo_num(sinfos)) {
|
---|
349 | ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
|
---|
350 | goto err;
|
---|
351 | }
|
---|
352 |
|
---|
353 | /* Attempt to verify all signers certs */
|
---|
354 | /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
|
---|
355 |
|
---|
356 | if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
|
---|
357 | if (cadesVerify) {
|
---|
358 | /* Certificate trust chain is required to check CAdES signature */
|
---|
359 | si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
|
---|
360 | if (si_chains == NULL)
|
---|
361 | goto err;
|
---|
362 | }
|
---|
363 | cms_certs = CMS_get1_certs(cms);
|
---|
364 | if (!(flags & CMS_NOCRL))
|
---|
365 | crls = CMS_get1_crls(cms);
|
---|
366 | for (i = 0; i < scount; i++) {
|
---|
367 | si = sk_CMS_SignerInfo_value(sinfos, i);
|
---|
368 |
|
---|
369 | if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
|
---|
370 | si_chains ? &si_chains[i] : NULL,
|
---|
371 | ctx))
|
---|
372 | goto err;
|
---|
373 | }
|
---|
374 | }
|
---|
375 |
|
---|
376 | /* Attempt to verify all SignerInfo signed attribute signatures */
|
---|
377 |
|
---|
378 | if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
|
---|
379 | for (i = 0; i < scount; i++) {
|
---|
380 | si = sk_CMS_SignerInfo_value(sinfos, i);
|
---|
381 | if (CMS_signed_get_attr_count(si) < 0)
|
---|
382 | continue;
|
---|
383 | if (CMS_SignerInfo_verify(si) <= 0)
|
---|
384 | goto err;
|
---|
385 | if (cadesVerify) {
|
---|
386 | STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
|
---|
387 |
|
---|
388 | if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
|
---|
389 | goto err;
|
---|
390 | }
|
---|
391 | }
|
---|
392 | }
|
---|
393 |
|
---|
394 | /*
|
---|
395 | * Performance optimization: if the content is a memory BIO then store
|
---|
396 | * its contents in a temporary read only memory BIO. This avoids
|
---|
397 | * potentially large numbers of slow copies of data which will occur when
|
---|
398 | * reading from a read write memory BIO when signatures are calculated.
|
---|
399 | */
|
---|
400 |
|
---|
401 | if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
|
---|
402 | char *ptr;
|
---|
403 | long len;
|
---|
404 |
|
---|
405 | len = BIO_get_mem_data(dcont, &ptr);
|
---|
406 | tmpin = (len == 0) ? dcont : BIO_new_mem_buf(ptr, len);
|
---|
407 | if (tmpin == NULL) {
|
---|
408 | ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB);
|
---|
409 | goto err2;
|
---|
410 | }
|
---|
411 | } else {
|
---|
412 | tmpin = dcont;
|
---|
413 | }
|
---|
414 | /*
|
---|
415 | * If not binary mode and detached generate digests by *writing* through
|
---|
416 | * the BIO. That makes it possible to canonicalise the input.
|
---|
417 | */
|
---|
418 | if (!(flags & SMIME_BINARY) && dcont) {
|
---|
419 | /*
|
---|
420 | * Create output BIO so we can either handle text or to ensure
|
---|
421 | * included content doesn't override detached content.
|
---|
422 | */
|
---|
423 | tmpout = cms_get_text_bio(out, flags);
|
---|
424 | if (tmpout == NULL) {
|
---|
425 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
426 | goto err;
|
---|
427 | }
|
---|
428 | cmsbio = CMS_dataInit(cms, tmpout);
|
---|
429 | if (cmsbio == NULL)
|
---|
430 | goto err;
|
---|
431 | /*
|
---|
432 | * Don't use SMIME_TEXT for verify: it adds headers and we want to
|
---|
433 | * remove them.
|
---|
434 | */
|
---|
435 | if (!SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT))
|
---|
436 | goto err;
|
---|
437 |
|
---|
438 | if (flags & CMS_TEXT) {
|
---|
439 | if (!SMIME_text(tmpout, out)) {
|
---|
440 | ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
|
---|
441 | goto err;
|
---|
442 | }
|
---|
443 | }
|
---|
444 | } else {
|
---|
445 | cmsbio = CMS_dataInit(cms, tmpin);
|
---|
446 | if (cmsbio == NULL)
|
---|
447 | goto err;
|
---|
448 |
|
---|
449 | if (!cms_copy_content(out, cmsbio, flags))
|
---|
450 | goto err;
|
---|
451 |
|
---|
452 | }
|
---|
453 | if (!(flags & CMS_NO_CONTENT_VERIFY)) {
|
---|
454 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
---|
455 | si = sk_CMS_SignerInfo_value(sinfos, i);
|
---|
456 | if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
|
---|
457 | ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR);
|
---|
458 | goto err;
|
---|
459 | }
|
---|
460 | }
|
---|
461 | }
|
---|
462 |
|
---|
463 | ret = 1;
|
---|
464 | err:
|
---|
465 | if (!(flags & SMIME_BINARY) && dcont) {
|
---|
466 | do_free_upto(cmsbio, tmpout);
|
---|
467 | if (tmpin != dcont)
|
---|
468 | BIO_free(tmpin);
|
---|
469 | } else {
|
---|
470 | if (dcont && (tmpin == dcont))
|
---|
471 | do_free_upto(cmsbio, dcont);
|
---|
472 | else
|
---|
473 | BIO_free_all(cmsbio);
|
---|
474 | }
|
---|
475 |
|
---|
476 | if (out != tmpout)
|
---|
477 | BIO_free_all(tmpout);
|
---|
478 |
|
---|
479 | err2:
|
---|
480 | if (si_chains != NULL) {
|
---|
481 | for (i = 0; i < scount; ++i)
|
---|
482 | OSSL_STACK_OF_X509_free(si_chains[i]);
|
---|
483 | OPENSSL_free(si_chains);
|
---|
484 | }
|
---|
485 | OSSL_STACK_OF_X509_free(cms_certs);
|
---|
486 | sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
---|
487 |
|
---|
488 | return ret;
|
---|
489 | }
|
---|
490 |
|
---|
491 | int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
|
---|
492 | STACK_OF(X509) *certs,
|
---|
493 | X509_STORE *store, unsigned int flags)
|
---|
494 | {
|
---|
495 | int r;
|
---|
496 |
|
---|
497 | flags &= ~(CMS_DETACHED | CMS_TEXT);
|
---|
498 | r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
|
---|
499 | if (r <= 0)
|
---|
500 | return r;
|
---|
501 | return ossl_cms_Receipt_verify(rcms, ocms);
|
---|
502 | }
|
---|
503 |
|
---|
504 | CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
|
---|
505 | STACK_OF(X509) *certs, BIO *data,
|
---|
506 | unsigned int flags, OSSL_LIB_CTX *libctx,
|
---|
507 | const char *propq)
|
---|
508 | {
|
---|
509 | CMS_ContentInfo *cms;
|
---|
510 | int i;
|
---|
511 |
|
---|
512 | cms = CMS_ContentInfo_new_ex(libctx, propq);
|
---|
513 | if (cms == NULL || !CMS_SignedData_init(cms)) {
|
---|
514 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
515 | goto err;
|
---|
516 | }
|
---|
517 | if (flags & CMS_ASCIICRLF
|
---|
518 | && !CMS_set1_eContentType(cms,
|
---|
519 | OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF))) {
|
---|
520 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
521 | goto err;
|
---|
522 | }
|
---|
523 |
|
---|
524 | if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
|
---|
525 | ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
|
---|
526 | goto err;
|
---|
527 | }
|
---|
528 |
|
---|
529 | for (i = 0; i < sk_X509_num(certs); i++) {
|
---|
530 | X509 *x = sk_X509_value(certs, i);
|
---|
531 |
|
---|
532 | if (!CMS_add1_cert(cms, x)) {
|
---|
533 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
534 | goto err;
|
---|
535 | }
|
---|
536 | }
|
---|
537 |
|
---|
538 | if (!(flags & CMS_DETACHED))
|
---|
539 | CMS_set_detached(cms, 0);
|
---|
540 |
|
---|
541 | if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
---|
542 | || CMS_final(cms, data, NULL, flags))
|
---|
543 | return cms;
|
---|
544 | else
|
---|
545 | goto err;
|
---|
546 |
|
---|
547 | err:
|
---|
548 | CMS_ContentInfo_free(cms);
|
---|
549 | return NULL;
|
---|
550 | }
|
---|
551 |
|
---|
552 | CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
---|
553 | BIO *data, unsigned int flags)
|
---|
554 | {
|
---|
555 | return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
|
---|
556 | }
|
---|
557 |
|
---|
558 | CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
---|
559 | X509 *signcert, EVP_PKEY *pkey,
|
---|
560 | STACK_OF(X509) *certs, unsigned int flags)
|
---|
561 | {
|
---|
562 | CMS_SignerInfo *rct_si;
|
---|
563 | CMS_ContentInfo *cms = NULL;
|
---|
564 | ASN1_OCTET_STRING **pos, *os = NULL;
|
---|
565 | BIO *rct_cont = NULL;
|
---|
566 | int r = 0;
|
---|
567 | const CMS_CTX *ctx = si->cms_ctx;
|
---|
568 |
|
---|
569 | flags &= ~(CMS_STREAM | CMS_TEXT);
|
---|
570 | /* Not really detached but avoids content being allocated */
|
---|
571 | flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
|
---|
572 | if (pkey == NULL || signcert == NULL) {
|
---|
573 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
|
---|
574 | return NULL;
|
---|
575 | }
|
---|
576 |
|
---|
577 | /* Initialize signed data */
|
---|
578 |
|
---|
579 | cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
|
---|
580 | ossl_cms_ctx_get0_libctx(ctx),
|
---|
581 | ossl_cms_ctx_get0_propq(ctx));
|
---|
582 | if (cms == NULL)
|
---|
583 | goto err;
|
---|
584 |
|
---|
585 | /* Set inner content type to signed receipt */
|
---|
586 | if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
|
---|
587 | goto err;
|
---|
588 |
|
---|
589 | rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
|
---|
590 | if (!rct_si) {
|
---|
591 | ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
|
---|
592 | goto err;
|
---|
593 | }
|
---|
594 |
|
---|
595 | os = ossl_cms_encode_Receipt(si);
|
---|
596 | if (os == NULL)
|
---|
597 | goto err;
|
---|
598 |
|
---|
599 | /* Set content to digest */
|
---|
600 | rct_cont = BIO_new_mem_buf(os->data, os->length);
|
---|
601 | if (rct_cont == NULL)
|
---|
602 | goto err;
|
---|
603 |
|
---|
604 | /* Add msgSigDigest attribute */
|
---|
605 |
|
---|
606 | if (!ossl_cms_msgSigDigest_add1(rct_si, si))
|
---|
607 | goto err;
|
---|
608 |
|
---|
609 | /* Finalize structure */
|
---|
610 | if (!CMS_final(cms, rct_cont, NULL, flags))
|
---|
611 | goto err;
|
---|
612 |
|
---|
613 | /* Set embedded content */
|
---|
614 | pos = CMS_get0_content(cms);
|
---|
615 | if (pos == NULL)
|
---|
616 | goto err;
|
---|
617 | *pos = os;
|
---|
618 |
|
---|
619 | r = 1;
|
---|
620 |
|
---|
621 | err:
|
---|
622 | BIO_free(rct_cont);
|
---|
623 | if (r)
|
---|
624 | return cms;
|
---|
625 | CMS_ContentInfo_free(cms);
|
---|
626 | ASN1_OCTET_STRING_free(os);
|
---|
627 | return NULL;
|
---|
628 |
|
---|
629 | }
|
---|
630 |
|
---|
631 | CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
|
---|
632 | const EVP_CIPHER *cipher, unsigned int flags,
|
---|
633 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
634 | {
|
---|
635 | CMS_ContentInfo *cms;
|
---|
636 | int i;
|
---|
637 | X509 *recip;
|
---|
638 |
|
---|
639 |
|
---|
640 | cms = (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
---|
641 | ? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
|
---|
642 | : CMS_EnvelopedData_create_ex(cipher, libctx, propq);
|
---|
643 | if (cms == NULL) {
|
---|
644 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
645 | goto err;
|
---|
646 | }
|
---|
647 | for (i = 0; i < sk_X509_num(certs); i++) {
|
---|
648 | recip = sk_X509_value(certs, i);
|
---|
649 | if (!CMS_add1_recipient_cert(cms, recip, flags)) {
|
---|
650 | ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
|
---|
651 | goto err;
|
---|
652 | }
|
---|
653 | }
|
---|
654 |
|
---|
655 | if (!(flags & CMS_DETACHED))
|
---|
656 | CMS_set_detached(cms, 0);
|
---|
657 |
|
---|
658 | if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
---|
659 | || CMS_final(cms, data, NULL, flags))
|
---|
660 | return cms;
|
---|
661 | else
|
---|
662 | ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
|
---|
663 |
|
---|
664 | err:
|
---|
665 | CMS_ContentInfo_free(cms);
|
---|
666 | return NULL;
|
---|
667 | }
|
---|
668 |
|
---|
669 | CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
|
---|
670 | const EVP_CIPHER *cipher, unsigned int flags)
|
---|
671 | {
|
---|
672 | return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
|
---|
673 | }
|
---|
674 |
|
---|
675 | static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
|
---|
676 | CMS_RecipientInfo *ri,
|
---|
677 | EVP_PKEY *pk, X509 *cert, X509 *peer)
|
---|
678 | {
|
---|
679 | int i;
|
---|
680 | STACK_OF(CMS_RecipientEncryptedKey) *reks;
|
---|
681 | CMS_RecipientEncryptedKey *rek;
|
---|
682 |
|
---|
683 | reks = CMS_RecipientInfo_kari_get0_reks(ri);
|
---|
684 | for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
|
---|
685 | int rv;
|
---|
686 |
|
---|
687 | rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
|
---|
688 | if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
|
---|
689 | continue;
|
---|
690 | CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
|
---|
691 | rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
|
---|
692 | CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
|
---|
693 | if (rv > 0)
|
---|
694 | return 1;
|
---|
695 | return cert == NULL ? 0 : -1;
|
---|
696 | }
|
---|
697 | return 0;
|
---|
698 | }
|
---|
699 |
|
---|
700 | int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
|
---|
701 | {
|
---|
702 | return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
|
---|
703 | }
|
---|
704 |
|
---|
705 | int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
|
---|
706 | X509 *cert, X509 *peer)
|
---|
707 | {
|
---|
708 | STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
|
---|
709 | CMS_RecipientInfo *ri;
|
---|
710 | int i, r, cms_pkey_ri_type;
|
---|
711 | int debug = 0, match_ri = 0;
|
---|
712 | CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
|
---|
713 |
|
---|
714 | /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
|
---|
715 | if (ec != NULL) {
|
---|
716 | OPENSSL_clear_free(ec->key, ec->keylen);
|
---|
717 | ec->key = NULL;
|
---|
718 | ec->keylen = 0;
|
---|
719 | }
|
---|
720 |
|
---|
721 | if (ris != NULL && ec != NULL)
|
---|
722 | debug = ec->debug;
|
---|
723 |
|
---|
724 | cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
|
---|
725 | if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
|
---|
726 | ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
---|
727 | return 0;
|
---|
728 | }
|
---|
729 |
|
---|
730 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
731 | int ri_type;
|
---|
732 |
|
---|
733 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
734 | ri_type = CMS_RecipientInfo_type(ri);
|
---|
735 | if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
|
---|
736 | continue;
|
---|
737 | match_ri = 1;
|
---|
738 | if (ri_type == CMS_RECIPINFO_AGREE) {
|
---|
739 | r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
|
---|
740 | if (r > 0)
|
---|
741 | return 1;
|
---|
742 | if (r < 0)
|
---|
743 | return 0;
|
---|
744 | }
|
---|
745 | /* If we have a cert, try matching RecipientInfo, else try them all */
|
---|
746 | else if (cert == NULL || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
|
---|
747 | EVP_PKEY_up_ref(pk);
|
---|
748 | CMS_RecipientInfo_set0_pkey(ri, pk);
|
---|
749 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
750 | CMS_RecipientInfo_set0_pkey(ri, NULL);
|
---|
751 | if (cert != NULL) {
|
---|
752 | /*
|
---|
753 | * If not debugging clear any error and return success to
|
---|
754 | * avoid leaking of information useful to MMA
|
---|
755 | */
|
---|
756 | if (!debug) {
|
---|
757 | ERR_clear_error();
|
---|
758 | return 1;
|
---|
759 | }
|
---|
760 | if (r > 0)
|
---|
761 | return 1;
|
---|
762 | ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
|
---|
763 | return 0;
|
---|
764 | }
|
---|
765 | /*
|
---|
766 | * If no cert and not debugging don't leave loop after first
|
---|
767 | * successful decrypt. Always attempt to decrypt all recipients
|
---|
768 | * to avoid leaking timing of a successful decrypt.
|
---|
769 | */
|
---|
770 | else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
|
---|
771 | return 1;
|
---|
772 | }
|
---|
773 | }
|
---|
774 | /* If no cert, key transport and not debugging always return success */
|
---|
775 | if (cert == NULL
|
---|
776 | && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
|
---|
777 | && match_ri
|
---|
778 | && !debug) {
|
---|
779 | ERR_clear_error();
|
---|
780 | return 1;
|
---|
781 | }
|
---|
782 |
|
---|
783 | if (!match_ri)
|
---|
784 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
785 | return 0;
|
---|
786 |
|
---|
787 | }
|
---|
788 |
|
---|
789 | int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
|
---|
790 | unsigned char *key, size_t keylen,
|
---|
791 | const unsigned char *id, size_t idlen)
|
---|
792 | {
|
---|
793 | STACK_OF(CMS_RecipientInfo) *ris;
|
---|
794 | CMS_RecipientInfo *ri;
|
---|
795 | int i, r, match_ri = 0;
|
---|
796 |
|
---|
797 | ris = CMS_get0_RecipientInfos(cms);
|
---|
798 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
799 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
800 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
|
---|
801 | continue;
|
---|
802 |
|
---|
803 | /* If we have an id, try matching RecipientInfo, else try them all */
|
---|
804 | if (id == NULL
|
---|
805 | || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
|
---|
806 | match_ri = 1;
|
---|
807 | CMS_RecipientInfo_set0_key(ri, key, keylen);
|
---|
808 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
809 | CMS_RecipientInfo_set0_key(ri, NULL, 0);
|
---|
810 | if (r > 0)
|
---|
811 | return 1;
|
---|
812 | if (id != NULL) {
|
---|
813 | ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
|
---|
814 | return 0;
|
---|
815 | }
|
---|
816 | ERR_clear_error();
|
---|
817 | }
|
---|
818 | }
|
---|
819 |
|
---|
820 | if (!match_ri)
|
---|
821 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
822 | return 0;
|
---|
823 |
|
---|
824 | }
|
---|
825 |
|
---|
826 | int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
|
---|
827 | unsigned char *pass, ossl_ssize_t passlen)
|
---|
828 | {
|
---|
829 | STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
|
---|
830 | CMS_RecipientInfo *ri;
|
---|
831 | int i, r, match_ri = 0;
|
---|
832 | CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
|
---|
833 |
|
---|
834 | /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
|
---|
835 | if (ec != NULL) {
|
---|
836 | OPENSSL_clear_free(ec->key, ec->keylen);
|
---|
837 | ec->key = NULL;
|
---|
838 | ec->keylen = 0;
|
---|
839 | }
|
---|
840 |
|
---|
841 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
842 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
843 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
|
---|
844 | continue;
|
---|
845 |
|
---|
846 | /* Must try each PasswordRecipientInfo */
|
---|
847 | match_ri = 1;
|
---|
848 | CMS_RecipientInfo_set0_password(ri, pass, passlen);
|
---|
849 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
850 | CMS_RecipientInfo_set0_password(ri, NULL, 0);
|
---|
851 | if (r > 0)
|
---|
852 | return 1;
|
---|
853 | }
|
---|
854 |
|
---|
855 | if (!match_ri)
|
---|
856 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
857 | return 0;
|
---|
858 |
|
---|
859 | }
|
---|
860 |
|
---|
861 | int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
|
---|
862 | BIO *dcont, BIO *out, unsigned int flags)
|
---|
863 | {
|
---|
864 | int r;
|
---|
865 | BIO *cont;
|
---|
866 | CMS_EncryptedContentInfo *ec;
|
---|
867 | int nid = OBJ_obj2nid(CMS_get0_type(cms));
|
---|
868 |
|
---|
869 | if (nid != NID_pkcs7_enveloped
|
---|
870 | && nid != NID_id_smime_ct_authEnvelopedData) {
|
---|
871 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
|
---|
872 | return 0;
|
---|
873 | }
|
---|
874 | if (dcont == NULL && !check_content(cms))
|
---|
875 | return 0;
|
---|
876 | ec = ossl_cms_get0_env_enc_content(cms);
|
---|
877 | ec->debug = (flags & CMS_DEBUG_DECRYPT) != 0;
|
---|
878 | ec->havenocert = cert == NULL;
|
---|
879 | if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
|
---|
880 | return 1;
|
---|
881 | if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
|
---|
882 | return 0;
|
---|
883 | cont = CMS_dataInit(cms, dcont);
|
---|
884 | if (cont == NULL)
|
---|
885 | return 0;
|
---|
886 | r = cms_copy_content(out, cont, flags);
|
---|
887 | do_free_upto(cont, dcont);
|
---|
888 | return r;
|
---|
889 | }
|
---|
890 |
|
---|
891 | int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
|
---|
892 | {
|
---|
893 | BIO *cmsbio;
|
---|
894 | int ret = 0;
|
---|
895 |
|
---|
896 | if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
|
---|
897 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
|
---|
898 | return 0;
|
---|
899 | }
|
---|
900 |
|
---|
901 | if (!SMIME_crlf_copy(data, cmsbio, flags)) {
|
---|
902 | goto err;
|
---|
903 | }
|
---|
904 |
|
---|
905 | (void)BIO_flush(cmsbio);
|
---|
906 |
|
---|
907 | if (!CMS_dataFinal(cms, cmsbio)) {
|
---|
908 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
|
---|
909 | goto err;
|
---|
910 | }
|
---|
911 |
|
---|
912 | ret = 1;
|
---|
913 |
|
---|
914 | err:
|
---|
915 | do_free_upto(cmsbio, dcont);
|
---|
916 |
|
---|
917 | return ret;
|
---|
918 |
|
---|
919 | }
|
---|
920 |
|
---|
921 | int CMS_final_digest(CMS_ContentInfo *cms,
|
---|
922 | const unsigned char *md, unsigned int mdlen,
|
---|
923 | BIO *dcont, unsigned int flags)
|
---|
924 | {
|
---|
925 | BIO *cmsbio;
|
---|
926 | int ret = 0;
|
---|
927 |
|
---|
928 | if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
|
---|
929 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
|
---|
930 | return 0;
|
---|
931 | }
|
---|
932 |
|
---|
933 | (void)BIO_flush(cmsbio);
|
---|
934 |
|
---|
935 | if (!ossl_cms_DataFinal(cms, cmsbio, md, mdlen)) {
|
---|
936 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
|
---|
937 | goto err;
|
---|
938 | }
|
---|
939 | ret = 1;
|
---|
940 |
|
---|
941 | err:
|
---|
942 | do_free_upto(cmsbio, dcont);
|
---|
943 | return ret;
|
---|
944 | }
|
---|
945 |
|
---|
946 | #ifndef OPENSSL_NO_ZLIB
|
---|
947 |
|
---|
948 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
---|
949 | unsigned int flags)
|
---|
950 | {
|
---|
951 | BIO *cont;
|
---|
952 | int r;
|
---|
953 |
|
---|
954 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
|
---|
955 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
|
---|
956 | return 0;
|
---|
957 | }
|
---|
958 |
|
---|
959 | if (dcont == NULL && !check_content(cms))
|
---|
960 | return 0;
|
---|
961 |
|
---|
962 | cont = CMS_dataInit(cms, dcont);
|
---|
963 | if (cont == NULL)
|
---|
964 | return 0;
|
---|
965 | r = cms_copy_content(out, cont, flags);
|
---|
966 | do_free_upto(cont, dcont);
|
---|
967 | return r;
|
---|
968 | }
|
---|
969 |
|
---|
970 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
---|
971 | {
|
---|
972 | CMS_ContentInfo *cms;
|
---|
973 |
|
---|
974 | if (comp_nid <= 0)
|
---|
975 | comp_nid = NID_zlib_compression;
|
---|
976 | cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
|
---|
977 | if (cms == NULL)
|
---|
978 | return NULL;
|
---|
979 |
|
---|
980 | if (!(flags & CMS_DETACHED))
|
---|
981 | CMS_set_detached(cms, 0);
|
---|
982 |
|
---|
983 | if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
---|
984 | return cms;
|
---|
985 |
|
---|
986 | CMS_ContentInfo_free(cms);
|
---|
987 | return NULL;
|
---|
988 | }
|
---|
989 |
|
---|
990 | #else
|
---|
991 |
|
---|
992 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
---|
993 | unsigned int flags)
|
---|
994 | {
|
---|
995 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
---|
996 | return 0;
|
---|
997 | }
|
---|
998 |
|
---|
999 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
---|
1000 | {
|
---|
1001 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
---|
1002 | return NULL;
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 | #endif
|
---|