Add unit test cases for SignatureValidator
[platform/core/security/cert-svc.git] / src / vcore / pkcs12.cpp
1 /**
2  * Copyright (c) 2016 - 2020 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_get_subject_name(x509), 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                                          const std::string &commonName,
300                                          CertType type)
301 {
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         if (fseek(fp, 0L, SEEK_END) != 0) {
339                 LogError("Fail in fseek");
340                 return std::string();
341         }
342         int len = ftell(fp);
343
344         if (len <= 0 || len == INT_MAX) {
345                 LogError("Fail to get proper certificate.");
346                 return std::string();
347         }
348
349         rewind(fp);
350         char *content = (char *)malloc(sizeof(char) * (len + 1));
351
352         if (content == NULL) {
353                 LogError("Fail to allocate memory");
354                 return std::string();
355         }
356
357         memset(content, 0x00, len + 1);
358         size_t readLen = fread(content, sizeof(char), (size_t)len, fp);
359
360         if (readLen != (size_t)len) {
361                 LogError("Fail to read file : " << path);
362                 free(content);
363                 return std::string();
364         }
365
366         content[len] = '\0';
367         std::string ret(content);
368         free(content);
369         return ret;
370 }
371
372 std::string parseCRT(const std::string &cert)
373 {
374         size_t from = 0;
375         size_t to = 0;
376         size_t tailLen = 0;
377         from = cert.find(START_CERT);
378         to = cert.find(END_CERT);
379         tailLen = END_CERT.length();
380
381         if (from == std::string::npos || to == std::string::npos || from > to) {
382                 from = cert.find(START_TRUSTED);
383                 to = cert.find(END_TRUSTED);
384                 tailLen = END_TRUSTED.length();
385         }
386
387         if (from == std::string::npos || to == std::string::npos || from > to)
388                 return std::string();
389
390         return std::string(cert, from, to - from + tailLen);
391 }
392
393 #define _CERT_SVC_VERIFY_PKCS12
394 int verify_cert_details(X509 *cert, STACK_OF(X509) *certv)
395 {
396         int result = CERTSVC_SUCCESS;
397         char *pSubject = NULL;
398         char *pIssuerName = NULL;
399         X509_STORE_CTX *cert_ctx = NULL;
400         X509_STORE *cert_store = NULL;
401         int res = 0;
402 #ifdef _CERT_SVC_VERIFY_PKCS12
403
404         if (certv == NULL) {
405                 pSubject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
406
407                 if (!pSubject) {
408                         LogError("Failed to get subject name");
409                         result = CERTSVC_FAIL;
410                         goto free_memory;
411                 }
412
413                 pIssuerName = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
414
415                 if (!pIssuerName) {
416                         LogError("Failed to get issuer name");
417                         result = CERTSVC_FAIL;
418                         goto free_memory;
419                 }
420
421                 if (strcmp((const char *)pSubject, (const char *)pIssuerName) == 0) {
422                         /*self signed.. */
423                         EVP_PKEY *pKey = NULL;
424                         pKey = X509_get_pubkey(cert);
425
426                         if (!pKey) {
427                                 LogError("Failed to get public key");
428                                 result = CERTSVC_FAIL;
429                                 goto free_memory;
430                         }
431
432                         if (X509_verify(cert, pKey) <= 0) {
433                                 LogError("P12 verification failed");
434                                 EVP_PKEY_free(pKey);
435                                 result = CERTSVC_FAIL;
436                                 goto free_memory;
437                         }
438
439                         LogDebug("P12 verification Success");
440                         EVP_PKEY_free(pKey);
441                 } else {
442                         cert_store = X509_STORE_new();
443
444                         if (!cert_store) {
445                                 LogError("Memory allocation failed");
446                                 result = CERTSVC_FAIL;
447                                 goto free_memory;
448                         }
449
450                         res = X509_STORE_load_locations(cert_store, NULL, TZ_SYS_CA_CERTS);
451
452                         if (res != 1) {
453                                 LogError("P12 load certificate store failed");
454                                 result = CERTSVC_FAIL;
455                                 goto free_memory;
456                         }
457
458                         res = X509_STORE_set_default_paths(cert_store);
459
460                         if (res != 1) {
461                                 LogError("P12 load certificate store path failed");
462                                 result = CERTSVC_FAIL;
463                                 goto free_memory;
464                         }
465
466                         /* initialise store and store context */
467                         cert_ctx = X509_STORE_CTX_new();
468
469                         if (cert_ctx == NULL) {
470                                 LogError("Memory allocation failed");
471                                 result = CERTSVC_FAIL;
472                                 goto free_memory;
473                         }
474
475                         /* construct store context */
476                         if (!X509_STORE_CTX_init(cert_ctx, cert_store, cert, NULL)) {
477                                 LogError("Memory allocation failed");
478                                 result = CERTSVC_FAIL;
479                                 goto free_memory;
480                         }
481
482 #ifdef P12_VERIFICATION_NEEDED
483                         res = X509_verify_cert(cert_ctx);
484
485                         if (res != 1) {
486                                 LogError("P12 verification failed");
487                                 result = CERTSVC_FAIL;
488                                 goto free_memory;
489                         }
490
491                         LogDebug("P12 verification Success");
492 #endif
493                 }
494         } else if (certv != NULL) {
495                 /* Cert Chain */
496                 cert_store = X509_STORE_new();
497
498                 if (!cert_store) {
499                         LogError("Memory allocation failed");
500                         result = CERTSVC_FAIL;
501                         goto free_memory;
502                 }
503
504                 res = X509_STORE_load_locations(cert_store, NULL, TZ_SYS_CA_CERTS);
505
506                 if (res != 1) {
507                         LogError("P12 load certificate store failed");
508                         result = CERTSVC_FAIL;
509                         goto free_memory;
510                 }
511
512                 res = X509_STORE_set_default_paths(cert_store);
513
514                 if (res != 1) {
515                         LogError("P12 load certificate path failed");
516                         result = CERTSVC_FAIL;
517                         goto free_memory;
518                 }
519
520                 /* initialise store and store context */
521                 cert_ctx = X509_STORE_CTX_new();
522
523                 if (cert_ctx == NULL) {
524                         LogError("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                         LogError("Memory allocation failed");
532                         result = CERTSVC_FAIL;
533                         goto free_memory;
534                 }
535
536                 X509_STORE_CTX_trusted_stack(cert_ctx, certv);
537 #ifdef P12_VERIFICATION_NEEDED
538                 res = X509_verify_cert(cert_ctx);
539
540                 if (res != 1) {
541                         LogError("P12 verification failed");
542                         result = CERTSVC_FAIL;
543                         goto free_memory;
544                 }
545
546                 LogDebug("P12 verification Success");
547 #endif
548         }
549
550 #endif //_CERT_SVC_VERIFY_PKCS12
551 free_memory:
552
553         X509_STORE_free(cert_store);
554         X509_STORE_CTX_free(cert_ctx);
555
556         OPENSSL_free(pSubject);
557         OPENSSL_free(pIssuerName);
558         return result;
559 }
560
561 enum class OsslType : int {
562         PKEY = 1,
563         X509,
564         X509AUX
565 };
566
567 std::string osslToPEM(OsslType type, void *data)
568 {
569         std::vector<char> buf(4096);
570         BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
571
572         if (bio.get() == NULL)
573                 return std::string();
574
575         switch (type) {
576         case OsslType::PKEY:
577                 PEM_write_bio_PrivateKey(bio.get(), static_cast<EVP_PKEY *>(data), NULL, NULL, 0, NULL, NULL);
578                 break;
579
580         case OsslType::X509:
581                 PEM_write_bio_X509(bio.get(), static_cast<X509 *>(data));
582                 break;
583
584         case OsslType::X509AUX:
585                 PEM_write_bio_X509_AUX(bio.get(), static_cast<X509 *>(data));
586                 break;
587
588         default:
589                 break;
590         }
591
592         int size = BIO_read(bio.get(), buf.data(), 4096);
593
594         if (size <= 0)
595                 return std::string();
596
597         buf[size] = '\0';
598         return std::string(buf.data());
599 }
600
601 int extractPkcs12(const std::string &path,
602                                   const std::string &password,
603                                   PKEYUniquePtr &keyPtr,
604                                   X509UniquePtr &certPtr,
605                                   X509StackUniquePtr &certvPtr)
606 {
607         FILE *stream = NULL;
608
609         if ((stream = fopen(path.c_str(), "rb")) == NULL) {
610                 LogError("Unable to open the file for reading : " << path);
611                 return CERTSVC_IO_ERROR;
612         }
613
614         PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
615         fclose(stream);
616
617         if (container == NULL) {
618                 LogError("Failed to parse the input file passed.");
619                 return CERTSVC_FAIL;
620         }
621
622         EVP_PKEY *key = NULL;
623         X509 *cert = NULL;
624         STACK_OF(X509) *certv = NULL;
625         int result = PKCS12_parse(container, password.c_str(), &key, &cert, &certv);
626         PKCS12_free(container);
627
628         if (result != 1) {
629                 unsigned long e = ERR_get_error();
630                 char buf[1024];
631                 ERR_error_string_n(e, buf, 1023);
632                 LogError("Failed to parse the file passed. openssl err: " << buf);
633                 return CERTSVC_FAIL;
634         }
635
636         keyPtr.reset(key);
637         certPtr.reset(cert);
638         certvPtr.reset(certv);
639         return CERTSVC_SUCCESS;
640 }
641
642 void rollbackStore(CertStoreType storeTypes, const std::string &endCertName)
643 {
644         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
645                         storeType = nextStore(storeType)) {
646                 if (!hasStore(storeTypes, storeType))
647                         continue;
648
649                 char **certChainName = NULL;
650                 size_t ncerts = 0;
651                 int result = vcore_client_load_certificates_from_store(storeType, endCertName.c_str(),
652                                          &certChainName, &ncerts);
653
654                 if (result != CERTSVC_SUCCESS) {
655                         LogError("Unable to load certificates from store. result : " << result);
656                         continue;
657                 }
658
659                 for (size_t i = 0; i < ncerts; i++) {
660                         if (certChainName[i] == NULL)
661                                 continue;
662
663                         vcore_client_delete_certificate_from_store(storeType, certChainName[i]);
664                         free(certChainName[i]);
665                 }
666                 free(certChainName);
667
668                 vcore_client_delete_certificate_from_store(storeType, endCertName.c_str());
669         }
670 }
671
672 int insertToStore(CertStoreType storeTypes,
673                                   const std::string &alias,
674                                   const std::string &prikeyName,
675                                   const std::string &prikeyBuffer,
676                                   const std::string &endCertName,
677                                   const std::string &endCertBuffer,
678                                   const std::vector<std::string> &certChainName,
679                                   const std::vector<std::string> &certChainBuffer,
680                                   CertSvcStoreCertList **certList,
681                                   size_t *length)
682 {
683         size_t ncerts = certChainName.size();
684
685         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
686                         storeType = nextStore(storeType)) {
687                 if (!hasStore(storeTypes, storeType))
688                         continue;
689
690                 LogDebug("Processing store type : " << storeType);
691                 int result = installPKEY(storeType, prikeyBuffer, prikeyName);
692
693                 if (result != CERTSVC_SUCCESS) {
694                         LogError("Failed to store the private key contents. result : " << result);
695                         return result;
696                 }
697
698                 result = installEndCert(storeType, endCertBuffer, alias, endCertName, prikeyName);
699
700                 if (result != CERTSVC_SUCCESS) {
701                         LogError("Failed to install the end user certificate. result : " << result);
702                         return result;
703                 }
704
705                 int res = appendStoreListNode(certList, length, endCertName, alias, storeType);
706                 if (res != CERTSVC_SUCCESS) {
707                         LogError("Failed to append store list node.");
708                         return result;
709                 }
710
711                 for (size_t i = 0; i < ncerts; i++) {
712                         CertType type = (i == ncerts - 1) ? P12_TRUSTED : P12_INTERMEDIATE;
713
714                         std::string commonName = getCommonName(type, certChainBuffer[i]);
715
716                         result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName,
717                                                                                   commonName, type);
718
719                         if (result != CERTSVC_SUCCESS) {
720                                 LogError("Failed to install the ca certificates. result : " << result);
721                                 return result;
722                         }
723
724                         int res = appendStoreListNode(certList, length, certChainName[i], commonName, storeType);
725                         if (res != CERTSVC_SUCCESS) {
726                                 LogError("Failed to append store list node.");
727                                 return result;
728                         }
729                 }
730         }
731
732         LogDebug("Success to insert extracted pkcs12 data to db");
733         return CERTSVC_SUCCESS;
734 }
735
736 int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const std::string &gname,
737                                          const std::string &alias, CertSvcStoreCertList **certList, size_t *length)
738 {
739         std::string content = readFromFile(path);
740
741         if (content.empty()) {
742                 LogError("Failed to read the file : " << path);
743                 return CERTSVC_IO_ERROR;
744         }
745
746         std::string parsed = parseCRT(content);
747
748         if (parsed.empty()) {
749                 LogError("Failed to parse CRT : " << path);
750                 return CERTSVC_FAIL;
751         }
752
753         for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE;
754                         storeType = nextStore(storeType)) {
755                 if (!hasStore(storeTypes, storeType))
756                         continue;
757
758                 int result = installCert(storeType, parsed, gname, alias);
759
760                 if (result != CERTSVC_SUCCESS) {
761                         LogError("Failed to install PEM/CRT to db store : " << storeType << " result : " << result);
762                         rollbackStore(storeTypes, gname);
763                         return result;
764                 }
765
766                 int res = appendStoreListNode(certList, length, gname, alias, storeType);
767                 if (res != CERTSVC_SUCCESS) {
768                         rollbackStore(storeTypes, gname);
769                         LogError("Failed to append store list node.");
770                         return result;
771                 }
772
773                 LogDebug("Success to install PEM/CRT to db store : " << storeType);
774         }
775
776         LogDebug("Success to install PEM/CRT to db stores : " << storeTypes);
777         return CERTSVC_SUCCESS;
778 }
779
780 } // namespace anonymous
781
782
783 int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
784                                                                          const char *_path,
785                                                                          const char *_password,
786                                                                          const char *_alias,
787                                                                          CertSvcStoreCertList **certList,
788                                                                          size_t *length)
789 {
790         int result = 0;
791
792         if (_alias == NULL || _path == NULL || strlen(_path) < 4) {
793                 LogError("Invalid input parameter.");
794                 return CERTSVC_WRONG_ARGUMENT;
795         }
796
797         std::string path(_path);
798         std::string alias(_alias);
799         std::string password;
800
801         if (_password != NULL)
802                 password = std::string(_password);
803
804         LogDebug("pkcs12_import_from_file_to_store start. path[" << path << "] password[" << password <<
805                          "] alias[" << alias << "]");
806
807         if (storeTypes & SYSTEM_STORE) {
808                 LogError("User should not install any form of certificates in SYSTEM_STORE.");
809                 return CERTSVC_INVALID_STORE_TYPE;
810         }
811
812         /*
813          * Installs CRT and PEM files.
814          * We will passing NULL for private_key_gname and associated_gname parameter
815          * in installFilePEM(). Which means that there is no private key involved
816          * in the certificate which we are installing and there are no other
817          * certificates related with the current certificate which is installed
818          */
819         std::string suffix = path.substr(path.length() - 4, 4);
820
821         if (strcasecmp(suffix.c_str(), ".pem") == 0 || strcasecmp(suffix.c_str(), ".crt") == 0) {
822                 std::string gnamePEM = generateGname();
823                 result = insertToStorePEM(storeTypes, path, gnamePEM, alias, certList, length);
824
825                 if (result != CERTSVC_SUCCESS) {
826                         destroyStoreList(certList, length);
827                         LogError("Failed to install PEM/CRT file to store. gname : " << gnamePEM << " result : " << result);
828                 }
829
830                 return result;;
831         }
832
833         LogDebug("Convert ossl type to string start");
834         /* 0. extract pkcs12 data from file */
835         PKEYUniquePtr key(nullptr, EVP_PKEY_free);
836         X509UniquePtr cert(nullptr, X509_free);
837         X509StackUniquePtr certv(nullptr, X509_stack_free);
838         result = extractPkcs12(path, password, key, cert, certv);
839
840         if (result != CERTSVC_SUCCESS) {
841                 LogError("Failed to extract pkcs12 file. result : " << result);
842                 return result;
843         }
844
845         LogDebug("extract pkcs12 to unique ptr success");
846         result = verify_cert_details(cert.get(), certv.get());
847
848         if (result != CERTSVC_SUCCESS) {
849                 LogError("Failed to verify p12 certificate. result : " << result);
850                 return result;
851         }
852
853         /* 1. handling private key */
854         std::string prikeyName = generateGname();
855         std::string prikeyBuffer = osslToPEM(OsslType::PKEY, key.get());
856
857         if (prikeyName.empty() || prikeyBuffer.empty()) {
858                 LogError("Failed to transform pkey to PEM. result : " << result);
859                 return CERTSVC_FAIL;
860         }
861
862         LogDebug("Convert pkey to string success");
863         /* 2. handling end user certificate */
864         std::string endCertName = generateGname();
865         std::string endCertBuffer = osslToPEM(OsslType::X509, cert.get());
866
867         if (endCertName.empty() || endCertBuffer.empty()) {
868                 LogError("Failed to transform x509 to PEM. result : " << result);
869                 return CERTSVC_FAIL;
870         }
871
872         LogDebug("Convert end cert to string success");
873         /* 3. handling certificate chain */
874         std::vector<std::string> certChainName;
875         std::vector<std::string> certChainBuffer;
876         int ncerts = certv ? sk_X509_num(certv.get()) : 0;
877
878         for (int i = 0; i < ncerts; i++) {
879                 std::string tempName = generateGname();
880                 std::string tempBuffer = osslToPEM(OsslType::X509AUX, sk_X509_value(certv.get(), i));
881
882                 if (tempName.empty() || tempBuffer.empty()) {
883                         LogError("Failed to transform x509 AUX to PEM");
884                         return CERTSVC_FAIL;
885                 }
886
887                 certChainName.push_back(std::move(tempName));
888                 certChainBuffer.push_back(std::move(tempBuffer));
889         }
890
891         LogDebug("Convert cert chain to string success");
892         /* 4. insert extracted pkcs12 data to db */
893         result = insertToStore(storeTypes,
894                                                    alias,
895                                                    prikeyName,
896                                                    prikeyBuffer,
897                                                    endCertName,
898                                                    endCertBuffer,
899                                                    certChainName,
900                                                    certChainBuffer,
901                                                    certList,
902                                                    length);
903
904         if (result != CERTSVC_SUCCESS) {
905                 destroyStoreList(certList, length);
906                 rollbackStore(storeTypes, endCertName);
907         }
908
909         LogDebug("Success to import pkcs12 to store");
910         return result;
911 }
912
913 int pkcs12_has_password(const char *filepath, int *passworded)
914 {
915         if (filepath == NULL || passworded == NULL)
916                 return CERTSVC_WRONG_ARGUMENT;
917
918         FILE *stream;
919
920         if ((stream = fopen(filepath, "rb")) == NULL)
921                 return CERTSVC_IO_ERROR;
922
923         PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
924         fclose(stream);
925
926         if (container == NULL)
927                 return CERTSVC_FAIL;
928
929         EVP_PKEY *pkey = NULL;
930         X509 *cert = NULL;
931         int result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
932         PKCS12_free(container);
933
934         if (pkey != NULL)
935                 EVP_PKEY_free(pkey);
936
937         if (cert != NULL)
938                 X509_free(cert);
939
940         if (result != 1) {
941                 unsigned long e = ERR_get_error();
942                 if (ERR_GET_REASON(e) == PKCS12_R_MAC_VERIFY_FAILURE) {
943                         LogInfo("verify failed without password. file(" << filepath << ") is password-protected.");
944                         *passworded = CERTSVC_TRUE;
945                 } else {
946                         char buf[1024];
947                         ERR_error_string_n(e, buf, 1023);
948                         LogError("Error on PKCS12_pasre file(" << filepath << "): " << buf);
949                         return CERTSVC_FAIL;
950                 }
951         } else {
952                 *passworded = CERTSVC_FALSE;
953         }
954
955         return CERTSVC_SUCCESS;
956 }