summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/pkcs7/pk7_smime.c
diff options
context:
space:
mode:
authorbeck <>2000-03-19 11:13:58 +0000
committerbeck <>2000-03-19 11:13:58 +0000
commit796d609550df3a33fc11468741c5d2f6d3df4c11 (patch)
tree6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/pkcs7/pk7_smime.c
parent5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff)
downloadopenbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2 if you are using the ssl26 packages for ssh and other things to work you will need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_smime.c')
-rw-r--r--src/lib/libcrypto/pkcs7/pk7_smime.c427
1 files changed, 427 insertions, 0 deletions
diff --git a/src/lib/libcrypto/pkcs7/pk7_smime.c b/src/lib/libcrypto/pkcs7/pk7_smime.c
new file mode 100644
index 0000000000..b41f42ed04
--- /dev/null
+++ b/src/lib/libcrypto/pkcs7/pk7_smime.c
@@ -0,0 +1,427 @@
1/* pk7_smime.c */
2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 1999.
4 */
5/* ====================================================================
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59/* Simple PKCS#7 processing functions */
60
61#include <stdio.h>
62#include "cryptlib.h"
63#include <openssl/x509.h>
64#include <openssl/x509v3.h>
65
66PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
67 BIO *data, int flags)
68{
69 PKCS7 *p7;
70 PKCS7_SIGNER_INFO *si;
71 BIO *p7bio;
72 STACK *smcap;
73 int i;
74
75 if(!X509_check_private_key(signcert, pkey)) {
76 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
77 return NULL;
78 }
79
80 if(!(p7 = PKCS7_new())) {
81 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
82 return NULL;
83 }
84
85 PKCS7_set_type(p7, NID_pkcs7_signed);
86
87 PKCS7_content_new(p7, NID_pkcs7_data);
88
89 if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
90 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
91 return NULL;
92 }
93
94 if(!(flags & PKCS7_NOCERTS)) {
95 PKCS7_add_certificate(p7, signcert);
96 if(certs) for(i = 0; i < sk_X509_num(certs); i++)
97 PKCS7_add_certificate(p7, sk_X509_value(certs, i));
98 }
99
100 if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
101 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
102 return NULL;
103 }
104
105
106 SMIME_crlf_copy(data, p7bio, flags);
107
108 if(!(flags & PKCS7_NOATTR)) {
109 PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
110 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
111 /* Add SMIMECapabilities */
112 if(!(smcap = sk_new(NULL))) {
113 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
114 return NULL;
115 }
116#ifndef NO_DES
117 PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1);
118#endif
119#ifndef NO_RC2
120 PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128);
121 PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64);
122#endif
123#ifndef NO_DES
124 PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
125#endif
126#ifndef NO_RC2
127 PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
128#endif
129 PKCS7_add_attrib_smimecap (si, smcap);
130 sk_pop_free(smcap, X509_ALGOR_free);
131 }
132
133 if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
134
135 if (!PKCS7_dataFinal(p7,p7bio)) {
136 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
137 return NULL;
138 }
139
140 BIO_free_all(p7bio);
141 return p7;
142}
143
144int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
145 BIO *indata, BIO *out, int flags)
146{
147 STACK_OF(X509) *signers;
148 X509 *signer;
149 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
150 PKCS7_SIGNER_INFO *si;
151 X509_STORE_CTX cert_ctx;
152 char buf[4096];
153 int i, j=0;
154 BIO *p7bio;
155 BIO *tmpout;
156
157 if(!p7) {
158 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
159 return 0;
160 }
161
162 if(!PKCS7_type_is_signed(p7)) {
163 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
164 return 0;
165 }
166
167 /* Check for no data and no content: no data to verify signature */
168 if(PKCS7_get_detached(p7) && !indata) {
169 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
170 return 0;
171 }
172
173 /* Check for data and content: two sets of data */
174 if(!PKCS7_get_detached(p7) && indata) {
175 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CONTENT_AND_DATA_PRESENT);
176 return 0;
177 }
178
179 sinfos = PKCS7_get_signer_info(p7);
180
181 if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
182 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
183 return 0;
184 }
185
186
187 signers = PKCS7_get0_signers(p7, certs, flags);
188
189 if(!signers) return 0;
190
191 /* Now verify the certificates */
192
193 if (!(flags & PKCS7_NOVERIFY)) for (i = 0; i < sk_X509_num(signers); i++) {
194 signer = sk_X509_value (signers, i);
195 if (!(flags & PKCS7_NOCHAIN)) {
196 X509_STORE_CTX_init(&cert_ctx, store, signer,
197 p7->d.sign->cert);
198 X509_STORE_CTX_set_purpose(&cert_ctx,
199 X509_PURPOSE_SMIME_SIGN);
200 } else X509_STORE_CTX_init (&cert_ctx, store, signer, NULL);
201 i = X509_verify_cert(&cert_ctx);
202 if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx);
203 X509_STORE_CTX_cleanup(&cert_ctx);
204 if (i <= 0) {
205 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CERTIFICATE_VERIFY_ERROR);
206 ERR_add_error_data(2, "Verify error:",
207 X509_verify_cert_error_string(j));
208 sk_X509_free(signers);
209 return 0;
210 }
211 /* Check for revocation status here */
212 }
213
214 p7bio=PKCS7_dataInit(p7,indata);
215
216 if(flags & PKCS7_TEXT) {
217 if(!(tmpout = BIO_new(BIO_s_mem()))) {
218 PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
219 goto err;
220 }
221 } else tmpout = out;
222
223 /* We now have to 'read' from p7bio to calculate digests etc. */
224 for (;;)
225 {
226 i=BIO_read(p7bio,buf,sizeof(buf));
227 if (i <= 0) break;
228 if (tmpout) BIO_write(tmpout, buf, i);
229 }
230
231 if(flags & PKCS7_TEXT) {
232 if(!SMIME_text(tmpout, out)) {
233 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SMIME_TEXT_ERROR);
234 BIO_free(tmpout);
235 goto err;
236 }
237 BIO_free(tmpout);
238 }
239
240 /* Now Verify All Signatures */
241 if (!(flags & PKCS7_NOSIGS))
242 for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
243 {
244 si=sk_PKCS7_SIGNER_INFO_value(sinfos,i);
245 signer = sk_X509_value (signers, i);
246 j=PKCS7_signatureVerify(p7bio,p7,si, signer);
247 if (j <= 0) {
248 PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SIGNATURE_FAILURE);
249 goto err;
250 }
251 }
252
253 sk_X509_free(signers);
254 if(indata) BIO_pop(p7bio);
255 BIO_free_all(p7bio);
256
257 return 1;
258
259 err:
260
261 sk_X509_free(signers);
262 BIO_free(p7bio);
263
264 return 0;
265}
266
267STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
268{
269 STACK_OF(X509) *signers;
270 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
271 PKCS7_SIGNER_INFO *si;
272 PKCS7_ISSUER_AND_SERIAL *ias;
273 X509 *signer;
274 int i;
275
276 if(!p7) {
277 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
278 return NULL;
279 }
280
281 if(!PKCS7_type_is_signed(p7)) {
282 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
283 return NULL;
284 }
285 if(!(signers = sk_X509_new(NULL))) {
286 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE);
287 return NULL;
288 }
289
290 /* Collect all the signers together */
291
292 sinfos = PKCS7_get_signer_info(p7);
293
294 if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
295 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS);
296 return 0;
297 }
298
299 for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
300 {
301 si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
302 ias = si->issuer_and_serial;
303 signer = NULL;
304 /* If any certificates passed they take priority */
305 if (certs) signer = X509_find_by_issuer_and_serial (certs,
306 ias->issuer, ias->serial);
307 if (!signer && !(flags & PKCS7_NOINTERN)
308 && p7->d.sign->cert) signer =
309 X509_find_by_issuer_and_serial (p7->d.sign->cert,
310 ias->issuer, ias->serial);
311 if (!signer) {
312 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
313 sk_X509_free(signers);
314 return 0;
315 }
316
317 sk_X509_push(signers, signer);
318 }
319 return signers;
320}
321
322
323/* Build a complete PKCS#7 enveloped data */
324
325PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher,
326 int flags)
327{
328 PKCS7 *p7;
329 BIO *p7bio = NULL;
330 int i;
331 X509 *x509;
332 if(!(p7 = PKCS7_new())) {
333 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
334 return NULL;
335 }
336
337 PKCS7_set_type(p7, NID_pkcs7_enveloped);
338 if(!PKCS7_set_cipher(p7, cipher)) {
339 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER);
340 goto err;
341 }
342
343 for(i = 0; i < sk_X509_num(certs); i++) {
344 x509 = sk_X509_value(certs, i);
345 if(!PKCS7_add_recipient(p7, x509)) {
346 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,
347 PKCS7_R_ERROR_ADDING_RECIPIENT);
348 goto err;
349 }
350 }
351
352 if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
353 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
354 goto err;
355 }
356
357 SMIME_crlf_copy(in, p7bio, flags);
358
359 BIO_flush(p7bio);
360
361 if (!PKCS7_dataFinal(p7,p7bio)) {
362 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
363 goto err;
364 }
365 BIO_free_all(p7bio);
366
367 return p7;
368
369 err:
370
371 BIO_free(p7bio);
372 PKCS7_free(p7);
373 return NULL;
374
375}
376
377int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
378{
379 BIO *tmpmem;
380 int ret, i;
381 char buf[4096];
382
383 if(!p7) {
384 PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
385 return 0;
386 }
387
388 if(!PKCS7_type_is_enveloped(p7)) {
389 PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
390 return 0;
391 }
392
393 if(!X509_check_private_key(cert, pkey)) {
394 PKCS7err(PKCS7_F_PKCS7_DECRYPT,
395 PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
396 return 0;
397 }
398
399 if(!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) {
400 PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR);
401 return 0;
402 }
403
404 if (flags & PKCS7_TEXT) {
405 BIO *tmpbuf, *bread;
406 /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
407 if(!(tmpbuf = BIO_new(BIO_f_buffer()))) {
408 PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
409 return 0;
410 }
411 if(!(bread = BIO_push(tmpbuf, tmpmem))) {
412 PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
413 return 0;
414 }
415 ret = SMIME_text(bread, data);
416 BIO_free_all(bread);
417 return ret;
418 } else {
419 for(;;) {
420 i = BIO_read(tmpmem, buf, sizeof(buf));
421 if(i <= 0) break;
422 BIO_write(data, buf, i);
423 }
424 BIO_free_all(tmpmem);
425 return 1;
426 }
427}