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