c53a3773c14e1751c3cfa218a39b223fe4fc0905
[platform/core/security/key-manager.git] / src / manager / common / pkcs12-impl.cpp
1 /* Copyright (c) 2014 Samsung Electronics Co.
2  *
3  *  Licensed under the Apache License, Version 2.0 (the "License");
4  *  you may not use this file except in compliance with the License.
5  *  You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  *  Unless required by applicable law or agreed to in writing, software
10  *  distributed under the License is distributed on an "AS IS" BASIS,
11  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  *  See the License for the specific language governing permissions and
13  *  limitations under the License
14  *
15  *
16  * @file        pkcs12-impl.cpp
17  * @author      Barlomiej Grzelewski (b.grzelewski@samsung.com)
18  * @version     1.0
19  * @brief       Certificate Implmentation.
20  */
21 #include <openssl/bio.h>
22 #include <openssl/evp.h>
23 #include <openssl/pkcs12.h>
24 #include <openssl/x509.h>
25
26 #include <dpl/log/log.h>
27
28 #include <crypto-init.h>
29 #include <pkcs12-impl.h>
30
31 #include <certificate-impl.h>
32 #include <key-impl.h>
33
34 namespace CKM {
35 namespace {
36
37 typedef std::unique_ptr<BIO, std::function<void(BIO *)>> BioUniquePtr;
38
39 } // anonymous namespace
40
41 PKCS12Impl::PKCS12Impl(const KeyShPtr &key, const CertificateShPtr &cert,
42                                            const CertificateShPtrVector &caChain)
43         : m_pkey(key),
44           m_cert(cert),
45           m_ca(caChain)
46 {
47 }
48
49 PKCS12Impl::PKCS12Impl(const RawBuffer &buffer, const Password &password)
50 {
51         EVP_PKEY *pkey = NULL;
52         X509 *cert = NULL;
53         STACK_OF(X509) *ca = NULL;
54         ::PKCS12 *pkcs12 = NULL;
55
56         BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
57         LogDebug("Start to parse PKCS12");
58
59         int result = BIO_write(bio.get(), buffer.data(), buffer.size());
60
61         if (result != static_cast<int>(buffer.size())) {
62                 LogError("BIO_write failed. result = " << result << " Expected: " <<
63                                  buffer.size());
64                 return;
65         }
66
67         pkcs12 = d2i_PKCS12_bio(bio.get(), NULL);
68
69         if (pkcs12 == NULL) {
70                 LogDebug("d2i_PKCS12_bio failed.");
71                 return;
72         }
73
74         // needed if parsing is done before manager initialization
75         initOpenSslOnce();
76
77         if (!PKCS12_verify_mac(pkcs12, password.c_str(), password.size())) {
78                 LogDebug("Pkcs12 verify failed. Wrong password");
79                 return;
80         }
81
82         if (!PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca)) {
83                 LogError("PKCS12_parse failed");
84                 return;
85         }
86
87         if (pkey) {
88                 KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free);
89
90                 switch (EVP_PKEY_type(pkey->type)) {
91                 case EVP_PKEY_RSA:
92                         m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_RSA_PRIVATE);
93                         break;
94
95                 case EVP_PKEY_DSA:
96                         m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_DSA_PRIVATE);
97                         break;
98
99                 case EVP_PKEY_EC:
100                         m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_ECDSA_PRIVATE);
101                         break;
102
103                 default:
104                         LogError("Unsupported private key type.");
105                         EVP_PKEY_free(pkey);
106                         break;
107                 }
108         }
109
110         if (cert)
111                 m_cert = std::make_shared<CertificateImpl>(cert, false);
112
113         if (ca) {
114                 while (sk_X509_num(ca) > 0) {
115                         X509 *top = sk_X509_pop(ca);
116                         m_ca.push_back(std::make_shared<CertificateImpl>(top, false));
117                 }
118
119                 sk_X509_pop_free(ca, X509_free);
120         }
121 }
122
123 PKCS12Impl::PKCS12Impl(PKCS12Impl &&other) :
124         m_pkey(std::move(other.m_pkey)),
125         m_cert(std::move(other.m_cert)),
126         m_ca(std::move(other.m_ca))
127 {
128 }
129
130 PKCS12Impl &PKCS12Impl::operator=(PKCS12Impl &&other)
131 {
132         if (this == &other)
133                 return *this;
134
135         m_pkey = std::move(other.m_pkey);
136         m_cert = std::move(other.m_cert);
137         m_ca = std::move(other.m_ca);
138
139         return *this;
140 }
141
142 PKCS12Impl::PKCS12Impl(const PKCS12 &other) :
143         m_pkey(other.getKey()),
144         m_cert(other.getCertificate()),
145         m_ca(other.getCaCertificateShPtrVector())
146 {
147 }
148
149 KeyShPtr PKCS12Impl::getKey() const
150 {
151         return m_pkey;
152 }
153
154 CertificateShPtr PKCS12Impl::getCertificate() const
155 {
156         return m_cert;
157 }
158
159 CertificateShPtrVector PKCS12Impl::getCaCertificateShPtrVector() const
160 {
161         return m_ca;
162 }
163
164 bool PKCS12Impl::empty() const
165 {
166         return m_pkey.get() == NULL && m_cert.get() == NULL && m_ca.empty();
167 }
168
169 PKCS12Impl::~PKCS12Impl()
170 {
171 }
172
173 PKCS12ShPtr PKCS12::create(const RawBuffer &rawBuffer, const Password &password)
174 {
175         try {
176                 auto output = std::make_shared<PKCS12Impl>(rawBuffer, password);
177
178                 if (output->empty())
179                         output.reset();
180
181                 return output;
182         } catch (const std::bad_alloc &e) {
183                 LogDebug("Bad alloc was caught during PKCS12 creation");
184         } catch (...) {
185                 LogError("Critical error: Unknown exception was caught during PCKS12Impl creation!");
186         }
187
188         return PKCS12ShPtr();
189 }
190
191 } // namespace CKM
192