Coverage Report

Created: 2026-09-28 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
    // cppcheck-suppress noExplicitConstructor
172
    constexpr X520DistinguishedName(Value value) : m_Value(value)
173
0
    {}
174
175
    /// @return A string representation of the distinguished name
176
    std::string toString() const;
177
178
    /// Gets the short name (abbreviation) of the distinguished name
179
    /// @return The short name (e.g., "CN" for CommonName)
180
    std::string getShortName() const;
181
182
    /// @return The OID value of the distinguished name
183
    std::string getOidValue() const;
184
185
    /// Creates an X520DistinguishedName from an OID value
186
    /// @param[in] value The ASN.1 object identifier
187
    /// @return The corresponding X520DistinguishedName value, or Unknown if no match is found
188
    static X520DistinguishedName fromOidValue(const Asn1ObjectIdentifier& value);
189
190
    // Allow switch and comparisons.
191
    constexpr operator Value() const
192
0
    {
193
0
      return m_Value;
194
0
    }
195
    explicit operator bool() const = delete;
196
197
  private:
198
    Value m_Value = Unknown;
199
  };
200
201
  /// @class X509ExtensionType
202
  /// Represents an X.509 extension type
203
  class X509ExtensionType
204
  {
205
  public:
206
    /// @enum Value
207
    /// Enumeration of supported X.509 extension types
208
    enum Value : uint8_t
209
    {
210
      /// Basic Constraints - Indicates if the subject is a CA and the maximum path length
211
      BasicConstraints,
212
      /// Key Usage - Defines the purpose of the key contained in the certificate
213
      KeyUsage,
214
      /// Extended Key Usage - Indicates one or more purposes for which the certified public key may be used
215
      ExtendedKeyUsage,
216
      /// Subject Key Identifier - Provides a means of identifying certificates that contain a particular public
217
      /// key
218
      SubjectKeyIdentifier,
219
      /// Authority Key Identifier - Identifies the public key used to verify the signature on this certificate
220
      AuthorityKeyIdentifier,
221
      /// Subject Alternative Name - Allows identities to be bound to the subject of the certificate
222
      SubjectAltName,
223
      /// Issuer Alternative Name - Allows additional identities to be associated with the issuer
224
      IssuerAltName,
225
      /// CRL Distribution Points - Identifies how CRL information is obtained
226
      CrlDistributionPoints,
227
      /// Authority Information Access - Describes how to access CA information and services
228
      AuthorityInfoAccess,
229
      /// Certificate Policies - Contains a sequence of one or more policy terms
230
      CertificatePolicies,
231
      /// Policy Mappings - Used in CA certificates to indicate that one or more policies can be considered
232
      /// equivalent
233
      PolicyMappings,
234
      /// Policy Constraints - Specifies constraints on path validation
235
      PolicyConstraints,
236
      /// Name Constraints - Indicates a name space within which all subject names in subsequent certificates must
237
      /// be located
238
      NameConstraints,
239
      /// Inhibit Any Policy - Indicates that the special anyPolicy OID is not considered an explicit match for
240
      /// other certificate policies
241
      InhibitAnyPolicy,
242
      /// Signed Certificate Timestamp - Contains a list of SCTs from Certificate Transparency logs
243
      CTPrecertificateSCTs,
244
      /// Subject Information Access - Describes how to access additional information about the subject
245
      SubjectInfoAccess,
246
      /// Freshest CRL - Identifies how delta CRL information is obtained
247
      FreshestCRL,
248
      /// TLS Feature - Indicates which TLS features are required for the certificate to be used
249
      TLSFeature,
250
      /// OCSP No Check - Indicates that an OCSP client should trust the certificate for OCSP signing
251
      OcspNoCheck,
252
      /// Subject Directory Attributes - Conveys identification attributes of the subject
253
      SubjectDirectoryAttributes,
254
      /// Unknown or unsupported extension type
255
      Unknown
256
    };
257
258
    X509ExtensionType() = default;
259
260
    // cppcheck-suppress noExplicitConstructor
261
    /// Construct X509ExtensionType from Value enum
262
    /// @param[in] value the extension type enum value
263
    constexpr X509ExtensionType(Value value) : m_Value(value)
264
0
    {}
265
266
    /// @return A string representation of the extension type
267
    std::string toString() const;
268
269
    /// @return The OID value of the extension
270
    std::string getOidValue() const;
271
272
    /// Creates an X509ExtensionType from an OID value
273
    /// @param[in] value The ASN.1 object identifier
274
    /// @return The corresponding X509ExtensionType value, or Unknown if no match is found
275
    static X509ExtensionType fromOidValue(const Asn1ObjectIdentifier& value);
276
277
    // Allow switch and comparisons.
278
    constexpr operator Value() const
279
0
    {
280
0
      return m_Value;
281
0
    }
282
    explicit operator bool() const = delete;
283
284
  private:
285
    Value m_Value = Unknown;
286
  };
