PcapPlusPlus  Next
Asn1Codec.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <string>
4 #include <memory>
5 #include <typeinfo>
6 #include <stdexcept>
7 #include <sstream>
8 #include <chrono>
9 #include <bitset>
10 #include "PointerVector.h"
11 
13 
16 namespace pcpp
17 {
19  enum class Asn1TagClass : uint8_t
20  {
22  Universal = 0,
24  Application = 1,
26  ContextSpecific = 2,
28  Private = 3,
29  };
30 
32  enum class Asn1UniversalTagType : uint8_t
33  {
35  EndOfContent = 0,
37  Boolean = 1,
39  Integer = 2,
41  BitString = 3,
43  OctetString = 4,
45  Null = 5,
47  ObjectIdentifier = 6,
49  ObjectDescriptor = 7,
51  External = 8,
53  Real = 9,
55  Enumerated = 10,
57  EmbeddedPDV = 11,
59  UTF8String = 12,
63  Time = 14,
65  Reserved = 15,
67  Sequence = 16,
69  Set = 17,
71  NumericString = 18,
73  PrintableString = 19,
75  T61String = 20,
77  VideotexString = 21,
79  IA5String = 22,
81  UTCTime = 23,
83  GeneralizedTime = 24,
85  GraphicString = 25,
87  VisibleString = 26,
89  GeneralString = 27,
91  UniversalString = 28,
93  CharacterString = 29,
95  BMPString = 30,
97  Date = 31,
99  TimeOfDay = 32,
101  DateTime = 33,
103  Duration = 34,
105  ObjectIdentifierIRI = 35,
109  NotApplicable = 255
110  };
111 
117  {
118  public:
126  static std::unique_ptr<Asn1Record> decode(const uint8_t* data, size_t dataLen, bool lazy = true);
127 
130  std::vector<uint8_t> encode();
131 
134  {
135  return m_TagClass;
136  }
137 
139  bool isConstructed() const
140  {
141  return m_IsConstructed;
142  }
143 
147 
149  uint8_t getTagType() const
150  {
151  return m_TagType;
152  }
153 
155  size_t getValueLength() const
156  {
157  return m_ValueLength;
158  }
159 
161  size_t getTotalLength() const
162  {
163  return m_TotalLength;
164  }
165 
167  std::string toString();
168 
173  template <class Asn1RecordType> Asn1RecordType* castAs()
174  {
175  auto result = dynamic_cast<Asn1RecordType*>(this);
176  if (result == nullptr)
177  {
178  throw std::bad_cast();
179  }
180  return result;
181  }
182 
183  virtual ~Asn1Record() = default;
184 
185  protected:
187  bool m_IsConstructed = false;
188  uint8_t m_TagType = 0;
189 
190  size_t m_ValueLength = 0;
191  size_t m_TotalLength = 0;
192 
193  uint8_t* m_EncodedValue = nullptr;
194 
195  Asn1Record() = default;
196 
197  static Asn1Record* decodeInternal(const uint8_t* data, size_t dataLen, bool lazy);
198 
199  virtual void decodeValue(uint8_t* data, bool lazy) = 0;
200  virtual std::vector<uint8_t> encodeValue() const = 0;
201 
202  static Asn1Record* decodeTagAndCreateRecord(const uint8_t* data, size_t dataLen, uint8_t& tagLen);
203  uint8_t decodeLength(const uint8_t* data, size_t dataLen);
204  void decodeValueIfNeeded();
205 
206  uint8_t encodeTag();
207  std::vector<uint8_t> encodeLength() const;
208 
209  virtual std::vector<std::string> toStringList();
210 
211  friend class Asn1ConstructedRecord;
212  };
213 
218  {
219  friend class Asn1Record;
220 
221  public:
228  Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value,
229  size_t valueLen);
230 
236  Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const std::string& value);
237 
238  ~Asn1GenericRecord() override;
239 
241  const uint8_t* getValue()
242  {
243  decodeValueIfNeeded();
244  return m_Value;
245  }
246 
247  protected:
248  Asn1GenericRecord() = default;
249 
250  void decodeValue(uint8_t* data, bool lazy) override;
251  std::vector<uint8_t> encodeValue() const override;
252 
253  private:
254  uint8_t* m_Value = nullptr;
255 
256  void init(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, size_t valueLen);
257  };
258 
262  {
263  friend class Asn1Record;
264 
265  public:
270  explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType,
271  const std::vector<Asn1Record*>& subRecords);
272 
277  explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType,
278  const PointerVector<Asn1Record>& subRecords);
279 
283  {
284  decodeValueIfNeeded();
285  return m_SubRecords;
286  };
287 
288  protected:
289  Asn1ConstructedRecord() = default;
290 
291  void decodeValue(uint8_t* data, bool lazy) override;
292  std::vector<uint8_t> encodeValue() const override;
293 
294  std::vector<std::string> toStringList() override;
295 
296  template <typename Iterator> void init(Asn1TagClass tagClass, uint8_t tagType, Iterator begin, Iterator end)
297  {
298  m_TagType = tagType;
299  m_TagClass = tagClass;
300  m_IsConstructed = true;
301 
302  size_t recordValueLength = 0;
303  for (Iterator recordIter = begin; recordIter != end; ++recordIter)
304  {
305  auto encodedRecord = (*recordIter)->encode();
306  auto copyRecord = Asn1Record::decode(encodedRecord.data(), encodedRecord.size(), false);
307  m_SubRecords.pushBack(std::move(copyRecord));
308  recordValueLength += encodedRecord.size();
309  }
310 
311  m_ValueLength = recordValueLength;
312  m_TotalLength = recordValueLength + 1 + (m_ValueLength < 128 ? 1 : 2);
313  }
314 
315  private:
316  PointerVector<Asn1Record> m_SubRecords;
317  };
318 
322  {
323  friend class Asn1Record;
324 
325  public:
328  explicit Asn1SequenceRecord(const std::vector<Asn1Record*>& subRecords);
329 
332  explicit Asn1SequenceRecord(const PointerVector<Asn1Record>& subRecords);
333 
334  private:
335  Asn1SequenceRecord() = default;
336  };
337 
341  {
342  friend class Asn1Record;
343 
344  public:
347  explicit Asn1SetRecord(const std::vector<Asn1Record*>& subRecords);
348 
351  explicit Asn1SetRecord(const PointerVector<Asn1Record>& subRecords);
352 
353  private:
354  Asn1SetRecord() = default;
355  };
356 
361  {
362  friend class Asn1Record;
363 
364  protected:
365  Asn1PrimitiveRecord() = default;
366  explicit Asn1PrimitiveRecord(Asn1UniversalTagType tagType);
367  };
368 
372  {
373  friend class Asn1Record;
374 
375  public:
376  template <typename T>
377  using EnableIfUnsignedIntegral =
378  std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, int>;
379 
382  explicit Asn1IntegerRecord(uint64_t value);
383 
387  explicit Asn1IntegerRecord(const std::string& value);
388 
391  template <typename T, EnableIfUnsignedIntegral<T> = 0> T getIntValue()
392  {
393  decodeValueIfNeeded();
394  return m_Value.getInt<T>();
395  }
396 
398  PCPP_DEPRECATED("Use getIntValue instead")
399  uint32_t getValue()
400  {
401  return getIntValue<uint32_t>();
402  }
403 
405  std::string getValueAsString()
406  {
407  decodeValueIfNeeded();
408  return m_Value.toString();
409  }
410 
411  protected:
412  Asn1IntegerRecord() = default;
413 
414  void decodeValue(uint8_t* data, bool lazy) override;
415  std::vector<uint8_t> encodeValue() const override;
416 
417  std::vector<std::string> toStringList() override;
418 
419  private:
420  class BigInt
421  {
422  public:
423  BigInt() = default;
424 
425  template <typename T, EnableIfUnsignedIntegral<T> = 0> explicit BigInt(T value)
426  {
427  m_Value = initFromInt(value);
428  }
429 
430  explicit BigInt(const std::string& value);
431  BigInt(const BigInt& other);
432 
433  template <typename T, EnableIfUnsignedIntegral<T> = 0> BigInt& operator=(T value)
434  {
435  m_Value = initFromInt(value);
436  return *this;
437  }
438  BigInt& operator=(const std::string& value);
439  size_t size() const;
440 
441  template <typename T, EnableIfUnsignedIntegral<T> = 0> T getInt() const
442  {
443  if (!canFit<T>())
444  {
445  throw std::overflow_error("Value cannot fit into requested int type");
446  }
447 
448  std::stringstream sstream;
449  sstream << std::hex << m_Value;
450 
451  uint64_t result;
452  sstream >> result;
453  return static_cast<T>(result);
454  }
455 
456  template <typename T, EnableIfUnsignedIntegral<T> = 0> bool canFit() const
457  {
458  return sizeof(T) >= (m_Value.size() + 1) / 2;
459  }
460 
461  std::string toString() const;
462  std::vector<uint8_t> toBytes() const;
463 
464  private:
465  std::string m_Value;
466 
467  static std::string initFromString(const std::string& value);
468 
469  template <typename T, EnableIfUnsignedIntegral<T> = 0> static std::string initFromInt(T value)
470  {
471  std::stringstream ss;
472  ss << std::hex << static_cast<uint64_t>(value);
473  return ss.str();
474  }
475  };
476 
477  BigInt m_Value;
478  };
479 
483  {
484  friend class Asn1Record;
485 
486  public:
489  explicit Asn1EnumeratedRecord(uint32_t value);
490 
491  private:
492  Asn1EnumeratedRecord() = default;
493  };
494 
498  {
499  friend class Asn1Record;
500 
501  public:
504  explicit Asn1OctetStringRecord(const std::string& value);
505 
509  explicit Asn1OctetStringRecord(const uint8_t* value, size_t valueLength);
510 
512  std::string getValue()
513  {
514  decodeValueIfNeeded();
515  return m_Value;
516  };
517 
518  protected:
519  void decodeValue(uint8_t* data, bool lazy) override;
520  std::vector<uint8_t> encodeValue() const override;
521 
522  std::vector<std::string> toStringList() override;
523 
524  private:
525  std::string m_Value;
526  bool m_IsPrintable = true;
527 
528  Asn1OctetStringRecord() = default;
529  };
530 
534  {
535  friend class Asn1Record;
536 
537  public:
540  explicit Asn1BooleanRecord(bool value);
541 
543  bool getValue()
544  {
545  decodeValueIfNeeded();
546  return m_Value;
547  };
548 
549  protected:
550  void decodeValue(uint8_t* data, bool lazy) override;
551  std::vector<uint8_t> encodeValue() const override;
552 
553  std::vector<std::string> toStringList() override;
554 
555  private:
556  Asn1BooleanRecord() = default;
557 
558  bool m_Value = false;
559  };
560 
564  {
565  friend class Asn1Record;
566 
567  public:
570 
571  protected:
572  void decodeValue(uint8_t* data, bool lazy) override
573  {}
574  std::vector<uint8_t> encodeValue() const override
575  {
576  return {};
577  }
578  };
579 
583  {
584  friend class Asn1ObjectIdentifierRecord;
585 
586  public:
590  explicit Asn1ObjectIdentifier(const uint8_t* data, size_t dataLen);
591 
595  explicit Asn1ObjectIdentifier(const std::string& oidString);
596 
598  const std::vector<uint32_t>& getComponents() const
599  {
600  return m_Components;
601  }
602 
605  bool operator==(const Asn1ObjectIdentifier& other) const
606  {
607  return m_Components == other.m_Components;
608  }
609 
612  bool operator!=(const Asn1ObjectIdentifier& other) const
613  {
614  return m_Components != other.m_Components;
615  }
616 
619  std::string toString() const;
620 
623  std::vector<uint8_t> toBytes() const;
624 
625  friend std::ostream& operator<<(std::ostream& os, const Asn1ObjectIdentifier& oid)
626  {
627  return os << oid.toString();
628  }
629 
630  protected:
631  Asn1ObjectIdentifier() = default;
632 
633  private:
634  std::vector<uint32_t> m_Components;
635  };
636 
640  {
641  friend class Asn1Record;
642 
643  public:
647 
650  {
651  decodeValueIfNeeded();
652  return m_Value;
653  }
654 
655  protected:
656  void decodeValue(uint8_t* data, bool lazy) override;
657  std::vector<uint8_t> encodeValue() const override;
658 
659  std::vector<std::string> toStringList() override;
660 
661  private:
662  Asn1ObjectIdentifier m_Value;
663 
664  Asn1ObjectIdentifierRecord() = default;
665  };
666 
671  {
672  public:
677  std::chrono::system_clock::time_point getValue(const std::string& timezone = "Z")
678  {
679  decodeValueIfNeeded();
680  return adjustTimezones(m_Value, "Z", timezone);
681  };
682 
689  std::string getValueAsString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z",
690  bool includeMilliseconds = false);
691 
692  protected:
693  Asn1TimeRecord() = default;
694  explicit Asn1TimeRecord(Asn1UniversalTagType tagType, const std::chrono::system_clock::time_point& value,
695  const std::string& timezone);
696 
697  std::chrono::system_clock::time_point m_Value;
698 
699  std::vector<std::string> toStringList() override;
700 
701  static void validateTimezone(const std::string& timezone);
702  static std::chrono::system_clock::time_point adjustTimezones(const std::chrono::system_clock::time_point& value,
703  const std::string& fromTimezone,
704  const std::string& toTimezone);
705  };
706 
710  {
711  friend class Asn1Record;
712 
713  public:
717  explicit Asn1UtcTimeRecord(const std::chrono::system_clock::time_point& value, bool withSeconds = true);
718 
719  protected:
720  void decodeValue(uint8_t* data, bool lazy) override;
721  std::vector<uint8_t> encodeValue() const override;
722 
723  private:
724  Asn1UtcTimeRecord() = default;
725  bool m_WithSeconds = true;
726  };
727 
731  {
732  friend class Asn1Record;
733 
734  public:
740  explicit Asn1GeneralizedTimeRecord(const std::chrono::system_clock::time_point& value,
741  const std::string& timezone = "Z");
742 
743  protected:
744  void decodeValue(uint8_t* data, bool lazy) override;
745  std::vector<uint8_t> encodeValue() const override;
746 
747  private:
748  Asn1GeneralizedTimeRecord() = default;
749  std::string m_Timezone;
750  };
751 
755  {
756  friend class Asn1Record;
757 
758  public:
762  explicit Asn1BitStringRecord(const std::string& value);
763 
765  std::string getValue()
766  {
767  decodeValueIfNeeded();
768  return m_Value.toString();
769  };
770 
771  protected:
772  void decodeValue(uint8_t* data, bool lazy) override;
773  std::vector<uint8_t> encodeValue() const override;
774 
775  std::vector<std::string> toStringList() override;
776 
777  private:
778  class BitSet
779  {
780  public:
781  BitSet() = default;
782  explicit BitSet(const std::string& value);
783  BitSet(const uint8_t* data, size_t numBits);
784 
785  BitSet& operator=(const std::string& value);
786 
787  size_t sizeInBytes() const;
788  std::string toString() const;
789  std::vector<uint8_t> toBytes() const;
790  size_t getNumBits() const
791  {
792  return m_NumBits;
793  }
794 
795  private:
796  void initFromString(const std::string& value);
797 
798  std::vector<std::bitset<8>> m_Data;
799  size_t m_NumBits = 0;
800  };
801 
802  Asn1BitStringRecord() = default;
803 
804  BitSet m_Value;
805  };
806 } // namespace pcpp
Definition: Asn1Codec.h:755
std::string getValue()
Definition: Asn1Codec.h:765
Asn1BitStringRecord(const std::string &value)
Definition: Asn1Codec.h:534
Asn1BooleanRecord(bool value)
bool getValue()
Definition: Asn1Codec.h:543
Definition: Asn1Codec.h:262
PointerVector< Asn1Record > & getSubRecords()
Definition: Asn1Codec.h:282
Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const PointerVector< Asn1Record > &subRecords)
Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const std::vector< Asn1Record * > &subRecords)
Definition: Asn1Codec.h:483
Asn1EnumeratedRecord(uint32_t value)
Definition: Asn1Codec.h:731
Asn1GeneralizedTimeRecord(const std::chrono::system_clock::time_point &value, const std::string &timezone="Z")
Definition: Asn1Codec.h:218
const uint8_t * getValue()
Definition: Asn1Codec.h:241
Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t *value, size_t valueLen)
Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const std::string &value)
Definition: Asn1Codec.h:372
Asn1IntegerRecord(uint64_t value)
T getIntValue()
Definition: Asn1Codec.h:391
uint32_t getValue()
Definition: Asn1Codec.h:399
std::string getValueAsString()
Definition: Asn1Codec.h:405
Asn1IntegerRecord(const std::string &value)
Definition: Asn1Codec.h:564
Asn1NullRecord()
A constructor to create a record of type Null.
Definition: Asn1Codec.h:583
std::vector< uint8_t > toBytes() const
bool operator==(const Asn1ObjectIdentifier &other) const
Definition: Asn1Codec.h:605
std::string toString() const
Asn1ObjectIdentifier(const uint8_t *data, size_t dataLen)
bool operator!=(const Asn1ObjectIdentifier &other) const
Definition: Asn1Codec.h:612
Asn1ObjectIdentifier(const std::string &oidString)
const std::vector< uint32_t > & getComponents() const
Definition: Asn1Codec.h:598
Definition: Asn1Codec.h:640
const Asn1ObjectIdentifier & getValue()
Definition: Asn1Codec.h:649
Asn1ObjectIdentifierRecord(const Asn1ObjectIdentifier &value)
Definition: Asn1Codec.h:498
Asn1OctetStringRecord(const std::string &value)
std::string getValue()
Definition: Asn1Codec.h:512
Asn1OctetStringRecord(const uint8_t *value, size_t valueLength)
Definition: Asn1Codec.h:361
Definition: Asn1Codec.h:117
uint8_t getTagType() const
Definition: Asn1Codec.h:149
std::vector< uint8_t > encode()
bool isConstructed() const
Definition: Asn1Codec.h:139
Asn1UniversalTagType getUniversalTagType() const
Asn1TagClass getTagClass() const
Definition: Asn1Codec.h:133
std::string toString()
size_t getTotalLength() const
Definition: Asn1Codec.h:161
Asn1RecordType * castAs()
Definition: Asn1Codec.h:173
size_t getValueLength() const
Definition: Asn1Codec.h:155
static std::unique_ptr< Asn1Record > decode(const uint8_t *data, size_t dataLen, bool lazy=true)
Definition: Asn1Codec.h:322
Asn1SequenceRecord(const PointerVector< Asn1Record > &subRecords)
Asn1SequenceRecord(const std::vector< Asn1Record * > &subRecords)
Definition: Asn1Codec.h:341
Asn1SetRecord(const PointerVector< Asn1Record > &subRecords)
Asn1SetRecord(const std::vector< Asn1Record * > &subRecords)
Definition: Asn1Codec.h:671
std::string getValueAsString(const std::string &format="%Y-%m-%d %H:%M:%S", const std::string &timezone="Z", bool includeMilliseconds=false)
std::chrono::system_clock::time_point getValue(const std::string &timezone="Z")
Definition: Asn1Codec.h:677
Definition: Asn1Codec.h:710
Asn1UtcTimeRecord(const std::chrono::system_clock::time_point &value, bool withSeconds=true)
Definition: PointerVector.h:50
The main namespace for the PcapPlusPlus lib.
Asn1TagClass
An enum for representing ASN.1 tag class.
Definition: Asn1Codec.h:20
@ ContextSpecific
The Context-Specific tag class.
@ Private
The Private tag class.
@ Universal
The Universal tag class.
@ Application
The Application tag class.
Asn1UniversalTagType
An enum for representing ASN.1 Universal tag types.
Definition: Asn1Codec.h:33
@ BitString
The universal tag type for Bit String.
@ Enumerated
The universal tag type for Enumerated.
@ ObjectIdentifierIRI
The universal tag type for Object Identifier Internationalized Resource Identifier (IRI)
@ ObjectDescriptor
The universal tag type for Object Descriptor.
@ TimeOfDay
The universal tag type for Time of Day.
@ GraphicString
The universal tag type for GraphicString.
@ UTCTime
The universal tag type for UTC time.
@ Boolean
The universal tag type for Boolean.
@ EmbeddedPDV
The universal tag type for Embedded-PDV.
@ OctetString
The universal tag type for Octet String.
@ UniversalString
The universal tag type for UniversalString.
@ Sequence
The universal tag type Sequence.
@ Date
The universal tag type for Date.
@ RelativeObjectIdentifierIRI
The universal tag type for Relative Object Identifier Internationalized Resource Identifier (IRI)
@ PrintableString
The universal tag type for Printable String.
@ CharacterString
The universal tag type for CharacterString.
@ RelativeObjectIdentifier
The universal tag type for Relative Object Identifier.
@ Set
The universal tag type for Set.
@ ObjectIdentifier
The universal tag type for Object Identifier.
@ IA5String
The universal tag type for IA5String.
@ VideotexString
The universal tag type for Videotex String.
@ NotApplicable
A non-applicable value.
@ Real
The universal tag type for Real.
@ DateTime
The universal tag type for Date-Time.
@ EndOfContent
The reserved identifier for the End-of-Contents marker in an indefinite length encoding.
@ Reserved
A reserved value.
@ Integer
The universal tag type for Integer.
@ Time
The universal tag type for Time.
@ External
The universal tag type for External.
@ BMPString
The universal tag type for BMPString.
@ UTF8String
The universal tag type for UTF8 String.
@ Null
The universal tag type for Null.
@ GeneralizedTime
The universal tag type for Generalized time.
@ T61String
The universal tag type for T61String.
@ Duration
The universal tag type for Duration.
@ VisibleString
The universal tag type for VisibleString.
@ GeneralString
The universal tag type for GeneralString.
@ NumericString
The universal tag type for Numeric String.