/src/PcapPlusPlus/Packet++/src/X509Decoder.cpp
Line | Count | Source |
1 | | #include "X509Decoder.h" |
2 | | #include "Asn1Codec.h" |
3 | | #include "GeneralUtils.h" |
4 | | #include "PemCodec.h" |
5 | | #include "json.hpp" |
6 | | #include <fstream> |
7 | | #include <unordered_map> |
8 | | |
9 | | namespace pcpp |
10 | | { |
11 | | std::string X509Algorithm::toString() const |
12 | 0 | { |
13 | 0 | switch (m_Value) |
14 | 0 | { |
15 | 0 | case SHA1: |
16 | 0 | return "SHA1"; |
17 | 0 | case SHA256: |
18 | 0 | return "SHA256"; |
19 | 0 | case SHA384: |
20 | 0 | return "SHA384"; |
21 | 0 | case SHA512: |
22 | 0 | return "SHA512"; |
23 | 0 | case MD5: |
24 | 0 | return "MD5"; |
25 | 0 | case RSA: |
26 | 0 | return "RSA"; |
27 | 0 | case RSAWithSHA1: |
28 | 0 | return "RSAWithSHA1"; |
29 | 0 | case RSAWithSHA256: |
30 | 0 | return "RSAWithSHA256"; |
31 | 0 | case RSAWithSHA384: |
32 | 0 | return "RSAWithSHA384"; |
33 | 0 | case RSAWithSHA512: |
34 | 0 | return "RSAWithSHA512"; |
35 | 0 | case RSAPSS: |
36 | 0 | return "RSAPSS"; |
37 | 0 | case ECDSA: |
38 | 0 | return "ECDSA"; |
39 | 0 | case ECDSAWithSHA1: |
40 | 0 | return "ECDSAWithSHA1"; |
41 | 0 | case ECDSAWithSHA256: |
42 | 0 | return "ECDSAWithSHA256"; |
43 | 0 | case ECDSAWithSHA384: |
44 | 0 | return "ECDSAWithSHA384"; |
45 | 0 | case ECDSAWithSHA512: |
46 | 0 | return "ECDSAWithSHA512"; |
47 | 0 | case ED25519: |
48 | 0 | return "ED25519"; |
49 | 0 | case ED448: |
50 | 0 | return "ED448"; |
51 | 0 | case DSA: |
52 | 0 | return "DSA"; |
53 | 0 | case DSAWithSHA1: |
54 | 0 | return "DSAWithSHA1"; |
55 | 0 | case DSAWithSHA256: |
56 | 0 | return "DSAWithSHA256"; |
57 | 0 | case DiffieHellman: |
58 | 0 | return "DiffieHellman"; |
59 | 0 | case Unknown: |
60 | 0 | default: |
61 | 0 | return "Unknown"; |
62 | 0 | } |
63 | 0 | } |
64 | | |
65 | | std::string X509Algorithm::getOidValue() const |
66 | 0 | { |
67 | 0 | switch (m_Value) |
68 | 0 | { |
69 | 0 | case SHA1: |
70 | 0 | return "1.3.14.3.2.26"; |
71 | 0 | case SHA256: |
72 | 0 | return "2.16.840.1.101.3.4.2.1"; |
73 | 0 | case SHA384: |
74 | 0 | return "2.16.840.1.101.3.4.2.2"; |
75 | 0 | case SHA512: |
76 | 0 | return "2.16.840.1.101.3.4.2.3"; |
77 | 0 | case MD5: |
78 | 0 | return "1.2.840.113549.2.5"; |
79 | | |
80 | 0 | case RSA: |
81 | 0 | return "1.2.840.113549.1.1.1"; |
82 | 0 | case RSAWithSHA1: |
83 | 0 | return "1.2.840.113549.1.1.5"; |
84 | 0 | case RSAWithSHA256: |
85 | 0 | return "1.2.840.113549.1.1.11"; |
86 | 0 | case RSAWithSHA384: |
87 | 0 | return "1.2.840.113549.1.1.12"; |
88 | 0 | case RSAWithSHA512: |
89 | 0 | return "1.2.840.113549.1.1.13"; |
90 | 0 | case RSAPSS: |
91 | 0 | return "1.2.840.113549.1.1.10"; |
92 | | |
93 | 0 | case ECDSA: |
94 | 0 | return "1.2.840.10045.2.1"; |
95 | 0 | case ECDSAWithSHA1: |
96 | 0 | return "1.2.840.10045.4.1"; |
97 | 0 | case ECDSAWithSHA256: |
98 | 0 | return "1.2.840.10045.4.3.2"; |
99 | 0 | case ECDSAWithSHA384: |
100 | 0 | return "1.2.840.10045.4.3.3"; |
101 | 0 | case ECDSAWithSHA512: |
102 | 0 | return "1.2.840.10045.4.3.4"; |
103 | | |
104 | 0 | case ED25519: |
105 | 0 | return "1.3.101.112"; |
106 | 0 | case ED448: |
107 | 0 | return "1.3.101.113"; |
108 | | |
109 | 0 | case DSA: |
110 | 0 | return "1.2.840.10040.4.1"; |
111 | 0 | case DSAWithSHA1: |
112 | 0 | return "1.2.840.10040.4.3"; |
113 | 0 | case DSAWithSHA256: |
114 | 0 | return "2.16.840.1.101.3.4.3.2"; |
115 | | |
116 | 0 | case DiffieHellman: |
117 | 0 | return "1.2.840.113549.1.3.1"; |
118 | | |
119 | 0 | case Unknown: |
120 | 0 | default: |
121 | 0 | return "0.0"; |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | static const std::unordered_map<std::string, X509Algorithm::Value> X509AlgorithmOidMap = { |
126 | | { "1.3.14.3.2.26", X509Algorithm::SHA1 }, |
127 | | { "2.16.840.1.101.3.4.2.1", X509Algorithm::SHA256 }, |
128 | | { "2.16.840.1.101.3.4.2.2", X509Algorithm::SHA384 }, |
129 | | { "2.16.840.1.101.3.4.2.3", X509Algorithm::SHA512 }, |
130 | | { "1.2.840.113549.2.5", X509Algorithm::MD5 }, |
131 | | { "1.2.840.113549.1.1.1", X509Algorithm::RSA }, |
132 | | { "1.2.840.113549.1.1.5", X509Algorithm::RSAWithSHA1 }, |
133 | | { "1.2.840.113549.1.1.11", X509Algorithm::RSAWithSHA256 }, |
134 | | { "1.2.840.113549.1.1.12", X509Algorithm::RSAWithSHA384 }, |
135 | | { "1.2.840.113549.1.1.13", X509Algorithm::RSAWithSHA512 }, |
136 | | { "1.2.840.113549.1.1.10", X509Algorithm::RSAPSS }, |
137 | | { "1.2.840.10045.2.1", X509Algorithm::ECDSA }, |
138 | | { "1.2.840.10045.4.1", X509Algorithm::ECDSAWithSHA1 }, |
139 | | { "1.2.840.10045.4.3.2", X509Algorithm::ECDSAWithSHA256 }, |
140 | | { "1.2.840.10045.4.3.3", X509Algorithm::ECDSAWithSHA384 }, |
141 | | { "1.2.840.10045.4.3.4", X509Algorithm::ECDSAWithSHA512 }, |
142 | | { "1.2.840.10040.4.1", X509Algorithm::DSA }, |
143 | | { "1.2.840.10040.4.3", X509Algorithm::DSAWithSHA1 }, |
144 | | { "2.16.840.1.101.3.4.3.2", X509Algorithm::DSAWithSHA256 }, |
145 | | { "1.3.101.112", X509Algorithm::ED25519 }, |
146 | | { "1.3.101.113", X509Algorithm::ED448 }, |
147 | | { "1.2.840.113549.1.3.1", X509Algorithm::DiffieHellman } |
148 | | }; |
149 | | |
150 | | X509Algorithm X509Algorithm::fromOidValue(const Asn1ObjectIdentifier& value) |
151 | 0 | { |
152 | 0 | std::string oidStringValue = value.toString(); |
153 | |
|
154 | 0 | auto it = X509AlgorithmOidMap.find(oidStringValue); |
155 | 0 | if (it != X509AlgorithmOidMap.end()) |
156 | 0 | { |
157 | 0 | return { it->second }; |
158 | 0 | } |
159 | | |
160 | 0 | return { Unknown }; |
161 | 0 | } |
162 | | |
163 | | std::string X520DistinguishedName::toString() const |
164 | 0 | { |
165 | 0 | switch (m_Value) |
166 | 0 | { |
167 | 0 | case CommonName: |
168 | 0 | return "CommonName"; |
169 | 0 | case Surname: |
170 | 0 | return "Surname"; |
171 | 0 | case SerialNumber: |
172 | 0 | return "SerialNumber"; |
173 | 0 | case Country: |
174 | 0 | return "Country"; |
175 | 0 | case Locality: |
176 | 0 | return "Locality"; |
177 | 0 | case StateOrProvince: |
178 | 0 | return "StateOrProvinceName"; |
179 | 0 | case Organization: |
180 | 0 | return "Organization"; |
181 | 0 | case OrganizationalUnit: |
182 | 0 | return "OrganizationalUnit"; |
183 | 0 | case Title: |
184 | 0 | return "Title"; |
185 | 0 | case GivenName: |
186 | 0 | return "GivenName"; |
187 | 0 | case Initials: |
188 | 0 | return "Initials"; |
189 | 0 | case Pseudonym: |
190 | 0 | return "Pseudonym"; |
191 | 0 | case GenerationQualifier: |
192 | 0 | return "GenerationQualifier"; |
193 | 0 | case DnQualifier: |
194 | 0 | return "DnQualifier"; |
195 | 0 | case DomainComponent: |
196 | 0 | return "DomainComponent"; |
197 | 0 | case EmailAddress: |
198 | 0 | return "EmailAddress"; |
199 | 0 | case PostalCode: |
200 | 0 | return "PostalCode"; |
201 | 0 | case StreetAddress: |
202 | 0 | return "StreetAddress"; |
203 | 0 | case BusinessCategory: |
204 | 0 | return "BusinessCategory"; |
205 | 0 | case Unknown: |
206 | 0 | default: |
207 | 0 | return "Unknown"; |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | std::string X520DistinguishedName::getShortName() const |
212 | 0 | { |
213 | 0 | switch (m_Value) |
214 | 0 | { |
215 | 0 | case CommonName: |
216 | 0 | return "CN"; |
217 | 0 | case Surname: |
218 | 0 | return "SN"; |
219 | 0 | case SerialNumber: |
220 | 0 | return "SERIALNUMBER"; |
221 | 0 | case Country: |
222 | 0 | return "C"; |
223 | 0 | case Locality: |
224 | 0 | return "L"; |
225 | 0 | case StateOrProvince: |
226 | 0 | return "ST"; |
227 | 0 | case Organization: |
228 | 0 | return "O"; |
229 | 0 | case OrganizationalUnit: |
230 | 0 | return "OU"; |
231 | 0 | case Title: |
232 | 0 | return "T"; |
233 | 0 | case GivenName: |
234 | 0 | return "G"; |
235 | 0 | case Initials: |
236 | 0 | return "Initials"; |
237 | 0 | case Pseudonym: |
238 | 0 | return "Pseudonym"; |
239 | 0 | case GenerationQualifier: |
240 | 0 | return "GENERATION"; |
241 | 0 | case DnQualifier: |
242 | 0 | return "dnQualifier"; |
243 | 0 | case DomainComponent: |
244 | 0 | return "DC"; |
245 | 0 | case EmailAddress: |
246 | 0 | return "E"; |
247 | 0 | case PostalCode: |
248 | 0 | return "postalCode"; |
249 | 0 | case StreetAddress: |
250 | 0 | return "STREET"; |
251 | 0 | case BusinessCategory: |
252 | 0 | return "businessCategory"; |
253 | 0 | case Unknown: |
254 | 0 | default: |
255 | 0 | return "Unknown"; |
256 | 0 | } |
257 | 0 | } |
258 | | |
259 | | std::string X520DistinguishedName::getOidValue() const |
260 | 0 | { |
261 | 0 | switch (m_Value) |
262 | 0 | { |
263 | 0 | case CommonName: |
264 | 0 | return "2.5.4.3"; |
265 | 0 | case Surname: |
266 | 0 | return "2.5.4.4"; |
267 | 0 | case SerialNumber: |
268 | 0 | return "2.5.4.5"; |
269 | 0 | case Country: |
270 | 0 | return "2.5.4.6"; |
271 | 0 | case Locality: |
272 | 0 | return "2.5.4.7"; |
273 | 0 | case StateOrProvince: |
274 | 0 | return "2.5.4.8"; |
275 | 0 | case Organization: |
276 | 0 | return "2.5.4.10"; |
277 | 0 | case OrganizationalUnit: |
278 | 0 | return "2.5.4.11"; |
279 | 0 | case Title: |
280 | 0 | return "2.5.4.12"; |
281 | 0 | case GivenName: |
282 | 0 | return "2.5.4.42"; |
283 | 0 | case Initials: |
284 | 0 | return "2.5.4.43"; |
285 | 0 | case GenerationQualifier: |
286 | 0 | return "2.5.4.44"; |
287 | 0 | case DnQualifier: |
288 | 0 | return "2.5.4.46"; |
289 | 0 | case Pseudonym: |
290 | 0 | return "2.5.4.65"; |
291 | 0 | case DomainComponent: |
292 | 0 | return "0.9.2342.19200300.100.1.25"; |
293 | 0 | case EmailAddress: |
294 | 0 | return "1.2.840.113549.1.9.1"; |
295 | 0 | case PostalCode: |
296 | 0 | return "2.5.4.17"; |
297 | 0 | case StreetAddress: |
298 | 0 | return "2.5.4.9"; |
299 | 0 | case BusinessCategory: |
300 | 0 | return "2.5.4.15"; |
301 | 0 | case Unknown: |
302 | 0 | default: |
303 | 0 | return "0.0"; |
304 | 0 | } |
305 | 0 | } |
306 | | |
307 | | static const std::unordered_map<std::string, X520DistinguishedName::Value> X520DistinguishedNameOidMap = { |
308 | | { "2.5.4.3", X520DistinguishedName::CommonName }, |
309 | | { "2.5.4.4", X520DistinguishedName::Surname }, |
310 | | { "2.5.4.5", X520DistinguishedName::SerialNumber }, |
311 | | { "2.5.4.6", X520DistinguishedName::Country }, |
312 | | { "2.5.4.7", X520DistinguishedName::Locality }, |
313 | | { "2.5.4.8", X520DistinguishedName::StateOrProvince }, |
314 | | { "2.5.4.10", X520DistinguishedName::Organization }, |
315 | | { "2.5.4.11", X520DistinguishedName::OrganizationalUnit }, |
316 | | { "2.5.4.12", X520DistinguishedName::Title }, |
317 | | { "2.5.4.42", X520DistinguishedName::GivenName }, |
318 | | { "2.5.4.43", X520DistinguishedName::Initials }, |
319 | | { "2.5.4.44", X520DistinguishedName::GenerationQualifier }, |
320 | | { "2.5.4.46", X520DistinguishedName::DnQualifier }, |
321 | | { "2.5.4.65", X520DistinguishedName::Pseudonym }, |
322 | | { "0.9.2342.19200300.100.1.25", X520DistinguishedName::DomainComponent }, |
323 | | { "1.2.840.113549.1.9.1", X520DistinguishedName::EmailAddress }, |
324 | | { "2.5.4.17", X520DistinguishedName::PostalCode }, |
325 | | { "2.5.4.9", X520DistinguishedName::StreetAddress }, |
326 | | { "2.5.4.15", X520DistinguishedName::BusinessCategory } |
327 | | }; |
328 | | |
329 | | X520DistinguishedName X520DistinguishedName::fromOidValue(const Asn1ObjectIdentifier& value) |
330 | 0 | { |
331 | 0 | std::string oidStringValue = value.toString(); |
332 | |
|
333 | 0 | auto it = X520DistinguishedNameOidMap.find(oidStringValue); |
334 | 0 | if (it != X520DistinguishedNameOidMap.end()) |
335 | 0 | { |
336 | 0 | return { it->second }; |
337 | 0 | } |
338 | | |
339 | 0 | return { Unknown }; |
340 | 0 | } |
341 | | |
342 | | std::string X509ExtensionType::toString() const |
343 | 0 | { |
344 | 0 | switch (m_Value) |
345 | 0 | { |
346 | 0 | case BasicConstraints: |
347 | 0 | return "BasicConstraints"; |
348 | 0 | case KeyUsage: |
349 | 0 | return "KeyUsage"; |
350 | 0 | case ExtendedKeyUsage: |
351 | 0 | return "ExtendedKeyUsage"; |
352 | 0 | case SubjectKeyIdentifier: |
353 | 0 | return "SubjectKeyIdentifier"; |
354 | 0 | case AuthorityKeyIdentifier: |
355 | 0 | return "AuthorityKeyIdentifier"; |
356 | 0 | case SubjectAltName: |
357 | 0 | return "SubjectAltName"; |
358 | 0 | case IssuerAltName: |
359 | 0 | return "IssuerAltName"; |
360 | 0 | case CrlDistributionPoints: |
361 | 0 | return "CRLDistributionPoints"; |
362 | 0 | case AuthorityInfoAccess: |
363 | 0 | return "AuthorityInfoAccess"; |
364 | 0 | case CertificatePolicies: |
365 | 0 | return "CertificatePolicies"; |
366 | 0 | case PolicyMappings: |
367 | 0 | return "PolicyMappings"; |
368 | 0 | case PolicyConstraints: |
369 | 0 | return "PolicyConstraints"; |
370 | 0 | case NameConstraints: |
371 | 0 | return "NameConstraints"; |
372 | 0 | case InhibitAnyPolicy: |
373 | 0 | return "InhibitAnyPolicy"; |
374 | 0 | case CTPrecertificateSCTs: |
375 | 0 | return "CTPrecertificateSCTs"; |
376 | 0 | case SubjectInfoAccess: |
377 | 0 | return "SubjectInfoAccess"; |
378 | 0 | case FreshestCRL: |
379 | 0 | return "FreshestCRL"; |
380 | 0 | case TLSFeature: |
381 | 0 | return "TLSFeature"; |
382 | 0 | case OcspNoCheck: |
383 | 0 | return "OcspNoCheck"; |
384 | 0 | case SubjectDirectoryAttributes: |
385 | 0 | return "SubjectDirectoryAttributes"; |
386 | 0 | case Unknown: |
387 | 0 | default: |
388 | 0 | return "Unknown"; |
389 | 0 | } |
390 | 0 | } |
391 | | |
392 | | std::string X509ExtensionType::getOidValue() const |
393 | 0 | { |
394 | 0 | switch (m_Value) |
395 | 0 | { |
396 | 0 | case BasicConstraints: |
397 | 0 | return "2.5.29.19"; |
398 | 0 | case KeyUsage: |
399 | 0 | return "2.5.29.15"; |
400 | 0 | case ExtendedKeyUsage: |
401 | 0 | return "2.5.29.37"; |
402 | 0 | case SubjectKeyIdentifier: |
403 | 0 | return "2.5.29.14"; |
404 | 0 | case AuthorityKeyIdentifier: |
405 | 0 | return "2.5.29.35"; |
406 | 0 | case SubjectAltName: |
407 | 0 | return "2.5.29.17"; |
408 | 0 | case IssuerAltName: |
409 | 0 | return "2.5.29.18"; |
410 | 0 | case CrlDistributionPoints: |
411 | 0 | return "2.5.29.31"; |
412 | 0 | case AuthorityInfoAccess: |
413 | 0 | return "1.3.6.1.5.5.7.1.1"; |
414 | 0 | case CertificatePolicies: |
415 | 0 | return "2.5.29.32"; |
416 | 0 | case PolicyMappings: |
417 | 0 | return "2.5.29.33"; |
418 | 0 | case PolicyConstraints: |
419 | 0 | return "2.5.29.36"; |
420 | 0 | case NameConstraints: |
421 | 0 | return "2.5.29.30"; |
422 | 0 | case InhibitAnyPolicy: |
423 | 0 | return "2.5.29.54"; |
424 | 0 | case CTPrecertificateSCTs: |
425 | 0 | return "1.3.6.1.4.1.11129.2.4.2"; |
426 | 0 | case SubjectInfoAccess: |
427 | 0 | return "1.3.6.1.5.5.7.1.11"; |
428 | 0 | case FreshestCRL: |
429 | 0 | return "2.5.29.46"; |
430 | 0 | case TLSFeature: |
431 | 0 | return "1.3.6.1.5.5.7.1.24"; |
432 | 0 | case OcspNoCheck: |
433 | 0 | return "1.3.6.1.5.5.7.48.1.5"; |
434 | 0 | case SubjectDirectoryAttributes: |
435 | 0 | return "2.5.29.9"; |
436 | 0 | case Unknown: |
437 | 0 | default: |
438 | 0 | return "0.0"; |
439 | 0 | } |
440 | 0 | } |
441 | | |
442 | | static const std::unordered_map<std::string, X509ExtensionType::Value> X509ExtensionTypeOidMap = { |
443 | | { "2.5.29.19", X509ExtensionType::BasicConstraints }, |
444 | | { "2.5.29.15", X509ExtensionType::KeyUsage }, |
445 | | { "2.5.29.37", X509ExtensionType::ExtendedKeyUsage }, |
446 | | { "2.5.29.14", X509ExtensionType::SubjectKeyIdentifier }, |
447 | | { "2.5.29.35", X509ExtensionType::AuthorityKeyIdentifier }, |
448 | | { "2.5.29.17", X509ExtensionType::SubjectAltName }, |
449 | | { "2.5.29.18", X509ExtensionType::IssuerAltName }, |
450 | | { "2.5.29.31", X509ExtensionType::CrlDistributionPoints }, |
451 | | { "1.3.6.1.5.5.7.1.1", X509ExtensionType::AuthorityInfoAccess }, |
452 | | { "2.5.29.32", X509ExtensionType::CertificatePolicies }, |
453 | | { "2.5.29.33", X509ExtensionType::PolicyMappings }, |
454 | | { "2.5.29.36", X509ExtensionType::PolicyConstraints }, |
455 | | { "2.5.29.30", X509ExtensionType::NameConstraints }, |
456 | | { "2.5.29.54", X509ExtensionType::InhibitAnyPolicy }, |
457 | | { "1.3.6.1.4.1.11129.2.4.2", X509ExtensionType::CTPrecertificateSCTs }, |
458 | | { "1.3.6.1.5.5.7.1.11", X509ExtensionType::SubjectInfoAccess }, |
459 | | { "2.5.29.46", X509ExtensionType::FreshestCRL }, |
460 | | { "1.3.6.1.5.5.7.1.24", X509ExtensionType::TLSFeature }, |
461 | | { "1.3.6.1.5.5.7.48.1.5", X509ExtensionType::OcspNoCheck }, |
462 | | { "2.5.29.9", X509ExtensionType::SubjectDirectoryAttributes }, |
463 | | }; |
464 | | |
465 | | X509ExtensionType X509ExtensionType::fromOidValue(const Asn1ObjectIdentifier& value) |
466 | 0 | { |
467 | 0 | std::string oidStr = value.toString(); |
468 | |
|
469 | 0 | auto it = X509ExtensionTypeOidMap.find(oidStr); |
470 | 0 | if (it != X509ExtensionTypeOidMap.end()) |
471 | 0 | return { it->second }; |
472 | | |
473 | 0 | return { Unknown }; |
474 | 0 | } |
475 | | |
476 | | template <class Asn1RecordType> |
477 | | static Asn1RecordType* castRecordAs(Asn1Record* record, const std::string& fieldName) |
478 | 0 | { |
479 | 0 | try |
480 | 0 | { |
481 | 0 | return record->castAs<Asn1RecordType>(); |
482 | 0 | } |
483 | 0 | catch (const std::bad_cast&) |
484 | 0 | { |
485 | 0 | throw std::runtime_error("Invalid X509 certificate data: " + fieldName); |
486 | 0 | } |
487 | 0 | } Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1IntegerRecord* pcpp::castRecordAs<pcpp::Asn1IntegerRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1ObjectIdentifierRecord* pcpp::castRecordAs<pcpp::Asn1ObjectIdentifierRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1SetRecord* pcpp::castRecordAs<pcpp::Asn1SetRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1TimeRecord* pcpp::castRecordAs<pcpp::Asn1TimeRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1BitStringRecord* pcpp::castRecordAs<pcpp::Asn1BitStringRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1BooleanRecord* pcpp::castRecordAs<pcpp::Asn1BooleanRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1OctetStringRecord* pcpp::castRecordAs<pcpp::Asn1OctetStringRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1SequenceRecord* pcpp::castRecordAs<pcpp::Asn1SequenceRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1ConstructedRecord* pcpp::castRecordAs<pcpp::Asn1ConstructedRecord>(pcpp::Asn1Record*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
488 | | |
489 | | template <class Asn1RecordType> |
490 | | static Asn1RecordType* getSubRecordAndCast(Asn1ConstructedRecord* record, int index, const std::string& fieldName) |
491 | 0 | { |
492 | 0 | try |
493 | 0 | { |
494 | 0 | return castRecordAs<Asn1RecordType>(record->getSubRecords().at(index), fieldName); |
495 | 0 | } |
496 | 0 | catch (const std::out_of_range&) |
497 | 0 | { |
498 | 0 | throw std::runtime_error("Invalid X509 certificate data: " + fieldName); |
499 | 0 | } |
500 | 0 | } Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1IntegerRecord* pcpp::getSubRecordAndCast<pcpp::Asn1IntegerRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1SequenceRecord* pcpp::getSubRecordAndCast<pcpp::Asn1SequenceRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1ObjectIdentifierRecord* pcpp::getSubRecordAndCast<pcpp::Asn1ObjectIdentifierRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1TimeRecord* pcpp::getSubRecordAndCast<pcpp::Asn1TimeRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1BitStringRecord* pcpp::getSubRecordAndCast<pcpp::Asn1BitStringRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1BooleanRecord* pcpp::getSubRecordAndCast<pcpp::Asn1BooleanRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1OctetStringRecord* pcpp::getSubRecordAndCast<pcpp::Asn1OctetStringRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: X509Decoder.cpp:pcpp::Asn1ConstructedRecord* pcpp::getSubRecordAndCast<pcpp::Asn1ConstructedRecord>(pcpp::Asn1ConstructedRecord*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
501 | | |
502 | | std::string X509SerialNumber::toString(const std::string& delimiter) const |
503 | 0 | { |
504 | 0 | if (delimiter.empty()) |
505 | 0 | { |
506 | 0 | return m_SerialNumber; |
507 | 0 | } |
508 | | |
509 | | // Add delimiter |
510 | 0 | std::string result; |
511 | 0 | result.reserve(m_SerialNumber.length() + delimiter.size() * (m_SerialNumber.length() / 2 - 1)); |
512 | |
|
513 | 0 | for (size_t i = 0; i < m_SerialNumber.length(); ++i) |
514 | 0 | { |
515 | 0 | result += m_SerialNumber[i]; |
516 | | // Add a delimiter after every two characters, except for the very last pair |
517 | 0 | if ((i + 1) % 2 == 0 && i + 1 < m_SerialNumber.length()) |
518 | 0 | { |
519 | 0 | result += delimiter; |
520 | 0 | } |
521 | 0 | } |
522 | 0 | return result; |
523 | 0 | } |
524 | | |
525 | | std::string X509Timestamp::toString(const std::string& format, const std::string& timezone, |
526 | | bool includeMilliseconds) const |
527 | 0 | { |
528 | 0 | return m_Record->getValueAsString(format, timezone, includeMilliseconds); |
529 | 0 | } |
530 | | |
531 | | std::chrono::system_clock::time_point X509Timestamp::getTimestamp(const std::string& timezone) const |
532 | 0 | { |
533 | 0 | return m_Record->getValue(timezone); |
534 | 0 | } |
535 | | |
536 | | std::string X509Key::toString(const std::string& delimiter) const |
537 | 0 | { |
538 | 0 | std::ostringstream result; |
539 | 0 | bool first = true; |
540 | |
|
541 | 0 | for (const auto& byte : m_Key) |
542 | 0 | { |
543 | 0 | if (!first) |
544 | 0 | { |
545 | 0 | result << delimiter; |
546 | 0 | } |
547 | 0 | result << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte); |
548 | 0 | first = false; |
549 | 0 | } |
550 | |
|
551 | 0 | return result.str(); |
552 | 0 | } |
553 | | |
554 | | const std::vector<uint8_t>& X509Key::getBytes() const |
555 | 0 | { |
556 | 0 | return m_Key; |
557 | 0 | } |
558 | | |
559 | | namespace X509Internal |
560 | | { |
561 | | X509Version X509VersionRecord::getVersion() const |
562 | 0 | { |
563 | 0 | auto intValue = getSubRecordAndCast<Asn1IntegerRecord>(m_Root, 0, "Version")->getIntValue<uint8_t>(); |
564 | 0 | if (intValue > 3) |
565 | 0 | { |
566 | 0 | throw std::runtime_error("Invalid X509 version value: " + std::to_string(intValue)); |
567 | 0 | } |
568 | | |
569 | 0 | return static_cast<X509Version>(intValue); |
570 | 0 | } |
571 | | |
572 | | bool X509VersionRecord::isValidVersionRecord(const Asn1Record* record) |
573 | 0 | { |
574 | 0 | return record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 0 && |
575 | 0 | record->isConstructed(); |
576 | 0 | } |
577 | | |
578 | | Asn1Record* X509RelativeDistinguishedName::getRecord(int index) const |
579 | 0 | { |
580 | 0 | auto attributeTypeAndValue = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, 0, "RDN"); |
581 | 0 | try |
582 | 0 | { |
583 | 0 | return attributeTypeAndValue->getSubRecords().at(index); |
584 | 0 | } |
585 | 0 | catch (const std::out_of_range&) |
586 | 0 | { |
587 | 0 | throw std::runtime_error("Invalid X509 certificate data: RDN"); |
588 | 0 | } |
589 | 0 | } |
590 | | |
591 | | X520DistinguishedName X509RelativeDistinguishedName::getType() const |
592 | 0 | { |
593 | 0 | auto oidRecord = castRecordAs<Asn1ObjectIdentifierRecord>(getRecord(typeOffset), "RDN Type"); |
594 | 0 | return X520DistinguishedName::fromOidValue(oidRecord->getValue()); |
595 | 0 | } |
596 | | |
597 | | std::string X509RelativeDistinguishedName::getValue() const |
598 | 0 | { |
599 | 0 | auto valueRecord = getRecord(valueOffset); |
600 | 0 | switch (valueRecord->getUniversalTagType()) |
601 | 0 | { |
602 | 0 | case Asn1UniversalTagType::PrintableString: |
603 | 0 | { |
604 | 0 | return valueRecord->castAs<Asn1PrintableStringRecord>()->getValue(); |
605 | 0 | } |
606 | 0 | case Asn1UniversalTagType::IA5String: |
607 | 0 | { |
608 | 0 | return valueRecord->castAs<Asn1IA5StringRecord>()->getValue(); |
609 | 0 | } |
610 | 0 | case Asn1UniversalTagType::UTF8String: |
611 | 0 | { |
612 | 0 | return valueRecord->castAs<Asn1UTF8StringRecord>()->getValue(); |
613 | 0 | } |
614 | 0 | default: |
615 | 0 | { |
616 | 0 | throw std::runtime_error("Invalid X509 certificate data: unsupported RDN value ASN.1 type: " + |
617 | 0 | std::to_string(static_cast<int>(valueRecord->getUniversalTagType()))); |
618 | 0 | } |
619 | 0 | } |
620 | 0 | } |
621 | | |
622 | | std::vector<X509RelativeDistinguishedName> X509Name::getRDNs() const |
623 | 0 | { |
624 | 0 | std::vector<X509RelativeDistinguishedName> result; |
625 | 0 | for (auto const& subRecord : m_Root->getSubRecords()) |
626 | 0 | { |
627 | 0 | result.push_back(X509RelativeDistinguishedName(castRecordAs<Asn1SetRecord>(subRecord, "RDN"))); |
628 | 0 | } |
629 | |
|
630 | 0 | return result; |
631 | 0 | } |
632 | | |
633 | | X509Algorithm X509AlgorithmIdentifier::getAlgorithm() const |
634 | 0 | { |
635 | 0 | auto oidRecord = getSubRecordAndCast<Asn1ObjectIdentifierRecord>(m_Root, algorithmOffset, "Algorithm"); |
636 | 0 | return X509Algorithm::fromOidValue(oidRecord->getValue()); |
637 | 0 | } |
638 | | |
639 | | X509Timestamp X509Validity::getNotBefore() const |
640 | 0 | { |
641 | 0 | return X509Timestamp(getSubRecordAndCast<Asn1TimeRecord>(m_Root, notBeforeOffset, "Not Before")); |
642 | 0 | } |
643 | | |
644 | | X509Timestamp X509Validity::getNotAfter() const |
645 | 0 | { |
646 | 0 | return X509Timestamp(getSubRecordAndCast<Asn1TimeRecord>(m_Root, notAfterOffset, "Not After")); |
647 | 0 | } |
648 | | |
649 | | X509AlgorithmIdentifier X509SubjectPublicKeyInfo::getAlgorithm() const |
650 | 0 | { |
651 | 0 | auto root = |
652 | 0 | getSubRecordAndCast<Asn1SequenceRecord>(m_Root, algorithmOffset, "Subject Public Key Algorithm"); |
653 | 0 | return X509AlgorithmIdentifier(root); |
654 | 0 | } |
655 | | |
656 | | X509Key X509SubjectPublicKeyInfo::getSubjectPublicKey() const |
657 | 0 | { |
658 | 0 | return X509Key( |
659 | 0 | getSubRecordAndCast<Asn1BitStringRecord>(m_Root, subjectPublicKeyOffset, "Subject Public Key") |
660 | 0 | ->getVecValue()); |
661 | 0 | } |
662 | | |
663 | 0 | X509Extension::X509Extension(Asn1SequenceRecord* root) : X509Base(root) |
664 | 0 | { |
665 | 0 | if (root->getSubRecords().size() > 2) |
666 | 0 | { |
667 | 0 | m_CriticalOffset = 1; |
668 | 0 | m_ExtensionValueOffset = 2; |
669 | 0 | } |
670 | 0 | } |
671 | | |
672 | | X509ExtensionType X509Extension::getType() const |
673 | 0 | { |
674 | 0 | auto extensionTypeRecord = |
675 | 0 | getSubRecordAndCast<Asn1ObjectIdentifierRecord>(m_Root, extensionIdOffset, "Extension Type"); |
676 | 0 | return X509ExtensionType::fromOidValue(extensionTypeRecord->getValue()); |
677 | 0 | } |
678 | | |
679 | | bool X509Extension::isCritical() const |
680 | 0 | { |
681 | 0 | if (m_CriticalOffset == -1) |
682 | 0 | { |
683 | 0 | return false; |
684 | 0 | } |
685 | | |
686 | 0 | return getSubRecordAndCast<Asn1BooleanRecord>(m_Root, m_CriticalOffset, "Extension Critical")->getValue(); |
687 | 0 | } |
688 | | |
689 | | std::string X509Extension::getValue() const |
690 | 0 | { |
691 | 0 | return getSubRecordAndCast<Asn1OctetStringRecord>(m_Root, m_ExtensionValueOffset, "Extension Value") |
692 | 0 | ->getValue(); |
693 | 0 | } |
694 | | |
695 | | std::vector<X509Extension> X509Extensions::getExtensions() const |
696 | 0 | { |
697 | 0 | std::vector<X509Extension> result; |
698 | 0 | auto extensionsRecord = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, 0, "Extensions"); |
699 | 0 | for (const auto& extension : extensionsRecord->getSubRecords()) |
700 | 0 | { |
701 | 0 | result.push_back(X509Extension(castRecordAs<Asn1SequenceRecord>(extension, "Extension"))); |
702 | 0 | } |
703 | |
|
704 | 0 | return result; |
705 | 0 | } |
706 | | |
707 | | bool X509Extensions::isValidExtensionsRecord(const Asn1Record* record) |
708 | 0 | { |
709 | 0 | return (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 3 && |
710 | 0 | record->isConstructed()); |
711 | 0 | } |
712 | | |
713 | | X509SerialNumber X509TBSCertificate::getSerialNumber() const |
714 | 0 | { |
715 | 0 | auto serialNumber = getSubRecordAndCast<Asn1IntegerRecord>(m_Root, m_SerialNumberOffset, "Serial Number") |
716 | 0 | ->getValueAsString(true); |
717 | 0 | return X509SerialNumber(serialNumber); |
718 | 0 | } |
719 | | |
720 | | X509AlgorithmIdentifier X509TBSCertificate::getSignature() const |
721 | 0 | { |
722 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_SignatureOffset, "Signature Algorithm"); |
723 | 0 | return X509AlgorithmIdentifier(root); |
724 | 0 | } |
725 | | |
726 | 0 | X509TBSCertificate::X509TBSCertificate(Asn1SequenceRecord* root) : X509Base(root) |
727 | 0 | { |
728 | 0 | try |
729 | 0 | { |
730 | 0 | int currIndex = 0; |
731 | 0 | auto record = root->getSubRecords().at(currIndex); |
732 | 0 | if (X509VersionRecord::isValidVersionRecord(record)) |
733 | 0 | { |
734 | 0 | m_VersionOffset = currIndex++; |
735 | 0 | } |
736 | |
|
737 | 0 | m_SerialNumberOffset = currIndex++; |
738 | 0 | m_SignatureOffset = currIndex++; |
739 | 0 | m_IssuerOffset = currIndex++; |
740 | 0 | m_ValidityOffset = currIndex++; |
741 | 0 | m_SubjectOffset = currIndex++; |
742 | 0 | m_SubjectPublicKeyInfoOffset = currIndex++; |
743 | |
|
744 | 0 | if (root->getSubRecords().size() > static_cast<size_t>(currIndex)) |
745 | 0 | { |
746 | 0 | record = root->getSubRecords().at(currIndex); |
747 | |
|
748 | 0 | if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 1) |
749 | 0 | { |
750 | 0 | m_IssuerUniqueID = currIndex++; |
751 | 0 | record = root->getSubRecords().at(currIndex); |
752 | 0 | } |
753 | |
|
754 | 0 | if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 2) |
755 | 0 | { |
756 | 0 | m_SubjectUniqueID = currIndex++; |
757 | 0 | record = root->getSubRecords().at(currIndex); |
758 | 0 | } |
759 | |
|
760 | 0 | if (X509Extensions::isValidExtensionsRecord(record)) |
761 | 0 | { |
762 | 0 | m_ExtensionsOffset = currIndex++; |
763 | 0 | } |
764 | 0 | } |
765 | 0 | } |
766 | 0 | catch (const std::out_of_range&) |
767 | 0 | { |
768 | 0 | throw std::runtime_error("Invalid X509 certificate data: TBS Certificate"); |
769 | 0 | } |
770 | 0 | } |
771 | | |
772 | | X509Version X509TBSCertificate::getVersion() const |
773 | 0 | { |
774 | 0 | if (m_VersionOffset == -1) |
775 | 0 | { |
776 | 0 | return X509Version::V1; |
777 | 0 | } |
778 | | |
779 | 0 | auto versionAsn1Record = getSubRecordAndCast<Asn1ConstructedRecord>(m_Root, m_VersionOffset, "Version"); |
780 | 0 | auto versionRecord = X509VersionRecord(versionAsn1Record); |
781 | 0 | return versionRecord.getVersion(); |
782 | 0 | } |
783 | | |
784 | | X509Name X509TBSCertificate::getIssuer() const |
785 | 0 | { |
786 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_IssuerOffset, "Issuer"); |
787 | 0 | return X509Name(root); |
788 | 0 | } |
789 | | |
790 | | X509Validity X509TBSCertificate::getValidity() const |
791 | 0 | { |
792 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_ValidityOffset, "Validity"); |
793 | 0 | return X509Validity(root); |
794 | 0 | } |
795 | | |
796 | | X509Name X509TBSCertificate::getSubject() const |
797 | 0 | { |
798 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_SubjectOffset, "Subject"); |
799 | 0 | return X509Name(root); |
800 | 0 | } |
801 | | |
802 | | X509SubjectPublicKeyInfo X509TBSCertificate::getSubjectPublicKeyInfo() const |
803 | 0 | { |
804 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_SubjectPublicKeyInfoOffset, |
805 | 0 | "Subject Public Key Info"); |
806 | 0 | return X509SubjectPublicKeyInfo(root); |
807 | 0 | } |
808 | | |
809 | | std::unique_ptr<X509Extensions> X509TBSCertificate::getExtensions() const |
810 | 0 | { |
811 | 0 | if (m_ExtensionsOffset == -1) |
812 | 0 | { |
813 | 0 | return nullptr; |
814 | 0 | } |
815 | | |
816 | 0 | auto root = getSubRecordAndCast<Asn1ConstructedRecord>(m_Root, m_ExtensionsOffset, "Extensions"); |
817 | 0 | return std::unique_ptr<X509Extensions>(new X509Extensions(root)); |
818 | 0 | } |
819 | | |
820 | | std::unique_ptr<X509Certificate> X509Certificate::decode(const uint8_t* data, size_t dataLen) |
821 | 0 | { |
822 | 0 | return std::unique_ptr<X509Certificate>(new X509Certificate(Asn1Record::decode(data, dataLen))); |
823 | 0 | } |
824 | | |
825 | | Asn1SequenceRecord* X509Certificate::getAsn1Root() const |
826 | 0 | { |
827 | 0 | return castRecordAs<Asn1SequenceRecord>(m_Root.get(), "Root"); |
828 | 0 | } |
829 | | |
830 | | X509TBSCertificate X509Certificate::getTbsCertificate() const |
831 | 0 | { |
832 | 0 | auto root = getSubRecordAndCast<Asn1SequenceRecord>(getAsn1Root(), tbsCertificateOffset, "TBS Certificate"); |
833 | 0 | return X509TBSCertificate(root); |
834 | 0 | } |
835 | | |
836 | | X509AlgorithmIdentifier X509Certificate::getSignatureAlgorithm() const |
837 | 0 | { |
838 | 0 | auto root = |
839 | 0 | getSubRecordAndCast<Asn1SequenceRecord>(getAsn1Root(), signatureAlgorithmOffset, "Signature Algorithm"); |
840 | 0 | return X509AlgorithmIdentifier(root); |
841 | 0 | } |
842 | | |
843 | | X509Key X509Certificate::getSignature() const |
844 | 0 | { |
845 | 0 | return X509Key( |
846 | 0 | getSubRecordAndCast<Asn1BitStringRecord>(getAsn1Root(), signatureOffset, "Signature")->getVecValue()); |
847 | 0 | } |
848 | | |
849 | | std::vector<uint8_t> X509Certificate::encode() |
850 | 0 | { |
851 | 0 | return m_Root->encode(); |
852 | 0 | } |
853 | | } // namespace X509Internal |
854 | | |
855 | | X509Name::X509Name(const X509Internal::X509Name& internalName) |
856 | 0 | { |
857 | 0 | for (const auto& rdn : internalName.getRDNs()) |
858 | 0 | { |
859 | 0 | m_RDNs.emplace_back(RDN{ rdn.getType(), rdn.getValue() }); |
860 | 0 | } |
861 | 0 | } |
862 | | |
863 | | std::string X509Name::toString(const std::string& delimiter) const |
864 | 0 | { |
865 | 0 | std::ostringstream result; |
866 | 0 | bool first = true; |
867 | |
|
868 | 0 | for (const auto& rdn : m_RDNs) |
869 | 0 | { |
870 | 0 | if (!first) |
871 | 0 | { |
872 | 0 | result << delimiter; |
873 | 0 | } |
874 | 0 | result << rdn.type.getShortName() << "=" << rdn.value; |
875 | 0 | first = false; |
876 | 0 | } |
877 | |
|
878 | 0 | return result.str(); |
879 | 0 | } |
880 | | |
881 | | X509Extension::X509Extension(const X509Internal::X509Extension& internalExtension) |
882 | 0 | : m_IsCritical(internalExtension.isCritical()), m_Type(internalExtension.getType()), |
883 | 0 | m_Data(internalExtension.getValue()) |
884 | 0 | {} |
885 | | |
886 | | std::unique_ptr<X509ExtensionData> X509Extension::getData() const |
887 | 0 | { |
888 | 0 | switch (m_Type) |
889 | 0 | { |
890 | 0 | case X509ExtensionType::BasicConstraints: |
891 | 0 | { |
892 | 0 | return std::unique_ptr<X509ExtensionData>(new X509BasicConstraintsExtension(m_Data)); |
893 | 0 | } |
894 | 0 | case X509ExtensionType::SubjectKeyIdentifier: |
895 | 0 | { |
896 | 0 | return std::unique_ptr<X509ExtensionData>(new X509SubjectKeyIdentifierExtension(m_Data)); |
897 | 0 | } |
898 | 0 | case X509ExtensionType::KeyUsage: |
899 | 0 | { |
900 | 0 | return std::unique_ptr<X509ExtensionData>(new X509KeyUsageExtension(m_Data)); |
901 | 0 | } |
902 | 0 | case X509ExtensionType::ExtendedKeyUsage: |
903 | 0 | { |
904 | 0 | return std::unique_ptr<X509ExtensionData>(new X509ExtendedKeyUsageExtension(m_Data)); |
905 | 0 | } |
906 | 0 | default: |
907 | 0 | { |
908 | 0 | return {}; |
909 | 0 | } |
910 | 0 | } |
911 | 0 | } |
912 | | |
913 | | X509Certificate::X509Certificate(uint8_t* derData, size_t derDataLen, bool ownDerData) |
914 | 0 | : m_X509Internal(X509Internal::X509Certificate::decode(derData, derDataLen)), |
915 | 0 | m_TBSCertificate(m_X509Internal->getTbsCertificate()) |
916 | 0 | { |
917 | 0 | if (ownDerData) |
918 | 0 | { |
919 | 0 | m_DerData.reset(derData); |
920 | 0 | } |
921 | 0 | } |
922 | | |
923 | | X509Certificate::X509Certificate(std::unique_ptr<uint8_t[]> derData, size_t derDataLen) |
924 | 0 | : m_X509Internal(X509Internal::X509Certificate::decode(derData.get(), derDataLen)), |
925 | 0 | m_TBSCertificate(m_X509Internal->getTbsCertificate()) |
926 | 0 | { |
927 | 0 | m_DerData = std::move(derData); |
928 | 0 | } |
929 | | |
930 | | X509Version X509Certificate::getVersion() const |
931 | 0 | { |
932 | 0 | return m_TBSCertificate.getVersion(); |
933 | 0 | } |
934 | | |
935 | | const std::vector<X509Extension>& X509Certificate::getExtensions() const |
936 | 0 | { |
937 | 0 | if (!m_ExtensionsParsed) |
938 | 0 | { |
939 | 0 | auto extensions = m_TBSCertificate.getExtensions(); |
940 | 0 | if (extensions != nullptr) |
941 | 0 | { |
942 | 0 | for (const auto& extension : extensions->getExtensions()) |
943 | 0 | { |
944 | 0 | m_Extensions.emplace_back(X509Extension(extension)); |
945 | 0 | } |
946 | 0 | } |
947 | 0 | m_ExtensionsParsed = true; |
948 | 0 | } |
949 | |
|
950 | 0 | return m_Extensions; |
951 | 0 | } |
952 | | |
953 | | bool X509Certificate::hasExtension(const X509ExtensionType& extensionType) const |
954 | 0 | { |
955 | 0 | auto extensions = m_TBSCertificate.getExtensions()->getExtensions(); |
956 | 0 | return std::any_of(extensions.begin(), extensions.end(), |
957 | 0 | [extensionType](const auto& ext) { return ext.getType() == extensionType; }); |
958 | 0 | } |
959 | | |
960 | | const X509Extension* X509Certificate::getExtension(X509ExtensionType extensionType) const |
961 | 0 | { |
962 | 0 | const auto& extensions = getExtensions(); |
963 | 0 | auto matchExtension = |
964 | 0 | std::find_if(extensions.begin(), extensions.end(), [&extensionType](const X509Extension& extension) { |
965 | 0 | return extension.getType() == extensionType; |
966 | 0 | }); |
967 | |
|
968 | 0 | if (matchExtension != extensions.end()) |
969 | 0 | { |
970 | 0 | return &(*matchExtension); |
971 | 0 | } |
972 | | |
973 | 0 | return nullptr; |
974 | 0 | } |
975 | | |
976 | | X509Name X509Certificate::getSubject() const |
977 | 0 | { |
978 | 0 | return X509Name(m_TBSCertificate.getSubject()); |
979 | 0 | } |
980 | | |
981 | | X509Name X509Certificate::getIssuer() const |
982 | 0 | { |
983 | 0 | return X509Name(m_TBSCertificate.getIssuer()); |
984 | 0 | } |
985 | | |
986 | | X509SerialNumber X509Certificate::getSerialNumber() const |
987 | 0 | { |
988 | 0 | return m_TBSCertificate.getSerialNumber(); |
989 | 0 | } |
990 | | |
991 | | X509Timestamp X509Certificate::getNotBefore() const |
992 | 0 | { |
993 | 0 | return m_TBSCertificate.getValidity().getNotBefore(); |
994 | 0 | } |
995 | | |
996 | | X509Timestamp X509Certificate::getNotAfter() const |
997 | 0 | { |
998 | 0 | return m_TBSCertificate.getValidity().getNotAfter(); |
999 | 0 | } |
1000 | | |
1001 | | X509Algorithm X509Certificate::getPublicKeyAlgorithm() const |
1002 | 0 | { |
1003 | 0 | return m_TBSCertificate.getSubjectPublicKeyInfo().getAlgorithm().getAlgorithm(); |
1004 | 0 | } |
1005 | | |
1006 | | X509Key X509Certificate::getPublicKey() const |
1007 | 0 | { |
1008 | 0 | return m_TBSCertificate.getSubjectPublicKeyInfo().getSubjectPublicKey(); |
1009 | 0 | } |
1010 | | |
1011 | | X509Algorithm X509Certificate::getSignatureAlgorithm() const |
1012 | 0 | { |
1013 | 0 | return m_X509Internal->getSignatureAlgorithm().getAlgorithm(); |
1014 | 0 | } |
1015 | | |
1016 | | X509Key X509Certificate::getSignature() const |
1017 | 0 | { |
1018 | 0 | return m_X509Internal->getSignature(); |
1019 | 0 | } |
1020 | | |
1021 | | const X509Internal::X509Certificate* X509Certificate::getRawCertificate() const |
1022 | 0 | { |
1023 | 0 | return m_X509Internal.get(); |
1024 | 0 | } |
1025 | | |
1026 | | std::vector<uint8_t> X509Certificate::toDER() const |
1027 | 0 | { |
1028 | 0 | return m_X509Internal->encode(); |
1029 | 0 | } |
1030 | | |
1031 | | std::string X509Certificate::toPEM() const |
1032 | 0 | { |
1033 | 0 | return PemCodec::encode(m_X509Internal->encode(), pemLabel); |
1034 | 0 | } |
1035 | | |
1036 | | std::string X509Certificate::toJson(int indent) const |
1037 | 0 | { |
1038 | 0 | auto extensions = nlohmann::ordered_json::array(); |
1039 | 0 | for (const auto& extension : getExtensions()) |
1040 | 0 | { |
1041 | 0 | extensions.push_back({ |
1042 | 0 | { "type", extension.getType().toString() }, |
1043 | 0 | { "isCritical", extension.isCritical() }, |
1044 | 0 | }); |
1045 | 0 | } |
1046 | |
|
1047 | 0 | nlohmann::ordered_json certificateJson = { |
1048 | 0 | { "version", static_cast<int>(getVersion()) + 1 }, |
1049 | 0 | { "serialNumber", getSerialNumber().toString() }, |
1050 | 0 | { "issuer", getIssuer().toString() }, |
1051 | 0 | { "validity", |
1052 | 0 | { |
1053 | 0 | { "notBefore", getNotBefore().toString() }, |
1054 | 0 | { "notAfter", getNotAfter().toString() }, |
1055 | 0 | } }, |
1056 | 0 | { "subject", getSubject().toString() }, |
1057 | 0 | { "subjectPublicKeyInfo", |
1058 | 0 | { { "subjectPublicKeyAlgorithm", getPublicKeyAlgorithm().toString() }, |
1059 | 0 | { "subjectPublicKey", getPublicKey().toString() } } }, |
1060 | 0 | { "extensions", extensions }, |
1061 | 0 | { "signatureAlgorithm", getSignatureAlgorithm().toString() }, |
1062 | 0 | { "signature", getSignature().toString() } |
1063 | 0 | }; |
1064 | |
|
1065 | 0 | return certificateJson.dump(indent); |
1066 | 0 | } |
1067 | | } // namespace pcpp |