287
288
  /// @class X509SerialNumber
289
  /// Represents the serial number of an X.509 certificate
290
  class X509SerialNumber
291
  {
292
  public:
293
    /// Constructs an X509SerialNumber from a serial number hex string
294
    /// @param[in] serialNumber The serial number as a hex string
295
    explicit X509SerialNumber(const std::string& serialNumber) : m_SerialNumber(serialNumber)
296
0
    {}
297
298
    /// Converts the serial number to a formatted string
299
    /// @param[in] delimiter The delimiter to use between the bytes (default: ":")
300
    /// @return A formatted string representation of the serial number
301
    std::string toString(const std::string& delimiter = ":") const;
302
303
  private:
304
    std::string m_SerialNumber;
305
  };
306
307
  /// @class X509Timestamp
308
  /// Represents a timestamp in an X.509 certificate
309
  class X509Timestamp
310
  {
311
  public:
312
    /// Constructs an X509Timestamp from an ASN.1 time record
313
    /// @param[in] timeRecord Pointer to the ASN.1 time record. Note: this class doesn't assume
314
    /// ownership over the record
315
    explicit X509Timestamp(Asn1TimeRecord* timeRecord) : m_Record(timeRecord)
316
0
    {}
317
318
    /// Converts the timestamp to a formatted string
319
    /// @param[in] format The format string (strftime format, default: "%Y-%m-%d %H:%M:%S")
320
    /// @param[in] timezone The timezone to use in the format of "Z" for UTC or +=HHMM for other timezones
321
    /// (default: "Z" for UTC)
322
    /// @param[in] includeMilliseconds Whether to include milliseconds in the output
323
    /// @return A formatted string representation of the timestamp
324
    std::string toString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z",
325
                         bool includeMilliseconds = false) const;
326
327
    /// Gets the timestamp as a system_clock::time_point
328
    /// @param[in] timezone The timezone to use in the format of "Z" for UTC or +=HHMM for other timezones
329
    /// (default: "Z" for UTC)
330
    /// @return A time_point representing the timestamp
331
    std::chrono::system_clock::time_point getTimestamp(const std::string& timezone = "Z") const;
332
333
  private:
334
    Asn1TimeRecord* m_Record;
335
  };
336
337
  /// @class X509Key
338
  /// Represents a key in an X.509 certificate
339
  class X509Key
340
  {
341
  public:
342
    /// Constructs an X509Key from a byte vector
343
    /// @param[in] key The key data as a vector of bytes
344
    explicit X509Key(const std::vector<uint8_t>& key) : m_Key(key)
345
0
    {}
346
347
    /// Converts the key to a formatted string
348
    /// @param[in] delimiter The delimiter to use between the bytes (default: ":")
349
    /// @return A formatted string representation of the key
350
    std::string toString(const std::string& delimiter = ":") const;
351
352
    /// Gets the raw key bytes
353
    /// @return A const reference to the vector containing the key bytes
354
    const std::vector<uint8_t>& getBytes() const;
355
356
  private:
357
    std::vector<uint8_t> m_Key;
358
  };
359
360
  /// @namespace X509Internal
361
  /// Internal implementation details for X.509 certificate parsing
362
  namespace X509Internal
363
  {
364
    // Forward declarations
365
    class X509Certificate;
366
    class X509TBSCertificate;
367
    class X509Name;
368
    class X509SubjectPublicKeyInfo;
369
    class X509Extension;
370
    class X509Extensions;
371
372
    /// @class X509Base
373
    /// @tparam Asn1RecordType The type of ASN.1 record this class wraps
374
    /// Base class for X.509 data structures that wrap ASN.1 records
375
    template <typename Asn1RecordType> class X509Base
376
    {
377
    protected:
378
0
      explicit X509Base(Asn1RecordType* root) : m_Root(root)
379
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*)
380
381
      Asn1RecordType* m_Root;
382
    };
