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