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, const CertificateShPtrVector &caChain)
48 PKCS12Impl::PKCS12Impl(const RawBuffer &buffer, const Password &password)
50 EVP_PKEY *pkey = NULL;
52 STACK_OF(X509) *ca = NULL;
53 ::PKCS12 *pkcs12 = NULL;
55 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
56 LogDebug("Start to parse PKCS12");
58 int result = BIO_write(bio.get(), buffer.data(), buffer.size());
59 if (result != static_cast<int>(buffer.size())) {
60 LogError("BIO_write failed. result = " << result << " Expected: " << buffer.size());
64 pkcs12 = d2i_PKCS12_bio(bio.get(), NULL);
67 LogDebug("d2i_PKCS12_bio failed.");
71 // needed if parsing is done before manager initialization
74 if (!PKCS12_verify_mac(pkcs12, password.c_str(), password.size())) {
75 LogDebug("Pkcs12 verify failed. Wrong password");
79 if (!PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca)) {
80 LogError("PKCS12_parse failed");
85 KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free);
86 switch(EVP_PKEY_type(pkey->type))
89 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_RSA_PRIVATE);
93 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_DSA_PRIVATE);
97 m_pkey = std::make_shared<KeyImpl>(ptr, KeyType::KEY_ECDSA_PRIVATE);
101 LogError("Unsupported private key type.");
108 m_cert = std::make_shared<CertificateImpl>(cert, false);
112 while (sk_X509_num(ca) > 0) {
113 X509 *top = sk_X509_pop(ca);
114 m_ca.push_back(std::make_shared<CertificateImpl>(top, false));
117 sk_X509_pop_free(ca, X509_free);
121 PKCS12Impl::PKCS12Impl(const PKCS12 &other)
122 : m_pkey(other.getKey()),
123 m_cert(other.getCertificate()),
124 m_ca(other.getCaCertificateShPtrVector())
128 PKCS12Impl::PKCS12Impl(PKCS12Impl &&other)
129 : m_pkey(std::move(other.m_pkey)),
130 m_cert(std::move(other.m_cert)),
131 m_ca(std::move(other.m_ca))
135 PKCS12Impl::PKCS12Impl(const PKCS12Impl &other)
136 : m_pkey(other.getKey()),
137 m_cert(other.getCertificate()),
138 m_ca(other.getCaCertificateShPtrVector())
142 PKCS12Impl& PKCS12Impl::operator=(const PKCS12Impl &other)
146 m_pkey = other.getKey();
147 m_cert = other.getCertificate();
148 m_ca = other.getCaCertificateShPtrVector();
153 KeyShPtr PKCS12Impl::getKey() const {
157 CertificateShPtr PKCS12Impl::getCertificate() const {
161 CertificateShPtrVector PKCS12Impl::getCaCertificateShPtrVector() const {
165 bool PKCS12Impl::empty() const {
166 return m_pkey.get() == NULL && m_cert.get() == NULL && m_ca.empty();
169 PKCS12Impl::~PKCS12Impl()
172 PKCS12ShPtr PKCS12::create(const RawBuffer &rawBuffer, const Password &password) {
174 auto output = std::make_shared<PKCS12Impl>(rawBuffer, password);
178 } catch (const std::bad_alloc &e) {
179 LogDebug("Bad alloc was caught during PKCS12 creation");
181 LogError("Critical error: Unknown exception was caught during PCKS12Impl creation!");
183 return PKCS12ShPtr();