summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/pkcs7/pk7_smime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_smime.c')
-rw-r--r--src/lib/libcrypto/pkcs7/pk7_smime.c263
1 files changed, 175 insertions, 88 deletions
diff --git a/src/lib/libcrypto/pkcs7/pk7_smime.c b/src/lib/libcrypto/pkcs7/pk7_smime.c
index fd18ec3d95..86742d0dcd 100644
--- a/src/lib/libcrypto/pkcs7/pk7_smime.c
+++ b/src/lib/libcrypto/pkcs7/pk7_smime.c
@@ -63,24 +63,19 @@
63#include <openssl/x509.h> 63#include <openssl/x509.h>
64#include <openssl/x509v3.h> 64#include <openssl/x509v3.h>
65 65
66static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
67
66PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, 68PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
67 BIO *data, int flags) 69 BIO *data, int flags)
68{ 70{
69 PKCS7 *p7 = NULL; 71 PKCS7 *p7;
70 PKCS7_SIGNER_INFO *si;
71 BIO *p7bio = NULL;
72 STACK_OF(X509_ALGOR) *smcap = NULL;
73 int i; 72 int i;
74 73
75 if(!X509_check_private_key(signcert, pkey)) { 74 if(!(p7 = PKCS7_new()))
76 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); 75 {
77 return NULL;
78 }
79
80 if(!(p7 = PKCS7_new())) {
81 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); 76 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
82 return NULL; 77 return NULL;
83 } 78 }
84 79
85 if (!PKCS7_set_type(p7, NID_pkcs7_signed)) 80 if (!PKCS7_set_type(p7, NID_pkcs7_signed))
86 goto err; 81 goto err;
@@ -88,82 +83,185 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
88 if (!PKCS7_content_new(p7, NID_pkcs7_data)) 83 if (!PKCS7_content_new(p7, NID_pkcs7_data))
89 goto err; 84 goto err;
90 85
91 if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) { 86 if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags))
92 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); 87 {
88 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
93 goto err; 89 goto err;
94 } 90 }
95 91
96 if(!(flags & PKCS7_NOCERTS)) { 92 if(!(flags & PKCS7_NOCERTS))
97 if (!PKCS7_add_certificate(p7, signcert)) 93 {
98 goto err; 94 for(i = 0; i < sk_X509_num(certs); i++)
99 if(certs) for(i = 0; i < sk_X509_num(certs); i++) 95 {
100 if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i))) 96 if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
101 goto err; 97 goto err;
102 } 98 }
99 }
103 100
104 if(!(flags & PKCS7_NOATTR)) { 101 if(flags & PKCS7_DETACHED)
105 if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, 102 PKCS7_set_detached(p7, 1);
106 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) 103
107 goto err; 104 if (flags & (PKCS7_STREAM|PKCS7_PARTIAL))
108 /* Add SMIMECapabilities */ 105 return p7;
109 if(!(flags & PKCS7_NOSMIMECAP)) 106
107 if (PKCS7_final(p7, data, flags))
108 return p7;
109
110 err:
111 PKCS7_free(p7);
112 return NULL;
113}
114
115int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
116 {
117 BIO *p7bio;
118 int ret = 0;
119 if (!(p7bio = PKCS7_dataInit(p7, NULL)))
110 { 120 {
111 if(!(smcap = sk_X509_ALGOR_new_null())) { 121 PKCS7err(PKCS7_F_PKCS7_FINAL,ERR_R_MALLOC_FAILURE);
112 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); 122 return 0;
113 goto err;
114 }
115#ifndef OPENSSL_NO_DES
116 if (!PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1))
117 goto err;
118#endif
119#ifndef OPENSSL_NO_RC2
120 if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128))
121 goto err;
122 if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64))
123 goto err;
124#endif
125#ifndef OPENSSL_NO_DES
126 if (!PKCS7_simple_smimecap (smcap, NID_des_cbc, -1))
127 goto err;
128#endif
129#ifndef OPENSSL_NO_RC2
130 if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40))
131 goto err;
132#endif
133 if (!PKCS7_add_attrib_smimecap (si, smcap))
134 goto err;
135 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
136 smcap = NULL;
137 } 123 }
138 }
139 124
140 if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1); 125 SMIME_crlf_copy(data, p7bio, flags);
141 126
142 if (flags & PKCS7_STREAM) 127 (void)BIO_flush(p7bio);
143 return p7;
144 128
145 129
146 if (!(p7bio = PKCS7_dataInit(p7, NULL))) { 130 if (!PKCS7_dataFinal(p7,p7bio))
147 PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); 131 {
132 PKCS7err(PKCS7_F_PKCS7_FINAL,PKCS7_R_PKCS7_DATASIGN);
148 goto err; 133 goto err;
134 }
135
136 ret = 1;
137
138 err:
139 BIO_free_all(p7bio);
140
141 return ret;
142
149 } 143 }
150 144
151 SMIME_crlf_copy(data, p7bio, flags); 145/* Check to see if a cipher exists and if so add S/MIME capabilities */
152 146
147static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
148 {
149 if (EVP_get_cipherbynid(nid))
150 return PKCS7_simple_smimecap(sk, nid, arg);
151 return 1;
152 }
153 153
154 if (!PKCS7_dataFinal(p7,p7bio)) { 154static int add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
155 PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN); 155 {
156 goto err; 156 if (EVP_get_digestbynid(nid))
157 return PKCS7_simple_smimecap(sk, nid, arg);
158 return 1;
157 } 159 }
158 160
159 BIO_free_all(p7bio); 161PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
160 return p7; 162 EVP_PKEY *pkey, const EVP_MD *md,
161err: 163 int flags)
162 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); 164 {
163 BIO_free_all(p7bio); 165 PKCS7_SIGNER_INFO *si = NULL;
164 PKCS7_free(p7); 166 STACK_OF(X509_ALGOR) *smcap = NULL;
167 if(!X509_check_private_key(signcert, pkey))
168 {
169 PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
170 PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
171 return NULL;
172 }
173
174 if (!(si = PKCS7_add_signature(p7,signcert,pkey, md)))
175 {
176 PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
177 PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
178 return NULL;
179 }
180
181 if(!(flags & PKCS7_NOCERTS))
182 {
183 if (!PKCS7_add_certificate(p7, signcert))
184 goto err;
185 }
186
187 if(!(flags & PKCS7_NOATTR))
188 {
189 if (!PKCS7_add_attrib_content_type(si, NULL))
190 goto err;
191 /* Add SMIMECapabilities */
192 if(!(flags & PKCS7_NOSMIMECAP))
193 {
194 if(!(smcap = sk_X509_ALGOR_new_null()))
195 {
196 PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
197 ERR_R_MALLOC_FAILURE);
198 goto err;
199 }
200 if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
201 || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
202 || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
203 || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
204 || !add_cipher_smcap(smcap, NID_aes_128_cbc, -1)
205 || !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
206 || !add_cipher_smcap(smcap, NID_rc2_cbc, 128)
207 || !add_cipher_smcap(smcap, NID_rc2_cbc, 64)
208 || !add_cipher_smcap(smcap, NID_des_cbc, -1)
209 || !add_cipher_smcap(smcap, NID_rc2_cbc, 40)
210 || !PKCS7_add_attrib_smimecap (si, smcap))
211 goto err;
212 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
213 smcap = NULL;
214 }
215 if (flags & PKCS7_REUSE_DIGEST)
216 {
217 if (!pkcs7_copy_existing_digest(p7, si))
218 goto err;
219 if (!(flags & PKCS7_PARTIAL) &&
220 !PKCS7_SIGNER_INFO_sign(si))
221 goto err;
222 }
223 }
224 return si;
225 err:
226 if (smcap)
227 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
165 return NULL; 228 return NULL;
166} 229 }
230
231/* Search for a digest matching SignerInfo digest type and if found
232 * copy across.
233 */
234
235static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
236 {
237 int i;
238 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
239 PKCS7_SIGNER_INFO *sitmp;
240 ASN1_OCTET_STRING *osdig = NULL;
241 sinfos = PKCS7_get_signer_info(p7);
242 for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
243 {
244 sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
245 if (si == sitmp)
246 break;
247 if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0)
248 continue;
249 if (!OBJ_cmp(si->digest_alg->algorithm,
250 sitmp->digest_alg->algorithm))
251 {
252 osdig = PKCS7_digest_from_attributes(sitmp->auth_attr);
253 break;
254 }
255
256 }
257
258 if (osdig)
259 return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length);
260
261 PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST,
262 PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND);
263 return 0;
264 }
167 265
168int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, 266int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
169 BIO *indata, BIO *out, int flags) 267 BIO *indata, BIO *out, int flags)
@@ -354,7 +452,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
354 452
355 if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) { 453 if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
356 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS); 454 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS);
357 return NULL; 455 return 0;
358 } 456 }
359 457
360 if(!(signers = sk_X509_new_null())) { 458 if(!(signers = sk_X509_new_null())) {
@@ -377,12 +475,12 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
377 if (!signer) { 475 if (!signer) {
378 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); 476 PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
379 sk_X509_free(signers); 477 sk_X509_free(signers);
380 return NULL; 478 return 0;
381 } 479 }
382 480
383 if (!sk_X509_push(signers, signer)) { 481 if (!sk_X509_push(signers, signer)) {
384 sk_X509_free(signers); 482 sk_X509_free(signers);
385 return NULL; 483 return NULL;
386 } 484 }
387 } 485 }
388 return signers; 486 return signers;
@@ -405,7 +503,7 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
405 503
406 if (!PKCS7_set_type(p7, NID_pkcs7_enveloped)) 504 if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
407 goto err; 505 goto err;
408 if(!PKCS7_set_cipher(p7, cipher)) { 506 if (!PKCS7_set_cipher(p7, cipher)) {
409 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER); 507 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER);
410 goto err; 508 goto err;
411 } 509 }
@@ -419,22 +517,11 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
419 } 517 }
420 } 518 }
421 519
422 if(!(p7bio = PKCS7_dataInit(p7, NULL))) { 520 if (flags & PKCS7_STREAM)
423 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE); 521 return p7;
424 goto err;
425 }
426
427 SMIME_crlf_copy(in, p7bio, flags);
428
429 (void)BIO_flush(p7bio);
430
431 if (!PKCS7_dataFinal(p7,p7bio)) {
432 PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
433 goto err;
434 }
435 BIO_free_all(p7bio);
436 522
437 return p7; 523 if (PKCS7_final(p7, in, flags))
524 return p7;
438 525
439 err: 526 err:
440 527