Introduce certsvc_pkcs12_import_from_file_to_store_ret_list()
[platform/core/security/cert-svc.git] / src / vcore / pkcs12.cpp
1 /**
2  * Copyright (c) 2016 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
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <limits.h>
31 #include <string>
32 #include <memory>
33 #include <functional>
34
35 #include <openssl/err.h>
36 #include <openssl/pkcs12.h>
37 #include <openssl/sha.h>
38 #include <openssl/x509.h>
39 #include <openssl/pem.h>
40
41 #include "dpl/log/log.h"
42 #include "cert-svc/cerror.h"
43
44 #include "vcore/Certificate.h"
45 #include "vcore/Client.h"
46 #include "vcore/pkcs12.h"
47
48 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
49
50 namespace {
51
52 static const std::string START_CERT    = "-----BEGIN CERTIFICATE-----";
53 static const std::string END_CERT      = "-----END CERTIFICATE-----";
54 static const std::string START_TRUSTED = "-----BEGIN TRUSTED CERTIFICATE-----";
55 static const std::string END_TRUSTED   = "-----END TRUSTED CERTIFICATE-----";
56 static const std::string START_KEY     = "-----BEGIN PRIVATE KEY-----";
57 static const std::string END_KEY       = "-----END PRIVATE KEY-----";
58
59 using ValidationCore::CertificatePtr;
60 using ValidationCore::Certificate;
61
62 using FileUniquePtr      = std::unique_ptr<FILE, std::function<int(FILE *)>>;
63 using BioUniquePtr       = std::unique_ptr<BIO, std::function<void(BIO *)>>;
64 using PKEYUniquePtr      = std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY *)>>;
65 using X509UniquePtr      = std::unique_ptr<X509, std::function<void(X509 *)>>;
66 using X509StackUniquePtr = std::unique_ptr<STACK_OF(X509), std::function<void(STACK_OF(X509) *)>>;
67
68 void X509_stack_free(STACK_OF(X509) *stack)
69 {
70         sk_X509_free(stack);
71 }
72
73 inline bool hasStore(CertStoreType types, CertStoreType type)
74 {
75         return (types & type) != 0;
76 }
77
78 inline CertStoreType nextStore(CertStoreType type)
79 {
80         switch (type) {
81         case NONE_STORE:
82                 return VPN_STORE;
83
84         case VPN_STORE:
85                 return WIFI_STORE;
86
87         case WIFI_STORE:
88                 return EMAIL_STORE;
89
90         case EMAIL_STORE:
91                 return SYSTEM_STORE;
92
93         case SYSTEM_STORE:
94                 return NONE_STORE;
95
96         default:
97                 return NONE_STORE;
98         }
99 }
100
101 CertSvcStoreCertList *createStoreListNode(const std::string &gname, const std::string &title,
102                                                                                   CertStoreType storeType)
103 {
104         CertSvcStoreCertList *node = (CertSvcStoreCertList *)malloc(sizeof(CertSvcStoreCertList));
105
106         if (node == NULL)
107                 return NULL;
108
109         node->gname = strdup(gname.c_str());
110         node->title = strdup(title.c_str());
111         node->status = ENABLED;
112         node->storeType = storeType;
113         node->next = NULL;
114
115         if (node->gname == NULL || node->title == NULL) {
116                 free(node->gname);
117                 free(node->title);
118                 free(node);
119                 return NULL;
120         }
121
122         return node;
123 }
124
125 void destroyStoreList(CertSvcStoreCertList **certList, size_t *length)
126 {
127         if (certList == NULL || length == NULL) {
128                 return;
129         }
130
131         CertSvcStoreCertList *list = *certList;
132
133         while (list) {
134                 CertSvcStoreCertList *next = list->next;
135                 free(list->gname);
136                 free(list->title);
137                 free(list);
138                 list = next;
139         }
140
141         *length = 0;
142 }
143
144 void addStoreListNode(CertSvcStoreCertList **list, CertSvcStoreCertList *node)
145 {
146         node->next = *list;
147         *list = node;
148 }
149
150 int appendStoreListNode(CertSvcStoreCertList **certList, size_t *length,
151                                                  const std::string &gname, const std::string &alias,
152                                                  CertStoreType storeType)
153 {
154         if (certList == NULL || length == NULL)
155                 return CERTSVC_SUCCESS;
156
157         CertSvcStoreCertList *node = createStoreListNode(gname, alias, storeType);
158         if (node == NULL) {
159                 return CERTSVC_BAD_ALLOC;
160         }
161
162         addStoreListNode(certList, node);
163         (*length)++;
164
165         return CERTSVC_SUCCESS;
166 }
167
168 std::string generateGname(void)
169 {
170         int generator;
171         int64_t random;
172         SHA_CTX ctx;
173         unsigned char d[SHA_DIGEST_LENGTH];
174         int result;
175         char *gname = NULL;
176         SYSCALL(generator = open("/dev/urandom", O_RDONLY));
177
178         if (generator == -1)
179                 return std::string();
180
181         SYSCALL(result = read(generator, &random, sizeof(random)));
182
183         if (result == -1) {
184                 SYSCALL(close(generator));
185                 return std::string();
186         }
187
188         SYSCALL(result = close(generator));
189
190         if (result == -1)
191                 return std::string();
192
193         SHA1_Init(&ctx);
194         SHA1_Update(&ctx, &random, sizeof(random));
195         SHA1_Final(d, &ctx);
196         result = asprintf(&gname,
197                                           "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
198                                           "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
199                                           d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9],
200                                           d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19]);
201
202         if (result == -1)
203                 return std::string();
204
205         std::string ret(gname);
206         free(gname);
207         return ret;
208 }
209
210 std::string getCommonName(CertType type, const std::string &cert)
211 {
212         BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
213
214         if (bio.get() == NULL) {
215                 LogError("Failed to allocate memory.");
216                 return std::string();
217         }
218
219         auto readCount = BIO_write(bio.get(), (const void *)cert.data(), (int)cert.length());
220
221         if (readCount < 1) {
222                 LogError("Failed to load cert into bio.");
223                 return std::string();
224         }
225
226         X509 *x509 = NULL;
227
228         switch (type) {
229         case P12_TRUSTED:
230         case P12_INTERMEDIATE:
231                 x509 = PEM_read_bio_X509_AUX(bio.get(), NULL, 0, NULL);
232                 break;
233
234         default:
235                 x509 = PEM_read_bio_X509(bio.get(), NULL, 0, NULL);
236                 break;
237         }
238
239         if (x509 == NULL) {
240                 LogError("Failed to create x509 structure.");
241                 return std::string();
242         }
243
244         X509UniquePtr x509Ptr(x509, X509_free);
245         const char *subject_c = X509_NAME_oneline(x509->cert_info->subject, NULL, 0);
246
247         if (subject_c == NULL) {
248                 LogError("Failed to parse x509 structure");
249                 return std::string();
250         }
251
252         return std::string(subject_c);
253 }
254
255 /*
256  *  column           / common name / associated gname / prikey gname /
257  *  PEM_CRT          : common name / gname            / none         /
258  *  P12_END_USER     : alias       / gname            / prikey gname /
259  *  P12_TRUSTED      : common name / end cert gname   / none         /
260  *  P12_INTERMEDIATE : common name / end cert gname   / none         /
261  */
262
263 int installPKEY(CertStoreType storeType,
264                                 const std::string &key,
265                                 const std::string &gname)
266 {
267         return vcore_client_install_certificate_to_store(
268                            storeType,
269                            gname.c_str(),
270                            NULL,
271                            NULL,
272                            NULL,
273                            key.c_str(),
274                            key.length(),
275                            P12_PKEY);
276 }
277
278 int installEndCert(CertStoreType storeType,
279                                    const std::string &cert,
280                                    const std::string &alias,
281                                    const std::string &gname,
282                                    const std::string &prikeyGname)
283 {
284         return vcore_client_install_certificate_to_store(
285                            storeType,
286                            gname.c_str(),
287                            alias.c_str(),
288                            prikeyGname.c_str(),
289                            gname.c_str(),
290                            cert.c_str(),
291                            cert.length(),
292                            P12_END_USER);
293 }
294
295 int installChainCert(CertStoreType storeType,
296                                          const std::string &cert,
297                                          const std::string &gname,
298                                          const std::string &endCertGname,
299                                          CertType type)
300 {
301         std::string commonName = getCommonName(type, cert);
302         return vcore_client_install_certificate_to_store(
303                            storeType,
304                            gname.c_str(),
305                            commonName.c_str(),
306                            NULL,
307                            endCertGname.c_str(),
308                            cert.c_str(),
309                            cert.length(),
310                            type);
311 }
312 int installCert(CertStoreType storeType,
313                                 const std::string &cert,
314                                 const std::string &gname,
315                                 const std::string &alias)
316 {
317         return vcore_client_install_certificate_to_store(
318                            storeType,
319                            gname.c_str(),
320                            alias.c_str(),
321                            NULL,
322                            NULL,
323                            cert.c_str(),
324                            cert.length(),
325                            PEM_CRT);
326 }
327
328 std::string readFromFile(const std::string &path)
329 {
330         FILE *fp = NULL;
331
332         if ((fp = fopen(path.c_str(), "rb")) == NULL) {
333                 LogError("Fail to open file for reading : " << path);
334                 return std::string();
335         }
336
337         FileUniquePtr filePtr(fp, fclose);
338         fseek(fp, 0L, SEEK_END);
339         int len = ftell(fp);
340
341         if (len <= 0 || len == INT_MAX) {
342                 LogError("Fail to get proper certificate.");
343                 return std::string();
344         }
345
346         rewind(fp);
347         char *content = (char *)malloc(sizeof(char) * (len + 1));
348
349         if (content == NULL) {
350                 LogError("Fail to allocate memory");
351                 return std::string();
352         }
353
354         memset(content, 0x00, len + 1);
355         size_t readLen = fread(content, sizeof(char), (size_t)len, fp);
356
357         if (readLen != (size_t)len) {
358                 LogError("Fail to read file : " << path);
359                 free(content);
360                 return std::string();
361         }
362
363         content[len] = '\0';
364         std::string ret(content);
365         free(content);
366         return ret;
367 }
368
369 std::string parseCRT(const std::string &cert)
370 {
371         size_t from = 0;
372         size_t to = 0;
373         size_t tailLen = 0;
374         from = cert.find(START_CERT);
375         to = cert.find(END_CERT);
376         tailLen = END_CERT.length();
377
378         if (from == std::string::npos || to == std::string::npos || from > to) {
379                 from = cert.find(START_TRUSTED);
380                 to = cert.find(END_TRUSTED);
381                 tailLen = END_TRUSTED.length();
382         }
383
384         if (from == std::string::npos || to == std::string::npos || from > to)
385                 return std::string();
386
387         return std::string(cert, from, to - from + tailLen);
388 }
389
390 #define _CERT_SVC_VERIFY_PKCS12
391 int verify_cert_details(X509 *cert, STACK_OF(X509) *certv)
392 {
393         int result = CERTSVC_SUCCESS;
394         char *pSubject = NULL;
395         char *pIssuerName = NULL;
396         X509_STORE_CTX *cert_ctx = NULL;
397         X509_STORE *cert_store = NULL;
398         int res = 0;
399 #ifdef _CERT_SVC_VERIFY_PKCS12
400
401         if (certv == NULL) {
402                 pSubject = X509_NAME_oneline(cert->cert_info->subject, NULL, 0);
403
404                 if (!pSubject) {
405                         LogError("Failed to get subject name");
406                         result = CERTSVC_FAIL;
407                         goto free_memory;
408                 }
409
410                 pIssuerName = X509_NAME_oneline(cert->cert_info->issuer, NULL, 0);
411
412                 if (!pIssuerName) {
413                         LogError("Failed to get issuer name");
414                         result = CERTSVC_FAIL;
415                         goto free_memory;
416                 }
417
418                 if (strcmp((const char *)pSubject, (const char *)pIssuerName) == 0) {
419                         /*self signed.. */
420                         EVP_PKEY *pKey = NULL;
421                         pKey = X509_get_pubkey(cert);
422
423                         if (!pKey) {
424                                 LogError("Failed to get public key");
425                                 result = CERTSVC_FAIL;
426                                 goto free_memory;
427                         }
428
429                         if (X509_verify(cert, pKey) <= 0) {
430                                 LogError("P12 verification failed");
431                                 EVP_PKEY_free(pKey);
432                                 result = CERTSVC_FAIL;
433                                 goto free_memory;
434                         }
435
436                         LogDebug("P12 verification Success");
437                         EVP_PKEY_free(pKey);
438                 } else {
439                         cert_store = X509_STORE_new();
440
441                         if (!cert_store) {
442                                 LogError("Memory allocation failed");
443                                 result = CERTSVC_FAIL;
444                                 goto free_memory;
445                         }
446
447                         res = X509_STORE_load_locations(cert_store, NULL, TZ_SYS_CA_CERTS);
448
449                         if (res != 1) {
450                                 LogError("P12 load certificate store failed");
451                                 X509_STORE_free(cert_store);
452                                 result = CERTSVC_FAIL;
453                                 goto free_memory;
454                         }
455
456                         res = X509_STORE_set_default_paths(cert_store);
457
458                         if (res != 1) {
459                                 LogError("P12 load certificate store path failed");
460                                 X509_STORE_free(cert_store);
461                                 result = CERTSVC_FAIL;
462                                 goto free_memory;
463                         }
464
465                         /* initialise store and store context */
466                         cert_ctx = X509_STORE_CTX_new();
467
468                         if (cert_ctx == NULL) {
469                                 LogError("Memory allocation failed");
470                                 result = CERTSVC_FAIL;
471                                 goto free_memory;
472                         }
473
474                         /* construct store context */
475                         if (!X509_STORE_CTX_init(cert_ctx, cert_store, cert, NULL)) {
476                                 LogError("Memory allocation failed");
477                                 result = CERTSVC_FAIL;
478                                 goto free_memory;
479                         }
480
481 #ifdef P12_VERIFICATION_NEEDED
482                         res = X509_verify_cert(cert_ctx);
483
484                         if (res != 1) {
485                                 LogError("P12 verification failed");
486                                 result = CERTSVC_FAIL;
487                                 goto free_memory;
488                         }
489
490                         LogDebug("P12 verification Success");
491 #endif
492                 }
493         } else if (certv != NULL) {
494                 /* Cert Chain */
495                 cert_store = X509_STORE_new();
496
497                 if (!cert_store) {
498                         LogError("Memory allocation failed");
499                         result = CERTSVC_FAIL;
500                         goto free_memory;
501                 }
502
503                 res = X509_STORE_load_locations(cert_store, NULL, TZ_SYS_CA_CERTS);
504
505                 if (res != 1) {
506                         LogError("P12 load certificate store failed");
507                         result = CERTSVC_FAIL;
508                         goto free_memory;
509                 }
510
511                 res = X509_STORE_set_default_paths(cert_store);
512
513                 if (res != 1) {
514                         LogError("P12 load certificate path failed");
515                         result = CERTSVC_FAIL;
516                         goto free_memory;
517                 }
518
519                 /* initialise store and store context */
520                 cert_ctx = X509_STORE_CTX_new();
521
522                 if (cert_ctx == NULL) {
523                         LogError("Memory allocation failed");
524                         result = CERTSVC_FAIL;
525                         goto free_memory;
526                 }
527
528                 /* construct store context */
529                 if (!X509_STORE_CTX_init(cert_ctx, cert_store, cert, NULL)) {
530                         LogError("Memory allocation failed");
531                         result = CERTSVC_FAIL;
532                         goto free_memory;
533                 }
534
535                 X509_STORE_CTX_trusted_stack(cert_ctx, certv);
536 #ifdef P12_VERIFICATION_NEEDED
537                 res = X509_verify_cert(cert_ctx);
538
539                 if (res != 1) {
540                         LogError("P12 verification failed");
541                         result = CERTSVC_FAIL;
542                         goto free_memory;
543                 }
544
545                 LogDebug("P12 verification Success");
546 #endif
547         }
548
549 #endif //_CERT_SVC_VERIFY_PKCS12
550 free_memory:
551
552         if (cert_store != NULL)
553                 X509_STORE_free(cert_store);
554
555         if (cert_ctx)
556                 X509_STORE_CTX_free(cert_ctx);
557
558         free(pSubject);
559         free(pIssuerName);
560         return result;
561 }
562
563 enum class OsslType : int {
564         PKEY = 1,
565         X509,
566         X509AUX
567 };
568
569 std::string osslToPEM(OsslType type, void *data)
570 {
571         std::vector<char> buf(4096);
572         BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
573
574         if (bio.get() == NULL)
575                 return std::string();
576
577         switch (type) {
578         case OsslType::PKEY:
579                 PEM_write_bio_PrivateKey(bio.get(), static_cast<EVP_PKEY *>(data), NULL, NULL, 0, NULL, NULL);
580                 break;
581
582         case OsslType::X509:
583                 PEM_write_bio_X509(bio.get(), static_cast<X509 *>(data));
584                 break;
585
586         case OsslType::X509AUX:
587                 PEM_write_bio_X509_AUX(bio.get(), static_cast<X509 *>(data));
588                 break;
589
590         default:
591                 break;
592         }
593
594         int size = BIO_read(bio.get(), buf.data(), 4096);
595
596         if (size <= 0)
597                 return std::string();
598
599         buf[size] = '\0';
600         return std::string(buf.data());
601 }
602
603 int extractPkcs12(const std::string &path,
604                                   const std::string &password,
605                                   PKEYUniquePtr &keyPtr,
606                                   X509UniquePtr &certPtr,
607                                   X509StackUniquePtr &certvPtr)
608 {
609         FILE *stream = NULL;
610
611         if ((stream = fopen(path.c_str(), "rb")) == NULL) {
612                 LogError("Unable to open the file for reading : " << path);
613                 return CERTSVC_IO_ERROR;
614         }
615
616         PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
617         fclose(stream);
618
619         if (container == NULL) {
620                 LogError("Failed to parse the input file passed.");
621                 return CERTSVC_FAIL;
622         }
623
624         EVP_PKEY *key = NULL;
625         X509 *cert = NULL;
626         STACK_OF(X509) *certv = NULL;
627         int result = PKCS12_parse(container, password.c_str(), &key, &cert, &certv);
628         PKCS12_free(container);
629
630         if (result != 1) {
631                 unsigned long e = ERR_get_error();
632                 char buf[1024];
633                 ERR_error_string_n(e, buf, 1023);
634                 LogError("Failed to parse the file passed. openssl err: " << buf);
635                 return CERTSVC_FAIL;
636         }
637
638         keyPtr.reset(key);
639         certPtr.reset(cert);
640         certvPtr.reset(certv);
641         return CERTSVC_SUCCESS;
642 }
643
644 void rollbackStore(CertStoreType storeTypes, const std::string &endCertName)
645 {
646         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
647                         storeType = nextStore(storeType)) {
648                 if (!hasStore(storeTypes, storeType))
649                         continue;
650
651                 char **certChainName = NULL;
652                 size_t ncerts = 0;
653                 int result = vcore_client_load_certificates_from_store(storeType, endCertName.c_str(),
654                                          &certChainName, &ncerts);
655
656                 if (result != CERTSVC_SUCCESS) {
657                         LogError("Unable to load certificates from store. result : " << result);
658                         continue;
659                 }
660
661                 for (size_t i = 0; i < ncerts; i++) {
662                         if (certChainName[i] == NULL)
663                                 continue;
664
665                         vcore_client_delete_certificate_from_store(storeType, certChainName[i]);
666                         free(certChainName[i]);
667                 }
668
669                 vcore_client_delete_certificate_from_store(storeType, endCertName.c_str());
670         }
671 }
672
673 int insertToStore(CertStoreType storeTypes,
674                                   const std::string &alias,
675                                   const std::string &prikeyName,
676                                   const std::string &prikeyBuffer,
677                                   const std::string &endCertName,
678                                   const std::string &endCertBuffer,
679                                   const std::vector<std::string> &certChainName,
680                                   const std::vector<std::string> &certChainBuffer,
681                                   CertSvcStoreCertList **certList,
682                                   size_t *length)
683 {
684         size_t ncerts = certChainName.size();
685
686         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
687                         storeType = nextStore(storeType)) {
688                 if (!hasStore(storeTypes, storeType))
689                         continue;
690
691                 LogDebug("Processing store type : " << storeType);
692                 int result = installPKEY(storeType, prikeyBuffer, prikeyName);
693
694                 if (result != CERTSVC_SUCCESS) {
695                         LogError("Failed to store the private key contents. result : " << result);
696                         return result;
697                 }
698
699                 result = installEndCert(storeType, endCertBuffer, alias, endCertName, prikeyName);
700
701                 if (result != CERTSVC_SUCCESS) {
702                         LogError("Failed to install the end user certificate. result : " << result);
703                         return result;
704                 }
705
706                 int res = appendStoreListNode(certList, length, endCertName, alias, storeType);
707                 if (res != CERTSVC_SUCCESS) {
708                         LogError("Failed to append store list node.");
709                         return result;
710                 }
711
712                 for (size_t i = 0; i < ncerts; i++) {
713                         if (i == ncerts - 1)
714                                 result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName,
715                                                                                   P12_TRUSTED);
716                         else
717                                 result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName,
718                                                                                   P12_INTERMEDIATE);
719
720                         if (result != CERTSVC_SUCCESS) {
721                                 LogError("Failed to install the ca certificates. result : " << result);
722                                 return result;
723                         }
724
725                         int res = appendStoreListNode(certList, length, certChainName[i], alias, storeType);
726                         if (res != CERTSVC_SUCCESS) {
727                                 LogError("Failed to append store list node.");
728                                 return result;
729                         }
730                 }
731         }
732
733         LogDebug("Success to insert extracted pkcs12 data to db");
734         return CERTSVC_SUCCESS;
735 }
736
737 int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const std::string &gname,
738                                          const std::string &alias, CertSvcStoreCertList **certList, size_t *length)
739 {
740         std::string content = readFromFile(path);
741
742         if (content.empty()) {
743                 LogError("Failed to read the file : " << path);
744                 return CERTSVC_IO_ERROR;
745         }
746
747         std::string parsed = parseCRT(content);
748
749         if (parsed.empty()) {
750                 LogError("Failed to parse CRT : " << path);
751                 return CERTSVC_FAIL;
752         }
753
754         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
755                         storeType = nextStore(storeType)) {
756                 if (!hasStore(storeTypes, storeType))
757                         continue;
758
759                 int result = installCert(storeType, parsed, gname, alias);
760
761                 if (result != CERTSVC_SUCCESS) {
762                         LogError("Failed to install PEM/CRT to db store : " << storeType << " result : " << result);
763                         rollbackStore(storeTypes, gname);
764                         return result;
765                 }
766
767                 int res = appendStoreListNode(certList, length, gname, alias, storeType);
768                 if (res != CERTSVC_SUCCESS) {
769                         rollbackStore(storeTypes, gname);
770                         LogError("Failed to append store list node.");
771                         return result;
772                 }
773
774                 LogDebug("Success to install PEM/CRT to db store : " << storeType);
775         }
776
777         LogDebug("Success to install PEM/CRT to db stores : " << storeTypes);
778         return CERTSVC_SUCCESS;
779 }
780
781 } // namespace anonymous
782
783
784 int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
785                                                                          const char *_path,
786                                                                          const char *_password,
787                                                                          const char *_alias,
788                                                                          CertSvcStoreCertList **certList,
789                                                                          size_t *length)
790 {
791         int result = 0;
792
793         if (_alias == NULL || _path == NULL || strlen(_path) < 4) {
794                 LogError("Invalid input parameter.");
795                 return CERTSVC_WRONG_ARGUMENT;
796         }
797
798         std::string path(_path);
799         std::string alias(_alias);
800         std::string password;
801
802         if (_password != NULL)
803                 password = std::string(_password);
804
805         LogDebug("pkcs12_import_from_file_to_store start. path[" << path << "] password[" << password <<
806                          "] alias[" << alias << "]");
807
808         if (storeTypes & SYSTEM_STORE) {
809                 LogError("User should not install any form of certificates in SYSTEM_STORE.");
810                 return CERTSVC_INVALID_STORE_TYPE;
811         }
812
813         /*
814          * Installs CRT and PEM files.
815          * We will passing NULL for private_key_gname and associated_gname parameter
816          * in installFilePEM(). Which means that there is no private key involved
817          * in the certificate which we are installing and there are no other
818          * certificates related with the current certificate which is installed
819          */
820         std::string suffix = path.substr(path.length() - 4, 4);
821
822         if (strcasecmp(suffix.c_str(), ".pem") == 0 || strcasecmp(suffix.c_str(), ".crt") == 0) {
823                 std::string gnamePEM = generateGname();
824                 result = insertToStorePEM(storeTypes, path, gnamePEM, alias, certList, length);
825
826                 if (result != CERTSVC_SUCCESS) {
827                         destroyStoreList(certList, length);
828                         LogError("Failed to install PEM/CRT file to store. gname : " << gnamePEM << " result : " << result);
829                 }
830
831                 return result;;
832         }
833
834         LogDebug("Convert ossl type to string start");
835         /* 0. extract pkcs12 data from file */
836         PKEYUniquePtr key(nullptr, EVP_PKEY_free);
837         X509UniquePtr cert(nullptr, X509_free);
838         X509StackUniquePtr certv(nullptr, X509_stack_free);
839         result = extractPkcs12(path, password, key, cert, certv);
840
841         if (result != CERTSVC_SUCCESS) {
842                 LogError("Failed to extract pkcs12 file. result : " << result);
843                 return result;
844         }
845
846         LogDebug("extract pkcs12 to unique ptr success");
847         result = verify_cert_details(cert.get(), certv.get());
848
849         if (result != CERTSVC_SUCCESS) {
850                 LogError("Failed to verify p12 certificate. result : " << result);
851                 return result;
852         }
853
854         /* 1. handling private key */
855         std::string prikeyName = generateGname();
856         std::string prikeyBuffer = osslToPEM(OsslType::PKEY, key.get());
857
858         if (prikeyName.empty() || prikeyBuffer.empty()) {
859                 LogError("Failed to transform pkey to PEM. result : " << result);
860                 return CERTSVC_FAIL;
861         }
862
863         LogDebug("Convert pkey to string success");
864         /* 2. handling end user certificate */
865         std::string endCertName = generateGname();
866         std::string endCertBuffer = osslToPEM(OsslType::X509, cert.get());
867
868         if (endCertName.empty() || endCertBuffer.empty()) {
869                 LogError("Failed to transform x509 to PEM. result : " << result);
870                 return CERTSVC_FAIL;
871         }
872
873         LogDebug("Convert end cert to string success");
874         /* 3. handling certificate chain */
875         std::vector<std::string> certChainName;
876         std::vector<std::string> certChainBuffer;
877         int ncerts = certv ? sk_X509_num(certv.get()) : 0;
878
879         for (int i = 0; i < ncerts; i++) {
880                 std::string tempName = generateGname();
881                 std::string tempBuffer = osslToPEM(OsslType::X509AUX, sk_X509_value(certv.get(), i));
882
883                 if (tempName.empty() || tempBuffer.empty()) {
884                         LogError("Failed to transform x509 AUX to PEM");
885                         return CERTSVC_FAIL;
886                 }
887
888                 certChainName.push_back(std::move(tempName));
889                 certChainBuffer.push_back(std::move(tempBuffer));
890         }
891
892         LogDebug("Convert cert chain to string success");
893         /* 4. insert extracted pkcs12 data to db */
894         result = insertToStore(storeTypes,
895                                                    alias,
896                                                    prikeyName,
897                                                    prikeyBuffer,
898                                                    endCertName,
899                                                    endCertBuffer,
900                                                    certChainName,
901                                                    certChainBuffer,
902                                                    certList,
903                                                    length);
904
905         if (result != CERTSVC_SUCCESS) {
906                 destroyStoreList(certList, length);
907                 rollbackStore(storeTypes, endCertName);
908         }
909
910         LogDebug("Success to import pkcs12 to store");
911         return result;
912 }
913
914 int pkcs12_has_password(const char *filepath, int *passworded)
915 {
916         if (filepath == NULL || passworded == NULL)
917                 return CERTSVC_WRONG_ARGUMENT;
918
919         FILE *stream;
920
921         if ((stream = fopen(filepath, "rb")) == NULL)
922                 return CERTSVC_IO_ERROR;
923
924         PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
925         fclose(stream);
926
927         if (container == NULL)
928                 return CERTSVC_FAIL;
929
930         EVP_PKEY *pkey = NULL;
931         X509 *cert = NULL;
932         int result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
933         PKCS12_free(container);
934
935         if (pkey != NULL)
936                 EVP_PKEY_free(pkey);
937
938         if (cert != NULL)
939                 X509_free(cert);
940
941         if (result != 1) {
942                 unsigned long e = ERR_get_error();
943                 if (ERR_GET_REASON(e) == PKCS12_R_MAC_VERIFY_FAILURE) {
944                         LogInfo("verify failed without password. file(" << filepath << ") is password-protected.");
945                         *passworded = CERTSVC_TRUE;
946                 } else {
947                         char buf[1024];
948                         ERR_error_string_n(e, buf, 1023);
949                         LogError("Error on PKCS12_pasre file(" << filepath << "): " << buf);
950                         return CERTSVC_FAIL;
951                 }
952         } else {
953                 *passworded = CERTSVC_FALSE;
954         }
955
956         return CERTSVC_SUCCESS;
957 }