9ee5483a3292b345ce77c0119e9a085099d9a76d
[platform/core/security/cert-svc.git] / vcore / src / vcore / pkcs12.cpp
1 /**
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        pkcs12.cpp
18  * @author      Jacek Migacz (j.migacz@samsung.com)
19  * @author      Kyungwook Tak (k.tak@samsung.com)
20  * @version     1.0
21  * @brief       PKCS#12 container manipulation routines.
22  */
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <openssl/err.h>
30 #include <openssl/pkcs12.h>
31 #include <openssl/sha.h>
32 #include <openssl/x509.h>
33 #include <openssl/pem.h>
34
35 #include <cert-service.h>
36 #include <cert-service-debug.h>
37 #include <cert-svc/cerror.h>
38 #include <cert-svc-client.h>
39
40 #include <vcore/utils.h>
41 #include <pkcs12.h>
42
43 #define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
44
45 #define START_CERT      "-----BEGIN CERTIFICATE-----"
46 #define END_CERT        "-----END CERTIFICATE-----"
47 #define START_TRUSTED   "-----BEGIN TRUSTED CERTIFICATE-----"
48 #define END_TRUSTED     "-----END TRUSTED CERTIFICATE-----"
49 #define START_KEY       "-----BEGIN PRIVATE KEY-----"
50 #define END_KEY         "-----END PRIVATE KEY-----"
51
52 #define _CERT_SVC_VERIFY_PKCS12
53
54 static int generate_random_filepath(char **filepath)
55 {
56   int generator;
57   int64_t random;
58   SHA_CTX ctx;
59   unsigned char d[SHA_DIGEST_LENGTH];
60   int result;
61
62   if(!filepath)
63     return CERTSVC_WRONG_ARGUMENT;
64
65   SYSCALL(generator = open("/dev/urandom", O_RDONLY));
66   if(generator == -1)
67     return CERTSVC_FAIL;
68   SYSCALL(result = read(generator, &random, sizeof(random)));
69   if(result == -1) {
70     SYSCALL(close(generator));
71     return CERTSVC_FAIL;
72   }
73   SYSCALL(result = close(generator));
74   if(result == -1)
75     return CERTSVC_FAIL;
76
77   SHA1_Init(&ctx);
78   SHA1_Update(&ctx, &random, sizeof(random));
79   SHA1_Final(d, &ctx);
80
81   result = asprintf(filepath, "%s/"                            \
82                     "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
83                     "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
84                     CERTSVC_PKCS12_STORAGE_DIR,
85                     d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9],
86                     d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19]);
87   return (result != -1) ? CERTSVC_SUCCESS : CERTSVC_BAD_ALLOC;
88 }
89
90 static int unique_filename(char **filepath)
91 {
92   int result;
93
94   for (unsigned trial = 0x00U; trial < 0xFFU; ++trial) {
95     result = generate_random_filepath(filepath);
96     if (result != CERTSVC_SUCCESS)
97         return result;
98
99     result = access(*filepath, F_OK);
100     if (result != 0)
101         return CERTSVC_SUCCESS;
102
103     free(*filepath);
104   }
105
106   return CERTSVC_FAIL;
107 }
108
109 static char *bare_filename(char *filepath)
110 {
111   char *needle;
112   if(!filepath)
113     return NULL;
114   needle = strrchr(filepath, '/');
115   if(!needle)
116     return NULL;
117   return *(++needle) ? needle : NULL;
118 }
119
120 int read_from_file(const char *fileName, char **certBuffer, int *length)
121 {
122     int result = CERTSVC_SUCCESS;
123     FILE *fp_out = NULL;
124     int certLength = 0;
125     struct stat st;
126
127     if (stat(fileName, &st) == -1) {
128         SLOGE("Certificate does not exist in disable folder.");
129         result = CERTSVC_FAIL;
130         goto err;
131     }
132
133     if (!(fp_out = fopen(fileName, "rb"))) {
134         SLOGE("Fail to open file for reading, [%s].", fileName);
135         result = CERTSVC_FAIL;
136         goto err;
137     }
138
139     fseek(fp_out, 0L, SEEK_END);
140     certLength = ftell(fp_out);
141     if (certLength < 1) {
142         SLOGE("Fail to get certificate length.");
143         result = CERT_SVC_ERR_FILE_IO;
144         goto err;
145     }
146
147     *certBuffer = (char*)malloc(sizeof(char) * ((int)certLength + 1));
148     if (*certBuffer == NULL) {
149         SLOGE("Fail to allocate memory");
150         result = CERTSVC_BAD_ALLOC;
151         goto err;
152     }
153
154     memset(*certBuffer, 0x00, certLength+1);
155     rewind (fp_out);
156     if (fread(*certBuffer, sizeof(char), (size_t)certLength, fp_out) != (size_t)certLength) {
157         SLOGE("Fail to read file, [%s]", fileName);
158         result = CERTSVC_IO_ERROR;
159         goto err;
160     }
161     *length = certLength;
162
163 err:
164     if (fp_out != NULL) {
165         fclose(fp_out);
166         fp_out = NULL;
167     }
168     return result;
169 }
170
171 int c_certsvc_pkcs12_set_certificate_status_to_store(CertStoreType storeType, int is_root_app, const char* gname, CertStatus status)
172 {
173         return vcore_client_set_certificate_status_to_store(storeType, is_root_app, gname, status);
174 }
175
176 int c_certsvc_pkcs12_get_certificate_buffer_from_store(CertStoreType storeType, const char* gname, char** certBuffer, size_t* certSize)
177 {
178     return vcore_client_get_certificate_from_store(storeType, gname, certBuffer, certSize, PEM_CRT);
179 }
180
181 int c_certsvc_pkcs12_get_certificate_status_from_store(CertStoreType storeType, const char *gname, CertStatus *status)
182 {
183     return vcore_client_get_certificate_status_from_store(storeType, gname, status);
184 }
185
186 int c_certsvc_pkcs12_alias_exists_in_store(CertStoreType storeType, const char *alias, int *isUnique)
187 {
188     return vcore_client_check_alias_exist_in_store(storeType, alias, isUnique);
189 }
190
191 int c_certsvc_pkcs12_private_key_load_from_store(CertStoreType storeType, const char *gname, char **certBuffer, size_t *certSize)
192 {
193     return vcore_client_get_certificate_from_store(storeType, gname, certBuffer, certSize, (CertType)P12_PKEY);
194 }
195
196 int c_certsvc_pkcs12_delete_certificate_from_store(CertStoreType storeType, const char* gname)
197 {
198         return vcore_client_delete_certificate_from_store(storeType, gname);
199 }
200
201 int c_certsvc_pkcs12_get_certificate_alias_from_store(CertStoreType storeType, const char *gname, char **alias)
202 {
203     return vcore_client_get_certificate_alias_from_store(storeType, gname, alias);
204 }
205
206 int c_certsvc_pkcs12_load_certificates_from_store(CertStoreType storeType, const char *gname, char ***certs, size_t *ncerts)
207 {
208     return vcore_client_load_certificates_from_store(storeType, gname, certs, ncerts);
209 }
210
211 int c_certsvc_pkcs12_free_aliases_loaded_from_store(CertSvcStoreCertList** certList)
212 {
213     int result = CERTSVC_SUCCESS;
214     CertSvcStoreCertList* tmpNode = NULL;
215
216     while (*certList) {
217         tmpNode = *certList;
218         if (tmpNode->title)
219             free(tmpNode->title);
220         if (tmpNode->gname)
221             free(tmpNode->gname);
222         *certList = (*certList)->next;
223         free(tmpNode);
224     }
225     return result;
226 }
227
228 int c_certsvc_pkcs12_get_root_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList** certList, size_t *length)
229 {
230     return vcore_client_get_root_certificate_list_from_store(storeType, certList, length);
231 }
232
233 int c_certsvc_pkcs12_get_end_user_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList** certList, size_t *length)
234 {
235     return vcore_client_get_end_user_certificate_list_from_store(storeType, certList, length);
236 }
237
238 int c_certsvc_pkcs12_get_certificate_list_from_store(CertStoreType storeType, int is_root_app, CertSvcStoreCertList** certList, size_t *length)
239 {
240     return vcore_client_get_certificate_list_from_store(storeType, is_root_app, certList, length);
241 }
242
243 int install_pem_file_format_to_store(CertStoreType storeType, const char *certBuffer, size_t certLength,
244                 const char *alias, const char* path, char *private_key_gname, char *associated_gname, CertType decideCert)
245 {
246     int result = CERTSVC_SUCCESS;
247     int readCount = 0;
248     char* fileName = NULL;
249     char* commonName = NULL;
250     char *unique = NULL;
251     BIO* pBio = NULL;
252     X509* x509Struct = NULL;
253     struct stat dirST;
254
255     if (!certBuffer || !certLength) {
256         SLOGE("Invalid argument. certBuffer is input cert.");
257         return CERTSVC_WRONG_ARGUMENT;
258     }
259
260     if (decideCert == PEM_CRT) {
261         result = unique_filename(&unique);
262         if (result != CERTSVC_SUCCESS) {
263             SLOGE("Fail to generate unique filename.");
264             return result;
265         }
266     }
267     else
268         unique = (char*)path;
269
270     if (unique == NULL) {
271         SLOGE("Failed to get unique file name.");
272         return result;
273     }
274
275     /* Get common name from buffer or from file */
276     if (stat(path, &dirST) != -1) {
277         result = get_common_name(path, NULL, &commonName);
278         if (result != CERTSVC_SUCCESS) {
279             pBio = BIO_new(BIO_s_mem());
280             if (pBio == NULL) {
281                 SLOGE("Failed to allocate memory.");
282                 result = CERTSVC_BAD_ALLOC;
283                 goto error;
284             }
285
286             readCount = BIO_write(pBio, (const void*) certBuffer, certLength);
287             if (readCount < 1) {
288                 SLOGE("Failed to load cert into bio.");
289                 result = CERTSVC_BAD_ALLOC;
290                 goto error;
291             }
292
293             x509Struct = PEM_read_bio_X509(pBio, NULL, 0, NULL);
294             if (x509Struct == NULL) {
295                 SLOGE("Failed to create x509 structure.");
296                 result = CERTSVC_IO_ERROR;
297                 goto error;
298             }
299
300             result = get_common_name(NULL, x509Struct, &commonName);
301             if (result != CERTSVC_SUCCESS) {
302                 SLOGE("CommonName is NULL");
303                 result = CERTSVC_FAIL;
304                 goto error;
305             }
306         }
307     }
308
309     /* storing the certificate to key-manager */
310     fileName = bare_filename(unique);
311     if ((decideCert == P12_END_USER) && (private_key_gname != NULL))
312         result =  vcore_client_install_certificate_to_store(storeType, fileName, alias, private_key_gname, fileName, certBuffer, certLength, decideCert);
313     else if ((decideCert == P12_TRUSTED) || (decideCert == P12_INTERMEDIATE))
314         result =  vcore_client_install_certificate_to_store(storeType, fileName, commonName, NULL, associated_gname, certBuffer, certLength, decideCert);
315     else
316         result =  vcore_client_install_certificate_to_store(storeType, fileName, commonName, NULL, fileName, certBuffer, certLength, decideCert);
317
318     if (result != CERTSVC_SUCCESS) {
319         SLOGE("Failed to intall certificate. result[%d]", result);
320         result = CERTSVC_FAIL;
321         goto error;
322      }
323
324     SLOGD("Success to add certificate in store.");
325
326 error:
327     if (commonName)
328         free(commonName);
329     return result;
330 }
331
332 int install_crt_file(
333         const char *path,
334         CertStoreType storeType,
335         const char *alias,
336                 char *private_key_gname,
337         char *associated_gname,
338         CertType decideCert)
339 {
340     int result = CERTSVC_SUCCESS;
341     int fileSize = 0;
342     int certLength = 0;
343     const char* header = NULL;
344     const char* trailer = NULL;
345     char* fileContent = NULL;
346     const char* tmpBuffer = NULL;
347     char* certBuffer = NULL;
348     const char* tailEnd = NULL;
349
350     if (read_from_file(path, &fileContent, &fileSize)!=CERTSVC_SUCCESS)
351     {
352         SLOGE("Failed to read the file. [%s]",path);
353         result = CERTSVC_IO_ERROR;
354         goto error;
355     }
356
357     tmpBuffer = fileContent;
358     if (decideCert == PEM_CRT)
359         header = strstr(tmpBuffer, START_CERT);
360     else if (decideCert == P12_END_USER)
361         header = strstr(tmpBuffer, START_CERT);
362     else if ((decideCert == P12_TRUSTED)||(decideCert == P12_INTERMEDIATE))
363         header = strstr(tmpBuffer, START_TRUSTED);
364     else {
365         SLOGE("Invalid cert.");
366         result = CERTSVC_IO_ERROR;
367         goto error;
368     }
369
370     if (header != NULL) {
371         /* Supports installation of only one certificate present in a CRT file */
372         if (decideCert == PEM_CRT) {
373             trailer = strstr(header, END_CERT);
374             tailEnd = END_CERT;
375         }
376         else if (decideCert == P12_END_USER) {
377             trailer = strstr(header, END_CERT);
378             tailEnd = END_CERT;
379         }
380         else if ((decideCert == P12_TRUSTED)||(decideCert == P12_INTERMEDIATE)) {
381             trailer = strstr(header, END_TRUSTED);
382             tailEnd = END_TRUSTED;
383         }
384         else {
385             SLOGE("Invalid certificate passed.");
386             result = CERTSVC_IO_ERROR;
387             goto error;
388         }
389
390         if (trailer != NULL) {
391             tmpBuffer = trailer;
392             certLength = ((int)(trailer - header) + strlen(tailEnd));
393             certBuffer = (char*) malloc(sizeof(char) * (certLength+2));
394             if (certBuffer == NULL) {
395                 result = CERTSVC_BAD_ALLOC;
396                 SLOGE("Fail to allocate memory.");
397                 goto error;
398             }
399
400             memset(certBuffer, 0x00, certLength+2);
401             memcpy(certBuffer, header, certLength);
402             certBuffer[certLength] = '\0';
403
404             result = install_pem_file_format_to_store(storeType, certBuffer, certLength, alias, \
405                                                       path, private_key_gname, associated_gname, decideCert);
406             if (result != CERTSVC_SUCCESS) {
407                 result = CERTSVC_FAIL;
408                 SLOGE("Fail to install certificate[%s]", path);
409             }
410         }
411     }
412     else {
413         SLOGE("Invalid file type passed.");
414         result = CERT_SVC_ERR_INVALID_CERTIFICATE;
415     }
416
417 error:
418     if (certBuffer)
419         free(certBuffer);
420     if (fileContent)
421         free(fileContent);
422     return result;
423 }
424
425 int handle_crt_pem_file_installation(CertStoreType storeType, const char *path, const char *alias)
426 {
427     int result = CERTSVC_SUCCESS;
428
429     if ((strstr(path, ".crt")) != NULL || (strstr(path, ".pem")) != NULL) {
430         SLOGD("certificate extention is .crt/.pem file");
431
432         /* Installs CRT and PEM files. We will passing NULL for private_key_gname and associated_gname parameter in
433          * install_crt_file(). Which means that there is no private key involved in the certificate which we are
434          * installing and there are no other certificates related with the current certificate which is installed */
435         result = install_crt_file(path, storeType, alias, NULL, NULL, PEM_CRT);
436         if (result != CERTSVC_SUCCESS) {
437             SLOGE("Failed to install the certificate.");
438             result = CERTSVC_FAIL;
439             goto error;
440         }
441     }
442     else {
443         SLOGE("Invalid certificate passed.");
444         result = CERTSVC_FAIL;
445         goto error;
446     }
447     SLOGD("Success to install the certificate.");
448
449 error:
450     return result;
451 }
452
453 int verify_cert_details(X509** cert, STACK_OF(X509) **certv)
454 {
455     int result = CERTSVC_SUCCESS;
456     char* pSubject = NULL;
457     char* pIssuerName = NULL;
458     X509_STORE_CTX *cert_ctx = NULL;
459     X509_STORE *cert_store = NULL;
460     int res = 0;
461
462 #ifdef _CERT_SVC_VERIFY_PKCS12
463     if (*certv == NULL) {
464         pSubject = X509_NAME_oneline((*cert)->cert_info->subject, NULL, 0);
465         if (!pSubject) {
466             SLOGE("Failed to get subject name");
467             result = CERTSVC_FAIL;
468             goto free_memory;
469         }
470
471         pIssuerName = X509_NAME_oneline((*cert)->cert_info->issuer, NULL, 0);
472         if (!pIssuerName) {
473             SLOGE("Failed to get issuer name");
474             result = CERTSVC_FAIL;
475             goto free_memory;
476         }
477
478         if (strcmp((const char*)pSubject, (const char*)pIssuerName) == 0) {
479             /*self signed.. */
480             EVP_PKEY* pKey = NULL;
481             pKey = X509_get_pubkey(*cert);
482             if (!pKey) {
483                 SLOGE("Failed to get public key");
484                 result = CERTSVC_FAIL;
485                 goto free_memory;
486             }
487
488             if (X509_verify(*cert, pKey) <= 0) {
489                 SLOGE("P12 verification failed");
490                 EVP_PKEY_free(pKey);
491                 result = CERTSVC_FAIL;
492                 goto free_memory;
493             }
494             SLOGD("P12 verification Success");
495             EVP_PKEY_free(pKey);
496         }
497         else {
498             cert_store = X509_STORE_new();
499             if (!cert_store) {
500                 SLOGE("Memory allocation failed");
501                 result = CERTSVC_FAIL;
502                 goto free_memory;
503             }
504
505             res = X509_STORE_load_locations(cert_store, NULL, "/opt/etc/ssl/certs/");
506             if (res != 1) {
507                 SLOGE("P12 load certificate store failed");
508                 X509_STORE_free(cert_store);
509                 result = CERTSVC_FAIL;
510                 goto free_memory;
511             }
512
513             res = X509_STORE_set_default_paths(cert_store);
514             if (res != 1) {
515                 SLOGE("P12 load certificate store path failed");
516                 X509_STORE_free(cert_store);
517                 result = CERTSVC_FAIL;
518                 goto free_memory;
519             }
520
521             /* initialise store and store context */
522             cert_ctx = X509_STORE_CTX_new();
523             if (cert_ctx == NULL) {
524                 SLOGE("Memory allocation failed");
525                 result = CERTSVC_FAIL;
526                 goto free_memory;
527             }
528
529             /* construct store context */
530             if (!X509_STORE_CTX_init(cert_ctx, cert_store, *cert, NULL)) {
531                 SLOGE("Memory allocation failed");
532                 result = CERTSVC_FAIL;
533                 goto free_memory;
534             }
535
536 #ifdef P12_VERIFICATION_NEEDED
537             res = X509_verify_cert(cert_ctx);
538             if (res != 1) {
539                 SLOGE("P12 verification failed");
540                 result = CERTSVC_FAIL;
541                 goto free_memory;
542             }
543             SLOGD("P12 verification Success");
544 #endif
545         }
546     }
547     else if (*certv != NULL) {
548         /* Cert Chain */
549         cert_store = X509_STORE_new();
550         if (!cert_store) {
551             SLOGE("Memory allocation failed");
552             result = CERTSVC_FAIL;
553             goto free_memory;
554         }
555
556         res = X509_STORE_load_locations(cert_store, NULL, CERTSVC_SSL_CERTS_DIR);
557         if (res != 1) {
558             SLOGE("P12 load certificate store failed");
559             result = CERTSVC_FAIL;
560             goto free_memory;
561         }
562
563         res = X509_STORE_set_default_paths(cert_store);
564         if (res != 1) {
565             SLOGE("P12 load certificate path failed");
566             result = CERTSVC_FAIL;
567             goto free_memory;
568         }
569
570         /* initialise store and store context */
571         cert_ctx = X509_STORE_CTX_new();
572         if (cert_ctx == NULL) {
573             SLOGE("Memory allocation failed");
574             result = CERTSVC_FAIL;
575             goto free_memory;
576         }
577
578         /* construct store context */
579         if (!X509_STORE_CTX_init(cert_ctx, cert_store, *cert, NULL)) {
580             SLOGE("Memory allocation failed");
581             result = CERTSVC_FAIL;
582             goto free_memory;
583         }
584
585         X509_STORE_CTX_trusted_stack(cert_ctx, *certv);
586 #ifdef P12_VERIFICATION_NEEDED
587         res = X509_verify_cert(cert_ctx);
588         if (res != 1) {
589             SLOGE("P12 verification failed");
590             result = CERTSVC_FAIL;
591             goto free_memory;
592         }
593         SLOGD("P12 verification Success");
594 #endif
595     }
596 #endif //_CERT_SVC_VERIFY_PKCS12
597
598 free_memory:
599     if (pSubject != NULL) { free(pSubject); }
600     if (pIssuerName != NULL) { free(pIssuerName); }
601     if (cert_store != NULL) { X509_STORE_free(cert_store); }
602     if (cert_ctx) { X509_STORE_CTX_free(cert_ctx); }
603     return result;
604 }
605
606 int c_certsvc_pkcs12_import_from_file_to_store(CertStoreType storeTypes, const char *path, const char *password, const char *alias)
607 {
608     int result = CERTSVC_SUCCESS;
609     int readLen = 0;
610     int tmpLen = 0;
611     int wr_res;
612     size_t nicerts = 0, i = 0, n = 0, ncerts = 0;
613     CertStoreType storeType = NONE_STORE;
614     FILE* stream = NULL;
615     PKCS12* container = NULL;
616     EVP_PKEY* key = NULL;
617     X509* cert = NULL;
618     STACK_OF(X509) *certv = NULL;
619     char* bare = NULL;
620     char* pkvalue = NULL;
621     char** cvaluev = NULL;
622     char **certs = NULL;
623     char* tmpPkValue = NULL;
624     char* unique = NULL;
625     char fileBuffer[4096] = {0,};
626     int loopCount = 0;
627     CertType decideCert = INVALID_DATA;
628     int exists = 0;
629
630     if ((!alias) || (strlen(alias) < 1) || (!path) || (strlen(path) < 1)) {
631         SLOGE("Invalid input parameter.");
632                 SLOG(LOG_INFO, "MDM_LOG_USER", "Object=certificate, AccessType=Install, Result=Failed");
633         return CERTSVC_WRONG_ARGUMENT;
634     }
635
636     while(1) {
637         /* Iteration only possible from VPN_STORE till SYSTEM_STORE */
638         if (loopCount == (MAX_STORE_ENUMS-1)) break;
639
640         /* User should not install any form of certificates inside SYSTEM_STORE */
641         if (((1 << loopCount) & storeTypes) == SYSTEM_STORE) {
642             SLOGE("Not a valid store type installing certificate, store type passed [%d].", (1 << loopCount));
643                         SLOG(LOG_INFO, "MDM_LOG_USER", "Object=certificate, AccessType=Install, Result=Failed");
644             return CERTSVC_INVALID_STORE_TYPE;
645         }
646
647         /* Iterating over all the stores */
648         if ((1 << loopCount) & storeTypes) {
649             storeType = NONE_STORE;
650             storeType = (CertStoreType) (1 << loopCount);
651             SLOGD("Processing store type : [%s]", (storeType == VPN_STORE)? "VPN" : (storeType == WIFI_STORE)? "WIFI" : "EMAIL");
652
653             /* check if the alias exists before installing certificate */
654             result = c_certsvc_pkcs12_alias_exists_in_store(storeType, alias, &exists);
655             if (result != CERTSVC_SUCCESS) {
656                 SLOGE("Failure to access database.");
657                 result = CERTSVC_FAIL;
658                 goto error;
659             }
660
661             if (exists!=CERTSVC_TRUE) {
662                 SLOGE("Alias exist in store [%s].", (storeType == VPN_STORE)? "VPN" : (storeType == WIFI_STORE)? "WIFI" : "EMAIL");
663                 result = CERTSVC_DUPLICATED_ALIAS;
664                 goto error;
665             }
666
667             /* Logic for handling crt/pem cert installation */
668             /* Check if the input file is a PEM/CRT, since a PFX cert can also be opened without a password */
669             if (password == NULL && ((strstr(path, ".pfx") == NULL) || (strstr(path, ".p12")))) {
670                 result = handle_crt_pem_file_installation(storeType, path, alias);
671                 if (result != CERTSVC_SUCCESS) {
672                     SLOGE("Failed to install PEM/CRT file to store.");
673                     result = CERTSVC_FAIL;
674                 }
675                 loopCount++;
676                 continue;
677             }
678
679             /* Logic for handling .pfx/.p12 cert installation */
680             if ((stream = fopen(path, "rb")) == NULL) {
681                 SLOGE("Unable to open the file for reading [%s].", path);
682                 result = CERTSVC_IO_ERROR;
683                 goto error;
684             }
685
686             if (container == NULL) {
687                 container = d2i_PKCS12_fp(stream, NULL);
688                 fclose(stream);
689                 if (container == NULL) {
690                     SLOGE("Failed to parse the input file passed.");
691                     result = CERTSVC_FAIL;
692                     goto error;
693                 }
694             }
695
696             /* To ensure when the code re-enters, we should clean up */
697             if (key==NULL && cert==NULL && certv==NULL) {
698                 result = PKCS12_parse(container, password, &key, &cert, &certv);
699                 PKCS12_free(container);
700                 if (result == CERTSVC_FAIL) {
701                     SLOGE("Failed to parse the file passed.");
702                     result = CERTSVC_FAIL;
703                     goto error;
704                 }
705
706                 result = verify_cert_details(&cert, &certv);
707                 if (result == CERTSVC_FAIL) {
708                     SLOGE("Failed to verify p12 certificate.");
709                     goto error;
710                 }
711             }
712
713             if (certv) {
714                 int tempCertNum = sk_X509_num(certv);
715                 if (tempCertNum < 0)
716                     nicerts = 0;
717                 else
718                     nicerts = static_cast<size_t>(tempCertNum);
719             } else {
720                 nicerts = 0;
721             }
722
723             if (cvaluev != NULL) {
724                 for (i = 0; i < n; i++)
725                     free(cvaluev[i]);
726                 if (cvaluev) free(cvaluev);
727                     cvaluev = NULL;
728             }
729
730             cvaluev = (char **)calloc(1 + nicerts, sizeof(char *));
731             if (unique != NULL) { free(unique); unique = NULL; }
732             result = unique_filename(&unique);
733             if (result != CERTSVC_SUCCESS || !unique) {
734                 SLOGE("Unique filename generation failed.");
735                 goto error;
736             }
737
738             if ((stream = fopen(unique, "w+")) == NULL) {
739                 SLOGE("Unable to open the file for writing [%s].",unique);
740                 result = CERTSVC_IO_ERROR;
741                 goto error;
742             }
743
744             result = PEM_write_PrivateKey(stream, key, NULL, NULL, 0, NULL, NULL);
745             if (result == 0) {
746                 SLOGE("Writing the private key contents failed.");
747                 result = CERTSVC_FAIL;
748                 fclose(stream);
749                 goto error;
750             }
751
752             fseek(stream, 0, SEEK_SET);
753             memset(fileBuffer, 0, (sizeof(char)*4096));
754             readLen=0;
755             readLen = fread(fileBuffer, sizeof(char), 4096, stream);
756             fclose(stream);
757             if (readLen <= 0){
758                                 SLOGE("Failed to read key file");
759                 result = CERTSVC_FAIL;
760                 goto error;
761             }
762
763             bare = bare_filename(unique);
764             if (bare) {
765                 pkvalue = strdup(bare);
766                 tmpLen = strlen((const char*)pkvalue);
767                 tmpPkValue = (char*)malloc(sizeof(char) * (tmpLen + 1));
768                 memset(tmpPkValue, 0x00, tmpLen+1);
769                 memcpy(tmpPkValue, pkvalue, tmpLen);
770             }
771
772             decideCert = P12_PKEY;
773             result = vcore_client_install_certificate_to_store(storeType, tmpPkValue, NULL, NULL, NULL, fileBuffer, readLen, decideCert);
774             if (result != CERTSVC_SUCCESS) {
775                 SLOGD("Failed to store the private key contents.");
776                 result = CERTSVC_FAIL;
777                 goto error;
778             }
779
780             unlink(unique);
781             if (unique!=NULL) { free(unique); unique=NULL; }
782             result = unique_filename(&unique);
783             if (result != CERTSVC_SUCCESS || !unique) {
784                 SLOGE("Unique filename generation failed.");
785                 goto error;
786             }
787
788             if ((stream = fopen(unique, "w")) == NULL) {
789                 SLOGE("Unable to open the file for writing [%s].", unique);
790                 result = CERTSVC_IO_ERROR;
791                 goto error;
792             }
793
794             result = PEM_write_X509(stream, cert);
795             fclose(stream);
796             if (result == 0) {
797                 SLOGE("Failed to write contents to file.");
798                 result = CERTSVC_FAIL;
799                 goto error;
800             }
801
802             n = 0;
803             bare = bare_filename(unique);
804             if (bare)
805                 cvaluev[n++] = strdup(bare);
806
807             decideCert = P12_END_USER;
808             wr_res = install_crt_file(unique, storeType, alias, tmpPkValue, NULL, decideCert);
809             if (wr_res != CERTSVC_SUCCESS) {
810                 result = CERTSVC_FAIL;
811                 SLOGE("Failed to install the end user certificate.");
812                 goto error;
813             }
814
815             unlink(unique);
816             for (i=nicerts; i>0; i--) {
817                  result = unique_filename(&unique);
818                  if (result != CERTSVC_SUCCESS || !unique) {
819                      SLOGE("Unique filename generation failed.");
820                      goto error;
821                  }
822
823                  if ((stream = fopen(unique, "w")) == NULL) {
824                       result = CERTSVC_IO_ERROR;
825                       SLOGE("Unable to open the file for writing.");
826                       goto error;
827                  }
828
829                  result = PEM_write_X509_AUX(stream, sk_X509_value(certv, i-1));
830                  fclose(stream);
831                  if (result == 0) {
832                      result = CERTSVC_FAIL;
833                      SLOGE("Unable to extract the certificates.");
834                      goto error;
835                  }
836
837                  if (i==nicerts)
838                      decideCert = P12_INTERMEDIATE;
839                  else
840                      decideCert = P12_TRUSTED;
841                  wr_res = install_crt_file(unique, storeType, alias, NULL, cvaluev[0], decideCert);
842                  if (wr_res != CERTSVC_SUCCESS) {
843                      result = CERTSVC_FAIL;
844                      goto error;
845                  }
846
847                  unlink(unique);
848                  bare = bare_filename(unique);
849                  if (bare)
850                      cvaluev[n++] = strdup(bare);
851             }
852         }
853         loopCount++;
854     }
855
856 error:
857     /* if any certificate parsing/installation fails in middle,
858      * the below logic will delete the chain installed in DB */
859     if (result != CERTSVC_SUCCESS) {
860                 SLOG(LOG_INFO, "MDM_LOG_USER", "Object=certificate, AccessType=Install, Result=Failed");
861         if (nicerts > 0) {
862                 nicerts = 0; i = 0;
863                 /* cvaluev[0] holds the end user certificate identifier which will be associated
864                  * to chain certs. Pull the cert chain based on end user cert and delete one by one. */
865             if (c_certsvc_pkcs12_load_certificates_from_store(storeType, cvaluev[0], &certs, &ncerts) != CERTSVC_SUCCESS) {
866                 SLOGE("Unable to load certificates from store.");
867                 return result;
868             }
869
870             for (i=0; i<ncerts; i++) {
871                  if (certs[i] != NULL) {
872                      SLOGD("file to delete : %s",certs[i]);
873                      c_certsvc_pkcs12_delete_certificate_from_store(storeType, (char *)certs[i]);
874                  }
875             }
876
877             if (certs[i] != NULL) {
878                 for (i=0; i<ncerts; i++)
879                      free(certs[i]);
880             }
881         }
882     }
883         else
884                 SLOG(LOG_INFO, "MDM_LOG_USER", "Object=certificate, AccessType=Install, Result=Succeed");
885
886     if (key != NULL) EVP_PKEY_free(key);
887     if (cert != NULL) X509_free(cert);
888     if (certv != NULL) sk_X509_free(certv);
889     if (pkvalue != NULL) free(pkvalue);
890     if (tmpPkValue != NULL) free(tmpPkValue);
891     if (unique != NULL) free(unique);
892     return result;
893 }
894
895 int c_certsvc_pkcs12_has_password(const char *filepath, int *passworded)
896 {
897   FILE *stream;
898   EVP_PKEY *pkey;
899   X509 *cert;
900   PKCS12 *container;
901   int result;
902
903   if(passworded == NULL)
904     return CERTSVC_WRONG_ARGUMENT;
905   if((stream = fopen(filepath, "rb")) == NULL)
906     return CERTSVC_IO_ERROR;
907   container = d2i_PKCS12_fp(stream, NULL);
908   fclose(stream);
909   if(container == NULL)
910     return CERTSVC_FAIL;
911   result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
912   PKCS12_free(container);
913   if(result == 1) {
914     EVP_PKEY_free(pkey);
915     X509_free(cert);
916     *passworded = 0;
917     return CERTSVC_SUCCESS;
918   }
919   else {
920     if(ERR_GET_REASON(ERR_peek_last_error()) == PKCS12_R_MAC_VERIFY_FAILURE) {
921       *passworded = 1;
922       return CERTSVC_SUCCESS;
923     }
924     else
925       return CERTSVC_FAIL;
926   }
927 }
928
929 void c_certsvc_pkcs12_free_certificates(char **certs)
930 {
931   size_t i = 0;
932   if (!certs)
933     return;
934   while (certs[i])
935     free(certs[i++]);
936   free(certs);
937 }