383
384
    /// @class X509VersionRecord
385
    /// Internal class for handling X.509 version records
386
    class X509VersionRecord : public X509Base<Asn1ConstructedRecord>
387
    {
388
      using X509Base::X509Base;
389
      friend class X509TBSCertificate;
390
391
    public:
392
      /// Gets the X.509 version from the version record
393
      /// @return The X.509 version
394
      X509Version getVersion() const;
395
396
      /// Checks if the given ASN.1 record is a valid version record
397
      /// @param[in] record The ASN.1 record to check
398
      /// @return true if the record is a valid version record, false otherwise
399
      static bool isValidVersionRecord(const Asn1Record* record);
400
401
    private:
402
      static constexpr int versionOffset = 0;
403
    };
404
405
    /// @class X509RelativeDistinguishedName
406
    /// Internal class for handling X.509 Relative Distinguished Names (RDNs)
407
    class X509RelativeDistinguishedName : public X509Base<Asn1SetRecord>
408
    {
409
      using X509Base::X509Base;
410
      friend class X509Name;
411
412
    public:
413
      /// Gets the type of the RDN
414
      /// @return The X520DistinguishedName type of this RDN
415
      X520DistinguishedName getType() const;
416
417
      /// Gets the value of the RDN
418
      /// @return The string value of this RDN
419
      std::string getValue() const;
420
421
    private:
422
      static constexpr int typeOffset = 0;
423
      static constexpr int valueOffset = 1;
424
425
      Asn1Record* getRecord(int index) const;
426
    };
427
428
    /// @class X509Name
429
    /// Internal class for handling X.509 distinguished names
430
    class X509Name : public X509Base<Asn1SequenceRecord>
431
    {
432
      using X509Base::X509Base;
433
      friend class X509TBSCertificate;
434
435
    public:
436
      /// Gets all Relative Distinguished Names (RDNs) in this name
437
      /// @return A vector of X509RelativeDistinguishedName objects
438
      std::vector<X509RelativeDistinguishedName> getRDNs() const;
439
    };
440
441
    /// @class X509AlgorithmIdentifier
442
    /// Internal class for handling X.509 algorithm identifiers
443
    class X509AlgorithmIdentifier : public X509Base<Asn1SequenceRecord>
444
    {
445
      using X509Base::X509Base;
446
      friend class X509SubjectPublicKeyInfo;
447
      friend class X509TBSCertificate;
448
      friend class X509Certificate;
449
450
    public:
451
      /// Gets the algorithm represented by this identifier
452
      /// @return The X509Algorithm value
453
      X509Algorithm getAlgorithm() const;
454
455
    private:
456
      static constexpr int algorithmOffset = 0;
457
    };
458
459
    /// @class X509Validity
460
    /// Internal class for handling X.509 certificate validity periods
461
    class X509Validity : public X509Base<Asn1SequenceRecord>
462
    {
463
      using X509Base::X509Base;
464
      friend class X509TBSCertificate;
465
466
    public:
467
      /// Gets the notBefore timestamp of the validity period
468
      /// @return The notBefore timestamp
469
      X509Timestamp getNotBefore() const;
470
471
      /// Gets the notAfter timestamp of the validity period
472
      /// @return The notAfter timestamp
473
      X509Timestamp getNotAfter() const;
474
475
    private:
476
      static constexpr int notBeforeOffset = 0;
477
      static constexpr int notAfterOffset = 1;
478
    };
479
480
    /// @class X509SubjectPublicKeyInfo
481
    /// Internal class for handling X.509 subject public key information
482
    class X509SubjectPublicKeyInfo : public X509Base<Asn1SequenceRecord>
483
    {
484
      using X509Base::X509Base;
485
      friend class X509TBSCertificate;
486
487
    public:
488
      /// Gets the algorithm identifier for the public key
489
      /// @return The X509AlgorithmIdentifier for the public key
490
      X509AlgorithmIdentifier getAlgorithm() const;
491
492
      /// Gets the subject's public key
493
      /// @return The X509Key containing the public key
494
      X509Key getSubjectPublicKey() const;
495
496
    private:
497
      static constexpr int algorithmOffset = 0;
498
      static constexpr int subjectPublicKeyOffset = 1;
499
    };
