/src/PcapPlusPlus/Packet++/header/X509Decoder.h
Line | Count | Source |
1 | | #pragma once |
2 | | #include <chrono> |
3 | | #include "Asn1Codec.h" |
4 | | #include "CryptoDataReader.h" |
5 | | #include "X509ExtensionDataDecoder.h" |
6 | | |
7 | | /// @namespace pcpp |
8 | | /// The main namespace for the PcapPlusPlus lib |
9 | | namespace pcpp |
10 | | { |
11 | | /// @enum X509Version |
12 | | /// Represents the version of an X.509 certificate |
13 | | enum class X509Version : uint8_t |
14 | | { |
15 | | /// X.509 Version 1 |
16 | | V1 = 0, |
17 | | /// X.509 Version 2 |
18 | | V2 = 1, |
19 | | /// X.509 Version 3 |
20 | | V3 = 2, |
21 | | }; |
22 | | |
23 | | /// @class X509Algorithm |
24 | | /// Represents cryptographic algorithms used in X.509 certificates |
25 | | /// This class encapsulates various hashing and signature algorithms that can be used |
26 | | /// in X.509 certificates for signing and key exchange. |
27 | | class X509Algorithm |
28 | | { |
29 | | public: |
30 | | /// Define enum types and the corresponding int values |
31 | | enum Value : uint8_t |
32 | | { |
33 | | /// SHA-1 hashing algorithm |
34 | | SHA1, |
35 | | /// SHA-256 hashing algorithm |
36 | | SHA256, |
37 | | /// SHA-384 hashing algorithm |
38 | | SHA384, |
39 | | /// SHA-512 hashing algorithm |
40 | | SHA512, |
41 | | /// MD5 hashing algorithm (considered cryptographically broken) |
42 | | MD5, |
43 | | |
44 | | /// RSA encryption/signature algorithm |
45 | | RSA, |
46 | | /// RSA with SHA-1 signature algorithm |
47 | | RSAWithSHA1, |
48 | | /// RSA with SHA-256 signature algorithm |
49 | | RSAWithSHA256, |
50 | | /// RSA with SHA-384 signature algorithm |
51 | | RSAWithSHA384, |
52 | | /// RSA with SHA-512 signature algorithm |
53 | | RSAWithSHA512, |
54 | | /// RSA Probabilistic Signature Scheme (PSS) |
55 | | RSAPSS, |
56 | | |
57 | | /// Elliptic Curve Digital Signature Algorithm |
58 | | ECDSA, |
59 | | /// ECDSA with SHA-1 signature algorithm |
60 | | ECDSAWithSHA1, |
61 | | /// ECDSA with SHA-256 signature algorithm |
62 | | ECDSAWithSHA256, |
63 | | /// ECDSA with SHA-384 signature algorithm |
64 | | ECDSAWithSHA384, |
65 | | /// ECDSA with SHA-512 signature algorithm |
66 | | ECDSAWithSHA512, |
67 | | |
68 | | /// Digital Signature Algorithm |
69 | | DSA, |
70 | | /// DSA with SHA-1 signature algorithm |
71 | | DSAWithSHA1, |
72 | | /// DSA with SHA-256 signature algorithm |
73 | | DSAWithSHA256, |
74 | | |
75 | | /// EdDSA using Curve25519 (Ed25519) |
76 | | ED25519, |
77 | | /// EdDSA using Curve448 (Ed448) |
78 | | ED448, |
79 | | /// Diffie-Hellman key exchange algorithm |
80 | | DiffieHellman, |
81 | | |
82 | | /// Unknown or unsupported algorithm |
83 | | Unknown, |
84 | | }; |
85 | | |
86 | | X509Algorithm() = default; |
87 | | |
88 | | // cppcheck-suppress noExplicitConstructor |
89 | | /// Construct LdapOperationType from Value enum |
90 | | /// @param[in] value the operation type enum value |
91 | | constexpr X509Algorithm(Value value) : m_Value(value) |
92 | 0 | {} |
93 | | |
94 | | /// @return A string representation of the operation type |
95 | | std::string toString() const; |
96 | | |
97 | | /// @return The OID value of the operation type |
98 | | std::string getOidValue() const; |
99 | | |
100 | | /// A static method that creates LdapOperationType from an integer value |
101 | | /// @param[in] value The operation type integer value |
102 | | /// @return The operation type that corresponds to the integer value. If the integer value |
103 | | /// doesn't correspond to any operation type, LdapOperationType::Unknown is returned |
104 | | static X509Algorithm fromOidValue(const Asn1ObjectIdentifier& value); |
105 | | |
106 | | // Allow switch and comparisons. |
107 | | constexpr operator Value() const |
108 | 0 | { |
109 | 0 | return m_Value; |
110 | 0 | } |
111 | | |
112 | | // Prevent usage: if(LdapOperationType) |
113 | | explicit operator bool() const = delete; |
114 | | |
115 | | private: |
116 | | Value m_Value = Unknown; |
117 | | }; |
118 | | |
119 | | /// @class X520DistinguishedName |
120 | | /// Represents a distinguished name in an X.509 certificate |
121 | | class X520DistinguishedName |
122 | | { |
123 | | public: |
124 | | /// Define enum types and the corresponding int values |
125 | | enum Value : uint8_t |
126 | | { |
127 | | /// Common Name (CN) - Typically the fully qualified domain name (FQDN) |
128 | | CommonName, |
129 | | /// Surname (SN) - Family name of a person |
130 | | Surname, |
131 | | /// Serial Number - Serial number of the certificate |
132 | | SerialNumber, |
133 | | /// Country Name (C) - Two-letter ISO 3166-1 alpha-2 country code |
134 | | Country, |
135 | | /// Locality (L) - City or locality name |
136 | | Locality, |
137 | | /// State or Province Name (ST) - State or province name |
138 | | StateOrProvince, |
139 | | /// Organization Name (O) - Name of the organization |
140 | | Organization, |
141 | | /// Organizational Unit (OU) - Department or division within an organization |
142 | | OrganizationalUnit, |
143 | | /// Title - Job title or position |
144 | | Title, |
145 | | /// Given Name (GN) - First name of a person |
146 | | GivenName, |
147 | | /// Initials - Initials of a person's name |
148 | | Initials, |
149 | | /// Pseudonym - A person's nickname or alias |
150 | | Pseudonym, |
151 | | /// Generation Qualifier - A qualifier indicating a person's generation (e.g., Jr., Sr., III) |
152 | | GenerationQualifier, |
153 | | /// Distinguished Name Qualifier - Disambiguates similar distinguished names |
154 | | DnQualifier, |
155 | | /// Domain Component (DC) - Domain component in domain names (e.g., "example" in "example.com") |
156 | | DomainComponent, |
157 | | /// Email Address - Email address in the format user\@domain |
158 | | EmailAddress, |
159 | | /// Postal Code - Postal or ZIP code |
160 | | PostalCode, |
161 | | /// Street Address - Physical street address |
162 | | StreetAddress, |
163 | | /// Business Category - Type of business or organization |
164 | | BusinessCategory, |
165 | | /// Unknown or unsupported distinguished name type |
166 | | Unknown |
167 | | }; |
168 | | |
169 | | X520DistinguishedName() = default; |
170 | | |
171 | | constexpr X520DistinguishedName(Value value) : m_Value(value) |
172 | 0 | {} |
173 | | |
174 | | /// @return A string representation of the distinguished name |
175 | | std::string toString() const; |
176 | | |
177 | | /// Gets the short name (abbreviation) of the distinguished name |
178 | | /// @return The short name (e.g., "CN" for CommonName) |
179 | | std::string getShortName() const; |
180 | | |
181 | | /// @return The OID value of the distinguished name |
182 | | std::string getOidValue() const; |
183 | | |
184 | | /// Creates an X520DistinguishedName from an OID value |
185 | | /// @param[in] value The ASN.1 object identifier |
186 | | /// @return The corresponding X520DistinguishedName value, or Unknown if no match is found |
187 | | static X520DistinguishedName fromOidValue(const Asn1ObjectIdentifier& value); |
188 | | |
189 | | // Allow switch and comparisons. |
190 | | constexpr operator Value() const |
191 | 0 | { |
192 | 0 | return m_Value; |
193 | 0 | } |
194 | | explicit operator bool() const = delete; |
195 | | |
196 | | private: |
197 | | Value m_Value = Unknown; |
198 | | }; |
199 | | |
200 | | /// @class X509ExtensionType |
201 | | /// Represents an X.509 extension type |
202 | | class X509ExtensionType |
203 | | { |
204 | | public: |
205 | | /// @enum Value |
206 | | /// Enumeration of supported X.509 extension types |
207 | | enum Value : uint8_t |
208 | | { |
209 | | /// Basic Constraints - Indicates if the subject is a CA and the maximum path length |
210 | | BasicConstraints, |
211 | | /// Key Usage - Defines the purpose of the key contained in the certificate |
212 | | KeyUsage, |
213 | | /// Extended Key Usage - Indicates one or more purposes for which the certified public key may be used |
214 | | ExtendedKeyUsage, |
215 | | /// Subject Key Identifier - Provides a means of identifying certificates that contain a particular public |
216 | | /// key |
217 | | SubjectKeyIdentifier, |
218 | | /// Authority Key Identifier - Identifies the public key used to verify the signature on this certificate |
219 | | AuthorityKeyIdentifier, |
220 | | /// Subject Alternative Name - Allows identities to be bound to the subject of the certificate |
221 | | SubjectAltName, |
222 | | /// Issuer Alternative Name - Allows additional identities to be associated with the issuer |
223 | | IssuerAltName, |
224 | | /// CRL Distribution Points - Identifies how CRL information is obtained |
225 | | CrlDistributionPoints, |
226 | | /// Authority Information Access - Describes how to access CA information and services |
227 | | AuthorityInfoAccess, |
228 | | /// Certificate Policies - Contains a sequence of one or more policy terms |
229 | | CertificatePolicies, |
230 | | /// Policy Mappings - Used in CA certificates to indicate that one or more policies can be considered |
231 | | /// equivalent |
232 | | PolicyMappings, |
233 | | /// Policy Constraints - Specifies constraints on path validation |
234 | | PolicyConstraints, |
235 | | /// Name Constraints - Indicates a name space within which all subject names in subsequent certificates must |
236 | | /// be located |
237 | | NameConstraints, |
238 | | /// Inhibit Any Policy - Indicates that the special anyPolicy OID is not considered an explicit match for |
239 | | /// other certificate policies |
240 | | InhibitAnyPolicy, |
241 | | /// Signed Certificate Timestamp - Contains a list of SCTs from Certificate Transparency logs |
242 | | CTPrecertificateSCTs, |
243 | | /// Subject Information Access - Describes how to access additional information about the subject |
244 | | SubjectInfoAccess, |
245 | | /// Freshest CRL - Identifies how delta CRL information is obtained |
246 | | FreshestCRL, |
247 | | /// TLS Feature - Indicates which TLS features are required for the certificate to be used |
248 | | TLSFeature, |
249 | | /// OCSP No Check - Indicates that an OCSP client should trust the certificate for OCSP signing |
250 | | OcspNoCheck, |
251 | | /// Subject Directory Attributes - Conveys identification attributes of the subject |
252 | | SubjectDirectoryAttributes, |
253 | | /// Unknown or unsupported extension type |
254 | | Unknown |
255 | | }; |
256 | | |
257 | | X509ExtensionType() = default; |
258 | | |
259 | | // cppcheck-suppress noExplicitConstructor |
260 | | /// Construct X509ExtensionType from Value enum |
261 | | /// @param[in] value the extension type enum value |
262 | | constexpr X509ExtensionType(Value value) : m_Value(value) |
263 | 0 | {} |
264 | | |
265 | | /// @return A string representation of the extension type |
266 | | std::string toString() const; |
267 | | |
268 | | /// @return The OID value of the extension |
269 | | std::string getOidValue() const; |
270 | | |
271 | | /// Creates an X509ExtensionType from an OID value |
272 | | /// @param[in] value The ASN.1 object identifier |
273 | | /// @return The corresponding X509ExtensionType value, or Unknown if no match is found |
274 | | static X509ExtensionType fromOidValue(const Asn1ObjectIdentifier& value); |
275 | | |
276 | | // Allow switch and comparisons. |
277 | | constexpr operator Value() const |
278 | 0 | { |
279 | 0 | return m_Value; |
280 | 0 | } |
281 | | explicit operator bool() const = delete; |
282 | | |
283 | | private: |
284 | | Value m_Value = Unknown; |
285 | | }; |
286 | | |
287 | | /// @class X509SerialNumber |
288 | | /// Represents the serial number of an X.509 certificate |
289 | | class X509SerialNumber |
290 | | { |
291 | | public: |
292 | | /// Constructs an X509SerialNumber from a serial number hex string |
293 | | /// @param[in] serialNumber The serial number as a hex string |
294 | | explicit X509SerialNumber(const std::string& serialNumber) : m_SerialNumber(serialNumber) |
295 | 0 | {} |
296 | | |
297 | | /// Converts the serial number to a formatted string |
298 | | /// @param[in] delimiter The delimiter to use between the bytes (default: ":") |
299 | | /// @return A formatted string representation of the serial number |
300 | | std::string toString(const std::string& delimiter = ":") const; |
301 | | |
302 | | private: |
303 | | std::string m_SerialNumber; |
304 | | }; |
305 | | |
306 | | /// @class X509Timestamp |
307 | | /// Represents a timestamp in an X.509 certificate |
308 | | class X509Timestamp |
309 | | { |
310 | | public: |
311 | | /// Constructs an X509Timestamp from an ASN.1 time record |
312 | | /// @param[in] timeRecord Pointer to the ASN.1 time record. Note: this class doesn't assume |
313 | | /// ownership over the record |
314 | | explicit X509Timestamp(Asn1TimeRecord* timeRecord) : m_Record(timeRecord) |
315 | 0 | {} |
316 | | |
317 | | /// Converts the timestamp to a formatted string |
318 | | /// @param[in] format The format string (strftime format, default: "%Y-%m-%d %H:%M:%S") |
319 | | /// @param[in] timezone The timezone to use in the format of "Z" for UTC or +=HHMM for other timezones |
320 | | /// (default: "Z" for UTC) |
321 | | /// @param[in] includeMilliseconds Whether to include milliseconds in the output |
322 | | /// @return A formatted string representation of the timestamp |
323 | | std::string toString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z", |
324 | | bool includeMilliseconds = false) const; |
325 | | |
326 | | /// Gets the timestamp as a system_clock::time_point |
327 | | /// @param[in] timezone The timezone to use in the format of "Z" for UTC or +=HHMM for other timezones |
328 | | /// (default: "Z" for UTC) |
329 | | /// @return A time_point representing the timestamp |
330 | | std::chrono::system_clock::time_point getTimestamp(const std::string& timezone = "Z") const; |
331 | | |
332 | | private: |
333 | | Asn1TimeRecord* m_Record; |
334 | | }; |
335 | | |
336 | | /// @class X509Key |
337 | | /// Represents a key in an X.509 certificate |
338 | | class X509Key |
339 | | { |
340 | | public: |
341 | | /// Constructs an X509Key from a byte vector |
342 | | /// @param[in] key The key data as a vector of bytes |
343 | | explicit X509Key(const std::vector<uint8_t>& key) : m_Key(key) |
344 | 0 | {} |
345 | | |
346 | | /// Converts the key to a formatted string |
347 | | /// @param[in] delimiter The delimiter to use between the bytes (default: ":") |
348 | | /// @return A formatted string representation of the key |
349 | | std::string toString(const std::string& delimiter = ":") const; |
350 | | |
351 | | /// Gets the raw key bytes |
352 | | /// @return A const reference to the vector containing the key bytes |
353 | | const std::vector<uint8_t>& getBytes() const; |
354 | | |
355 | | private: |
356 | | std::vector<uint8_t> m_Key; |
357 | | }; |
358 | | |
359 | | /// @namespace X509Internal |
360 | | /// Internal implementation details for X.509 certificate parsing |
361 | | namespace X509Internal |
362 | | { |
363 | | // Forward declarations |
364 | | class X509Certificate; |
365 | | class X509TBSCertificate; |
366 | | class X509Name; |
367 | | class X509SubjectPublicKeyInfo; |
368 | | class X509Extension; |
369 | | class X509Extensions; |
370 | | |
371 | | /// @class X509Base |
372 | | /// @tparam Asn1RecordType The type of ASN.1 record this class wraps |
373 | | /// Base class for X.509 data structures that wrap ASN.1 records |
374 | | template <typename Asn1RecordType> class X509Base |
375 | | { |
376 | | protected: |
377 | 0 | explicit X509Base(Asn1RecordType* root) : m_Root(root) |
378 | 0 | {} Unexecuted instantiation: pcpp::X509Internal::X509Base<pcpp::Asn1SetRecord>::X509Base(pcpp::Asn1SetRecord*) Unexecuted instantiation: pcpp::X509Internal::X509Base<pcpp::Asn1ConstructedRecord>::X509Base(pcpp::Asn1ConstructedRecord*) Unexecuted instantiation: pcpp::X509Internal::X509Base<pcpp::Asn1SequenceRecord>::X509Base(pcpp::Asn1SequenceRecord*) |
379 | | |
380 | | Asn1RecordType* m_Root; |
381 | | }; |
382 | | |
383 | | /// @class X509VersionRecord |
384 | | /// Internal class for handling X.509 version records |
385 | | class X509VersionRecord : public X509Base<Asn1ConstructedRecord> |
386 | | { |
387 | | using X509Base::X509Base; |
388 | | friend class X509TBSCertificate; |
389 | | |
390 | | public: |
391 | | /// Gets the X.509 version from the version record |
392 | | /// @return The X.509 version |
393 | | X509Version getVersion() const; |
394 | | |
395 | | /// Checks if the given ASN.1 record is a valid version record |
396 | | /// @param[in] record The ASN.1 record to check |
397 | | /// @return true if the record is a valid version record, false otherwise |
398 | | static bool isValidVersionRecord(const Asn1Record* record); |
399 | | |
400 | | private: |
401 | | static constexpr int versionOffset = 0; |
402 | | }; |
403 | | |
404 | | /// @class X509RelativeDistinguishedName |
405 | | /// Internal class for handling X.509 Relative Distinguished Names (RDNs) |
406 | | class X509RelativeDistinguishedName : public X509Base<Asn1SetRecord> |
407 | | { |
408 | | using X509Base::X509Base; |
409 | | friend class X509Name; |
410 | | |
411 | | public: |
412 | | /// Gets the type of the RDN |
413 | | /// @return The X520DistinguishedName type of this RDN |
414 | | X520DistinguishedName getType() const; |
415 | | |
416 | | /// Gets the value of the RDN |
417 | | /// @return The string value of this RDN |
418 | | std::string getValue() const; |
419 | | |
420 | | private: |
421 | | static constexpr int typeOffset = 0; |
422 | | static constexpr int valueOffset = 1; |
423 | | |
424 | | Asn1Record* getRecord(int index) const; |
425 | | }; |
426 | | |
427 | | /// @class X509Name |
428 | | /// Internal class for handling X.509 distinguished names |
429 | | class X509Name : public X509Base<Asn1SequenceRecord> |
430 | | { |
431 | | using X509Base::X509Base; |
432 | | friend class X509TBSCertificate; |
433 | | |
434 | | public: |
435 | | /// Gets all Relative Distinguished Names (RDNs) in this name |
436 | | /// @return A vector of X509RelativeDistinguishedName objects |
437 | | std::vector<X509RelativeDistinguishedName> getRDNs() const; |
438 | | }; |
439 | | |
440 | | /// @class X509AlgorithmIdentifier |
441 | | /// Internal class for handling X.509 algorithm identifiers |
442 | | class X509AlgorithmIdentifier : public X509Base<Asn1SequenceRecord> |
443 | | { |
444 | | using X509Base::X509Base; |
445 | | friend class X509SubjectPublicKeyInfo; |
446 | | friend class X509TBSCertificate; |
447 | | friend class X509Certificate; |
448 | | |
449 | | public: |
450 | | /// Gets the algorithm represented by this identifier |
451 | | /// @return The X509Algorithm value |
452 | | X509Algorithm getAlgorithm() const; |
453 | | |
454 | | private: |
455 | | static constexpr int algorithmOffset = 0; |
456 | | }; |
457 | | |
458 | | /// @class X509Validity |
459 | | /// Internal class for handling X.509 certificate validity periods |
460 | | class X509Validity : public X509Base<Asn1SequenceRecord> |
461 | | { |
462 | | using X509Base::X509Base; |
463 | | friend class X509TBSCertificate; |
464 | | |
465 | | public: |
466 | | /// Gets the notBefore timestamp of the validity period |
467 | | /// @return The notBefore timestamp |
468 | | X509Timestamp getNotBefore() const; |
469 | | |
470 | | /// Gets the notAfter timestamp of the validity period |
471 | | /// @return The notAfter timestamp |
472 | | X509Timestamp getNotAfter() const; |
473 | | |
474 | | private: |
475 | | static constexpr int notBeforeOffset = 0; |
476 | | static constexpr int notAfterOffset = 1; |
477 | | }; |
478 | | |
479 | | /// @class X509SubjectPublicKeyInfo |
480 | | /// Internal class for handling X.509 subject public key information |
481 | | class X509SubjectPublicKeyInfo : public X509Base<Asn1SequenceRecord> |
482 | | { |
483 | | using X509Base::X509Base; |
484 | | friend class X509TBSCertificate; |
485 | | |
486 | | public: |
487 | | /// Gets the algorithm identifier for the public key |
488 | | /// @return The X509AlgorithmIdentifier for the public key |
489 | | X509AlgorithmIdentifier getAlgorithm() const; |
490 | | |
491 | | /// Gets the subject's public key |
492 | | /// @return The X509Key containing the public key |
493 | | X509Key getSubjectPublicKey() const; |
494 | | |
495 | | private: |
496 | | static constexpr int algorithmOffset = 0; |
497 | | static constexpr int subjectPublicKeyOffset = 1; |
498 | | }; |
499 | | |
500 | | /// @class X509Extension |
501 | | /// Internal class for handling X.509 extension records |
502 | | class X509Extension : public X509Base<Asn1SequenceRecord> |
503 | | { |
504 | | friend class X509Extensions; |
505 | | using X509Base::X509Base; |
506 | | |
507 | | public: |
508 | | /// Gets the type of this extension |
509 | | /// @return The X509ExtensionType of this extension |
510 | | X509ExtensionType getType() const; |
511 | | |
512 | | /// Checks if this extension is marked as critical |
513 | | /// @return true if the extension is critical, false otherwise |
514 | | bool isCritical() const; |
515 | | |
516 | | /// Gets the value of this extension |
517 | | /// @return The extension value as a string |
518 | | std::string getValue() const; |
519 | | |
520 | | private: |
521 | | static constexpr int extensionIdOffset = 0; |
522 | | |
523 | | int m_CriticalOffset = -1; |
524 | | int m_ExtensionValueOffset = 1; |
525 | | |
526 | | X509Extension(Asn1SequenceRecord* root); |
527 | | }; |
528 | | |
529 | | /// @class X509Extensions |
530 | | /// Internal class for handling X.509 extensions record |
531 | | class X509Extensions : public X509Base<Asn1ConstructedRecord> |
532 | | { |
533 | | using X509Base::X509Base; |
534 | | friend class X509TBSCertificate; |
535 | | |
536 | | public: |
537 | | /// Gets all extensions in this record |
538 | | /// @return A vector of X509Extension objects |
539 | | std::vector<X509Extension> getExtensions() const; |
540 | | |
541 | | /// Checks if the given ASN.1 record is a valid extensions record |
542 | | /// @param[in] record The ASN.1 record to check |
543 | | /// @return true if the record is a valid extensions record, false otherwise |
544 | | static bool isValidExtensionsRecord(const Asn1Record* record); |
545 | | }; |
546 | | |
547 | | /// @class X509TBSCertificate |
548 | | /// Internal class for handling the To-Be-Signed (TBS) portion of an X.509 certificate |
549 | | class X509TBSCertificate : public X509Base<Asn1SequenceRecord> |
550 | | { |
551 | | using X509Base::X509Base; |
552 | | friend class X509Certificate; |
553 | | |
554 | | public: |
555 | | /// Gets the version of the TBS certificate |
556 | | /// @return The X509Version of the certificate |
557 | | X509Version getVersion() const; |
558 | | |
559 | | /// Gets the serial number of the TBS certificate |
560 | | /// @return The X509SerialNumber of the certificate |
561 | | X509SerialNumber getSerialNumber() const; |
562 | | |
563 | | /// Gets the signature algorithm of the TBS certificate |
564 | | /// @return The X509AlgorithmIdentifier for the signature |
565 | | X509AlgorithmIdentifier getSignature() const; |
566 | | |
567 | | /// Gets the issuer name from the TBS certificate |
568 | | /// @return The X509Name of the issuer |
569 | | X509Name getIssuer() const; |
570 | | |
571 | | /// Gets the validity period of the TBS certificate |
572 | | /// @return The X509Validity object containing notBefore and notAfter timestamps |
573 | | X509Validity getValidity() const; |
574 | | |
575 | | /// Gets the subject name from the TBS certificate |
576 | | /// @return The X509Name of the subject |
577 | | X509Name getSubject() const; |
578 | | |
579 | | /// Gets the subject's public key information |
580 | | /// @return The X509SubjectPublicKeyInfo containing the public key |
581 | | X509SubjectPublicKeyInfo getSubjectPublicKeyInfo() const; |
582 | | |
583 | | /// Gets the extensions from the TBS certificate |
584 | | /// @return A unique_ptr to X509Extensions, or nullptr if no extensions are present |
585 | | std::unique_ptr<X509Extensions> getExtensions() const; |
586 | | |
587 | | private: |
588 | | int m_VersionOffset = -1; |
589 | | int m_SerialNumberOffset = 0; |
590 | | int m_SignatureOffset = 1; |
591 | | int m_IssuerOffset = 2; |
592 | | int m_ValidityOffset = 3; |
593 | | int m_SubjectOffset = 4; |
594 | | int m_SubjectPublicKeyInfoOffset = 5; |
595 | | int m_IssuerUniqueID = -1; |
596 | | int m_SubjectUniqueID = -1; |
597 | | int m_ExtensionsOffset = -1; |
598 | | |
599 | | X509TBSCertificate(Asn1SequenceRecord* root); |
600 | | }; |
601 | | |
602 | | /// @class X509Certificate |
603 | | /// Internal class for handling X.509 certificate parsing and encoding |
604 | | class X509Certificate |
605 | | { |
606 | | public: |
607 | | /// Gets the TBS (To Be Signed) portion of the certificate |
608 | | /// @return The X509TBSCertificate containing the TBS data |
609 | | X509TBSCertificate getTbsCertificate() const; |
610 | | |
611 | | /// Gets the signature algorithm used to sign the certificate |
612 | | /// @return The X509AlgorithmIdentifier for the signature |
613 | | X509AlgorithmIdentifier getSignatureAlgorithm() const; |
614 | | |
615 | | /// Gets the signature value from the certificate |
616 | | /// @return The X509Key containing the signature |
617 | | X509Key getSignature() const; |
618 | | |
619 | | /// Gets the root ASN.1 record of the certificate |
620 | | /// @return Pointer to the root ASN.1 sequence record |
621 | | Asn1SequenceRecord* getAsn1Root() const; |
622 | | |
623 | | /// Decodes an X.509 certificate from binary data |
624 | | /// @param[in] data Pointer to the binary certificate data |
625 | | /// @param[in] dataLen Length of the binary data |
626 | | /// @return A unique_ptr to the decoded X509Certificate, or nullptr on failure |
627 | | static std::unique_ptr<X509Certificate> decode(const uint8_t* data, size_t dataLen); |
628 | | |
629 | | /// Encodes the certificate to binary DER format |
630 | | /// @return A vector containing the DER-encoded certificate |
631 | | std::vector<uint8_t> encode(); |
632 | | |
633 | | private: |
634 | | static constexpr int tbsCertificateOffset = 0; |
635 | | static constexpr int signatureAlgorithmOffset = 1; |
636 | | static constexpr int signatureOffset = 2; |
637 | | |
638 | | explicit X509Certificate(std::unique_ptr<Asn1Record> root) : m_Root(std::move(root)) |
639 | 0 | {} |
640 | | |
641 | | std::unique_ptr<Asn1Record> m_Root; |
642 | | }; |
643 | | } // namespace X509Internal |
644 | | |
645 | | // Forward declarations |
646 | | class X509Certificate; |
647 | | |
648 | | /// @class X509Name |
649 | | /// Represents a name in an X.509 certificate |
650 | | class X509Name |
651 | | { |
652 | | friend class X509Certificate; |
653 | | |
654 | | public: |
655 | | /// @struct RDN |
656 | | /// Represents a Relative Distinguished Name (RDN) in an X.509 certificate |
657 | | struct RDN |
658 | | { |
659 | | X520DistinguishedName type; ///< The type of the distinguished name |
660 | | std::string value; ///< The value of the distinguished name |
661 | | |
662 | | /// Equality comparison operator |
663 | | bool operator==(const RDN& other) const |
664 | 0 | { |
665 | 0 | return type == other.type && value == other.value; |
666 | 0 | } |
667 | | |
668 | | /// Inequality comparison operator |
669 | | bool operator!=(const RDN& other) const |
670 | 0 | { |
671 | 0 | return !(*this == other); |
672 | 0 | } |
673 | | |
674 | | /// Stream output operator for RDN |
675 | | friend std::ostream& operator<<(std::ostream& os, const RDN& rdn) |
676 | 0 | { |
677 | 0 | os << "RDN{type=" << rdn.type.getShortName() << ", value=" << rdn.value << "}"; |
678 | 0 | return os; |
679 | 0 | } |
680 | | }; |
681 | | |
682 | | /// Converts the X509Name to a string representation, e.g C=US, ST=California, CN=example.com |
683 | | /// @param[in] delimiter The delimiter to use between RDNs (default: ", ") |
684 | | /// @return A string representation of the X509Name |
685 | | std::string toString(const std::string& delimiter = ", ") const; |
686 | | |
687 | | /// Gets the list of Relative Distinguished Names (RDNs) |
688 | | /// @return A vector of RDN objects |
689 | | const std::vector<RDN>& getRDNs() const |
690 | 0 | { |
691 | 0 | return m_RDNs; |
692 | 0 | } |
693 | | |
694 | | private: |
695 | | explicit X509Name(const X509Internal::X509Name& internalName); |
696 | | std::vector<RDN> m_RDNs; |
697 | | }; |
698 | | |
699 | | /// @class X509Extension |
700 | | /// Represents an X.509 extension |
701 | | class X509Extension |
702 | | { |
703 | | friend class X509Certificate; |
704 | | |
705 | | public: |
706 | | /// Gets the type of this X.509 extension |
707 | | /// @return The X509ExtensionType representing the extension type |
708 | | X509ExtensionType getType() const |
709 | 0 | { |
710 | 0 | return m_Type; |
711 | 0 | } |
712 | | |
713 | | /// Checks if this extension is marked as critical |
714 | | /// @return true if the extension is critical, false otherwise |
715 | | bool isCritical() const |
716 | 0 | { |
717 | 0 | return m_IsCritical; |
718 | 0 | } |
719 | | |
720 | | /// Gets the extension parsed data |
721 | | /// @return A unique_ptr to an object containing the parsed extension data if such class exists |
722 | | /// (not all extensions have parsed data classes), or nullptr if it doesn't |
723 | | std::unique_ptr<X509ExtensionData> getData() const; |
724 | | |
725 | | /// Gets the extension data as a hex string |
726 | | /// @return A string containing the extension data in hex format |
727 | | std::string getRawDataAsHexString() const |
728 | 0 | { |
729 | 0 | return m_Data; |
730 | 0 | } |
731 | | |
732 | | private: |
733 | | X509Extension(const X509Internal::X509Extension& internalExtension); |
734 | | |
735 | | bool m_IsCritical; |
736 | | X509ExtensionType m_Type; |
737 | | std::string m_Data; |
738 | | }; |
739 | | |
740 | | /// @class X509Certificate |
741 | | /// Represents an X.509 certificate |
742 | | class X509Certificate : public internal::CryptoDataReader<X509Certificate> |
743 | | { |
744 | | public: |
745 | | /// Gets the version of the certificate |
746 | | /// @return The X509Version of the certificate |
747 | | X509Version getVersion() const; |
748 | | |
749 | | /// Gets the serial number of the certificate |
750 | | /// @return The certificate's serial number |
751 | | X509SerialNumber getSerialNumber() const; |
752 | | |
753 | | /// Gets the issuer of the certificate |
754 | | /// @return The certificate's issuer name |
755 | | X509Name getIssuer() const; |
756 | | |
757 | | /// Gets the subject of the certificate |
758 | | /// @return The certificate's subject name |
759 | | X509Name getSubject() const; |
760 | | |
761 | | /// Gets the notBefore timestamp of the certificate's validity period |
762 | | /// @return The notBefore timestamp |
763 | | X509Timestamp getNotBefore() const; |
764 | | |
765 | | /// Gets the notAfter timestamp of the certificate's validity period |
766 | | /// @return The notAfter timestamp |
767 | | X509Timestamp getNotAfter() const; |
768 | | |
769 | | /// Gets the public key algorithm used in the certificate |
770 | | /// @return The public key algorithm |
771 | | X509Algorithm getPublicKeyAlgorithm() const; |
772 | | |
773 | | /// Gets the public key from the certificate |
774 | | /// @return The public key |
775 | | X509Key getPublicKey() const; |
776 | | |
777 | | /// Gets the signature algorithm used to sign the certificate |
778 | | /// @return The signature algorithm |
779 | | X509Algorithm getSignatureAlgorithm() const; |
780 | | |
781 | | /// Gets the signature of the certificate |
782 | | /// @return The certificate's signature |
783 | | X509Key getSignature() const; |
784 | | |
785 | | /// Gets the list of extensions in the certificate |
786 | | /// @return A vector containing the certificate's extensions |
787 | | const std::vector<X509Extension>& getExtensions() const; |
788 | | |
789 | | /// Checks if the certificate has a specific extension |
790 | | /// @param[in] extensionType The extension type to check for |
791 | | /// @return true if the extension is present, false otherwise |
792 | | bool hasExtension(const X509ExtensionType& extensionType) const; |
793 | | |
794 | | /// Gets an extension by its type |
795 | | /// @param[in] extensionType The type of extension to get |
796 | | /// @return Pointer to the extension if found or nullptr otherwise |
797 | | const X509Extension* getExtension(X509ExtensionType extensionType) const; |
798 | | |
799 | | /// Converts the certificate to DER-encoded format |
800 | | /// @return A byte vector containing the DER-encoded data |
801 | | std::vector<uint8_t> toDER() const; |
802 | | |
803 | | /// Converts the certificate to PEM-encoded format |
804 | | /// @return A string containing the PEM-encoded data |
805 | | std::string toPEM() const; |
806 | | |
807 | | /// Converts the certificate to a JSON string representation |
808 | | /// @param[in] indent Number of spaces to use for indentation (-1 for no pretty printing) |
809 | | /// @return A JSON string representation of the certificate |
810 | | std::string toJson(int indent = -1) const; |
811 | | |
812 | | /// Gets the raw internal certificate object |
813 | | /// @return Pointer to the internal X509Certificate implementation |
814 | | const X509Internal::X509Certificate* getRawCertificate() const; |
815 | | |
816 | | // Prevent copying |
817 | | X509Certificate(const X509Certificate&) = delete; |
818 | | X509Certificate& operator=(const X509Certificate&) = delete; |
819 | | |
820 | | private: |
821 | | // Constructor/Destructor |
822 | | X509Certificate(uint8_t* derData, size_t derDataLen, bool ownDerData); |
823 | | X509Certificate(std::unique_ptr<uint8_t[]> derData, size_t derDataLen); |
824 | | |
825 | | friend class internal::CryptoDataReader<X509Certificate>; |
826 | | |
827 | | std::unique_ptr<X509Internal::X509Certificate> m_X509Internal; |
828 | | X509Internal::X509TBSCertificate m_TBSCertificate; |
829 | | mutable std::vector<X509Extension> m_Extensions; |
830 | | mutable bool m_ExtensionsParsed = false; |
831 | | std::unique_ptr<uint8_t[]> m_DerData; |
832 | | |
833 | | static constexpr const char* pemLabel = "CERTIFICATE"; |
834 | | }; |
835 | | } // namespace pcpp |