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