500
501
    /// @class X509Extension
502
    /// Internal class for handling X.509 extension records
503
    class X509Extension : public X509Base<Asn1SequenceRecord>
504
    {
505
      friend class X509Extensions;
506
      using X509Base::X509Base;
507
508
    public:
509
      /// Gets the type of this extension
510
      /// @return The X509ExtensionType of this extension
511
      X509ExtensionType getType() const;
512
513
      /// Checks if this extension is marked as critical
514
      /// @return true if the extension is critical, false otherwise
515
      bool isCritical() const;
516
517
      /// Gets the value of this extension
518
      /// @return The extension value as a string
519
      std::string getValue() const;
520
521
    private:
522
      static constexpr int extensionIdOffset = 0;
523
524
      int m_CriticalOffset = -1;
525
      int m_ExtensionValueOffset = 1;
526
527
      explicit X509Extension(Asn1SequenceRecord* root);
528
    };
529
530
    /// @class X509Extensions
531
    /// Internal class for handling X.509 extensions record
532
    class X509Extensions : public X509Base<Asn1ConstructedRecord>
533
    {
534
      using X509Base::X509Base;
535
      friend class X509TBSCertificate;
536
537
    public:
538
      /// Gets all extensions in this record
539
      /// @return A vector of X509Extension objects
540
      std::vector<X509Extension> getExtensions() const;
541
542
      /// Checks if the given ASN.1 record is a valid extensions record
543
      /// @param[in] record The ASN.1 record to check
544
      /// @return true if the record is a valid extensions record, false otherwise
545
      static bool isValidExtensionsRecord(const Asn1Record* record);
546
    };
547
548
    /// @class X509TBSCertificate
549
    /// Internal class for handling the To-Be-Signed (TBS) portion of an X.509 certificate
550
    class X509TBSCertificate : public X509Base<Asn1SequenceRecord>
551
    {
552
      using X509Base::X509Base;
553
      friend class X509Certificate;
554
555
    public:
556
      /// Gets the version of the TBS certificate
557
      /// @return The X509Version of the certificate
558
      X509Version getVersion() const;
559
560
      /// Gets the serial number of the TBS certificate
561
      /// @return The X509SerialNumber of the certificate
562
      X509SerialNumber getSerialNumber() const;
563
564
      /// Gets the signature algorithm of the TBS certificate
565
      /// @return The X509AlgorithmIdentifier for the signature
566
      X509AlgorithmIdentifier getSignature() const;
567
568
      /// Gets the issuer name from the TBS certificate
569
      /// @return The X509Name of the issuer
570
      X509Name getIssuer() const;
571
572
      /// Gets the validity period of the TBS certificate
573
      /// @return The X509Validity object containing notBefore and notAfter timestamps
574
      X509Validity getValidity() const;
575
576
      /// Gets the subject name from the TBS certificate
577
      /// @return The X509Name of the subject
578
      X509Name getSubject() const;
579
580
      /// Gets the subject's public key information
581
      /// @return The X509SubjectPublicKeyInfo containing the public key
582
      X509SubjectPublicKeyInfo getSubjectPublicKeyInfo() const;
583
584
      /// Gets the extensions from the TBS certificate
585
      /// @return A unique_ptr to X509Extensions, or nullptr if no extensions are present
586
      std::unique_ptr<X509Extensions> getExtensions() const;
587
588
    private:
589
      int m_VersionOffset = -1;
590
      int m_SerialNumberOffset = 0;
591
      int m_SignatureOffset = 1;
592
      int m_IssuerOffset = 2;
593
      int m_ValidityOffset = 3;
594
      int m_SubjectOffset = 4;
595
      int m_SubjectPublicKeyInfoOffset = 5;
596
      int m_IssuerUniqueID = -1;
597
      int m_SubjectUniqueID = -1;
598
      int m_ExtensionsOffset = -1;
599
600
      explicit X509TBSCertificate(Asn1SequenceRecord* root);
601
    };
602
603
    /// @class X509Certificate
604
    /// Internal class for handling X.509 certificate parsing and encoding
605
    class X509Certificate
