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