1 | /*
|
---|
2 | * Copyright 2008-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 |
|
---|
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_MALLOC_FAILURE);
|
---|
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 | return NULL;
|
---|
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 | CMS_ContentInfo_free(cms);
|
---|
249 | return NULL;
|
---|
250 | }
|
---|
251 |
|
---|
252 | CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
|
---|
253 | const unsigned char *key,
|
---|
254 | size_t keylen, unsigned int flags)
|
---|
255 | {
|
---|
256 | return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
|
---|
257 | NULL);
|
---|
258 | }
|
---|
259 |
|
---|
260 | static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
|
---|
261 | X509_STORE *store,
|
---|
262 | STACK_OF(X509) *certs,
|
---|
263 | STACK_OF(X509_CRL) *crls,
|
---|
264 | STACK_OF(X509) **chain,
|
---|
265 | const CMS_CTX *cms_ctx)
|
---|
266 | {
|
---|
267 | X509_STORE_CTX *ctx;
|
---|
268 | X509 *signer;
|
---|
269 | int i, j, r = 0;
|
---|
270 |
|
---|
271 | ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
|
---|
272 | ossl_cms_ctx_get0_propq(cms_ctx));
|
---|
273 | if (ctx == NULL) {
|
---|
274 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
|
---|
275 | goto err;
|
---|
276 | }
|
---|
277 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
---|
278 | if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
|
---|
279 | ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
|
---|
280 | goto err;
|
---|
281 | }
|
---|
282 | X509_STORE_CTX_set_default(ctx, "smime_sign");
|
---|
283 | if (crls != NULL)
|
---|
284 | X509_STORE_CTX_set0_crls(ctx, crls);
|
---|
285 |
|
---|
286 | i = X509_verify_cert(ctx);
|
---|
287 | if (i <= 0) {
|
---|
288 | j = X509_STORE_CTX_get_error(ctx);
|
---|
289 | ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
|
---|
290 | "Verify error: %s", X509_verify_cert_error_string(j));
|
---|
291 | goto err;
|
---|
292 | }
|
---|
293 | r = 1;
|
---|
294 |
|
---|
295 | /* also send back the trust chain when required */
|
---|
296 | if (chain != NULL)
|
---|
297 | *chain = X509_STORE_CTX_get1_chain(ctx);
|
---|
298 | err:
|
---|
299 | X509_STORE_CTX_free(ctx);
|
---|
300 | return r;
|
---|
301 |
|
---|
302 | }
|
---|
303 |
|
---|
304 | int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
|
---|
305 | X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
|
---|
306 | {
|
---|
307 | CMS_SignerInfo *si;
|
---|
308 | STACK_OF(CMS_SignerInfo) *sinfos;
|
---|
309 | STACK_OF(X509) *cms_certs = NULL;
|
---|
310 | STACK_OF(X509_CRL) *crls = NULL;
|
---|
311 | STACK_OF(X509) **si_chains = NULL;
|
---|
312 | X509 *signer;
|
---|
313 | int i, scount = 0, ret = 0;
|
---|
314 | BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
|
---|
315 | int cadesVerify = (flags & CMS_CADES) != 0;
|
---|
316 | const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
|
---|
317 |
|
---|
318 | if (dcont == NULL && !check_content(cms))
|
---|
319 | return 0;
|
---|
320 | if (dcont != NULL && !(flags & CMS_BINARY)) {
|
---|
321 | const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
|
---|
322 |
|
---|
323 | if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
|
---|
324 | flags |= CMS_ASCIICRLF;
|
---|
325 | }
|
---|
326 |
|
---|
327 | /* Attempt to find all signer certificates */
|
---|
328 |
|
---|
329 | sinfos = CMS_get0_SignerInfos(cms);
|
---|
330 |
|
---|
331 | if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
|
---|
332 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
|
---|
333 | goto err;
|
---|
334 | }
|
---|
335 |
|
---|
336 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
---|
337 | si = sk_CMS_SignerInfo_value(sinfos, i);
|
---|
338 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
|
---|
339 | if (signer)
|
---|
340 | scount++;
|
---|
341 | }
|
---|
342 |
|
---|
343 | if (scount != sk_CMS_SignerInfo_num(sinfos))
|
---|
344 | scount += CMS_set1_signers_certs(cms, certs, flags);
|
---|
345 |
|
---|
346 | if (scount != sk_CMS_SignerInfo_num(sinfos)) {
|
---|
347 | ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
|
---|
348 | goto err;
|
---|
349 | }
|
---|
350 |
|
---|
351 | /* Attempt to verify all signers certs */
|
---|
352 | /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
|
---|
353 |
|
---|
354 | if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
|
---|
355 | if (cadesVerify) {
|
---|
356 | /* Certificate trust chain is required to check CAdES signature */
|
---|
357 | si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
|
---|
358 | if (si_chains == NULL) {
|
---|
359 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
|
---|
360 | goto err;
|
---|
361 | }
|
---|
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_MALLOC_FAILURE);
|
---|
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_MALLOC_FAILURE);
|
---|
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 | sk_X509_pop_free(si_chains[i], X509_free);
|
---|
483 | OPENSSL_free(si_chains);
|
---|
484 | }
|
---|
485 | sk_X509_pop_free(cms_certs, X509_free);
|
---|
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 | goto merr;
|
---|
515 | if (flags & CMS_ASCIICRLF
|
---|
516 | && !CMS_set1_eContentType(cms,
|
---|
517 | OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
|
---|
518 | goto err;
|
---|
519 |
|
---|
520 | if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
|
---|
521 | ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
|
---|
522 | goto err;
|
---|
523 | }
|
---|
524 |
|
---|
525 | for (i = 0; i < sk_X509_num(certs); i++) {
|
---|
526 | X509 *x = sk_X509_value(certs, i);
|
---|
527 |
|
---|
528 | if (!CMS_add1_cert(cms, x))
|
---|
529 | goto merr;
|
---|
530 | }
|
---|
531 |
|
---|
532 | if (!(flags & CMS_DETACHED))
|
---|
533 | CMS_set_detached(cms, 0);
|
---|
534 |
|
---|
535 | if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
---|
536 | || CMS_final(cms, data, NULL, flags))
|
---|
537 | return cms;
|
---|
538 | else
|
---|
539 | goto err;
|
---|
540 |
|
---|
541 | merr:
|
---|
542 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
|
---|
543 |
|
---|
544 | err:
|
---|
545 | CMS_ContentInfo_free(cms);
|
---|
546 | return NULL;
|
---|
547 | }
|
---|
548 |
|
---|
549 | CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
|
---|
550 | BIO *data, unsigned int flags)
|
---|
551 | {
|
---|
552 | return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
|
---|
553 | }
|
---|
554 |
|
---|
555 | CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
|
---|
556 | X509 *signcert, EVP_PKEY *pkey,
|
---|
557 | STACK_OF(X509) *certs, unsigned int flags)
|
---|
558 | {
|
---|
559 | CMS_SignerInfo *rct_si;
|
---|
560 | CMS_ContentInfo *cms = NULL;
|
---|
561 | ASN1_OCTET_STRING **pos, *os;
|
---|
562 | BIO *rct_cont = NULL;
|
---|
563 | int r = 0;
|
---|
564 | const CMS_CTX *ctx = si->cms_ctx;
|
---|
565 |
|
---|
566 | flags &= ~(CMS_STREAM | CMS_TEXT);
|
---|
567 | /* Not really detached but avoids content being allocated */
|
---|
568 | flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
|
---|
569 | if (pkey == NULL || signcert == NULL) {
|
---|
570 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
|
---|
571 | return NULL;
|
---|
572 | }
|
---|
573 |
|
---|
574 | /* Initialize signed data */
|
---|
575 |
|
---|
576 | cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
|
---|
577 | ossl_cms_ctx_get0_libctx(ctx),
|
---|
578 | ossl_cms_ctx_get0_propq(ctx));
|
---|
579 | if (cms == NULL)
|
---|
580 | goto err;
|
---|
581 |
|
---|
582 | /* Set inner content type to signed receipt */
|
---|
583 | if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
|
---|
584 | goto err;
|
---|
585 |
|
---|
586 | rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
|
---|
587 | if (!rct_si) {
|
---|
588 | ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
|
---|
589 | goto err;
|
---|
590 | }
|
---|
591 |
|
---|
592 | os = ossl_cms_encode_Receipt(si);
|
---|
593 | if (os == NULL)
|
---|
594 | goto err;
|
---|
595 |
|
---|
596 | /* Set content to digest */
|
---|
597 | rct_cont = BIO_new_mem_buf(os->data, os->length);
|
---|
598 | if (rct_cont == NULL)
|
---|
599 | goto err;
|
---|
600 |
|
---|
601 | /* Add msgSigDigest attribute */
|
---|
602 |
|
---|
603 | if (!ossl_cms_msgSigDigest_add1(rct_si, si))
|
---|
604 | goto err;
|
---|
605 |
|
---|
606 | /* Finalize structure */
|
---|
607 | if (!CMS_final(cms, rct_cont, NULL, flags))
|
---|
608 | goto err;
|
---|
609 |
|
---|
610 | /* Set embedded content */
|
---|
611 | pos = CMS_get0_content(cms);
|
---|
612 | if (pos == NULL)
|
---|
613 | goto err;
|
---|
614 | *pos = os;
|
---|
615 |
|
---|
616 | r = 1;
|
---|
617 |
|
---|
618 | err:
|
---|
619 | BIO_free(rct_cont);
|
---|
620 | if (r)
|
---|
621 | return cms;
|
---|
622 | CMS_ContentInfo_free(cms);
|
---|
623 | return NULL;
|
---|
624 |
|
---|
625 | }
|
---|
626 |
|
---|
627 | CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
|
---|
628 | const EVP_CIPHER *cipher, unsigned int flags,
|
---|
629 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
630 | {
|
---|
631 | CMS_ContentInfo *cms;
|
---|
632 | int i;
|
---|
633 | X509 *recip;
|
---|
634 |
|
---|
635 |
|
---|
636 | cms = (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
---|
637 | ? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
|
---|
638 | : CMS_EnvelopedData_create_ex(cipher, libctx, propq);
|
---|
639 | if (cms == NULL)
|
---|
640 | goto merr;
|
---|
641 | for (i = 0; i < sk_X509_num(certs); i++) {
|
---|
642 | recip = sk_X509_value(certs, i);
|
---|
643 | if (!CMS_add1_recipient_cert(cms, recip, flags)) {
|
---|
644 | ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
|
---|
645 | goto err;
|
---|
646 | }
|
---|
647 | }
|
---|
648 |
|
---|
649 | if (!(flags & CMS_DETACHED))
|
---|
650 | CMS_set_detached(cms, 0);
|
---|
651 |
|
---|
652 | if ((flags & (CMS_STREAM | CMS_PARTIAL))
|
---|
653 | || CMS_final(cms, data, NULL, flags))
|
---|
654 | return cms;
|
---|
655 | else
|
---|
656 | goto err;
|
---|
657 |
|
---|
658 | merr:
|
---|
659 | ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
|
---|
660 | err:
|
---|
661 | CMS_ContentInfo_free(cms);
|
---|
662 | return NULL;
|
---|
663 | }
|
---|
664 |
|
---|
665 | CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
|
---|
666 | const EVP_CIPHER *cipher, unsigned int flags)
|
---|
667 | {
|
---|
668 | return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
|
---|
669 | }
|
---|
670 |
|
---|
671 | static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
|
---|
672 | CMS_RecipientInfo *ri,
|
---|
673 | EVP_PKEY *pk, X509 *cert, X509 *peer)
|
---|
674 | {
|
---|
675 | int i;
|
---|
676 | STACK_OF(CMS_RecipientEncryptedKey) *reks;
|
---|
677 | CMS_RecipientEncryptedKey *rek;
|
---|
678 |
|
---|
679 | reks = CMS_RecipientInfo_kari_get0_reks(ri);
|
---|
680 | for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
|
---|
681 | int rv;
|
---|
682 |
|
---|
683 | rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
|
---|
684 | if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
|
---|
685 | continue;
|
---|
686 | CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
|
---|
687 | rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
|
---|
688 | CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
|
---|
689 | if (rv > 0)
|
---|
690 | return 1;
|
---|
691 | return cert == NULL ? 0 : -1;
|
---|
692 | }
|
---|
693 | return 0;
|
---|
694 | }
|
---|
695 |
|
---|
696 | int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
|
---|
697 | {
|
---|
698 | return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
|
---|
699 | }
|
---|
700 |
|
---|
701 | int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
|
---|
702 | X509 *cert, X509 *peer)
|
---|
703 | {
|
---|
704 | STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
|
---|
705 | CMS_RecipientInfo *ri;
|
---|
706 | int i, r, cms_pkey_ri_type;
|
---|
707 | int debug = 0, match_ri = 0;
|
---|
708 | CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
|
---|
709 |
|
---|
710 | /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
|
---|
711 | if (ec != NULL) {
|
---|
712 | OPENSSL_clear_free(ec->key, ec->keylen);
|
---|
713 | ec->key = NULL;
|
---|
714 | ec->keylen = 0;
|
---|
715 | }
|
---|
716 |
|
---|
717 | if (ris != NULL && ec != NULL)
|
---|
718 | debug = ec->debug;
|
---|
719 |
|
---|
720 | cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
|
---|
721 | if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
|
---|
722 | ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
|
---|
723 | return 0;
|
---|
724 | }
|
---|
725 |
|
---|
726 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
727 | int ri_type;
|
---|
728 |
|
---|
729 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
730 | ri_type = CMS_RecipientInfo_type(ri);
|
---|
731 | if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
|
---|
732 | continue;
|
---|
733 | match_ri = 1;
|
---|
734 | if (ri_type == CMS_RECIPINFO_AGREE) {
|
---|
735 | r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
|
---|
736 | if (r > 0)
|
---|
737 | return 1;
|
---|
738 | if (r < 0)
|
---|
739 | return 0;
|
---|
740 | }
|
---|
741 | /* If we have a cert, try matching RecipientInfo, else try them all */
|
---|
742 | else if (cert == NULL || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
|
---|
743 | EVP_PKEY_up_ref(pk);
|
---|
744 | CMS_RecipientInfo_set0_pkey(ri, pk);
|
---|
745 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
746 | CMS_RecipientInfo_set0_pkey(ri, NULL);
|
---|
747 | if (cert != NULL) {
|
---|
748 | /*
|
---|
749 | * If not debugging clear any error and return success to
|
---|
750 | * avoid leaking of information useful to MMA
|
---|
751 | */
|
---|
752 | if (!debug) {
|
---|
753 | ERR_clear_error();
|
---|
754 | return 1;
|
---|
755 | }
|
---|
756 | if (r > 0)
|
---|
757 | return 1;
|
---|
758 | ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
|
---|
759 | return 0;
|
---|
760 | }
|
---|
761 | /*
|
---|
762 | * If no cert and not debugging don't leave loop after first
|
---|
763 | * successful decrypt. Always attempt to decrypt all recipients
|
---|
764 | * to avoid leaking timing of a successful decrypt.
|
---|
765 | */
|
---|
766 | else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
|
---|
767 | return 1;
|
---|
768 | }
|
---|
769 | }
|
---|
770 | /* If no cert, key transport and not debugging always return success */
|
---|
771 | if (cert == NULL
|
---|
772 | && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
|
---|
773 | && match_ri
|
---|
774 | && !debug) {
|
---|
775 | ERR_clear_error();
|
---|
776 | return 1;
|
---|
777 | }
|
---|
778 |
|
---|
779 | if (!match_ri)
|
---|
780 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
781 | return 0;
|
---|
782 |
|
---|
783 | }
|
---|
784 |
|
---|
785 | int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
|
---|
786 | unsigned char *key, size_t keylen,
|
---|
787 | const unsigned char *id, size_t idlen)
|
---|
788 | {
|
---|
789 | STACK_OF(CMS_RecipientInfo) *ris;
|
---|
790 | CMS_RecipientInfo *ri;
|
---|
791 | int i, r, match_ri = 0;
|
---|
792 |
|
---|
793 | ris = CMS_get0_RecipientInfos(cms);
|
---|
794 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
795 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
796 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
|
---|
797 | continue;
|
---|
798 |
|
---|
799 | /* If we have an id, try matching RecipientInfo, else try them all */
|
---|
800 | if (id == NULL
|
---|
801 | || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
|
---|
802 | match_ri = 1;
|
---|
803 | CMS_RecipientInfo_set0_key(ri, key, keylen);
|
---|
804 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
805 | CMS_RecipientInfo_set0_key(ri, NULL, 0);
|
---|
806 | if (r > 0)
|
---|
807 | return 1;
|
---|
808 | if (id != NULL) {
|
---|
809 | ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
|
---|
810 | return 0;
|
---|
811 | }
|
---|
812 | ERR_clear_error();
|
---|
813 | }
|
---|
814 | }
|
---|
815 |
|
---|
816 | if (!match_ri)
|
---|
817 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
818 | return 0;
|
---|
819 |
|
---|
820 | }
|
---|
821 |
|
---|
822 | int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
|
---|
823 | unsigned char *pass, ossl_ssize_t passlen)
|
---|
824 | {
|
---|
825 | STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
|
---|
826 | CMS_RecipientInfo *ri;
|
---|
827 | int i, r, match_ri = 0;
|
---|
828 | CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
|
---|
829 |
|
---|
830 | /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
|
---|
831 | if (ec != NULL) {
|
---|
832 | OPENSSL_clear_free(ec->key, ec->keylen);
|
---|
833 | ec->key = NULL;
|
---|
834 | ec->keylen = 0;
|
---|
835 | }
|
---|
836 |
|
---|
837 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
|
---|
838 | ri = sk_CMS_RecipientInfo_value(ris, i);
|
---|
839 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
|
---|
840 | continue;
|
---|
841 |
|
---|
842 | /* Must try each PasswordRecipientInfo */
|
---|
843 | match_ri = 1;
|
---|
844 | CMS_RecipientInfo_set0_password(ri, pass, passlen);
|
---|
845 | r = CMS_RecipientInfo_decrypt(cms, ri);
|
---|
846 | CMS_RecipientInfo_set0_password(ri, NULL, 0);
|
---|
847 | if (r > 0)
|
---|
848 | return 1;
|
---|
849 | }
|
---|
850 |
|
---|
851 | if (!match_ri)
|
---|
852 | ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
|
---|
853 | return 0;
|
---|
854 |
|
---|
855 | }
|
---|
856 |
|
---|
857 | int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
|
---|
858 | BIO *dcont, BIO *out, unsigned int flags)
|
---|
859 | {
|
---|
860 | int r;
|
---|
861 | BIO *cont;
|
---|
862 | CMS_EncryptedContentInfo *ec;
|
---|
863 | int nid = OBJ_obj2nid(CMS_get0_type(cms));
|
---|
864 |
|
---|
865 | if (nid != NID_pkcs7_enveloped
|
---|
866 | && nid != NID_id_smime_ct_authEnvelopedData) {
|
---|
867 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
|
---|
868 | return 0;
|
---|
869 | }
|
---|
870 | if (dcont == NULL && !check_content(cms))
|
---|
871 | return 0;
|
---|
872 | ec = ossl_cms_get0_env_enc_content(cms);
|
---|
873 | ec->debug = (flags & CMS_DEBUG_DECRYPT) != 0;
|
---|
874 | ec->havenocert = cert == NULL;
|
---|
875 | if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
|
---|
876 | return 1;
|
---|
877 | if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
|
---|
878 | return 0;
|
---|
879 | cont = CMS_dataInit(cms, dcont);
|
---|
880 | if (cont == NULL)
|
---|
881 | return 0;
|
---|
882 | r = cms_copy_content(out, cont, flags);
|
---|
883 | do_free_upto(cont, dcont);
|
---|
884 | return r;
|
---|
885 | }
|
---|
886 |
|
---|
887 | int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
|
---|
888 | {
|
---|
889 | BIO *cmsbio;
|
---|
890 | int ret = 0;
|
---|
891 |
|
---|
892 | if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
|
---|
893 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
|
---|
894 | return 0;
|
---|
895 | }
|
---|
896 |
|
---|
897 | if (!SMIME_crlf_copy(data, cmsbio, flags)) {
|
---|
898 | goto err;
|
---|
899 | }
|
---|
900 |
|
---|
901 | (void)BIO_flush(cmsbio);
|
---|
902 |
|
---|
903 | if (!CMS_dataFinal(cms, cmsbio)) {
|
---|
904 | ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
|
---|
905 | goto err;
|
---|
906 | }
|
---|
907 |
|
---|
908 | ret = 1;
|
---|
909 |
|
---|
910 | err:
|
---|
911 | do_free_upto(cmsbio, dcont);
|
---|
912 |
|
---|
913 | return ret;
|
---|
914 |
|
---|
915 | }
|
---|
916 |
|
---|
917 | #ifdef ZLIB
|
---|
918 |
|
---|
919 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
---|
920 | unsigned int flags)
|
---|
921 | {
|
---|
922 | BIO *cont;
|
---|
923 | int r;
|
---|
924 |
|
---|
925 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
|
---|
926 | ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
|
---|
927 | return 0;
|
---|
928 | }
|
---|
929 |
|
---|
930 | if (dcont == NULL && !check_content(cms))
|
---|
931 | return 0;
|
---|
932 |
|
---|
933 | cont = CMS_dataInit(cms, dcont);
|
---|
934 | if (cont == NULL)
|
---|
935 | return 0;
|
---|
936 | r = cms_copy_content(out, cont, flags);
|
---|
937 | do_free_upto(cont, dcont);
|
---|
938 | return r;
|
---|
939 | }
|
---|
940 |
|
---|
941 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
---|
942 | {
|
---|
943 | CMS_ContentInfo *cms;
|
---|
944 |
|
---|
945 | if (comp_nid <= 0)
|
---|
946 | comp_nid = NID_zlib_compression;
|
---|
947 | cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
|
---|
948 | if (cms == NULL)
|
---|
949 | return NULL;
|
---|
950 |
|
---|
951 | if (!(flags & CMS_DETACHED))
|
---|
952 | CMS_set_detached(cms, 0);
|
---|
953 |
|
---|
954 | if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
|
---|
955 | return cms;
|
---|
956 |
|
---|
957 | CMS_ContentInfo_free(cms);
|
---|
958 | return NULL;
|
---|
959 | }
|
---|
960 |
|
---|
961 | #else
|
---|
962 |
|
---|
963 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
---|
964 | unsigned int flags)
|
---|
965 | {
|
---|
966 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
---|
967 | return 0;
|
---|
968 | }
|
---|
969 |
|
---|
970 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
|
---|
971 | {
|
---|
972 | ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
---|
973 | return NULL;
|
---|
974 | }
|
---|
975 |
|
---|
976 | #endif
|
---|