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 | |
23 | namespace Poco { |
24 | namespace Crypto { |
25 | |
26 | |
27 | PKCS12Container::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 | |
49 | PKCS12Container::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 | |
66 | PKCS12Container::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 | |
76 | PKCS12Container& 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 | |
91 | PKCS12Container::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 | |
102 | PKCS12Container& 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 | |
117 | PKCS12Container::~PKCS12Container() |
118 | { |
119 | if (_pKey) EVP_PKEY_free(_pKey); |
120 | } |
121 | |
122 | |
123 | std::string PKCS12Container::(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 | |
148 | void 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 | |