606
    {
607
    public:
608
      /// Gets the TBS (To Be Signed) portion of the certificate
609
      /// @return The X509TBSCertificate containing the TBS data
610
      X509TBSCertificate getTbsCertificate() const;
611
612
      /// Gets the signature algorithm used to sign the certificate
613
      /// @return The X509AlgorithmIdentifier for the signature
614
      X509AlgorithmIdentifier getSignatureAlgorithm() const;
615
616
      /// Gets the signature value from the certificate
617
      /// @return The X509Key containing the signature
618
      X509Key getSignature() const;
619
620
      /// Gets the root ASN.1 record of the certificate
621
      /// @return Pointer to the root ASN.1 sequence record
622
      Asn1SequenceRecord* getAsn1Root() const;
623
624
      /// Decodes an X.509 certificate from binary data
625
      /// @param[in] data Pointer to the binary certificate data
626
      /// @param[in] dataLen Length of the binary data
627
      /// @return A unique_ptr to the decoded X509Certificate, or nullptr on failure
628
      static std::unique_ptr<X509Certificate> decode(const uint8_t* data, size_t dataLen);
629
630
      /// Encodes the certificate to binary DER format
631
      /// @return A vector containing the DER-encoded certificate
632
      std::vector<uint8_t> encode();
633
634
    private:
635
      static constexpr int tbsCertificateOffset = 0;
636
      static constexpr int signatureAlgorithmOffset = 1;
637
      static constexpr int signatureOffset = 2;
638
639
      explicit X509Certificate(std::unique_ptr<Asn1Record> root) : m_Root(std::move(root))
640
0
      {}
641
642
      std::unique_ptr<Asn1Record> m_Root;
643
    };
644
  }  // namespace X509Internal
645
646
  // Forward declarations
647
  class X509Certificate;
648
649
  /// @class X509Name
650
  /// Represents a name in an X.509 certificate
651
  class X509Name
652
  {
653
    friend class X509Certificate;
654
655
  public:
656
    /// @struct RDN
657
    /// Represents a Relative Distinguished Name (RDN) in an X.509 certificate
658
    struct RDN
659
    {
660
      X520DistinguishedName type;  ///< The type of the distinguished name
661
      std::string value;           ///< The value of the distinguished name
662
663
      /// Equality comparison operator
664
      bool operator==(const RDN& other) const
665
0
      {
666
0
        return type == other.type && value == other.value;
667
0
      }
668
669
      /// Inequality comparison operator
670
      bool operator!=(const RDN& other) const
671
0
      {
672
0
        return !(*this == other);
673
0
      }
674
675
      /// Stream output operator for RDN
676
      friend std::ostream& operator<<(std::ostream& os, const RDN& rdn)
677
0
      {
678
0
        os << "RDN{type=" << rdn.type.getShortName() << ", value=" << rdn.value << "}";
679
0
        return os;
680
0
      }
681
    };
682
683
    /// Converts the X509Name to a string representation, e.g C=US, ST=California, CN=example.com
684
    /// @param[in] delimiter The delimiter to use between RDNs (default: ", ")
685
    /// @return A string representation of the X509Name
686
    std::string toString(const std::string& delimiter = ", ") const;
687
688
    /// Gets the list of Relative Distinguished Names (RDNs)
689
    /// @return A vector of RDN objects
690
    const std::vector<RDN>& getRDNs() const
691
0
    {
692
0
      return m_RDNs;
693
0
    }
694
695
  private:
696
    explicit X509Name(const X509Internal::X509Name& internalName);
697
    std::vector<RDN> m_RDNs;
698
  };
699
700
  /// @class X509Extension
701
  /// Represents an X.509 extension
702
  class X509Extension
703
  {
704
    friend class X509Certificate;
705
706
  public:
707
    /// Gets the type of this X.509 extension
708
    /// @return The X509ExtensionType representing the extension type
709
    X509ExtensionType getType() const
710
0
    {
711
0
      return m_Type;
712
0
    }
713
714
    /// Checks if this extension is marked as critical
715
    /// @return true if the extension is critical, false otherwise
716
    bool isCritical() const
717
0
    {
718
0
      return m_IsCritical;
719
0
    }
720
721
    /// Gets the extension parsed data
722
    /// @return A unique_ptr to an object containing the parsed extension data if such class exists
723
    ///         (not all extensions have parsed data classes), or nullptr if it doesn't
724
    std::unique_ptr<X509ExtensionData> getData() const;
725
726
    /// Gets the extension data as a hex string
727
    /// @return A string containing the extension data in hex format
728
    std::string getRawDataAsHexString() const
729
0
    {
730
0
      return m_Data;
731
0
    }
732
733
  private:
734
    explicit X509Extension(const X509Internal::X509Extension& internalExtension);
735
736
    bool m_IsCritical;
737
    X509ExtensionType m_Type;
738
    std::string m_Data;
739
  };
