2.0_alpha release commit
[framework/messaging/email-service.git] / email-core / email-core-cert.c
1 /*
2 *  email-service
3 *
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5 *
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>
7
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21
22
23 /******************************************************************************
24  * File :  email-core-cert.h
25  * Desc :  Certificate API
26  *
27  * Auth : 
28  *
29  * History : 
30  *    2006.08.16  :  created
31  *****************************************************************************/
32 #include <openssl/pkcs7.h>
33 #include <openssl/pkcs12.h>
34 #include <openssl/pem.h>
35 #include <openssl/err.h>
36 #include <cert-service.h>
37 #include <glib.h>
38
39 #include "email-core-cert.h"
40 #include "email-core-mail.h"
41 #include "email-utilities.h"
42 #include "email-storage.h"
43 #include "email-debug-log.h"
44
45 #define READ_MODE "r"
46 #define WRITE_MODE "w"
47
48 #define EMAIL_ERROR_CERTIFICATE_LOAD_FAIL 2300
49 #define EMAIL_ERROR_FILE_NOT_OPEN 2301
50 #define EMAIL_ERROR_INVALID_CERTIFICATE 2302
51
52 #define TRUSTED_USER "trusteduser/email/"
53
54 typedef enum {
55         CERT_TYPE_ETC          = 0,
56         CERT_TYPE_PKCS12,       
57         CERT_TYPE_PKCS7,
58         CERT_TYPE_P7S
59 } cert_type;
60
61 static int emcore_get_certificate_type(char *extension, int *err_code)
62 {
63         EM_DEBUG_FUNC_BEGIN("extensiong is [%s]", extension);
64         int index = 0;
65         int type = 0;
66         int err = EMAIL_ERROR_NONE;
67         char *supported_file_type[] = {"pfx", "p12", "p7s", "pem", "der", "crt", "cer", NULL};
68
69         if (!extension) {
70                 EM_DEBUG_EXCEPTION("Invalid parameter");
71                 err = EMAIL_ERROR_INVALID_PARAM;
72                 goto FINISH_OFF;
73         }
74         
75         while(supported_file_type[index]) {
76                 EM_DEBUG_LOG("certificate extension[%d]:[%s]", index, supported_file_type[index]);
77                 if (strcasecmp(extension, supported_file_type[index]) == 0) {
78                         switch (index) {
79                         case 0:
80                         case 1:
81                                 type = CERT_TYPE_PKCS12;
82                                 err = EMAIL_ERROR_INVALID_CERTIFICATE;
83                                 break;
84                         case 2:
85                                 type = CERT_TYPE_P7S;
86                                 break;
87                         case 3:
88                         case 4:
89                         case 5:
90                         case 6:
91                                 type = CERT_TYPE_PKCS7;
92                                 break;
93                         default:
94                                 type = CERT_TYPE_ETC;
95                                 err = EMAIL_ERROR_INVALID_CERTIFICATE;
96                                 break;                  
97                         }
98                 }
99                 index++;
100         }
101
102 FINISH_OFF:
103
104         if (err_code) {
105                 *err_code = err;
106         }
107
108         EM_DEBUG_FUNC_END("File type is [%d]", type);
109         return type;
110 }
111 /*      
112 static GList *emcore_make_glist_from_string(char *email_address_list)
113 {
114         EM_DEBUG_FUNC_BEGIN("email_address list : [%s]", email_address_list);
115         int index = 0;
116         const gchar seperator = 0x01;
117         GList *email_list = NULL;
118         gchar *p_email_address_list = NULL;
119         gchar **token_list = NULL;
120
121         p_email_address_list = g_strdup(email_address_list);
122
123         token_list = g_strsplit(p_email_address_list, &seperator, -1);
124         while (token_list[index] != NULL) {
125                 email_list = g_list_append(email_list, token_list[index]);
126                 index++;
127         }
128         
129         if (p_email_address_list)
130                 g_free(p_email_address_list);
131
132         return email_list;      
133 }
134 */
135 static int emcore_load_public_of_p7s(CERT_CONTEXT *context, char *public_cert_path, STACK_OF(X509) **certificates, int *err_code)
136 {
137         EM_DEBUG_FUNC_BEGIN();
138         
139         int ret = false;
140         int err = EMAIL_ERROR_NONE;
141         int cert_size = 0;
142         unsigned char *cert_string = NULL;
143         PKCS7 *pkcs7 = NULL;
144         BIO *infile = NULL;
145         X509 *cert = NULL;
146         STACK_OF(X509) *certs = NULL;
147         
148         if (public_cert_path == NULL) {
149                 EM_DEBUG_EXCEPTION("Invalid parameter");
150                 err = EMAIL_ERROR_INVALID_PARAM;
151                 goto FINISH_OFF;
152         }
153
154         OpenSSL_add_all_algorithms();
155         
156         /* Open p7s file */
157         infile = BIO_new_file(public_cert_path, READ_MODE);
158         if (infile == NULL) {
159                 EM_DEBUG_EXCEPTION("File open failed [%s]", public_cert_path);
160                 err = EMAIL_ERROR_FILE_NOT_FOUND;
161                 goto FINISH_OFF;
162         }
163
164         /* Load the p7s file */
165         pkcs7 = d2i_PKCS7_bio(infile, NULL);
166         if (pkcs7 == NULL) {
167                 EM_DEBUG_EXCEPTION("smime.p7s load failed");
168                 err = EMAIL_ERROR_CERTIFICATE_LOAD_FAIL;
169                 goto FINISH_OFF;
170         }
171
172         /* Extract the signature in pkcs7 */
173         certs = PKCS7_get0_signers(pkcs7, NULL, 0);
174         if (certs == NULL) {
175                 EM_DEBUG_EXCEPTION("smime.p7s extract failed");
176                 err = EMAIL_ERROR_CERTIFICATE_LOAD_FAIL;
177                 goto FINISH_OFF;
178         }
179         
180         /* Change from the p7s to the pem file */
181         if (sk_X509_num(certs) > 1) {
182                 EM_DEBUG_EXCEPTION("Has one or more signature.\nIt is not support");
183                 err = EMAIL_ERROR_UNKNOWN;
184                 goto FINISH_OFF;
185         }
186
187         cert = sk_X509_value(certs, 0);
188         cert_size = i2d_X509(cert, &cert_string);
189         if (cert_size < 0) {
190                 EM_DEBUG_EXCEPTION("Fail to convert certificate");
191                 err = EMAIL_ERROR_UNKNOWN;
192                 goto FINISH_OFF;
193         }
194
195         /* Initilize the certificate and CERT_CONTEXT buffer */
196         cert_string = (unsigned char *)em_malloc(sizeof(unsigned char *) * cert_size);
197         if (cert_string == NULL) {
198                 EM_DEBUG_EXCEPTION("em_malloc failed");
199                 err = EMAIL_ERROR_OUT_OF_MEMORY;
200                 goto FINISH_OFF;
201         }
202
203         context->certBuf = (cert_svc_mem_buff *)em_malloc(sizeof(cert_svc_mem_buff));
204         if (context->certBuf == NULL) {
205                 EM_DEBUG_EXCEPTION("em_malloc failed");
206                 err = EMAIL_ERROR_OUT_OF_MEMORY;
207                 goto FINISH_OFF;
208         }
209
210         /* Set CERT_CONTEXT structure */
211         context->certBuf->data = cert_string;
212         context->certBuf->size = cert_size;
213         
214         ret = true;
215
216 FINISH_OFF:
217
218         if (infile) 
219                 BIO_free(infile);
220         
221         if (pkcs7)
222                 PKCS7_free(pkcs7);
223         
224         if (cert)
225                 X509_free(cert);
226
227         if (ret) {
228                 if (certificates != NULL)
229                         *certificates = certs;
230
231                 if (err_code != NULL)
232                         *err_code = err;
233         } else {
234                 if (certs)
235                         sk_X509_free(certs);
236
237                 EM_SAFE_FREE(cert_string);
238         }
239
240         EVP_cleanup();
241
242         EM_DEBUG_FUNC_END();
243
244         return ret;
245 }
246 /*
247 static char *emcore_store_public_certificate(STACK_OF(X509) *certificates, char *email_address, int *err_code)
248 {
249         EM_DEBUG_FUNC_BEGIN();
250         int index = 0;
251         int err = EMAIL_ERROR_NONE;
252         char *file_path = NULL;
253         BIO *outfile = NULL;
254
255         file_path = (char *)em_malloc(256);
256         if (file_path == NULL) {
257                 EM_DEBUG_EXCEPTION("em_malloc failed");
258                 err = EMAIL_ERROR_OUT_OF_MEMORY;
259                 goto FINISH_OFF;
260         }
261
262         SNPRINTF(file_path, 256, "%s%s%s", CERT_SVC_STORE_PATH, TRUSTED_USER, email_address);
263         outfile = BIO_new_file(file_path, WRITE_MODE);
264         if (outfile == NULL) {
265                 EM_DEBUG_EXCEPTION("File open failed[write mode]");
266                 err = EMAIL_ERROR_FILE_NOT_OPEN;
267                 goto FINISH_OFF;
268         }
269
270         for (index = 0; index < sk_X509_num(certificates); index++) {
271                 EM_DEBUG_LOG("Write the certificate in pem file : [%d]", index);
272                 PEM_write_bio_X509(outfile, sk_X509_value(certificates, index));
273         }
274         
275 FINISH_OFF:
276
277         if (outfile)
278                 BIO_free(outfile);
279
280         EM_DEBUG_FUNC_END();
281
282         return file_path;
283 }
284 */
285 INTERNAL_FUNC int emcore_load_PFX_file(char *certificate, char *password, EVP_PKEY **pri_key, X509 **cert, STACK_OF(X509) **ca, int *err_code)
286 {
287         EM_DEBUG_FUNC_BEGIN("Certificate path : [%s], password : [%s]", certificate, password);
288
289         int err = EMAIL_ERROR_NONE;
290         int ret = false;
291         FILE *fp = NULL;
292         PKCS12 *p12 = NULL;
293
294         OpenSSL_add_all_algorithms();
295         ERR_load_crypto_strings();
296         if (!(fp = fopen(certificate, "rb"))) {
297                 EM_DEBUG_EXCEPTION("fopen failed : [%s]", certificate);
298                 err = EMAIL_ERROR_SYSTEM_FAILURE;
299                 goto FINISH_OFF;
300         }
301         
302         p12 = d2i_PKCS12_fp(fp, NULL);
303         if (!p12) {
304                 EM_DEBUG_EXCEPTION("d2i_PKCS12_fp failed");
305                 err = EMAIL_ERROR_SYSTEM_FAILURE;
306                 goto FINISH_OFF;
307         }
308
309         if (!PKCS12_parse(p12, password, pri_key, cert, ca)) {
310                 EM_DEBUG_EXCEPTION("PKCS12_parse failed");
311                 err = EMAIL_ERROR_SYSTEM_FAILURE;
312                 goto FINISH_OFF;
313         }
314
315         ret = true;
316
317 FINISH_OFF:
318
319         if (fp)
320                 fclose(fp);
321
322         if (p12)
323                 PKCS12_free(p12);
324
325         if (err_code)
326                 *err_code = err;
327
328         return ret;     
329 }
330
331 INTERNAL_FUNC int emcore_add_public_certificate(char *public_cert_path, char *save_name, int *err_code)
332 {
333         EM_DEBUG_FUNC_BEGIN("Path [%s], filename [%s]", public_cert_path, save_name);
334         int err = EMAIL_ERROR_NONE;     
335         int ret = false;
336         int validity = 0;
337         int cert_type = 0;
338         char temp_file[512] = {0, };
339         char temp_save_name[512] = {0, };
340         char filepath[512] = {0, };
341         char *extension = NULL;
342         emstorage_certificate_tbl_t *cert = NULL;
343         CERT_CONTEXT *context = NULL;
344
345         if (public_cert_path == NULL || save_name == NULL) {
346                 EM_DEBUG_EXCEPTION("Invalid parameter");
347                 err = EMAIL_ERROR_INVALID_PARAM;
348                 goto FINISH_OFF;                
349         }
350         
351         /* Initilize the structure of certificate */
352         context = cert_svc_cert_context_init();
353
354         /* Parse the file type */
355         extension = em_get_extension_from_file_path(public_cert_path, NULL);
356         if (extension == NULL) {
357                 EM_DEBUG_EXCEPTION("Invalid parameter");
358                 err = EMAIL_ERROR_INVALID_PARAM;
359                 goto FINISH_OFF;
360         }
361
362         /* Get the file type information */
363         cert_type = emcore_get_certificate_type(extension, &err);
364         if (!cert_type || err == EMAIL_ERROR_INVALID_CERTIFICATE) {
365                 EM_DEBUG_EXCEPTION("Invalid certificate");
366                 goto FINISH_OFF;
367         }
368
369         /* Create temp file and rename */
370         if (cert_type == CERT_TYPE_P7S) {
371                 extension = "der";
372         }
373         
374         SNPRINTF(temp_file, sizeof(temp_file), "%s%s%s%s%s.%s", MAILHOME, DIR_SEPERATOR, MAILTEMP, DIR_SEPERATOR, save_name, extension);
375         EM_DEBUG_LOG("temp cert path : [%s]", temp_file);
376
377         if (!emstorage_copy_file(public_cert_path, temp_file, false, &err)) {
378                 EM_DEBUG_EXCEPTION("emstorage_copy_file failed [%d]", err);
379                 goto FINISH_OFF;
380         }
381         
382         /* Load the public certificate */
383         err = cert_svc_load_file_to_context(context, temp_file);
384         if (err != CERT_SVC_ERR_NO_ERROR) {
385                 EM_DEBUG_EXCEPTION("Load cert failed : [%d]", err);
386                 err = EMAIL_ERROR_INVALID_CERTIFICATE;
387                 goto FINISH_OFF;
388         }
389
390         /* Verify the certificate */
391         if (cert_svc_verify_certificate(context, &validity) != CERT_SVC_ERR_NO_ERROR) {
392                 EM_DEBUG_EXCEPTION("cert_svc_verify_certificate failed");
393 //              err = EMAIL_ERROR_INVALID_CERTIFICATE;
394 //              goto FINISH_OFF;
395         } 
396
397         if (validity <= 0) {
398                 EM_DEBUG_LOG("Invalid certificate");
399         }
400
401         /* Load the certificate information */
402         if (cert_svc_extract_certificate_data(context) != CERT_SVC_ERR_NO_ERROR) {
403                 EM_DEBUG_EXCEPTION("Extract the certificate failed");
404                 err = EMAIL_ERROR_UNKNOWN;
405                 goto FINISH_OFF;
406         }
407
408         /* Store the certificate file to trusted folder */
409         if (cert_svc_add_certificate_to_store(temp_file, TRUSTED_USER) != CERT_SVC_ERR_NO_ERROR) {
410                 EM_DEBUG_EXCEPTION("Add certificate to trusted folder");
411                 err = EMAIL_ERROR_UNKNOWN;
412                 goto FINISH_OFF;
413         }
414
415         /* Store the certificate to DB */
416         SNPRINTF(filepath, sizeof(filepath), "%s%s%s.%s", CERT_SVC_STORE_PATH, TRUSTED_USER, save_name, extension);
417         SNPRINTF(temp_save_name, sizeof(temp_save_name), "<%s>", save_name);
418
419         cert = (emstorage_certificate_tbl_t *)em_malloc(sizeof(emstorage_certificate_tbl_t));
420         if (cert == NULL) {
421                 EM_DEBUG_EXCEPTION("em_malloc failed");
422                 err = EMAIL_ERROR_OUT_OF_MEMORY;
423                 goto FINISH_OFF;
424         }
425
426         cert->issue_year = context->certDesc->info.validPeriod.firstYear;
427         cert->issue_year = context->certDesc->info.validPeriod.firstYear;
428         cert->issue_month = context->certDesc->info.validPeriod.firstMonth;
429         cert->issue_day = context->certDesc->info.validPeriod.firstDay;         
430         cert->expiration_year= context->certDesc->info.validPeriod.secondYear;          
431         cert->expiration_month = context->certDesc->info.validPeriod.secondMonth;               
432         cert->expiration_day = context->certDesc->info.validPeriod.secondDay;                           
433         cert->issue_organization_name = EM_SAFE_STRDUP(context->certDesc->info.issuer.organizationName);
434         cert->email_address = EM_SAFE_STRDUP(temp_save_name);
435         cert->subject_str = EM_SAFE_STRDUP(context->certDesc->info.issuerStr);          
436         cert->filepath = EM_SAFE_STRDUP(filepath);                              
437
438         if (emstorage_add_certificate(cert, true, &err)) {
439                 EM_DEBUG_EXCEPTION("emstorage_add_certificate failed");
440                 goto FINISH_OFF;
441         }
442
443         if (!emstorage_delete_file(public_cert_path, &err)) {
444                 EM_DEBUG_EXCEPTION("emstorage_delete_file failed [%d]", err);
445                 goto FINISH_OFF;
446         }
447
448         ret = true;
449
450 FINISH_OFF:
451         
452         emstorage_free_certificate(&cert, 1, NULL);
453
454         cert_svc_cert_context_final(context);
455
456         if (err_code != NULL) {
457                 *err_code = err;
458         }
459
460         EM_DEBUG_FUNC_END();
461
462         return ret;
463
464 }
465
466 INTERNAL_FUNC int emcore_delete_public_certificate(char *email_address, int *err_code)
467 {
468         EM_DEBUG_FUNC_BEGIN();
469         int ret = false;
470         int err = EMAIL_ERROR_NONE;
471         emstorage_certificate_tbl_t *certificate = NULL;
472
473         if (email_address == NULL) {
474                 EM_DEBUG_EXCEPTION("Invalid parameter");
475                 err = EMAIL_ERROR_INVALID_PARAM;
476                 goto FINISH_OFF;
477         }
478
479         if (!emstorage_get_certificate_by_email_address(email_address, &certificate, false, 0, &err)) {
480                 EM_DEBUG_EXCEPTION("emstorage_get_certificate failed");
481                 goto FINISH_OFF;
482         }
483
484         if (remove(certificate->filepath) < 0) {
485                 EM_DEBUG_EXCEPTION("remove failed : [%s]", certificate->filepath);
486                 goto FINISH_OFF;
487         }
488
489         if (!emstorage_delete_certificate(certificate->certificate_id, true, &err)) {
490                 EM_DEBUG_EXCEPTION("emstorage_delete_certificate failed");
491                 goto FINISH_OFF;
492         }
493
494         ret = true;
495 FINISH_OFF:
496
497         if (certificate != NULL)
498                 emstorage_free_certificate(&certificate, 1, NULL);
499
500         if (err_code != NULL)
501                 *err_code = err;
502
503         EM_DEBUG_FUNC_END();
504
505         return ret;
506 }
507
508 INTERNAL_FUNC int emcore_verify_signature(char *p7s_file_path, char *mime_entity, int *validity, int *err_code)
509 {
510         EM_DEBUG_FUNC_BEGIN("path[%s], mime_entiy[%s]", p7s_file_path, mime_entity);
511         int ret = false;
512         int err = EMAIL_ERROR_NONE;
513         int i = 0, j = 0;
514
515         int p_validity = 0;
516         int msg_len = 0;
517         unsigned char *msg = NULL;
518         int sig_len = 0;
519         unsigned char *sig = NULL;
520         unsigned char *tmp_sig = NULL;
521         FILE *fp_msg = NULL;
522         FILE *fp_sig = NULL;
523         size_t f_size = 0;
524
525         CERT_CONTEXT *context = NULL;
526
527         context = cert_svc_cert_context_init();
528
529         if (!emcore_load_public_of_p7s(context, p7s_file_path, NULL, &err)) {
530                 EM_DEBUG_EXCEPTION("emcore_load_public_of_p7s failed");
531                 goto FINISH_OFF;
532         }
533
534         fp_msg = fopen(mime_entity, "rb");
535         fseek(fp_msg, 0L, SEEK_END);
536         msg_len = ftell(fp_msg);
537         fseek(fp_msg, 0L, SEEK_SET);
538         msg = (unsigned char *)em_malloc(sizeof(unsigned char) * (msg_len + 1));
539         if (msg == NULL) {
540                 EM_DEBUG_EXCEPTION("em_malloc failed");
541                 err = EMAIL_ERROR_OUT_OF_MEMORY;
542                 goto FINISH_OFF;
543         }
544
545         if ((f_size = fread(msg, sizeof(unsigned char), msg_len, fp_msg)) < 0) {
546                 EM_DEBUG_EXCEPTION("File read failed");
547                 goto FINISH_OFF;                
548         }
549
550         fp_sig = fopen(p7s_file_path, "rb");
551         fseek(fp_sig, 0L, SEEK_END);
552         sig_len = ftell(fp_sig);
553         fseek(fp_sig, 0L, SEEK_SET);
554         sig = (unsigned char *)em_malloc(sizeof(unsigned char) * (sig_len + 1));
555         if (sig == NULL) {
556                 EM_DEBUG_EXCEPTION("em_malloc failed");
557                 err = EMAIL_ERROR_OUT_OF_MEMORY;
558                 goto FINISH_OFF;
559         }
560         tmp_sig = (unsigned char *)em_malloc(sizeof(unsigned char) * (sig_len + 1));
561         if (tmp_sig == NULL) {
562                 EM_DEBUG_EXCEPTION("em_malloc failed");
563                 err = EMAIL_ERROR_OUT_OF_MEMORY;
564                 goto FINISH_OFF;
565         }
566
567         if ((f_size = fread(sig, sizeof(unsigned char), sig_len, fp_sig)) < 0) {
568                 EM_DEBUG_EXCEPTION("File read failed");
569                 goto FINISH_OFF;
570         }
571
572         for(i = 0; i < sig_len; i++) {
573                 if(sig[i] != '\n') {
574                         tmp_sig[j] = sig[i];
575                         j++;
576                 }
577         }
578         
579         err = cert_svc_verify_signature(context, msg, msg_len, tmp_sig, NULL, &p_validity);
580         if (err != CERT_SVC_ERR_NO_ERROR) {
581                 EM_DEBUG_EXCEPTION("Verify signature failed");
582                 goto FINISH_OFF;
583         }
584
585         ret = true;
586
587 FINISH_OFF:
588
589         EM_SAFE_FREE(tmp_sig);
590
591         EM_SAFE_FREE(sig);
592
593         EM_SAFE_FREE(msg);
594
595         if (fp_sig != NULL)
596                 fclose(fp_sig);
597         
598         if (fp_msg != NULL)
599                 fclose(fp_msg);
600
601         cert_svc_cert_context_final(context);
602
603         
604
605         if (err_code != NULL)
606                 *err_code = err;
607
608         EM_DEBUG_FUNC_END();
609         return ret;
610 }
611
612 INTERNAL_FUNC int emcore_verify_certificate(char *certificate, int *validity, int *err_code)
613 {
614         EM_DEBUG_FUNC_BEGIN();
615         int ret = false;
616         int err = EMAIL_ERROR_NONE;
617         int p_validity = 0;
618
619         CERT_CONTEXT *context = NULL;
620         
621         context = cert_svc_cert_context_init();
622
623         err = cert_svc_load_file_to_context(context, certificate);
624         if (err != CERT_SVC_ERR_NO_ERROR) {
625                 EM_DEBUG_EXCEPTION("Certificate load failed");
626                 goto FINISH_OFF;
627         }
628
629         err = cert_svc_verify_certificate(context, &p_validity);
630         if (err != CERT_SVC_ERR_NO_ERROR) {
631                 EM_DEBUG_EXCEPTION("Certificate verify failed");
632                 goto FINISH_OFF;
633         }
634
635         ret = true;
636
637 FINISH_OFF:
638
639         if (validity != NULL) 
640                 *validity = p_validity;
641
642         if (err_code != NULL) {
643                 *err_code = err;
644         }
645
646         EM_DEBUG_FUNC_END();
647         return ret;
648 }
649
650 INTERNAL_FUNC int emcore_free_certificate(email_certificate_t **certificate, int count, int *err_code)
651 {
652         EM_DEBUG_FUNC_BEGIN("certificate [%p], count [%d]", certificate, count);
653         
654         if (count <= 0 || !certificate || !*certificate) {
655                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");
656                 if (err_code)   
657                         *err_code = EMAIL_ERROR_INVALID_PARAM;
658                 return false;
659         }
660
661         email_certificate_t *p_certificate = *certificate;
662         int i;
663         
664         for (i=0;i<count;i++) {
665                 EM_SAFE_FREE(p_certificate[i].issue_organization_name);
666                 EM_SAFE_FREE(p_certificate[i].email_address);
667                 EM_SAFE_FREE(p_certificate[i].subject_str);
668                 EM_SAFE_FREE(p_certificate[i].filepath);
669         }
670
671         EM_SAFE_FREE(p_certificate);
672         *certificate = NULL;
673
674         if (err_code)
675                 *err_code = EMAIL_ERROR_NONE;
676
677         EM_DEBUG_FUNC_END();
678         return true;
679 }