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