2.0_alpha release commit
[framework/messaging/email-service.git] / email-core / email-core-smime.c
1 /*
2 *  email-service
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
7
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21
22
23
24 /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ***
25  *File :  email-core-smime.c
26  *Desc :  MIME Operation
27  *
28  *Auth :
29  *
30  *History :
31  *   2011.04.14  :  created
32  ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ***/
33 #undef close
34
35 #include <openssl/pkcs7.h>
36 #include <openssl/pkcs12.h>
37 #include <openssl/buffer.h>
38 #include <openssl/pem.h>
39 #include <openssl/err.h>
40
41 #include "email-utilities.h"
42 #include "email-core-global.h"
43 #include "email-core-utils.h"
44 #include "email-core-mail.h"
45 #include "email-core-smtp.h"
46 #include "email-storage.h"
47 #include "email-core-smime.h"
48 #include "email-core-cert.h"
49 #include "email-debug-log.h"
50
51 /* /opt/share/cert-svc/certs is a base path */
52
53 #define SMIME_SIGNED_FILE "smime.p7s"
54 #define SMIME_ENCRYPT_FILE "smime.p7m"
55
56 #define OUTMODE "wb"
57 #define INMODE "rb"
58 #define READMODE "r"
59
60 /* If not present then the default digest algorithm for signing key will be used SHA1 */
61 static const EVP_MD *emcore_get_digest_algorithm(email_digest_type digest_type)
62 {
63         const EVP_MD *digest_algo = NULL;
64         
65         switch (digest_type) {
66         case DIGEST_TYPE_MD5:
67                 digest_algo = EVP_md5();
68                 break;
69         case DIGEST_TYPE_SHA1:
70         default:
71                 digest_algo = EVP_sha1();
72                 break;
73         }
74
75         return digest_algo;
76 }
77
78 /* If not present then the default cipher algorithm for signing key will be used RC2(40) */
79 static const EVP_CIPHER *emcore_get_cipher_algorithm(email_cipher_type cipher_type)
80 {
81         const EVP_CIPHER *cipher = NULL;
82
83         switch (cipher_type) {
84         case CIPHER_TYPE_RC2_128 :
85                 cipher = EVP_rc2_cbc();
86                 break;
87         case CIPHER_TYPE_RC2_64 :
88                 cipher = EVP_rc2_64_cbc();
89                 break;
90         case CIPHER_TYPE_DES3 :
91                 cipher = EVP_des_ede3_cbc();
92                 break;
93         case CIPHER_TYPE_DES :
94                 cipher = EVP_des_cbc();
95                 break;
96 #ifdef __FEATURE_USE_MORE_CIPHER_TYPE__
97         case CIPHER_TYPE_SEED :
98                 cipher = EVP_seed_cbc();
99                 break;
100         case CIPHER_TYPE_AES128 :
101                 cipher = EVP_aes_128_cbc();
102                 break;
103         case CIPHER_TYPE_AES192 :
104                 cipher = EVP_aes_192_cbc();
105                 break;
106         case CIPHER_TYPE_AES256 :
107                 cipher = EVP_aes_256_cbc();
108                 break;
109 #ifndef OPENSSL_NO_CAMELLIA             
110         case CIPHER_TYPE_CAMELLIA128 :
111                 cipher = EVP_camellia_128_cbc();
112                 break;
113         case CIPHER_TYPE_CAMELLIA192 :
114                 cipher = EVP_camellia_192_cbc();
115                 break;
116         case CIPHER_TYPE_CAMELLIA256 :
117                 cipher = EVP_camellia_256_cbc();
118                 break;
119 #endif
120 #endif
121         case CIPHER_TYPE_RC2_40 :
122         default :
123                 cipher = EVP_rc2_40_cbc();
124                 break;
125         }
126
127         return cipher;
128 }
129
130 static int get_x509_stack_of_recipient_certs(char *recipients, STACK_OF(X509) **output_recipient_certs, int *err_code)
131 {
132         EM_DEBUG_FUNC_BEGIN("recipients : [%s], STACK_OF(X509) : [%p]", recipients, output_recipient_certs);
133
134         int err = EMAIL_ERROR_NONE;
135         int ret = false;        
136         int cert_size = 0;
137         char *temp_recipients = NULL;
138         char *token = NULL;
139         char *str = NULL;
140         char file_name[512] = {0, };
141         const unsigned char *in_cert = NULL;
142
143         X509 *x509_cert = NULL;
144         STACK_OF(X509) *temp_recipient_certs = NULL;
145
146         CERT_CONTEXT *context = NULL;
147         emstorage_certificate_tbl_t *cert = NULL;
148
149         if (!recipients || !output_recipient_certs) {
150                 EM_DEBUG_EXCEPTION("Invalid parameter");
151                 err = EMAIL_ERROR_INVALID_PARAM;
152                 goto FINISH_OFF;
153         }
154
155         /* Initialize the variable */
156         context = cert_svc_cert_context_init();
157         temp_recipient_certs = sk_X509_new_null();
158
159         temp_recipients = EM_SAFE_STRDUP(recipients);
160         token = strtok_r(temp_recipients, ";", &str);
161
162         do {
163                 if (!emstorage_get_certificate_by_email_address(token, &cert, false, 0, &err)) {
164                         EM_DEBUG_EXCEPTION("emstorage_get_certificate_by_email_address failed : [%d]", err);
165                         goto FINISH_OFF;
166                 }
167                 
168                 SNPRINTF(file_name, sizeof(file_name), "%s", cert->filepath);
169                 EM_DEBUG_LOG("file_name : [%s]", file_name);
170                 err = cert_svc_load_file_to_context(context, file_name);
171                 if (err != CERT_SVC_ERR_NO_ERROR) {
172                         EM_DEBUG_EXCEPTION("cert_svc_load_file_to_context failed : [%d]", err);
173                         err = EMAIL_ERROR_SYSTEM_FAILURE;
174                         goto FINISH_OFF;
175                 }
176
177                 in_cert = context->certBuf->data;
178                 cert_size = context->certBuf->size;
179
180                 if (d2i_X509(&x509_cert, &in_cert, cert_size) == NULL) {
181                         EM_DEBUG_EXCEPTION("d2i_X509 failed");
182                         err = EMAIL_ERROR_SYSTEM_FAILURE;
183                         goto FINISH_OFF;
184                 }
185
186                 if (!sk_X509_push(temp_recipient_certs, x509_cert)) {
187                         EM_DEBUG_EXCEPTION("sk_X509_push failed");
188                         err = EMAIL_ERROR_SYSTEM_FAILURE;
189                         goto FINISH_OFF;
190                 }
191
192                 x509_cert = NULL;
193                 context = NULL;
194                 emstorage_free_certificate(&cert, 1, NULL);
195                 cert = NULL;
196         } while ((token = strtok_r(NULL, ";", &str)));
197
198         *output_recipient_certs = temp_recipient_certs;
199
200         ret = true;
201
202 FINISH_OFF:
203
204         if (!ret) {
205                 if (x509_cert)
206                         X509_free(x509_cert);
207
208                 if (temp_recipient_certs)
209                         sk_X509_pop_free(temp_recipient_certs, X509_free);
210         }
211
212         if (cert)
213                 emstorage_free_certificate(&cert, 1, NULL);
214
215         cert_svc_cert_context_final(context);
216
217         EM_SAFE_FREE(temp_recipients);
218
219         if (err_code)
220                 *err_code = err;
221
222         return ret;
223 }
224
225 /* Opaque signed and encrypted method */
226 /*
227 static PKCS7 *opaque_signed_and_encrypt(STACK_OF(X509) *recipients_cert, X509 *signer, EVP_PKEY *private_key, BIO *mime_entity, const EVP_CIPHER *cipher, const EVP_MD *md, int flags)
228 {
229         EM_DEBUG_FUNC_BEGIN();
230         int i = 0;
231         PKCS7 *pkcs7 = NULL;
232         BIO *p7bio = NULL;
233         X509 *x509;
234
235         if (!(pkcs7 = PKCS7_new())) {
236                 EM_DEBUG_EXCEPTION("PKCS7 malloc failed");
237                 return NULL;
238         }
239         
240         if (!PKCS7_set_type(pkcs7, NID_pkcs7_signedAndEnveloped)) {
241                 EM_DEBUG_EXCEPTION("Set type failed");
242                 goto FINISH_OFF;
243         }
244
245         if (!PKCS7_add_signature(pkcs7, signer, private_key, md)) {
246                 EM_DEBUG_EXCEPTION("PKCS7_add_signature failed");
247                 goto FINISH_OFF;
248         }
249
250         if (!PKCS7_add_certificate(pkcs7, signer)) {
251                 EM_DEBUG_EXCEPTION("PKCS7_add_certificate failed");
252                 goto FINISH_OFF;
253         }
254
255         for (i = 0; i < sk_X509_num(recipients_cert); i++) {
256                 x509 = sk_X509_value(recipients_cert, i);
257                 if (!PKCS7_add_recipient(pkcs7, x509)) {
258                         EM_DEBUG_EXCEPTION("PKCS7_add_recipient failed");
259                         goto FINISH_OFF;
260                 }
261         }
262
263         if (!PKCS7_set_cipher(pkcs7, cipher)) {
264                 EM_DEBUG_EXCEPTION("Cipher failed");
265                 goto FINISH_OFF;
266         }
267
268         if (flags & PKCS7_STREAM)
269                 return pkcs7;
270
271         if (PKCS7_final(pkcs7, mime_entity, flags))
272                 return pkcs7;
273         
274 FINISH_OFF:
275         BIO_free_all(p7bio);
276         PKCS7_free(pkcs7);
277         return NULL;
278 }
279 */
280 #define SMIME_DEBUG 1
281
282 #ifdef SMIME_DEBUG
283 #define TEMP_PASSWORD_PATH "/opt/data/cert_password"
284 #endif
285
286 INTERNAL_FUNC int emcore_smime_set_signed_message(char *certificate, char *password, char *mime_entity, email_digest_type digest_type, char **file_path, int *err_code)
287 {
288         EM_DEBUG_FUNC_BEGIN("certificate path : [%s], password : [%s], mime_entity : [%s]", certificate, password, mime_entity);
289         int err, ret = false;
290         char temp_smime_filepath[512];
291         X509 *cert = NULL;
292         STACK_OF(X509) *other_certs = NULL;
293         EVP_PKEY *private_key = NULL;
294         const EVP_MD *digest = NULL;
295         BIO *bio_mime_entity = NULL, *bio_cert = NULL, *bio_prikey = NULL;
296         BIO *smime_attachment = NULL;
297         PKCS7 *signed_message = NULL;
298         int flags = PKCS7_DETACHED | PKCS7_PARTIAL;
299
300         OpenSSL_add_all_algorithms();
301         ERR_load_crypto_strings();
302
303         SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s%s%s", MAILHOME, DIR_SEPERATOR, MAILTEMP, DIR_SEPERATOR, SMIME_SIGNED_FILE);
304         EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath);
305
306         smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE);
307         if (!smime_attachment) {
308                 EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath);
309                 err = EMAIL_ERROR_FILE_NOT_FOUND;
310                 goto FINISH_OFF;
311         }
312
313         /* Load certificate for getting the certificate and private key */
314         if (!emcore_load_PFX_file(certificate, password, &private_key, &cert, &other_certs, &err)) {
315                 EM_DEBUG_EXCEPTION("Load the private certificate failed : [%d]", err);
316                 goto FINISH_OFF;
317         }
318
319         bio_mime_entity = BIO_new_file(mime_entity, READMODE);
320         if (!bio_mime_entity) {
321                 EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity);
322                 goto FINISH_OFF;
323         }
324
325         signed_message = PKCS7_sign(NULL, NULL, other_certs, bio_mime_entity, flags);
326         if (!signed_message) {
327                 EM_DEBUG_EXCEPTION("Error creating PKCS#7 structure");
328                 goto FINISH_OFF;
329         }
330         
331         /* Get the digest algorithm */
332         digest = emcore_get_digest_algorithm(digest_type);
333
334         if (!PKCS7_sign_add_signer(signed_message, cert, private_key, digest, flags)) {
335                 EM_DEBUG_EXCEPTION("PKCS7_sign_add_signer failed");
336                 goto FINISH_OFF;
337         }
338
339         if (!PKCS7_final(signed_message, bio_mime_entity, flags)) {
340                 EM_DEBUG_EXCEPTION("PKCS7_final failed");
341                 goto FINISH_OFF;
342         }
343
344         if (!i2d_PKCS7_bio_stream(smime_attachment, signed_message, bio_mime_entity, flags)) {
345                 EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed");
346                 err = EMAIL_ERROR_SYSTEM_FAILURE;
347                 goto FINISH_OFF;
348         }
349         BIO_flush(smime_attachment);
350 #ifdef SMIME_DEBUG
351         BIO *out = NULL;
352         
353         out = BIO_new_file("/opt/data/email/.emfdata/tmp/smout.txt", "w");
354         if (!out)
355                 goto FINISH_OFF;
356
357         if (!SMIME_write_PKCS7(out, signed_message, bio_mime_entity, flags))
358                 goto FINISH_OFF;
359
360         if (out)
361                 BIO_free(out);
362 #endif
363         ret = true;
364
365 FINISH_OFF:
366         if (file_path)
367                 *file_path = temp_smime_filepath;
368
369         X509_free(cert);
370         EVP_PKEY_free(private_key);
371         PKCS7_free(signed_message);
372
373         BIO_free(bio_mime_entity);
374         BIO_free(bio_cert);
375         BIO_free(bio_prikey);
376         BIO_free_all(smime_attachment);
377
378         EVP_cleanup();
379         if (err_code != NULL)
380                 *err_code = err;
381
382         EM_DEBUG_FUNC_END("err [%d]", err);
383         return ret;
384 }
385
386 INTERNAL_FUNC int emcore_smime_set_encrypt_message(char *recipient_list, char *mime_entity, email_cipher_type cipher_type, char **file_path, int *err_code)
387 {
388         EM_DEBUG_FUNC_BEGIN("certificate path : [%p], mime_entity : [%p]", recipient_list, mime_entity);
389         char temp_smime_filepath[512];
390         int err = EMAIL_ERROR_NONE, ret = false;
391 //      int flags = PKCS7_DETACHED | PKCS7_STREAM;
392         int flags = 0;
393
394         CERT_CONTEXT *loaded_cert = NULL;
395         STACK_OF(X509) *recipient_certs = NULL;
396         X509 *cert = NULL;
397         BIO *bio_mime_entity = NULL, *bio_cert = NULL;
398         BIO *smime_attachment = NULL;
399         PKCS7 *encrypt_message = NULL;
400         const EVP_CIPHER *cipher = NULL;
401
402         OpenSSL_add_all_algorithms();
403         ERR_load_crypto_strings();
404
405         loaded_cert = cert_svc_cert_context_init();
406
407         SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s%s%s", MAILHOME, DIR_SEPERATOR, MAILTEMP, DIR_SEPERATOR, SMIME_ENCRYPT_FILE);
408         EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath);
409
410         smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE);
411         if (!smime_attachment) {
412                 EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath);
413                 err = EMAIL_ERROR_FILE_NOT_FOUND;
414                 goto FINISH_OFF;
415         }
416
417         if (!get_x509_stack_of_recipient_certs(recipient_list, &recipient_certs, &err)) {
418                 EM_DEBUG_EXCEPTION("get_x509_stack_of_recipient_certs failed [%d]", err);
419                 goto FINISH_OFF;
420         }
421
422         bio_mime_entity = BIO_new_file(mime_entity, READMODE);
423         if (!bio_mime_entity) {
424                 EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity);
425                 goto FINISH_OFF;
426         }
427         
428         /* Get cipher algorithm */
429         cipher = emcore_get_cipher_algorithm(cipher_type);
430         
431         encrypt_message = PKCS7_encrypt(recipient_certs, bio_mime_entity, cipher, flags);
432         if (encrypt_message == NULL) {
433                 EM_DEBUG_EXCEPTION("PKCS7_encrypt failed [%ld]", ERR_get_error());
434                 goto FINISH_OFF;
435         }
436
437         if (!i2d_PKCS7_bio_stream(smime_attachment, encrypt_message, bio_mime_entity, flags)) {
438                 EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed");
439                 err = EMAIL_ERROR_SYSTEM_FAILURE;
440                 goto FINISH_OFF;
441         }
442         BIO_flush(smime_attachment);
443
444 #ifdef SMIME_DEBUG
445         BIO *out = NULL;
446         
447         out = BIO_new_file("/opt/data/email/.emfdata/tmp/smout.txt", "w");
448         if (!out)
449                 goto FINISH_OFF;
450
451         if (!SMIME_write_PKCS7(out, encrypt_message, bio_mime_entity, flags))
452                 goto FINISH_OFF;
453
454         if (out)
455                 BIO_free(out);
456 #endif
457
458         ret = true;
459
460 FINISH_OFF:
461         if (file_path)
462                 *file_path = temp_smime_filepath;
463
464         PKCS7_free(encrypt_message);
465
466         X509_free(cert);
467         sk_X509_pop_free(recipient_certs, X509_free);
468
469         BIO_free(bio_cert);
470         BIO_free(bio_mime_entity);
471         BIO_free_all(smime_attachment);
472
473         cert_svc_cert_context_final(loaded_cert);
474         EVP_cleanup();
475         if (err_code != NULL)
476                 *err_code = err;
477
478         EM_DEBUG_FUNC_END("err [%d]", err);
479         return ret;
480 }
481
482 INTERNAL_FUNC int emcore_smime_set_signed_and_encrypt_message(char *recipient_list, char *certificate, char *password, char *mime_entity, email_cipher_type cipher_type, email_digest_type digest_type, char **file_path, int *err_code)
483 {
484         EM_DEBUG_FUNC_BEGIN("certificate path : [%s], mime_entity : [%s]", recipient_list, mime_entity);
485         char temp_smime_filepath[512];
486         int err = EMAIL_ERROR_NONE, ret = false;
487         int flags = PKCS7_DETACHED | PKCS7_PARTIAL | PKCS7_STREAM;
488
489         STACK_OF(X509) *recipient_certs = NULL;
490         STACK_OF(X509) *other_certs = NULL;
491         BIO *bio_mime_entity = NULL, *bio_cert = NULL;
492         BIO *bio_signed_message = BIO_new(BIO_s_mem());
493         BIO *smime_attachment = NULL;
494         PKCS7 *signed_message = NULL;
495         PKCS7 *encrypt_message = NULL;
496         const EVP_CIPHER *cipher = NULL;
497         const EVP_MD *digest = NULL;
498
499 #ifdef SMIME_DEBUG
500         char *signed_string = NULL;
501         BUF_MEM *buf_mem = NULL;
502 #endif
503         /* Variable for private certificate */
504         EVP_PKEY *private_key = NULL;
505         X509 *cert = NULL;
506
507         OpenSSL_add_all_algorithms();
508         ERR_load_crypto_strings();
509
510         SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s%s%s", MAILHOME, DIR_SEPERATOR, MAILTEMP, DIR_SEPERATOR, SMIME_ENCRYPT_FILE);
511         EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath);
512
513         smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE);
514         if (!smime_attachment) {
515                 EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath);
516                 err = EMAIL_ERROR_FILE_NOT_FOUND;
517                 goto FINISH_OFF;
518         }
519
520         /* Signing the mail */
521         /* 1. Load the private certificate */
522         if (!emcore_load_PFX_file(certificate, password, &private_key, &cert, &other_certs, &err)) {
523                 EM_DEBUG_EXCEPTION("Load the certificate failed : [%d]", err);
524                 goto FINISH_OFF;
525         }
526
527         /* 2. Read mime entity */
528         bio_mime_entity = BIO_new_file(mime_entity, READMODE);
529         if (!bio_mime_entity) {
530                 EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity);
531                 goto FINISH_OFF;
532         }
533
534         /* 3. signing */
535         signed_message = PKCS7_sign(NULL, NULL, other_certs, bio_mime_entity, flags);
536         if (!signed_message) {
537                 EM_DEBUG_EXCEPTION("Error creating PKCS#7 structure");
538                 goto FINISH_OFF;
539         }
540         
541         /* 4. Get the digest algorithm */
542         digest = emcore_get_digest_algorithm(digest_type);
543
544         /* 5. Apply a digest algorithm */
545         if (!PKCS7_sign_add_signer(signed_message, cert, private_key, digest, flags)) {
546                 EM_DEBUG_EXCEPTION("PKCS7_sign_add_signer failed");
547                 goto FINISH_OFF;
548         }
549
550         /* 6. Create signing message */
551         if (!SMIME_write_PKCS7(bio_signed_message, signed_message, bio_mime_entity, flags | SMIME_OLDMIME | SMIME_CRLFEOL)) {
552                 EM_DEBUG_EXCEPTION("SMIME_write_PKCS7 error");
553                 goto FINISH_OFF;
554         }
555
556 #ifdef SMIME_DEBUG
557         BIO_get_mem_ptr(bio_signed_message, &buf_mem);
558         signed_string = em_malloc(buf_mem->length);
559         memcpy(signed_string, buf_mem->data, buf_mem->length-1);
560         EM_DEBUG_LOG("Signed message : [%d]", buf_mem->length);
561         EM_DEBUG_LOG("%s", signed_string);
562         EM_DEBUG_LOG("buf data: \n, %s", buf_mem->data);
563         EM_SAFE_FREE(signed_string);
564 #endif  
565
566         /* Encrypting the mail */
567         /* 1. Get the recipient certs */
568         if (!get_x509_stack_of_recipient_certs(recipient_list, &recipient_certs, &err)) {
569                 EM_DEBUG_EXCEPTION("get_x509_stack_of_recipient_certs failed [%d]", err);
570                 goto FINISH_OFF;
571         }
572
573         /* 2. Get cipher algorithm */
574         cipher = emcore_get_cipher_algorithm(cipher_type);
575         
576         flags = 0;
577
578         /* 3. Encrypt the signing message */    
579         encrypt_message = PKCS7_encrypt(recipient_certs, bio_signed_message, cipher, flags);
580         if (encrypt_message == NULL) {
581                 EM_DEBUG_EXCEPTION("PKCS7_encrypt failed [%ld]", ERR_get_error());
582                 goto FINISH_OFF;
583         }
584         
585         /* 4. Write the encrypt message in file */
586         if (!i2d_PKCS7_bio_stream(smime_attachment, encrypt_message, bio_mime_entity, flags)) {
587                 EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed");
588                 err = EMAIL_ERROR_SYSTEM_FAILURE;
589                 goto FINISH_OFF;
590         }
591         BIO_flush(smime_attachment);
592
593 #ifdef SMIME_DEBUG
594         BIO *out = NULL;
595         
596         out = BIO_new_file("/opt/data/email/.emfdata/tmp/smout.txt", "w");
597         if (!out)
598                 goto FINISH_OFF;
599
600         if (!SMIME_write_PKCS7(out, encrypt_message, bio_mime_entity, flags))
601                 goto FINISH_OFF;
602
603         if (out)
604                 BIO_free(out);
605 #endif
606
607         ret = true;
608
609 FINISH_OFF:
610         if (file_path)
611                 *file_path = temp_smime_filepath;
612
613         PKCS7_free(signed_message);
614         PKCS7_free(encrypt_message);
615
616         X509_free(cert);
617         sk_X509_pop_free(other_certs, X509_free);
618         sk_X509_pop_free(recipient_certs, X509_free);
619
620         BIO_free(bio_cert);
621         BIO_free(bio_mime_entity);
622         BIO_free(bio_signed_message);
623         BIO_free_all(smime_attachment);
624
625         EVP_cleanup();
626         if (err_code != NULL)
627                 *err_code = err;
628
629         EM_DEBUG_FUNC_END("err [%d]", err);
630         return ret;
631 }
632
633
634
635 INTERNAL_FUNC int emcore_smime_set_decrypt_message(char *encrypt_message, char *certificate, char *password, char **decrypt_message, int *err_code)
636 {
637         int ret = false;
638         int err = EMAIL_ERROR_NONE;
639         long string_len = 0;
640         char *temp_decrypt_message;
641         FILE *fp = NULL;
642
643         X509 *cert = NULL;
644         STACK_OF(X509) *ca = NULL;
645         EVP_PKEY *private_key = NULL;
646         BIO *bio_cert = NULL, *bio_prikey = NULL;
647         BIO *infile = NULL, *out_buf = NULL;
648         PKCS7 *p7_encrypt_message = NULL;
649         PKCS12 *p12 = NULL;
650         CERT_CONTEXT *loaded_cert = NULL;
651
652         infile = BIO_new_file(encrypt_message, INMODE);
653
654         p7_encrypt_message = d2i_PKCS7_bio(infile, NULL);
655         if (!p7_encrypt_message) {
656                 EM_DEBUG_EXCEPTION("Error reading S/MIME message");
657                 err = EMAIL_ERROR_INVALID_PARAM;
658                 goto FINISH_OFF;
659         }
660
661         loaded_cert = cert_svc_cert_context_init();
662
663         fp = fopen(certificate, INMODE);
664         if (!fp) {
665                 EM_DEBUG_EXCEPTION("Certificate file open failed");
666                 goto FINISH_OFF;
667         }
668         
669         p12 = d2i_PKCS12_fp(fp, NULL);
670         fclose(fp);
671
672         if (!p12) {
673                 EM_DEBUG_EXCEPTION("Error reading PKCS#12 file\n");
674                 goto FINISH_OFF;
675         }       
676
677         if (!PKCS12_parse(p12, password, &private_key, &cert, &ca)) {
678                 EM_DEBUG_EXCEPTION("PKCS12_parse failed");
679                 goto FINISH_OFF;
680         }
681
682         out_buf = BIO_new(BIO_s_mem());
683         if (!out_buf) {
684                 EM_DEBUG_EXCEPTION("There is not enough memory.");
685                 err = EMAIL_ERROR_OUT_OF_MEMORY;
686                 goto FINISH_OFF;
687         }
688
689         PKCS7_decrypt(p7_encrypt_message, private_key, cert, out_buf, 0);
690         string_len = BIO_get_mem_data(out_buf, &temp_decrypt_message);
691
692         ret = true;
693
694 FINISH_OFF:
695         *decrypt_message = temp_decrypt_message;
696
697         X509_free(cert);
698         BIO_free(out_buf);
699         BIO_free(bio_cert);
700         BIO_free(bio_prikey);
701         BIO_free_all(infile);
702
703         if (err_code != NULL)
704                 *err_code = err;
705
706         cert_svc_cert_context_final(loaded_cert);
707         EM_DEBUG_FUNC_END("err [%d]", err);
708         return ret;
709 }
710
711 /*
712 INTERNAL_FUNC int emcore_smime_verify_signed_message(char *signed_message, char *ca_file, char *ca_path, int *verify)
713 {
714         int ret = false;
715         int temp_verify = 0;
716         BIO *indata = NULL;
717         BIO *content = NULL;
718         X509_STORE *store = NULL;
719         X509_LOOKUP *lookup = NULL;
720         PKCS7 *p7 = NULL;
721
722         OpenSSL_add_all_algorithms();
723         ERR_load_crypto_strings();
724
725         if (BIO_write(indata, signed_message, sizeof(signed_message)) <= 0) {
726                 EM_DEBUG_EXCEPTION("Char to Bio failed");
727                 goto FINISH_OFF;
728         }
729
730         p7 = SMIME_read_PKCS7(indata, &content);
731         if (!p7) {
732                 EM_DEBUG_EXCEPTION("SMIME_read_PKCS7 failed");
733                 goto FINISH_OFF;
734         }
735
736         if (!(store = X509_STORE_new())) {
737                 EM_DEBUG_EXCEPTION("Initialize x509_store failed");
738                 goto FINISH_OFF;
739         }
740         
741         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
742         if (lookup == NULL) {
743                 EM_DEBUG_EXCEPTION("Initialize lookup store failed");
744                 goto FINISH_OFF;
745         }
746
747         if (ca_file) {
748                 if (!X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM)) {
749                         EM_DEBUG_EXCEPTION("X509_LOOKUP_load_file failed");
750                         goto FINISH_OFF;
751                 }
752         } else {
753                 X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
754         }
755
756         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
757         if (lookup == NULL) {
758                 EM_DEBUG_EXCEPTION("X509_STORE_add_lookup failed");
759                 goto FINISH_OFF;
760         }
761         
762         if (ca_path) {
763                 if (!X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM)) {
764                         EM_DEBUG_EXCEPTION("CA path load failed");
765                         goto FINISH_OFF;
766                 }
767         } else {
768                 X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
769         }
770         
771         temp_verify = PKCS7_verify(p7, NULL, store, content, NULL, 0);
772         if (temp_verify) 
773                 EM_DEBUG_LOG("Verification Successful\n");
774
775         ret = true;
776
777 FINISH_OFF:
778         if (store)
779                 X509_STORE_free(store);
780         if (p7)
781                 PKCS7_free(p7);
782         
783         if (indata)
784                 BIO_free(indata);
785
786         if (verify != NULL)
787                 *verify = temp_verify;
788
789         ERR_clear_error();
790         EVP_cleanup();
791         return ret;
792 }
793 */
794
795 static char *emcore_get_mime_entity(char *mime_path)
796 {
797         EM_DEBUG_FUNC_BEGIN("mime_path : [%s]", mime_path);
798         FILE *fp_read = NULL;
799         FILE *fp_write = NULL;
800         char *mime_entity = NULL;
801         char *mime_entity_path = NULL;
802         char temp_buffer[255] = {0,};
803         int err;
804         int searched = 0;
805
806         if (!emcore_get_temp_file_name(&mime_entity_path, &err))  {
807                 EM_DEBUG_EXCEPTION(" em_core_get_temp_file_name failed[%d]", err);
808                 goto FINISH_OFF;
809         }
810
811         /* get mime entity */
812         if (mime_path != NULL) {
813                 fp_read = fopen(mime_path, "r");
814                 if (fp_read == NULL) {
815                         EM_DEBUG_EXCEPTION("File open(read) is failed : filename [%s]", mime_path);
816                         goto FINISH_OFF;
817                 }
818
819                 fp_write = fopen(mime_entity_path, "w");
820                 if (fp_write == NULL) {
821                         EM_DEBUG_EXCEPTION("File open(write) is failed : filename [%s]", mime_entity_path);
822                         goto FINISH_OFF;
823                 }
824
825                 fseek(fp_read, 0, SEEK_SET);
826                 fseek(fp_write, 0, SEEK_SET);           
827
828                 while (fgets(temp_buffer, 255, fp_read) != NULL) {
829                         mime_entity = strcasestr(temp_buffer, "content-type");
830                         if (mime_entity != NULL && !searched)
831                                 searched = 1;
832
833                         if (searched) {
834                                 EM_DEBUG_LOG("temp_buffer : %s", temp_buffer);
835                                 fprintf(fp_write, "%s", temp_buffer);
836                         }
837                 }
838         }       
839
840 FINISH_OFF:
841         if (fp_read)
842                 fclose(fp_read);
843
844         if (fp_write)
845                 fclose(fp_write);
846
847         EM_SAFE_FREE(mime_entity);
848         EM_SAFE_FREE(mime_path);
849
850         EM_DEBUG_FUNC_END();
851         return mime_entity_path;
852 }
853
854 INTERNAL_FUNC int emcore_convert_mail_data_to_smime_data(emstorage_account_tbl_t *account_tbl_item, email_mail_data_t *input_mail_data, email_attachment_data_t *input_attachment_data_list, int input_attachment_count, email_mail_data_t **output_mail_data, email_attachment_data_t **output_attachment_data_list, int *output_attachment_count)
855 {
856         EM_DEBUG_FUNC_BEGIN("input_mail_data[%p], input_attachment_data_list [%p], input_attachment_count [%d], output_mail_data [%p], output_attachment_data_list [%p]", input_mail_data, input_attachment_data_list, input_attachment_count, output_mail_data, output_attachment_data_list);
857
858         int ret = false;
859         int err = EMAIL_ERROR_NONE;
860         int smime_type = EMAIL_SMIME_NONE;
861         int address_length = 0;
862         int attachment_count = input_attachment_count;
863         char *name = NULL;
864         char *rfc822_file = NULL;
865         char *mime_entity = NULL;
866         char *smime_file_path = NULL;
867         char *other_certificate_list = NULL;
868 #ifdef SMIME_DEBUG
869         char *buf_pointer = NULL;
870         char *password = NULL;
871         char buf[81] = {0, };
872         FILE *fp = NULL;
873 #endif
874         email_attachment_data_t new_attachment_data = {0};
875         email_attachment_data_t *temp_attachment_data = NULL;
876
877         /* Validating parameters */
878         
879         if (!input_mail_data || !(input_mail_data->account_id) || !(input_mail_data->mailbox_id)) {
880                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
881                 goto FINISH_OFF;
882         }
883
884         
885 #ifdef SMIME_DEBUG
886         fp = fopen(TEMP_PASSWORD_PATH, "r");
887         if (fp == NULL) {
888                 EM_DEBUG_EXCEPTION("Open failed");
889                 err = EMAIL_ERROR_SYSTEM_FAILURE;
890                 goto FINISH_OFF;
891         }
892
893         while (!feof(fp)) {
894                 buf_pointer = fgets(buf, 80, fp);
895         }
896
897         fclose(fp);
898         
899         EM_DEBUG_LOG("password : [%s], strlen : [%d]", buf, strlen(buf)-1);
900         password = em_malloc(sizeof(buf));
901         memcpy(password, buf, strlen(buf) - 1);
902
903 #endif
904         
905         if (!emcore_make_rfc822_file(input_mail_data, input_attachment_data_list, attachment_count, &rfc822_file, &err))  {
906                 EM_DEBUG_EXCEPTION("emcore_make_rfc822_file_from_mail failed [%d]", err);
907                 goto FINISH_OFF;
908         }
909
910         mime_entity = emcore_get_mime_entity(rfc822_file);
911
912         smime_type = input_mail_data->smime_type;
913         if (!smime_type) 
914                 smime_type = account_tbl_item->smime_type;
915
916         /* Signed and Encrypt the message */
917         switch (smime_type) {
918         case EMAIL_SMIME_SIGNED:                        /* Clear signed message */
919                 if (!emcore_smime_set_signed_message(account_tbl_item->certificate_path, password, mime_entity, account_tbl_item->digest_type, &smime_file_path, &err)) {
920                         EM_DEBUG_EXCEPTION("em_core_smime_set_clear_signed_message is failed : [%d]", err);
921                         goto FINISH_OFF;
922                 }
923         
924                 EM_DEBUG_LOG("smime_file_path : %s", smime_file_path);  
925                 name = strrchr(smime_file_path, '/');
926
927                 new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1);
928                 new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path);
929                 new_attachment_data.attachment_size = 1;
930                 new_attachment_data.save_status = 1;
931
932                 attachment_count += 1;
933
934                 break;
935         case EMAIL_SMIME_ENCRYPTED:                     /* Encryption message */
936                 address_length = EM_SAFE_STRLEN(input_mail_data->full_address_to) + EM_SAFE_STRLEN(input_mail_data->full_address_cc) + EM_SAFE_STRLEN(input_mail_data->full_address_bcc);
937
938                 other_certificate_list = em_malloc(address_length + 3);
939                 
940                 SNPRINTF(other_certificate_list, address_length + 2, "%s;%s;%s", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc);
941
942                 EM_DEBUG_LOG("to:[%s], cc:[%s], bcc:[%s]", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc);
943                 EM_DEBUG_LOG("length : [%d], email_address : [%s]", address_length, other_certificate_list);
944
945                 if (!emcore_smime_set_encrypt_message(other_certificate_list, mime_entity, account_tbl_item->cipher_type, &smime_file_path, &err)) {
946                         EM_DEBUG_EXCEPTION("emcore_smime_set_encrypt_message is failed : [%d]", err);
947                         goto FINISH_OFF;
948                 }
949
950                 EM_DEBUG_LOG("smime_file_path : %s", smime_file_path);  
951                 name = strrchr(smime_file_path, '/');
952
953                 new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1);
954                 new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path);
955                 new_attachment_data.attachment_size = 1;
956                 new_attachment_data.save_status = 1;
957
958                 attachment_count += 1;
959
960                 break;
961         case EMAIL_SMIME_SIGNED_AND_ENCRYPTED:                  /* Signed and Encryption message */
962                 address_length = EM_SAFE_STRLEN(input_mail_data->full_address_to) + EM_SAFE_STRLEN(input_mail_data->full_address_cc) + EM_SAFE_STRLEN(input_mail_data->full_address_bcc);
963
964                 other_certificate_list = em_malloc(address_length + 3);
965
966                 SNPRINTF(other_certificate_list, address_length + 2, "%s;%s;%s", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc);
967
968                 EM_DEBUG_LOG("to:[%s], cc:[%s], bcc:[%s]", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc);
969                 EM_DEBUG_LOG("length : [%d], email_address : [%s]", address_length, other_certificate_list);
970
971                 if (!emcore_smime_set_signed_and_encrypt_message(other_certificate_list, account_tbl_item->certificate_path, password, mime_entity, account_tbl_item->cipher_type, account_tbl_item->digest_type, &smime_file_path, &err)) {
972                         EM_DEBUG_EXCEPTION("em_core_smime_set_signed_and_encrypt_message is failed : [%d]", err);
973                         goto FINISH_OFF;
974                 }
975
976                 EM_DEBUG_LOG("smime_file_path : %s", smime_file_path);  
977                 name = strrchr(smime_file_path, '/');
978
979                 new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1);
980                 new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path);
981                 new_attachment_data.attachment_size = 1;
982                 new_attachment_data.save_status = 1;
983
984                 attachment_count = 1;
985
986                 break;
987         default:
988                 break;
989         }
990
991         temp_attachment_data = (email_attachment_data_t *)em_malloc(sizeof(email_attachment_data_t) * attachment_count);
992         if (input_attachment_data_list != NULL)
993                 temp_attachment_data = input_attachment_data_list;
994
995         temp_attachment_data[attachment_count-1] = new_attachment_data;
996
997         input_mail_data->smime_type = smime_type;
998         input_mail_data->file_path_mime_entity = EM_SAFE_STRDUP(mime_entity);
999         input_mail_data->digest_type = account_tbl_item->digest_type;
1000
1001         ret = true;
1002
1003 FINISH_OFF:     
1004         if (output_attachment_count)
1005                 *output_attachment_count = attachment_count;
1006         
1007         if (output_attachment_data_list) 
1008                 *output_attachment_data_list = temp_attachment_data;
1009         
1010
1011         *output_mail_data = input_mail_data;
1012
1013         if (!ret && temp_attachment_data)
1014                 emcore_free_attachment_data(&temp_attachment_data, attachment_count, NULL);     
1015         
1016 #ifdef SMIME_DEBUG
1017         if (password)
1018                 EM_SAFE_FREE(password);
1019 #endif
1020         
1021         return ret;                             
1022 }
1023
1024