740
741
  /// @class X509Certificate
742
  /// Represents an X.509 certificate
743
  class X509Certificate : public internal::CryptoDataReader<X509Certificate>
744
  {
745
  public:
746
    /// Gets the version of the certificate
747
    /// @return The X509Version of the certificate
748
    X509Version getVersion() const;
749
750
    /// Gets the serial number of the certificate
751
    /// @return The certificate's serial number
752
    X509SerialNumber getSerialNumber() const;
753
754
    /// Gets the issuer of the certificate
755
    /// @return The certificate's issuer name
756
    X509Name getIssuer() const;
757
758
    /// Gets the subject of the certificate
759
    /// @return The certificate's subject name
760
    X509Name getSubject() const;
761
762
    /// Gets the notBefore timestamp of the certificate's validity period
763
    /// @return The notBefore timestamp
764
    X509Timestamp getNotBefore() const;
765
766
    /// Gets the notAfter timestamp of the certificate's validity period
767
    /// @return The notAfter timestamp
768
    X509Timestamp getNotAfter() const;
769
770
    /// Gets the public key algorithm used in the certificate
771
    /// @return The public key algorithm
772
    X509Algorithm getPublicKeyAlgorithm() const;
773
774
    /// Gets the public key from the certificate
775
    /// @return The public key
776
    X509Key getPublicKey() const;
777
778
    /// Gets the signature algorithm used to sign the certificate
779
    /// @return The signature algorithm
780
    X509Algorithm getSignatureAlgorithm() const;
781
782
    /// Gets the signature of the certificate
783
    /// @return The certificate's signature
784
    X509Key getSignature() const;
785
786
    /// Gets the list of extensions in the certificate
787
    /// @return A vector containing the certificate's extensions
788
    const std::vector<X509Extension>& getExtensions() const;
789
790
    /// Checks if the certificate has a specific extension
791
    /// @param[in] extensionType The extension type to check for
792
    /// @return true if the extension is present, false otherwise
793
    bool hasExtension(const X509ExtensionType& extensionType) const;
794
795
    /// Gets an extension by its type
796
    /// @param[in] extensionType The type of extension to get
797
    /// @return Pointer to the extension if found or nullptr otherwise
798
    const X509Extension* getExtension(X509ExtensionType extensionType) const;
799
800
    /// Converts the certificate to DER-encoded format
801
    /// @return A byte vector containing the DER-encoded data
802
    std::vector<uint8_t> toDER() const;
803
804
    /// Converts the certificate to PEM-encoded format
805
    /// @return A string containing the PEM-encoded data
806
    std::string toPEM() const;
807
808
    /// Converts the certificate to a JSON string representation
809
    /// @param[in] indent Number of spaces to use for indentation (-1 for no pretty printing)
810
    /// @return A JSON string representation of the certificate
811
    std::string toJson(int indent = -1) const;
812
813
    /// Gets the raw internal certificate object
814
    /// @return Pointer to the internal X509Certificate implementation
815
    const X509Internal::X509Certificate* getRawCertificate() const;
816
817
    // Prevent copying
818
    X509Certificate(const X509Certificate&) = delete;
819
    X509Certificate& operator=(const X509Certificate&) = delete;
820
821
  private:
822
    // Constructor/Destructor
823
    X509Certificate(uint8_t* derData, size_t derDataLen, bool ownDerData);
824
    X509Certificate(std::unique_ptr<uint8_t[]> derData, size_t derDataLen);
825
826
    friend class internal::CryptoDataReader<X509Certificate>;
827
828
    std::unique_ptr<X509Internal::X509Certificate> m_X509Internal;
829
    X509Internal::X509TBSCertificate m_TBSCertificate;
830
    mutable std::vector<X509Extension> m_Extensions;
831
    mutable bool m_ExtensionsParsed = false;
832
    std::unique_ptr<uint8_t[]> m_DerData;
833
834
    static constexpr const char* pemLabel = "CERTIFICATE";
835
  };
836
}  // namespace pcpp