1//
2// PKCS12Container.cpp
3//
4//
5// Library: Crypto
6// Package: Certificate
7// Module: PKCS12Container
8//
9// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
10// and Contributors.
11//
12// SPDX-License-Identifier: BSL-1.0
13//
14
15
16#include "Poco/Crypto/PKCS12Container.h"
17#include "Poco/NumberFormatter.h"
18#include "Poco/StreamCopier.h"
19#include <sstream>
20#include <openssl/err.h>
21
22
23namespace Poco {
24namespace Crypto {
25
26
27PKCS12Container::PKCS12Container(std::istream& istr, const std::string& password)
28{
29 std::ostringstream ostr;
30 Poco::StreamCopier::copyStream(istr, ostr);
31 const std::string& cont = ostr.str();
32
33 BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(cont.data()), static_cast<int>(cont.size()));
34 if (pBIO)
35 {
36 PKCS12* pPKCS12 = 0;
37 d2i_PKCS12_bio(pBIO, &pPKCS12);
38 BIO_free(pBIO);
39 if (!pPKCS12) throw OpenSSLException("PKCS12Container(istream&, const string&)");
40 load(pPKCS12, password);
41 }
42 else
43 {
44 throw Poco::NullPointerException("PKCS12Container(istream&, const string&)");
45 }
46}
47
48
49PKCS12Container::PKCS12Container(const std::string& path, const std::string& password)
50{
51 FILE* pFile = fopen(path.c_str(), "rb");
52 if (pFile)
53 {
54 PKCS12* pPKCS12 = d2i_PKCS12_fp(pFile, NULL);
55 fclose (pFile);
56 if (!pPKCS12) throw OpenSSLException("PKCS12Container(const string&, const string&)");
57 load(pPKCS12, password);
58 }
59 else
60 {
61 throw Poco::OpenFileException("PKCS12Container: " + path);
62 }
63}
64
65
66PKCS12Container::PKCS12Container(const PKCS12Container& other):
67 _pKey(EVPPKey::duplicate(other._pKey, &_pKey)),
68 _pX509Cert(new X509Certificate(*other._pX509Cert)),
69 _caCertList(other._caCertList),
70 _caCertNames(other._caCertNames),
71 _pkcsFriendlyName(other._pkcsFriendlyName)
72{
73}
74
75
76PKCS12Container& PKCS12Container::operator = (const PKCS12Container& other)
77{
78 if (&other != this)
79 {
80 if (_pKey) EVP_PKEY_free(_pKey);
81 _pKey = EVPPKey::duplicate(other._pKey, &_pKey);
82 _pX509Cert.reset(new X509Certificate(*other._pX509Cert));
83 _caCertList = other._caCertList;
84 _caCertNames = other._caCertNames;
85 _pkcsFriendlyName = other._pkcsFriendlyName;
86 }
87 return *this;
88}
89
90
91PKCS12Container::PKCS12Container(PKCS12Container&& other):
92 _pKey(other._pKey),
93 _pX509Cert(std::move(other._pX509Cert)),
94 _caCertList(std::move(other._caCertList)),
95 _caCertNames(std::move(other._caCertNames)),
96 _pkcsFriendlyName(std::move(other._pkcsFriendlyName))
97{
98 other._pKey = 0;
99}
100
101
102PKCS12Container& PKCS12Container::operator = (PKCS12Container&& other)
103{
104 if (&other != this)
105 {
106 if (_pKey) EVP_PKEY_free(_pKey);
107 _pKey = other._pKey; other._pKey = 0;
108 _pX509Cert = std::move(other._pX509Cert);
109 _caCertList = std::move(other._caCertList);
110 _caCertNames = std::move(other._caCertNames);
111 _pkcsFriendlyName = std::move(other._pkcsFriendlyName);
112 }
113 return *this;
114}
115
116
117PKCS12Container::~PKCS12Container()
118{
119 if (_pKey) EVP_PKEY_free(_pKey);
120}
121
122
123std::string PKCS12Container::extractFriendlyName(X509* pCert)
124{
125 std::string friendlyName;
126 if(pCert)
127 {
128 STACK_OF(PKCS12_SAFEBAG)*pBags = 0;
129 PKCS12_SAFEBAG*pBag = PKCS12_add_cert(&pBags, pCert);
130 if(pBag)
131 {
132 char* pBuffer = PKCS12_get_friendlyname(pBag);
133 if(pBuffer)
134 {
135 friendlyName = pBuffer;
136 OPENSSL_free(pBuffer);
137 }
138 if(pBags) sk_PKCS12_SAFEBAG_pop_free(pBags, PKCS12_SAFEBAG_free);
139 }
140 else throw OpenSSLException("PKCS12Container::extractFriendlyName()");
141 }
142 else throw NullPointerException("PKCS12Container::extractFriendlyName()");
143
144 return friendlyName;
145}
146
147
148void PKCS12Container::load(PKCS12* pPKCS12, const std::string& password)
149{
150 if (pPKCS12)
151 {
152 X509* pCert = 0;
153 STACK_OF(X509)* pCA = 0;
154 if (PKCS12_parse(pPKCS12, password.c_str(), &_pKey, &pCert, &pCA))
155 {
156 if (pCert)
157 {
158 _pX509Cert.reset(new X509Certificate(pCert, true));
159 _pkcsFriendlyName = extractFriendlyName(pCert);
160 }
161 else _pX509Cert.reset();
162
163 _caCertList.clear();
164 _caCertNames.clear();
165 if (pCA)
166 {
167 int certCount = sk_X509_num(pCA);
168 for (int i = 0; i < certCount; ++i)
169 {
170 X509* pX509 = sk_X509_value(pCA, i);
171 if (pX509)
172 {
173 _caCertList.push_back(X509Certificate(pX509, true));
174 _caCertNames.push_back(extractFriendlyName(pX509));
175 }
176 else throw OpenSSLException("PKCS12Container::load()");
177 }
178 }
179 }
180 else
181 {
182 throw OpenSSLException();
183 }
184 PKCS12_free(pPKCS12);
185 sk_X509_pop_free(pCA, X509_free);
186 if (pCert) X509_free(pCert);
187 poco_assert_dbg (_caCertList.size() == _caCertNames.size());
188 }
189 else
190 {
191 throw NullPointerException("PKCS12Container::load(): struct PKCS12");
192 }
193}
194
195
196} } // namespace Poco::Crypto
197