Coverity issue fixes for email service
[platform/core/messaging/email-service.git] / email-core / email-core-cert.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  * 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 <glib.h>
37 #include <cert-svc/ccert.h>
38 #include <cert-svc/cstring.h>
39 #include <cert-svc/cpkcs12.h>
40 #include <cert-svc/cinstance.h>
41 #include <cert-svc/cprimitives.h>
42
43 #include "email-core-cert.h"
44 #include "email-core-mail.h"
45 #include "email-core-utils.h"
46 #include "email-utilities.h"
47 #include "email-storage.h"
48 #include "email-debug-log.h"
49
50 #define READ_MODE "r"
51 #define WRITE_MODE "w"
52
53 typedef enum {
54         CERT_TYPE_ETC          = 0,
55         CERT_TYPE_PKCS12,
56         CERT_TYPE_PKCS7,
57         CERT_TYPE_P7S
58 } cert_type;
59
60 INTERNAL_FUNC int emcore_load_PFX_file(char *certificate, EVP_PKEY **pri_key, X509 **cert,
61                                                                         STACK_OF(X509) **ca, int *err_code)
62 {
63         EM_DEBUG_FUNC_BEGIN_SEC("certificate : [%s]", certificate);
64         int err = EMAIL_ERROR_NONE;
65         int ret = false;
66         size_t key_size = 0;
67         char *private_key = NULL;
68
69         /* Variable for certificate */
70         X509 *t_cert = NULL;
71         BIO *bio_mem = NULL;
72 //      STACK_OF(X509) *t_ca = NULL;
73
74         /* Variable for private key */
75         EVP_PKEY *t_pri_key = NULL;
76
77         CertSvcString csstring;
78         CertSvcInstance cert_instance;
79         CertSvcCertificate csc_cert;
80         CertSvcCertificateList certificate_list;
81         CertSvcStoreCertList* certList = NULL;
82         CertSvcStoreCertList* tempList = NULL;
83         char *alias =  NULL;
84         size_t length = 0;
85
86         if (certificate == NULL) {
87                 EM_DEBUG_EXCEPTION("Invalid parameter");
88                 err = EMAIL_ERROR_INVALID_PARAM;
89                 goto FINISH_OFF;
90         }
91
92         EM_DEBUG_LOG("emcore_load_PFX_file - certificate passed : %s", certificate);
93
94         /* Create instance */
95         err = certsvc_instance_new(&cert_instance);
96         if (err != CERTSVC_SUCCESS) {
97                 EM_DEBUG_EXCEPTION("certsvc_instance_new failed : [%d]", err);
98                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
99                 goto FINISH_OFF;
100         }
101
102         /* Make the pfxID string */
103         err = certsvc_string_new(cert_instance, certificate, EM_SAFE_STRLEN(certificate), &csstring);
104         if (err != CERTSVC_SUCCESS) {
105                 EM_DEBUG_EXCEPTION("certsvc_string_new failed : [%d]", err);
106                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
107                 goto FINISH_OFF;
108         }
109
110         if (certsvc_pkcs12_get_end_user_certificate_list_from_store(
111                         cert_instance,
112                         EMAIL_STORE,
113                         &certList,
114                         &length) != CERTSVC_SUCCESS) {
115                 EM_DEBUG_EXCEPTION("certsvc_string_new failed : [%d]", err);
116                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
117                 if (certList)
118                         certsvc_pkcs12_free_certificate_list_loaded_from_store(cert_instance, &certList);
119                 goto FINISH_OFF;
120         }
121
122         tempList = certList;
123         while (tempList) {
124                 if (strcmp(tempList->title, certificate) == 0
125                                 || strcmp(tempList->gname, certificate) == 0) {
126                         alias = strdup(tempList->gname);
127                         break;
128                 }
129
130                 tempList = tempList->next;
131         }
132
133         certsvc_pkcs12_free_certificate_list_loaded_from_store(cert_instance, &certList);
134         if (alias == NULL) {
135                 EM_DEBUG_EXCEPTION("Failed to strdup");
136                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
137                 goto FINISH_OFF;
138         }
139
140         /* Make the pfxID string */
141         err = certsvc_string_new(cert_instance, alias, EM_SAFE_STRLEN(alias), &csstring);
142         if (err != CERTSVC_SUCCESS) {
143                 EM_DEBUG_EXCEPTION("certsvc_string_new failed : [%d]", err);
144                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
145                 goto FINISH_OFF;
146         }
147
148         err = certsvc_pkcs12_load_certificate_list_from_store(cert_instance, EMAIL_STORE, csstring, &certificate_list);
149         if (err != CERTSVC_SUCCESS) {
150                 certsvc_string_free(csstring);
151                 err = certsvc_string_new(cert_instance, certificate, EM_SAFE_STRLEN(certificate), &csstring);
152                 if (err != CERTSVC_SUCCESS) {
153                         EM_DEBUG_EXCEPTION("certsvc_string_new failed : [%d]", err);
154                         err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
155                         goto FINISH_OFF;
156                 }
157
158                 /* Load the certificate list of pkcs12 type */
159                 err = certsvc_pkcs12_load_certificate_list_from_store(cert_instance, EMAIL_STORE, csstring, &certificate_list);
160                 if (err != CERTSVC_SUCCESS) {
161                         EM_DEBUG_EXCEPTION("certsvc_pkcs12_load_certificate_list_from_store failed : [%d]", err);
162                         err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
163                         goto FINISH_OFF;
164                 }
165         }
166
167
168         /* Get a certificate */
169         err = certsvc_certificate_list_get_one(certificate_list, 0, &csc_cert);
170         if (err != CERTSVC_SUCCESS) {
171                 EM_DEBUG_EXCEPTION("certsvc_certificate_list_get_one failed : [%d]", err);
172                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
173                 goto FINISH_OFF;
174         }
175
176         /* Convert from char to X509 */
177         err = certsvc_certificate_dup_x509(csc_cert, &t_cert);
178         if (t_cert == NULL || err != CERTSVC_SUCCESS) {
179                 EM_DEBUG_EXCEPTION("certsvc_certificate_dup_x509 failed");
180                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
181                 goto FINISH_OFF;
182         }
183
184         /* Get the private key */
185         err = certsvc_pkcs12_private_key_dup_from_store(cert_instance, EMAIL_STORE, csstring, &private_key, &key_size);
186         if (err != CERTSVC_SUCCESS) {
187                 EM_DEBUG_EXCEPTION("certsvc_pkcs12_private_key_dup_from_store failed : [%d]", err);
188                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
189                 goto FINISH_OFF;
190         }
191
192         EM_DEBUG_LOG_DEV("key_size : [%u], private_key : [%s]", key_size, private_key);
193
194         /* Convert char to pkey */
195         bio_mem = BIO_new(BIO_s_mem());
196         if (bio_mem == NULL) {
197                 EM_DEBUG_EXCEPTION("malloc failed");
198                 err = EMAIL_ERROR_OUT_OF_MEMORY;
199                 goto FINISH_OFF;
200         }
201
202         if (BIO_write(bio_mem, private_key, (int)key_size) <= 0) {
203                 EM_DEBUG_EXCEPTION("BIO_write failed");
204                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
205                 goto FINISH_OFF;
206         }
207
208         t_pri_key = PEM_read_bio_PrivateKey(bio_mem, NULL, 0, NULL);
209         if (t_pri_key == NULL) {
210                 EM_DEBUG_EXCEPTION("PEM_read_bio_PrivateKey failed");
211                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
212                 goto FINISH_OFF;
213         }
214
215         ret = true;
216
217 FINISH_OFF:
218
219         if (bio_mem)
220                 BIO_free(bio_mem);
221
222         if (true) {
223                 if (cert)
224                         *cert = t_cert;
225
226                 if (pri_key)
227                         *pri_key = t_pri_key;
228         } else {
229                 X509_free(t_cert);
230                 EVP_PKEY_free(t_pri_key);
231         }
232
233         if (private_key)
234                 EM_SAFE_FREE(private_key);
235
236         if (err_code)
237                 *err_code = err;
238
239         if (alias)
240                 free(alias);
241
242         certsvc_instance_free(cert_instance);
243
244         return ret;
245 }
246
247 INTERNAL_FUNC int emcore_verify_signature(char *p7s_file_path, char *mime_entity, int *validity, int *err_code)
248 {
249         EM_DEBUG_FUNC_BEGIN_SEC("path : [%s], mime_entity : [%s]", p7s_file_path, mime_entity);
250         int ret = false;
251         int err = EMAIL_ERROR_NONE;
252         int t_validity = 0;
253         int flags = PKCS7_NOVERIFY;
254
255         BIO *bio_p7s = NULL;
256
257         BIO *bio_indata = NULL;
258
259         PKCS7 *pkcs7_p7s = NULL;
260
261         /* Open p7s file */
262         bio_p7s = BIO_new_file(p7s_file_path, INMODE);
263         if (!bio_p7s) {
264                 EM_DEBUG_EXCEPTION("File open failed");
265                 err = EMAIL_ERROR_SYSTEM_FAILURE;
266                 goto FINISH_OFF;
267         }
268
269         /* Open input data file */
270         bio_indata = BIO_new_file(mime_entity, INMODE);
271         if (!bio_indata) {
272                 EM_DEBUG_EXCEPTION("File open failed");
273                 err = EMAIL_ERROR_SYSTEM_FAILURE;
274                 goto FINISH_OFF;
275         }
276
277         /* Load the p7s file */
278         pkcs7_p7s = d2i_PKCS7_bio(bio_p7s, NULL);
279         if (!pkcs7_p7s) {
280                 EM_DEBUG_EXCEPTION("d2i_PKCS7_bio failed");
281                 err = EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE;
282                 goto FINISH_OFF;
283         }
284
285         if (!PKCS7_verify(pkcs7_p7s, NULL, NULL, bio_indata, NULL, flags)) {
286                 EM_DEBUG_EXCEPTION("PKCS7_verify failed");
287                 goto FINISH_OFF;
288         }
289
290         t_validity = 1;
291
292         ret = true;
293
294 FINISH_OFF:
295
296         if (pkcs7_p7s)
297                 PKCS7_free(pkcs7_p7s);
298
299         if (bio_p7s)
300                 BIO_free(bio_p7s);
301
302         if (bio_indata)
303                 BIO_free(bio_indata);
304
305         if (validity)
306                 *validity = t_validity;
307
308         if (err_code)
309                 *err_code = err;
310
311         EM_DEBUG_FUNC_END();
312         return ret;
313 }