diff options
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_smime.c')
-rw-r--r-- | src/lib/libcrypto/pkcs7/pk7_smime.c | 263 |
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 | ||
66 | static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); | ||
67 | |||
66 | PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, | 68 | PKCS7 *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 | |||
115 | int 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 | ||
147 | static 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)) { | 154 | static 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); | 161 | PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, |
160 | return p7; | 162 | EVP_PKEY *pkey, const EVP_MD *md, |
161 | err: | 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 | |||
235 | static 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 | ||
168 | int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, | 266 | int 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 | ||