Coverage Report

Created: 2025-09-27 08:03

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
    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