1 /* Copyright (c) 2014 Samsung Electronics Co.
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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
16 * @file pkcs12-impl.cpp
17 * @author Barlomiej Grzelewski (b.grzelewski@samsung.com)
19 * @brief Certificate Implmentation.
21 #include <openssl/bio.h>
22 #include <openssl/evp.h>
23 #include <openssl/pkcs12.h>
24 #include <openssl/x509.h>
26 #include <dpl/log/log.h>
28 #include <crypto-init.h>
29 #include <pkcs12-impl.h>
31 #include <certificate-impl.h>
37 typedef std::unique_ptr<BIO, std::function<void(BIO *)>> BioUniquePtr;
39 } // anonymous namespace
41 PKCS12Impl::PKCS12Impl(const KeyShPtr &key, const CertificateShPtr &cert,
42 const CertificateShPtrVector &caChain)
49 PKCS12Impl::PKCS12Impl(const RawBuffer &buffer, const Password &password)
51 EVP_PKEY *pkey = NULL;
53 STACK_OF(X509) *ca = NULL;
54 ::PKCS12 *pkcs12 = NULL;
56 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
57 LogDebug("Start to parse PKCS12");
59 int result = BIO_write(bio.get(), buffer.data(), buffer.size());
61 if (result != static_cast<int>(buffer.size())) {
62 LogError("BIO_write failed. result = " << result << " Expected: " <<
67 pkcs12 = d2i_PKCS12_bio(bio.get(), NULL);
70 LogDebug("d2i_PKCS12_bio failed.");
74 // needed if parsing is done before manager initialization
77 if (!PKCS12_verify_mac(pkcs12, password.c_str(), password.size())) {
78 LogDebug("Pkcs12 verify failed. Wrong password");
82 if (!PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca)) {
83 LogError("PKCS12_parse failed");
88 KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free);
90 switch (EVP_PKEY_type(pkey->type)) {
92 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_RSA_PRIVATE);
96 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_DSA_PRIVATE);
100 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_ECDSA_PRIVATE);
104 LogError("Unsupported private key type.");
111 m_cert = std::make_shared<CertificateImpl>(cert, false);
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));
119 sk_X509_pop_free(ca, X509_free);
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))
130 PKCS12Impl &PKCS12Impl::operator=(PKCS12Impl &&other)
135 m_pkey = std::move(other.m_pkey);
136 m_cert = std::move(other.m_cert);
137 m_ca = std::move(other.m_ca);
142 PKCS12Impl::PKCS12Impl(const PKCS12 &other) :
143 m_pkey(other.getKey()),
144 m_cert(other.getCertificate()),
145 m_ca(other.getCaCertificateShPtrVector())
149 KeyShPtr PKCS12Impl::getKey() const
154 CertificateShPtr PKCS12Impl::getCertificate() const
159 CertificateShPtrVector PKCS12Impl::getCaCertificateShPtrVector() const
164 bool PKCS12Impl::empty() const
166 return m_pkey.get() == NULL && m_cert.get() == NULL && m_ca.empty();
169 PKCS12Impl::~PKCS12Impl()
173 PKCS12ShPtr PKCS12::create(const RawBuffer &rawBuffer, const Password &password)
176 auto output = std::make_shared<PKCS12Impl>(rawBuffer, password);
182 } catch (const std::bad_alloc &e) {
183 LogDebug("Bad alloc was caught during PKCS12 creation");
185 LogError("Critical error: Unknown exception was caught during PCKS12Impl creation!");
188 return PKCS12ShPtr();