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