1//
2// PKCS12ContainerTest.cpp
3//
4// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "PKCS12ContainerTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Crypto/EVPPKey.h"
15#include "Poco/Crypto/RSAKey.h"
16#include "Poco/Crypto/KeyPairImpl.h"
17#include "Poco/Environment.h"
18#include "Poco/Path.h"
19#include "Poco/File.h"
20#include "Poco/TemporaryFile.h"
21#include <iostream>
22#include <sstream>
23#include <fstream>
24
25
26using Poco::Crypto::PKCS12Container;
27using Poco::Crypto::X509Certificate;
28using Poco::Crypto::EVPPKey;
29using Poco::Crypto::RSAKey;
30using Poco::Crypto::KeyPairImpl;
31using Poco::Environment;
32using Poco::Path;
33using Poco::File;
34using Poco::TemporaryFile;
35
36
37PKCS12ContainerTest::PKCS12ContainerTest(const std::string& name): CppUnit::TestCase(name)
38{
39}
40
41
42PKCS12ContainerTest::~PKCS12ContainerTest()
43{
44}
45
46
47void PKCS12ContainerTest::testFullPKCS12()
48{
49 try
50 {
51 std::string file = getTestFilesPath("full");
52 full(PKCS12Container(file, "crypto"));
53
54 std::ifstream ifs(file, std::ios::binary);
55 PKCS12Container pkcs(ifs, "crypto");
56 full(pkcs);
57
58 PKCS12Container pkcs2(pkcs);
59 full(pkcs2);
60
61 PKCS12Container pkcs3(pkcs);
62 pkcs3 = pkcs2;
63 full(pkcs3);
64
65 pkcs3 = std::move(pkcs);
66 full(pkcs3);
67
68 PKCS12Container pkcs4(std::move(pkcs2));
69 full(pkcs4);
70 }
71 catch (Poco::Exception& ex)
72 {
73 std::cerr << ex.displayText() << std::endl;
74 throw;
75 }
76}
77
78
79void PKCS12ContainerTest::full(const PKCS12Container& pkcs12)
80{
81 assertTrue ("vally" == pkcs12.getFriendlyName());
82
83 assertTrue (pkcs12.hasKey());
84 EVPPKey pKey = pkcs12.getKey();
85 assertTrue (EVP_PKEY_RSA == pKey.type());
86
87 RSAKey rsa(pkcs12);
88 assertTrue (rsa.impl()->type() == KeyPairImpl::KT_RSA_IMPL);
89
90 assertTrue (pkcs12.hasX509Certificate());
91 fullCert(pkcs12.getX509Certificate());
92
93 std::vector<int> certOrder;
94 for (int i = 0; i < 2; ++i) certOrder.push_back(i);
95 fullList(pkcs12.getCACerts(), pkcs12.getFriendlyNamesCA(), certOrder);
96}
97
98
99void PKCS12ContainerTest::fullCert(const X509Certificate& x509)
100{
101 std::string subjectName(x509.subjectName());
102 std::string issuerName(x509.issuerName());
103 std::string commonName(x509.commonName());
104 std::string country(x509.subjectName(X509Certificate::NID_COUNTRY));
105 std::string localityName(x509.subjectName(X509Certificate::NID_LOCALITY_NAME));
106 std::string stateOrProvince(x509.subjectName(X509Certificate::NID_STATE_OR_PROVINCE));
107 std::string organizationName(x509.subjectName(X509Certificate::NID_ORGANIZATION_NAME));
108 std::string organizationUnitName(x509.subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME));
109 std::string emailAddress(x509.subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS));
110 std::string serialNumber(x509.serialNumber());
111
112 assertTrue (subjectName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Server");
113 assertTrue (issuerName == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
114 assertTrue (commonName == "CV Server");
115 assertTrue (country == "CH");
116 assertTrue (localityName.empty());
117 assertTrue (stateOrProvince == "Zug");
118 assertTrue (organizationName == "Crypto Vally");
119 assertTrue (organizationUnitName.empty());
120 assertTrue (emailAddress.empty());
121 assertTrue (serialNumber == "1000");
122 assertTrue (x509.version() == 3);
123 assertTrue (x509.signatureAlgorithm() == "sha256WithRSAEncryption");
124}
125
126
127void PKCS12ContainerTest::fullList(const PKCS12Container::CAList& caList,
128 const PKCS12Container::CANameList& caNamesList, const std::vector<int>& certOrder)
129{
130 assertTrue (certOrder.size() == caList.size());
131 assertTrue ((0 == caNamesList.size()) || (certOrder.size() == caNamesList.size()));
132
133 if (caNamesList.size())
134 {
135 assertTrue (caNamesList[certOrder[0]].empty());
136 assertTrue (caNamesList[certOrder[1]].empty());
137 }
138
139 assertTrue (caList[certOrder[0]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
140 assertTrue (caList[certOrder[0]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
141 assertTrue (caList[certOrder[0]].commonName() == "CV Root CA v3");
142 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_COUNTRY) == "CH");
143 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
144 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE) == "Zug");
145 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
146 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
147 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
148 assertTrue (caList[certOrder[0]].serialNumber() == "C3ECA1FCEAA16055");
149 assertTrue (caList[certOrder[0]].version() == 3);
150 assertTrue (caList[certOrder[0]].signatureAlgorithm() == "sha256WithRSAEncryption");
151
152 assertTrue (caList[certOrder[1]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
153 assertTrue (caList[certOrder[1]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
154 assertTrue (caList[certOrder[1]].commonName() == "CV Intermediate CA v3");
155 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_COUNTRY) == "CH");
156 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
157 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE) == "Zug");
158 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
159 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
160 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
161 assertTrue (caList[certOrder[1]].serialNumber() == "1000");
162 assertTrue (caList[certOrder[1]].version() == 3);
163 assertTrue (caList[certOrder[1]].signatureAlgorithm() == "sha256WithRSAEncryption");
164}
165
166
167void PKCS12ContainerTest::testCertsOnlyPKCS12()
168{
169 try
170 {
171 std::string file = getTestFilesPath("certs-only");
172 certsOnly(PKCS12Container(file.c_str(), "crypto"));
173
174 std::ifstream ifs(file.c_str(), std::ios::binary);
175 certsOnly(PKCS12Container(ifs, "crypto"));
176 }
177 catch (Poco::Exception& ex)
178 {
179 std::cerr << ex.displayText() << std::endl;
180 throw;
181 }
182}
183
184
185void PKCS12ContainerTest::certsOnly(const PKCS12Container& pkcs12)
186{
187 assertTrue (!pkcs12.hasKey());
188 assertTrue (!pkcs12.hasX509Certificate());
189 assertTrue (pkcs12.getFriendlyName().empty());
190
191 std::vector<int> certOrder;
192 for (int i = 0; i < 5; ++i) certOrder.push_back(i);
193 certsOnlyList(pkcs12.getCACerts(), pkcs12.getFriendlyNamesCA(), certOrder);
194}
195
196
197void PKCS12ContainerTest::certsOnlyList(const PKCS12Container::CAList& caList,
198 const PKCS12Container::CANameList& caNamesList, const std::vector<int>& certOrder)
199{
200 assertTrue (certOrder.size() == caList.size());
201 assertTrue ((0 == caNamesList.size()) || (certOrder.size() == caNamesList.size()));
202
203 if (caNamesList.size())
204 {
205 assertTrue (caNamesList[certOrder[0]].empty());
206 assertTrue (caNamesList[certOrder[1]].empty());
207 assertTrue (caNamesList[certOrder[2]].empty());
208 assertTrue (caNamesList[certOrder[3]] == "vally-ca");
209 assertTrue (caNamesList[certOrder[4]] == "vally-ca");
210 }
211
212 assertTrue (caList[certOrder[0]].subjectName() == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3");
213 assertTrue (caList[certOrder[0]].issuerName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
214 assertTrue (caList[certOrder[0]].commonName() == "Let's Encrypt Authority X3");
215 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_COUNTRY) == "US");
216 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
217 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE).empty());
218 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
219 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
220 assertTrue (caList[certOrder[0]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
221 assertTrue (caList[certOrder[0]].serialNumber() == "D3B17226342332DCF40528512AEC9C6A");
222 assertTrue (caList[certOrder[0]].version() == 3);
223 assertTrue (caList[certOrder[0]].signatureAlgorithm() == "sha256WithRSAEncryption");
224
225 assertTrue (caList[certOrder[1]].subjectName() == "/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3");
226 assertTrue (caList[certOrder[1]].issuerName() == "/O=Digital Signature Trust Co./CN=DST Root CA X3");
227 assertTrue (caList[certOrder[1]].commonName() == "Let's Encrypt Authority X3");
228 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_COUNTRY) == "US");
229 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
230 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE).empty());
231 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Let's Encrypt");
232 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
233 assertTrue (caList[certOrder[1]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
234 assertTrue (caList[certOrder[1]].serialNumber() == "0A0141420000015385736A0B85ECA708");
235 assertTrue (caList[certOrder[1]].version() == 3);
236 assertTrue (caList[certOrder[1]].signatureAlgorithm() == "sha256WithRSAEncryption");
237
238 assertTrue (caList[certOrder[2]].subjectName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
239 assertTrue (caList[certOrder[2]].issuerName() == "/C=US/O=Internet Security Research Group/CN=ISRG Root X1");
240 assertTrue (caList[certOrder[2]].commonName() == "ISRG Root X1");
241 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_COUNTRY) == "US");
242 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
243 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE).empty());
244 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Internet Security Research Group");
245 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
246 assertTrue (caList[certOrder[2]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
247 assertTrue (caList[certOrder[2]].serialNumber() == "8210CFB0D240E3594463E0BB63828B00");
248 assertTrue (caList[certOrder[2]].version() == 3);
249 assertTrue (caList[certOrder[2]].signatureAlgorithm() == "sha256WithRSAEncryption");
250
251 assertTrue (caList[certOrder[3]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
252 assertTrue (caList[certOrder[3]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
253 assertTrue (caList[certOrder[3]].commonName() == "CV Root CA v3");
254 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_COUNTRY) == "CH");
255 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
256 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE) == "Zug");
257 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
258 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
259 assertTrue (caList[certOrder[3]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
260 assertTrue (caList[certOrder[3]].serialNumber() == "C3ECA1FCEAA16055");
261 assertTrue (caList[certOrder[3]].version() == 3);
262 assertTrue (caList[certOrder[3]].signatureAlgorithm() == "sha256WithRSAEncryption");
263
264 assertTrue (caList[certOrder[4]].subjectName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Intermediate CA v3");
265 assertTrue (caList[certOrder[4]].issuerName() == "/C=CH/ST=Zug/O=Crypto Vally/CN=CV Root CA v3");
266 assertTrue (caList[certOrder[4]].commonName() == "CV Intermediate CA v3");
267 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_COUNTRY) == "CH");
268 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_LOCALITY_NAME).empty());
269 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_STATE_OR_PROVINCE) == "Zug");
270 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_NAME) == "Crypto Vally");
271 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME).empty());
272 assertTrue (caList[certOrder[4]].subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS).empty());
273 assertTrue (caList[certOrder[4]].serialNumber()== "1000");
274 assertTrue (caList[certOrder[4]].version() == 3);
275 assertTrue (caList[certOrder[4]].signatureAlgorithm() == "sha256WithRSAEncryption");
276}
277
278
279void PKCS12ContainerTest::testPEMReadWrite()
280{
281 try
282 {
283 std::string file = getTestFilesPath("certs-only", "pem");
284 X509Certificate::List certsOnly = X509Certificate::readPEM(file);
285 assertTrue (certsOnly.size() == 5);
286 // PEM is written by openssl in reverse order from p12
287 std::vector<int> certOrder;
288 for(int i = (int)certsOnly.size() - 1; i >= 0; --i) certOrder.push_back(i);
289 certsOnlyList(certsOnly, PKCS12Container::CANameList(), certOrder);
290
291 TemporaryFile tmpFile;
292 X509Certificate::writePEM(tmpFile.path(), certsOnly);
293
294 certsOnly.clear();
295 certsOnly = X509Certificate::readPEM(tmpFile.path());
296 certsOnlyList(certsOnly, PKCS12Container::CANameList(), certOrder);
297
298 file = getTestFilesPath("full", "pem");
299 X509Certificate::List full = X509Certificate::readPEM(file);
300 assertTrue (full.size() == 3);
301 fullCert(full[0]);
302 full.erase(full.begin());
303 assertTrue (full.size() == 2);
304
305 certOrder.clear();
306 for(int i = (int)full.size() - 1; i >= 0; --i) certOrder.push_back(i);
307 fullList(full, PKCS12Container::CANameList(), certOrder);
308
309 TemporaryFile tmpFile2;
310 X509Certificate::writePEM(tmpFile2.path(), full);
311
312 full.clear();
313 full = X509Certificate::readPEM(tmpFile2.path());
314 fullList(full, PKCS12Container::CANameList(), certOrder);
315 }
316 catch (Poco::Exception& ex)
317 {
318 std::cerr << ex.displayText() << std::endl;
319 throw;
320 }
321}
322
323
324void PKCS12ContainerTest::setUp()
325{
326}
327
328
329void PKCS12ContainerTest::tearDown()
330{
331}
332
333
334std::string PKCS12ContainerTest::getTestFilesPath(const std::string& name, const std::string& ext)
335{
336 std::ostringstream ostr;
337 ostr << "data/" << name << '.' << ext;
338 std::string fileName(ostr.str());
339 Poco::Path path(fileName);
340 if (Poco::File(path).exists())
341 {
342 return fileName;
343 }
344
345 ostr.str("");
346 ostr << "/Crypto/testsuite/data/" << name << '.' << ext;
347 fileName = Poco::Environment::get("POCO_BASE") + ostr.str();
348 path = fileName;
349
350 if (!Poco::File(path).exists())
351 {
352 std::cerr << "Can't find " << fileName << std::endl;
353 throw Poco::NotFoundException("cannot locate directory containing valid Crypto test files");
354 }
355 return fileName;
356}
357
358
359CppUnit::Test* PKCS12ContainerTest::suite()
360{
361 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PKCS12ContainerTest");
362
363 CppUnit_addTest(pSuite, PKCS12ContainerTest, testFullPKCS12);
364 CppUnit_addTest(pSuite, PKCS12ContainerTest, testCertsOnlyPKCS12);
365 CppUnit_addTest(pSuite, PKCS12ContainerTest, testPEMReadWrite);
366
367 return pSuite;
368}
369