/src/PcapPlusPlus/Packet++/header/Asn1Codec.h
Line | Count | Source |
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 | | |
12 | | /// @file |
13 | | |
14 | | /// @namespace pcpp |
15 | | /// @brief The main namespace for the PcapPlusPlus lib |
16 | | namespace pcpp |
17 | | { |
18 | | /// An enum for representing ASN.1 tag class |
19 | | enum class Asn1TagClass : uint8_t |
20 | | { |
21 | | /// The Universal tag class |
22 | | Universal = 0, |
23 | | /// The Application tag class |
24 | | Application = 1, |
25 | | /// The Context-Specific tag class |
26 | | ContextSpecific = 2, |
27 | | /// The Private tag class |
28 | | Private = 3, |
29 | | }; |
30 | | |
31 | | /// An enum for representing ASN.1 Universal tag types |
32 | | enum class Asn1UniversalTagType : uint8_t |
33 | | { |
34 | | /// The reserved identifier for the End-of-Contents marker in an indefinite length encoding |
35 | | EndOfContent = 0, |
36 | | /// The universal tag type for Boolean |
37 | | Boolean = 1, |
38 | | /// The universal tag type for Integer |
39 | | Integer = 2, |
40 | | /// The universal tag type for Bit String |
41 | | BitString = 3, |
42 | | /// The universal tag type for Octet String |
43 | | OctetString = 4, |
44 | | /// The universal tag type for Null |
45 | | Null = 5, |
46 | | /// The universal tag type for Object Identifier |
47 | | ObjectIdentifier = 6, |
48 | | /// The universal tag type for Object Descriptor |
49 | | ObjectDescriptor = 7, |
50 | | /// The universal tag type for External |
51 | | External = 8, |
52 | | /// The universal tag type for Real |
53 | | Real = 9, |
54 | | /// The universal tag type for Enumerated |
55 | | Enumerated = 10, |
56 | | /// The universal tag type for Embedded-PDV |
57 | | EmbeddedPDV = 11, |
58 | | /// The universal tag type for UTF8 String |
59 | | UTF8String = 12, |
60 | | /// The universal tag type for Relative Object Identifier |
61 | | RelativeObjectIdentifier = 13, |
62 | | /// The universal tag type for Time |
63 | | Time = 14, |
64 | | /// A reserved value |
65 | | Reserved = 15, |
66 | | /// The universal tag type Sequence |
67 | | Sequence = 16, |
68 | | /// The universal tag type for Set |
69 | | Set = 17, |
70 | | /// The universal tag type for Numeric String |
71 | | NumericString = 18, |
72 | | /// The universal tag type for Printable String |
73 | | PrintableString = 19, |
74 | | /// The universal tag type for T61String |
75 | | T61String = 20, |
76 | | /// The universal tag type for Videotex String |
77 | | VideotexString = 21, |
78 | | /// The universal tag type for IA5String |
79 | | IA5String = 22, |
80 | | /// The universal tag type for UTC time |
81 | | UTCTime = 23, |
82 | | /// The universal tag type for Generalized time |
83 | | GeneralizedTime = 24, |
84 | | /// The universal tag type for GraphicString |
85 | | GraphicString = 25, |
86 | | /// The universal tag type for VisibleString |
87 | | VisibleString = 26, |
88 | | /// The universal tag type for GeneralString |
89 | | GeneralString = 27, |
90 | | /// The universal tag type for UniversalString |
91 | | UniversalString = 28, |
92 | | /// The universal tag type for CharacterString |
93 | | CharacterString = 29, |
94 | | /// The universal tag type for BMPString |
95 | | BMPString = 30, |
96 | | /// The universal tag type for Date |
97 | | Date = 31, |
98 | | /// The universal tag type for Time of Day |
99 | | TimeOfDay = 32, |
100 | | /// The universal tag type for Date-Time |
101 | | DateTime = 33, |
102 | | /// The universal tag type for Duration |
103 | | Duration = 34, |
104 | | /// The universal tag type for Object Identifier Internationalized Resource Identifier (IRI) |
105 | | ObjectIdentifierIRI = 35, |
106 | | /// The universal tag type for Relative Object Identifier Internationalized Resource Identifier (IRI) |
107 | | RelativeObjectIdentifierIRI = 36, |
108 | | /// A non-applicable value |
109 | | NotApplicable = 255 |
110 | | }; |
111 | | |
112 | | namespace internal |
113 | | { |
114 | | /// @enum Asn1LoadPolicy |
115 | | /// @brief Policy for when to evaluate (decode) ASN.1 record values. |
116 | | /// Determines whether the value is decoded immediately (eager) or on first access (lazy). |
117 | | enum class Asn1LoadPolicy |
118 | | { |
119 | | /// The value is evaluated on first access (lazy decoding). |
120 | | Lazy, |
121 | | /// The value is evaluated immediately on construction (eager decoding). |
122 | | Eager |
123 | | }; |
124 | | } // namespace internal |
125 | | |
126 | | /// @class Asn1Record |
127 | | /// Represents an ASN.1 record, as described in ITU-T Recommendation X.680: |
128 | | /// <https://www.itu.int/rec/T-REC-X.680/en> |
129 | | /// <https://en.wikipedia.org/wiki/ASN.1> |
130 | | class Asn1Record |
131 | | { |
132 | | public: |
133 | | /// A static method to decode a byte array into an Asn1Record |
134 | | /// @param data A byte array to decode |
135 | | /// @param dataLen The byte array length |
136 | | /// @param lazy Use lazy decoding, set to true by default. Lazy decoding entails delaying the decoding |
137 | | /// of the record value until it is accessed |
138 | | /// @return A smart pointer to the decoded ASN.1 record. If the byte stream is not a valid ASN.1 record |
139 | | /// an exception is thrown |
140 | | static std::unique_ptr<Asn1Record> decode(const uint8_t* data, size_t dataLen, bool lazy = true); |
141 | | |
142 | | /// Encode this record and convert it to a byte stream |
143 | | /// @return A vector of bytes representing the record |
144 | | std::vector<uint8_t> encode() const; |
145 | | |
146 | | /// @return The ASN.1 tag class |
147 | | Asn1TagClass getTagClass() const |
148 | 0 | { |
149 | 0 | return m_TagClass; |
150 | 0 | } |
151 | | |
152 | | /// @return True if it's a constructed record, or false if it's a primitive record |
153 | | bool isConstructed() const |
154 | 0 | { |
155 | 0 | return m_IsConstructed; |
156 | 0 | } |
157 | | |
158 | | /// @return The ASN.1 Universal tag type if the record is of class Universal, otherwise |
159 | | /// Asn1UniversalTagType#NotApplicable |
160 | | Asn1UniversalTagType getUniversalTagType() const; |
161 | | |
162 | | /// @return The ASN.1 tag type value |
163 | | uint8_t getTagType() const |
164 | 71.1k | { |
165 | 71.1k | return m_TagType; |
166 | 71.1k | } |
167 | | |
168 | | /// @return The length of the record value |
169 | | size_t getValueLength() const |
170 | 0 | { |
171 | 0 | return m_ValueLength; |
172 | 0 | } |
173 | | |
174 | | /// @return The total length of the record |
175 | | size_t getTotalLength() const |
176 | 815k | { |
177 | 815k | return m_TotalLength; |
178 | 815k | } |
179 | | |
180 | | /// @return A string representation of the record |
181 | | std::string toString() const; |
182 | | |
183 | | /// A templated method that accepts a class derived from Asn1Record as its template argument and attempts |
184 | | /// to cast the current instance to that type |
185 | | /// @tparam Asn1RecordType The type to cast to |
186 | | /// @return A pointer to the type after casting |
187 | | template <class Asn1RecordType> Asn1RecordType* castAs() |
188 | 119k | { |
189 | 119k | auto result = dynamic_cast<Asn1RecordType*>(this); |
190 | 119k | if (result == nullptr) |
191 | 2.39k | { |
192 | 2.39k | throw std::bad_cast(); |
193 | 2.39k | } |
194 | 116k | return result; |
195 | 119k | } pcpp::Asn1SequenceRecord* pcpp::Asn1Record::castAs<pcpp::Asn1SequenceRecord>() Line | Count | Source | 188 | 88.2k | { | 189 | 88.2k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 88.2k | if (result == nullptr) | 191 | 1.95k | { | 192 | 1.95k | throw std::bad_cast(); | 193 | 1.95k | } | 194 | 86.2k | return result; | 195 | 88.2k | } |
Unexecuted instantiation: pcpp::Asn1IntegerRecord* pcpp::Asn1Record::castAs<pcpp::Asn1IntegerRecord>() Unexecuted instantiation: pcpp::Asn1ObjectIdentifierRecord* pcpp::Asn1Record::castAs<pcpp::Asn1ObjectIdentifierRecord>() Unexecuted instantiation: pcpp::Asn1PrintableStringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1PrintableStringRecord>() Unexecuted instantiation: pcpp::Asn1IA5StringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1IA5StringRecord>() Unexecuted instantiation: pcpp::Asn1UTF8StringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1UTF8StringRecord>() Unexecuted instantiation: pcpp::Asn1SetRecord* pcpp::Asn1Record::castAs<pcpp::Asn1SetRecord>() Unexecuted instantiation: pcpp::Asn1TimeRecord* pcpp::Asn1Record::castAs<pcpp::Asn1TimeRecord>() Unexecuted instantiation: pcpp::Asn1BitStringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1BitStringRecord>() Unexecuted instantiation: pcpp::Asn1BooleanRecord* pcpp::Asn1Record::castAs<pcpp::Asn1BooleanRecord>() pcpp::Asn1OctetStringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1OctetStringRecord>() Line | Count | Source | 188 | 1.03k | { | 189 | 1.03k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 1.03k | if (result == nullptr) | 191 | 0 | { | 192 | 0 | throw std::bad_cast(); | 193 | 0 | } | 194 | 1.03k | return result; | 195 | 1.03k | } |
pcpp::Asn1ConstructedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1ConstructedRecord>() Line | Count | Source | 188 | 24.3k | { | 189 | 24.3k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 24.3k | if (result == nullptr) | 191 | 440 | { | 192 | 440 | throw std::bad_cast(); | 193 | 440 | } | 194 | 23.9k | return result; | 195 | 24.3k | } |
pcpp::Asn1EnumeratedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1EnumeratedRecord>() Line | Count | Source | 188 | 5.45k | { | 189 | 5.45k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 5.45k | if (result == nullptr) | 191 | 0 | { | 192 | 0 | throw std::bad_cast(); | 193 | 0 | } | 194 | 5.45k | return result; | 195 | 5.45k | } |
Unexecuted instantiation: pcpp::Asn1GenericRecord* pcpp::Asn1Record::castAs<pcpp::Asn1GenericRecord>() |
196 | | |
197 | 452k | virtual ~Asn1Record() = default; |
198 | | |
199 | | protected: |
200 | | Asn1TagClass m_TagClass = Asn1TagClass::Universal; |
201 | | bool m_IsConstructed = false; |
202 | | uint8_t m_TagType = 0; |
203 | | |
204 | | size_t m_ValueLength = 0; |
205 | | size_t m_TotalLength = 0; |
206 | | |
207 | 452k | Asn1Record() = default; |
208 | | |
209 | | /// @brief Decodes the record value from a byte array into the mutable cache variables. |
210 | | /// This method is marked as const as it can be called on a const instance of the record for lazy decoding. |
211 | | virtual void decodeValue(uint8_t const* data) const = 0; |
212 | | |
213 | | /// @brief Encodes the record value into a byte array |
214 | | /// Prefer using encodeValueSafe() to ensure the value is decoded first if needed |
215 | | virtual std::vector<uint8_t> encodeValue() const = 0; |
216 | | |
217 | | /// @brief Encodes the record value into a byte array, ensuring that the value is decoded first if needed |
218 | | std::vector<uint8_t> encodeValueSafe() const |
219 | 0 | { |
220 | 0 | decodeValueIfNeeded(); |
221 | 0 | return encodeValue(); |
222 | 0 | } |
223 | | |
224 | | static std::unique_ptr<Asn1Record> decodeTagAndCreateRecord(const uint8_t* data, size_t dataLen, |
225 | | uint8_t& tagLen); |
226 | | uint8_t decodeLength(const uint8_t* data, size_t dataLen); |
227 | | void decodeValueIfNeeded() const; |
228 | | |
229 | | uint8_t encodeTag() const; |
230 | | std::vector<uint8_t> encodeLength() const; |
231 | | |
232 | | // note: Requires the value to be decoded first if lazy decoding is used |
233 | | virtual std::vector<std::string> toStringList() const; |
234 | | |
235 | | friend class Asn1ConstructedRecord; |
236 | | |
237 | | private: |
238 | | void setEncodedValue(uint8_t const* dataSource, |
239 | | internal::Asn1LoadPolicy loadPolicy = internal::Asn1LoadPolicy::Lazy); |
240 | | |
241 | | mutable uint8_t const* m_EncodedValue = nullptr; |
242 | | }; |
243 | | |
244 | | /// @class Asn1GenericRecord |
245 | | /// Represents a generic ASN.1 record, either of an unknown type or of a known type that doesn't |
246 | | /// have a dedicated parser yet |
247 | | class Asn1GenericRecord : public Asn1Record |
248 | | { |
249 | | friend class Asn1Record; |
250 | | |
251 | | public: |
252 | | /// A constructor to create a generic record |
253 | | /// @param tagClass The record tag class |
254 | | /// @param isConstructed A flag to indicate if the record is constructed or primitive |
255 | | /// @param tagType The record tag type value |
256 | | /// @param value A byte array of the tag value |
257 | | /// @param valueLen The length of the value byte array |
258 | | Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, |
259 | | size_t valueLen); |
260 | | |
261 | | /// A constructor to create a generic record |
262 | | /// @param tagClass The record tag class |
263 | | /// @param isConstructed A flag to indicate if the record is constructed or primitive |
264 | | /// @param tagType The record tag type value |
265 | | /// @param value A string representing the tag value |
266 | | Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const std::string& value); |
267 | | |
268 | 36.3k | ~Asn1GenericRecord() override = default; |
269 | | |
270 | | /// @return A pointer to the tag value |
271 | | const uint8_t* getValue() |
272 | 0 | { |
273 | 0 | decodeValueIfNeeded(); |
274 | 0 | return m_Value.get(); |
275 | 0 | } |
276 | | |
277 | | protected: |
278 | 36.3k | Asn1GenericRecord() = default; |
279 | | |
280 | | void decodeValue(uint8_t const* data) const override; |
281 | | std::vector<uint8_t> encodeValue() const override; |
282 | | |
283 | | private: |
284 | | mutable std::unique_ptr<uint8_t[]> m_Value = nullptr; |
285 | | |
286 | | void init(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, size_t valueLen); |
287 | | }; |
288 | | |
289 | | /// @class Asn1ConstructedRecord |
290 | | /// Represents a constructed ASN.1 record, which is a record that has sub-records |
291 | | class Asn1ConstructedRecord : public Asn1Record |
292 | | { |
293 | | friend class Asn1Record; |
294 | | |
295 | | public: |
296 | | /// A constructor to create a constructed record |
297 | | /// @param tagClass The record tag class |
298 | | /// @param tagType The record tag type value |
299 | | /// @param subRecords A list of sub-records to assign as the record value |
300 | | explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, |
301 | | const std::vector<Asn1Record*>& subRecords); |
302 | | |
303 | | /// A constructor to create a constructed record |
304 | | /// @param tagClass The record tag class |
305 | | /// @param tagType The record tag type value |
306 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
307 | | explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, |
308 | | const PointerVector<Asn1Record>& subRecords); |
309 | | |
310 | | /// @return A reference to the list of sub-records. It's important to note that any modifications made to |
311 | | /// this list will directly affect the internal structure |
312 | | PointerVector<Asn1Record>& getSubRecords() |
313 | 95.3k | { |
314 | 95.3k | decodeValueIfNeeded(); |
315 | 95.3k | return m_SubRecords; |
316 | 95.3k | }; |
317 | | |
318 | | protected: |
319 | 178k | Asn1ConstructedRecord() = default; |
320 | | |
321 | | void decodeValue(uint8_t const* data) const override; |
322 | | std::vector<uint8_t> encodeValue() const override; |
323 | | |
324 | | std::vector<std::string> toStringList() const override; |
325 | | |
326 | | template <typename Iterator> void init(Asn1TagClass tagClass, uint8_t tagType, Iterator begin, Iterator end) |
327 | 0 | { |
328 | 0 | m_TagType = tagType; |
329 | 0 | m_TagClass = tagClass; |
330 | 0 | m_IsConstructed = true; |
331 | |
|
332 | 0 | size_t recordValueLength = 0; |
333 | 0 | for (Iterator recordIter = begin; recordIter != end; ++recordIter) |
334 | 0 | { |
335 | 0 | auto encodedRecord = (*recordIter)->encode(); |
336 | 0 | auto copyRecord = Asn1Record::decode(encodedRecord.data(), encodedRecord.size(), LazySubRecordDecoding); |
337 | 0 | m_SubRecords.pushBack(std::move(copyRecord)); |
338 | 0 | recordValueLength += encodedRecord.size(); |
339 | 0 | } |
340 | |
|
341 | 0 | m_ValueLength = recordValueLength; |
342 | 0 | m_TotalLength = recordValueLength + 1 + (m_ValueLength < 128 ? 1 : 2); |
343 | 0 | } |
344 | | |
345 | | private: |
346 | | // Set to false as there are issues with lazy decoding of sub-records in some cases. |
347 | | static constexpr bool LazySubRecordDecoding = false; |
348 | | |
349 | | mutable PointerVector<Asn1Record> m_SubRecords; |
350 | | }; |
351 | | |
352 | | /// @class Asn1SequenceRecord |
353 | | /// Represents an ASN.1 record with a value of type Sequence |
354 | | class Asn1SequenceRecord : public Asn1ConstructedRecord |
355 | | { |
356 | | friend class Asn1Record; |
357 | | |
358 | | public: |
359 | | /// A constructor to create a record of type Sequence |
360 | | /// @param subRecords A list of sub-records to assign as the record value |
361 | | explicit Asn1SequenceRecord(const std::vector<Asn1Record*>& subRecords); |
362 | | |
363 | | /// A constructor to create a record of type Sequence |
364 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
365 | | explicit Asn1SequenceRecord(const PointerVector<Asn1Record>& subRecords); |
366 | | |
367 | | private: |
368 | 89.4k | Asn1SequenceRecord() = default; |
369 | | }; |
370 | | |
371 | | /// @class Asn1SetRecord |
372 | | /// Represents an ASN.1 record with a value of type Set |
373 | | class Asn1SetRecord : public Asn1ConstructedRecord |
374 | | { |
375 | | friend class Asn1Record; |
376 | | |
377 | | public: |
378 | | /// A constructor to create a record of type Set |
379 | | /// @param subRecords A list of sub-records to assign as the record value |
380 | | explicit Asn1SetRecord(const std::vector<Asn1Record*>& subRecords); |
381 | | |
382 | | /// A constructor to create a record of type Set |
383 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
384 | | explicit Asn1SetRecord(const PointerVector<Asn1Record>& subRecords); |
385 | | |
386 | | private: |
387 | 15.0k | Asn1SetRecord() = default; |
388 | | }; |
389 | | |
390 | | /// @class Asn1PrimitiveRecord |
391 | | /// Represents a primitive ASN.1 record, meaning a record that doesn't have sub-records. |
392 | | /// This is an abstract class that cannot be instantiated |
393 | | class Asn1PrimitiveRecord : public Asn1Record |
394 | | { |
395 | | friend class Asn1Record; |
396 | | |
397 | | protected: |
398 | 103k | Asn1PrimitiveRecord() = default; |
399 | | explicit Asn1PrimitiveRecord(Asn1UniversalTagType tagType); |
400 | | }; |
401 | | |
402 | | /// @class Asn1IntegerRecord |
403 | | /// Represents an ASN.1 record with a value of type Integer |
404 | | class Asn1IntegerRecord : public Asn1PrimitiveRecord |
405 | | { |
406 | | friend class Asn1Record; |
407 | | |
408 | | public: |
409 | | template <typename T> |
410 | | using EnableIfUnsignedIntegral = |
411 | | std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, int>; |
412 | | |
413 | | /// A constructor to create a record of type Integer |
414 | | /// @param value An integer to set as the record value |
415 | | explicit Asn1IntegerRecord(uint64_t value); |
416 | | |
417 | | /// A constructor to create a record of type Integer |
418 | | /// @param value An integer represented as a hex stream to set as the record value |
419 | | /// @throw std::invalid_argument if the value isn't a valid hex stream |
420 | | explicit Asn1IntegerRecord(const std::string& value); |
421 | | |
422 | | /// @return The integer value of this record |
423 | | /// @throw std::invalid_argument if the value doesn't fit the requested integer size |
424 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> T getIntValue() const |
425 | 5.45k | { |
426 | 5.45k | decodeValueIfNeeded(); |
427 | 5.45k | return m_Value.getInt<T>(); |
428 | 5.45k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord11getIntValueIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v _ZNK4pcpp17Asn1IntegerRecord11getIntValueIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Line | Count | Source | 425 | 5.45k | { | 426 | 5.45k | decodeValueIfNeeded(); | 427 | 5.45k | return m_Value.getInt<T>(); | 428 | 5.45k | } |
Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord11getIntValueImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord11getIntValueItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v |
429 | | |
430 | | /// @deprecated This method is deprecated, please use getIntValue() |
431 | | PCPP_DEPRECATED("Use getIntValue instead") |
432 | | uint32_t getValue() |
433 | 0 | { |
434 | 0 | return getIntValue<uint32_t>(); |
435 | 0 | } |
436 | | |
437 | | /// Get the integer value of this record as a hex string |
438 | | /// @param removeLeadingZeros If true, leading zeros will be removed |
439 | | /// @return A hex string representation of the record value |
440 | | std::string getValueAsString(bool removeLeadingZeros = false) const |
441 | 0 | { |
442 | 0 | decodeValueIfNeeded(); |
443 | 0 | return m_Value.toString(removeLeadingZeros); |
444 | 0 | } |
445 | | |
446 | | protected: |
447 | 91.9k | Asn1IntegerRecord() = default; |
448 | | |
449 | | void decodeValue(uint8_t const* data) const override; |
450 | | std::vector<uint8_t> encodeValue() const override; |
451 | | |
452 | | std::vector<std::string> toStringList() const override; |
453 | | |
454 | | private: |
455 | | class BigInt |
456 | | { |
457 | | public: |
458 | 91.9k | BigInt() = default; |
459 | | |
460 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> |
461 | | explicit BigInt(T value) : m_Value(initFromInt(value)) |
462 | | {} |
463 | | |
464 | | explicit BigInt(const std::string& value); |
465 | | BigInt(const BigInt& other); |
466 | | |
467 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> BigInt& operator=(T value) |
468 | 0 | { |
469 | 0 | m_Value = initFromInt(value); |
470 | 0 | return *this; |
471 | 0 | } |
472 | | BigInt& operator=(const std::string& value); |
473 | | size_t size() const; |
474 | | |
475 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> T getInt() const |
476 | 5.45k | { |
477 | 5.45k | if (!canFit<T>()) |
478 | 0 | { |
479 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); |
480 | 0 | } |
481 | | |
482 | 5.45k | std::stringstream sstream; |
483 | 5.45k | sstream << std::hex << m_Value; |
484 | | |
485 | 5.45k | uint64_t result; |
486 | 5.45k | sstream >> result; |
487 | 5.45k | return static_cast<T>(result); |
488 | 5.45k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Line | Count | Source | 476 | 5.45k | { | 477 | 5.45k | if (!canFit<T>()) | 478 | 0 | { | 479 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); | 480 | 0 | } | 481 | | | 482 | 5.45k | std::stringstream sstream; | 483 | 5.45k | sstream << std::hex << m_Value; | 484 | | | 485 | 5.45k | uint64_t result; | 486 | 5.45k | sstream >> result; | 487 | 5.45k | return static_cast<T>(result); | 488 | 5.45k | } |
Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v |
489 | | |
490 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> bool canFit() const |
491 | 5.45k | { |
492 | 5.45k | return sizeof(T) >= (m_Value.size() + 1) / 2; |
493 | 5.45k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Line | Count | Source | 491 | 5.45k | { | 492 | 5.45k | return sizeof(T) >= (m_Value.size() + 1) / 2; | 493 | 5.45k | } |
Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv |
494 | | |
495 | | std::string toString(bool removeLeadingZeros = false) const; |
496 | | std::vector<uint8_t> toBytes() const; |
497 | | |
498 | | private: |
499 | | std::string m_Value; |
500 | | |
501 | | static std::string initFromString(const std::string& value); |
502 | | |
503 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> static std::string initFromInt(T value) |
504 | 0 | { |
505 | 0 | std::stringstream ss; |
506 | 0 | ss << std::hex << static_cast<uint64_t>(value); |
507 | 0 | return ss.str(); |
508 | 0 | } |
509 | | }; |
510 | | |
511 | | mutable BigInt m_Value; |
512 | | }; |
513 | | |
514 | | /// @class Asn1EnumeratedRecord |
515 | | /// Represents an ASN.1 record with a value of type Enumerated |
516 | | class Asn1EnumeratedRecord : public Asn1IntegerRecord |
517 | | { |
518 | | friend class Asn1Record; |
519 | | |
520 | | public: |
521 | | /// A constructor to create a record of type Enumerated |
522 | | /// @param value An integer to set as the record value |
523 | | explicit Asn1EnumeratedRecord(uint32_t value); |
524 | | |
525 | | private: |
526 | 21.7k | Asn1EnumeratedRecord() = default; |
527 | | }; |
528 | | |
529 | | /// @class Asn1StringRecord |
530 | | /// An abstract class for representing ASN.1 string records. |
531 | | /// This class is not instantiable, users should use the derived classes |
532 | | template <Asn1UniversalTagType TagType> class Asn1StringRecord : public Asn1PrimitiveRecord |
533 | | { |
534 | | public: |
535 | | /// @return The string value of this record |
536 | | std::string getValue() const |
537 | 1.03k | { |
538 | 1.03k | decodeValueIfNeeded(); |
539 | 1.03k | return m_Value; |
540 | 1.03k | }; Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::getValue() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::getValue() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::getValue() const pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::getValue() const Line | Count | Source | 537 | 1.03k | { | 538 | 1.03k | decodeValueIfNeeded(); | 539 | 1.03k | return m_Value; | 540 | 1.03k | }; |
|
541 | | |
542 | | protected: |
543 | 133k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) |
544 | 133k | {}pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::Asn1StringRecord() Line | Count | Source | 543 | 69 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 544 | 69 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::Asn1StringRecord() Line | Count | Source | 543 | 31 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 544 | 31 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::Asn1StringRecord() Line | Count | Source | 543 | 87 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 544 | 87 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::Asn1StringRecord() Line | Count | Source | 543 | 133k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 544 | 133k | {} |
|
545 | | |
546 | 0 | explicit Asn1StringRecord(const std::string& value) : Asn1PrimitiveRecord(TagType), m_Value(value) |
547 | 0 | { |
548 | 0 | m_ValueLength = value.size(); |
549 | 0 | m_TotalLength = m_ValueLength + 2; |
550 | 0 | } |
551 | | |
552 | | void decodeValue(uint8_t const* data) const override |
553 | 120k | { |
554 | 120k | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); |
555 | 120k | } pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::decodeValue(unsigned char const*) const Line | Count | Source | 553 | 120k | { | 554 | 120k | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 555 | 120k | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::decodeValue(unsigned char const*) const Line | Count | Source | 553 | 69 | { | 554 | 69 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 555 | 69 | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::decodeValue(unsigned char const*) const Line | Count | Source | 553 | 16 | { | 554 | 16 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 555 | 16 | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::decodeValue(unsigned char const*) const Line | Count | Source | 553 | 87 | { | 554 | 87 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 555 | 87 | } |
|
556 | | std::vector<uint8_t> encodeValue() const override |
557 | 0 | { |
558 | 0 | return { m_Value.begin(), m_Value.end() }; |
559 | 0 | } Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::encodeValue() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::encodeValue() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::encodeValue() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::encodeValue() const |
560 | | |
561 | | std::vector<std::string> toStringList() const override |
562 | 0 | { |
563 | 0 | return { Asn1Record::toStringList().front() + ", Value: " + getValue() }; |
564 | 0 | } Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::toStringList() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::toStringList() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::toStringList() const Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::toStringList() const |
565 | | |
566 | | mutable std::string m_Value; |
567 | | }; |
568 | | |
569 | | /// @class Asn1OctetStringRecord |
570 | | /// Represents an ASN.1 record with a value of type Octet String |
571 | | class Asn1OctetStringRecord : public Asn1StringRecord<Asn1UniversalTagType::OctetString> |
572 | | { |
573 | | friend class Asn1Record; |
574 | | |
575 | | public: |
576 | | using Asn1StringRecord::Asn1StringRecord; |
577 | | |
578 | | /// A constructor to create a record of type Octet String from a non-printable value |
579 | | /// @param value A byte array to set as the record value |
580 | | /// @param valueLength The length of the byte array |
581 | | explicit Asn1OctetStringRecord(const uint8_t* value, size_t valueLength); |
582 | | |
583 | | /// A constructor to create a record from a printable string value |
584 | | /// @param value A string to set as the record value |
585 | | explicit Asn1OctetStringRecord(const std::string& value) : Asn1StringRecord(value) |
586 | 0 | {} |
587 | | |
588 | | protected: |
589 | | void decodeValue(uint8_t const* data) const override; |
590 | | std::vector<uint8_t> encodeValue() const override; |
591 | | |
592 | | private: |
593 | 133k | Asn1OctetStringRecord() = default; |
594 | | |
595 | | mutable bool m_IsPrintable = true; |
596 | | }; |
597 | | |
598 | | /// @class Asn1UTF8StringRecord |
599 | | /// Represents an ASN.1 record with a value of type UTF8 String |
600 | | class Asn1UTF8StringRecord : public Asn1StringRecord<Asn1UniversalTagType::UTF8String> |
601 | | { |
602 | | friend class Asn1Record; |
603 | | |
604 | | public: |
605 | | /// A constructor to create a record from a printable string value |
606 | | /// @param value A string to set as the record value |
607 | | explicit Asn1UTF8StringRecord(const std::string& value) : Asn1StringRecord(value) |
608 | 0 | {} |
609 | | |
610 | | private: |
611 | 69 | Asn1UTF8StringRecord() = default; |
612 | | }; |
613 | | |
614 | | /// @class Asn1PrintableStringRecord |
615 | | /// Represents an ASN.1 record with a value of type Printable String |
616 | | class Asn1PrintableStringRecord : public Asn1StringRecord<Asn1UniversalTagType::PrintableString> |
617 | | { |
618 | | friend class Asn1Record; |
619 | | |
620 | | public: |
621 | | /// A constructor to create a record from a printable string value |
622 | | /// @param value A string to set as the record value |
623 | | explicit Asn1PrintableStringRecord(const std::string& value) : Asn1StringRecord(value) |
624 | 0 | {} |
625 | | |
626 | | private: |
627 | 31 | Asn1PrintableStringRecord() = default; |
628 | | }; |
629 | | |
630 | | /// @class Asn1IA5StringRecord |
631 | | /// Represents an ASN.1 record with a value of type IA5 String |
632 | | class Asn1IA5StringRecord : public Asn1StringRecord<Asn1UniversalTagType::IA5String> |
633 | | { |
634 | | friend class Asn1Record; |
635 | | |
636 | | public: |
637 | | /// A constructor to create a record from a printable string value |
638 | | /// @param value A string to set as the record value |
639 | | explicit Asn1IA5StringRecord(const std::string& value) : Asn1StringRecord(value) |
640 | 0 | {} |
641 | | |
642 | | private: |
643 | 87 | Asn1IA5StringRecord() = default; |
644 | | }; |
645 | | |
646 | | /// @class Asn1BooleanRecord |
647 | | /// Represents an ASN.1 record with a value of type Boolean |
648 | | class Asn1BooleanRecord : public Asn1PrimitiveRecord |
649 | | { |
650 | | friend class Asn1Record; |
651 | | |
652 | | public: |
653 | | /// A constructor to create a record of type Boolean |
654 | | /// @param value A boolean to set as the record value |
655 | | explicit Asn1BooleanRecord(bool value); |
656 | | |
657 | | /// @return The boolean value of this record |
658 | | bool getValue() const |
659 | 0 | { |
660 | 0 | decodeValueIfNeeded(); |
661 | 0 | return m_Value; |
662 | 0 | }; |
663 | | |
664 | | protected: |
665 | | void decodeValue(uint8_t const* data) const override; |
666 | | std::vector<uint8_t> encodeValue() const override; |
667 | | |
668 | | std::vector<std::string> toStringList() const override; |
669 | | |
670 | | private: |
671 | 9.66k | Asn1BooleanRecord() = default; |
672 | | |
673 | | mutable bool m_Value = false; |
674 | | }; |
675 | | |
676 | | /// @class Asn1NullRecord |
677 | | /// Represents an ASN.1 record with a value of type Null |
678 | | class Asn1NullRecord : public Asn1PrimitiveRecord |
679 | | { |
680 | | friend class Asn1Record; |
681 | | |
682 | | public: |
683 | | /// A constructor to create a record of type Null |
684 | | Asn1NullRecord(); |
685 | | |
686 | | protected: |
687 | | void decodeValue(uint8_t const* data) const override |
688 | 566 | {} |
689 | | std::vector<uint8_t> encodeValue() const override |
690 | 0 | { |
691 | 0 | return {}; |
692 | 0 | } |
693 | | }; |
694 | | |
695 | | /// @class Asn1ObjectIdentifier |
696 | | /// Represents an ASN.1 Object Identifier (OID). |
697 | | class Asn1ObjectIdentifier |
698 | | { |
699 | | friend class Asn1ObjectIdentifierRecord; |
700 | | |
701 | | public: |
702 | | /// Construct an OID from an encoded byte buffer |
703 | | /// @param[in] data The byte buffer of the encoded OID data |
704 | | /// @param[in] dataLen The byte buffer size |
705 | | explicit Asn1ObjectIdentifier(const uint8_t* data, size_t dataLen); |
706 | | |
707 | | /// Construct an OID from its string representation (e.g., "1.2.840.113549"). |
708 | | /// @param[in] oidString The string representation of the OID |
709 | | /// @throws std::invalid_argument if the string is malformed or contains invalid components |
710 | | explicit Asn1ObjectIdentifier(const std::string& oidString); |
711 | | |
712 | | /// @return A const reference to the internal vector of components |
713 | | const std::vector<uint32_t>& getComponents() const |
714 | 0 | { |
715 | 0 | return m_Components; |
716 | 0 | } |
717 | | |
718 | | /// Equality operator to compare two OIDs |
719 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
720 | | bool operator==(const Asn1ObjectIdentifier& other) const |
721 | 0 | { |
722 | 0 | return m_Components == other.m_Components; |
723 | 0 | } |
724 | | |
725 | | /// Inequality operator to compare two OIDs |
726 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
727 | | bool operator!=(const Asn1ObjectIdentifier& other) const |
728 | 0 | { |
729 | 0 | return m_Components != other.m_Components; |
730 | 0 | } |
731 | | |
732 | | /// Convert the OID to its string representation (e.g., "1.2.840.113549") |
733 | | /// @return A string representing the OID |
734 | | std::string toString() const; |
735 | | |
736 | | /// Encode the OID to a byte buffer |
737 | | /// @return A byte buffer containing the encoded OID value |
738 | | std::vector<uint8_t> toBytes() const; |
739 | | |
740 | | friend std::ostream& operator<<(std::ostream& os, const Asn1ObjectIdentifier& oid) |
741 | 0 | { |
742 | 0 | return os << oid.toString(); |
743 | 0 | } |
744 | | |
745 | | protected: |
746 | 1.20k | Asn1ObjectIdentifier() = default; |
747 | | |
748 | | private: |
749 | | std::vector<uint32_t> m_Components; |
750 | | }; |
751 | | |
752 | | /// @class Asn1ObjectIdentifierRecord |
753 | | /// Represents an ASN.1 record with a value of type ObjectIdentifier |
754 | | class Asn1ObjectIdentifierRecord : public Asn1PrimitiveRecord |
755 | | { |
756 | | friend class Asn1Record; |
757 | | |
758 | | public: |
759 | | /// A constructor to create a ObjectIdentifier record |
760 | | /// @param[in] value The ObjectIdentifier (OID) to set as the record value |
761 | | explicit Asn1ObjectIdentifierRecord(const Asn1ObjectIdentifier& value); |
762 | | |
763 | | /// @return The OID value of this record |
764 | | const Asn1ObjectIdentifier& getValue() const |
765 | 0 | { |
766 | 0 | decodeValueIfNeeded(); |
767 | 0 | return m_Value; |
768 | 0 | } |
769 | | |
770 | | protected: |
771 | | void decodeValue(uint8_t const* data) const override; |
772 | | std::vector<uint8_t> encodeValue() const override; |
773 | | |
774 | | std::vector<std::string> toStringList() const override; |
775 | | |
776 | | private: |
777 | | mutable Asn1ObjectIdentifier m_Value; |
778 | | |
779 | 1.20k | Asn1ObjectIdentifierRecord() = default; |
780 | | }; |
781 | | |
782 | | /// @class Asn1TimeRecord |
783 | | /// An abstract class for representing ASN.1 time records (UTCTime and GeneralizedTime). |
784 | | /// This class is not instantiable, users should use either Asn1UtcTimeRecord or Asn1GeneralizedTimeRecord |
785 | | class Asn1TimeRecord : public Asn1PrimitiveRecord |
786 | | { |
787 | | public: |
788 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
789 | | /// timezones. The default value is UTC |
790 | | /// @return The time-point value of this record |
791 | | /// @throws std::invalid_argument if timezone is not in the correct format |
792 | | std::chrono::system_clock::time_point getValue(const std::string& timezone = "Z") const |
793 | 0 | { |
794 | 0 | decodeValueIfNeeded(); |
795 | 0 | return adjustTimezones(m_Value, "Z", timezone); |
796 | 0 | }; |
797 | | |
798 | | /// @param[in] format Requested value format |
799 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
800 | | /// timezones. The default value is UTC |
801 | | /// @param[in] includeMilliseconds Should Include milliseconds in the returned string |
802 | | /// @return The value as string |
803 | | /// @throws std::invalid_argument if timezone is not in the correct format |
804 | | std::string getValueAsString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z", |
805 | | bool includeMilliseconds = false) const; |
806 | | |
807 | | protected: |
808 | 775 | Asn1TimeRecord() = default; |
809 | | explicit Asn1TimeRecord(Asn1UniversalTagType tagType, const std::chrono::system_clock::time_point& value, |
810 | | const std::string& timezone); |
811 | | |
812 | | mutable std::chrono::system_clock::time_point m_Value; |
813 | | |
814 | | std::vector<std::string> toStringList() const override; |
815 | | |
816 | | static void validateTimezone(const std::string& timezone); |
817 | | static std::chrono::system_clock::time_point adjustTimezones(const std::chrono::system_clock::time_point& value, |
818 | | const std::string& fromTimezone, |
819 | | const std::string& toTimezone); |
820 | | }; |
821 | | |
822 | | /// @class Asn1UtcTimeRecord |
823 | | /// Represents an ASN.1 record with a value of type UTCTime |
824 | | class Asn1UtcTimeRecord : public Asn1TimeRecord |
825 | | { |
826 | | friend class Asn1Record; |
827 | | |
828 | | public: |
829 | | /// A constructor to create a record of type UTC time |
830 | | /// @param[in] value A time-point to set as the record value |
831 | | /// @param[in] withSeconds Should write the ASN.1 record with second precision. The default is true |
832 | | explicit Asn1UtcTimeRecord(const std::chrono::system_clock::time_point& value, bool withSeconds = true); |
833 | | |
834 | | protected: |
835 | | void decodeValue(uint8_t const* data) const override; |
836 | | std::vector<uint8_t> encodeValue() const override; |
837 | | |
838 | | private: |
839 | 105 | Asn1UtcTimeRecord() = default; |
840 | | mutable bool m_WithSeconds = true; |
841 | | }; |
842 | | |
843 | | /// @class Asn1GeneralizedTimeRecord |
844 | | /// Represents an ASN.1 record with a value of type GeneralizedTime |
845 | | class Asn1GeneralizedTimeRecord : public Asn1TimeRecord |
846 | | { |
847 | | friend class Asn1Record; |
848 | | |
849 | | public: |
850 | | /// A constructor to create a record of type generalized time |
851 | | /// @param[in] value A time-point to set as the record value |
852 | | /// @param[in] timezone The time-point's timezone - should be in the format of "Z" for UTC or +=HHMM for other |
853 | | /// timezones. If not provided it's assumed the timezone is UTC |
854 | | /// @throws std::invalid_argument if timezone is not in the correct format |
855 | | explicit Asn1GeneralizedTimeRecord(const std::chrono::system_clock::time_point& value, |
856 | | const std::string& timezone = "Z"); |
857 | | |
858 | | protected: |
859 | | void decodeValue(uint8_t const* data) const override; |
860 | | std::vector<uint8_t> encodeValue() const override; |
861 | | |
862 | | private: |
863 | 670 | Asn1GeneralizedTimeRecord() = default; |
864 | | mutable std::string m_Timezone; |
865 | | }; |
866 | | |
867 | | /// @class Asn1BitStringRecord |
868 | | /// Represents an ASN.1 record with a value of type BitString |
869 | | class Asn1BitStringRecord : public Asn1PrimitiveRecord |
870 | | { |
871 | | friend class Asn1Record; |
872 | | |
873 | | public: |
874 | | /// A constructor to create a record of type BitString |
875 | | /// @param value A bit string to set as the record value |
876 | | /// @throw std::invalid_argument if the string is not a valid bit string |
877 | | explicit Asn1BitStringRecord(const std::string& value); |
878 | | |
879 | | /// @return The bit string value of this record |
880 | | std::string getValue() |
881 | 0 | { |
882 | 0 | decodeValueIfNeeded(); |
883 | 0 | return m_Value.toString(); |
884 | 0 | }; |
885 | | |
886 | | /// @return The byte vector value of this record |
887 | | std::vector<uint8_t> getVecValue() |
888 | 0 | { |
889 | 0 | decodeValueIfNeeded(); |
890 | 0 | return m_Value.toBytes(); |
891 | 0 | } |
892 | | |
893 | | protected: |
894 | | void decodeValue(uint8_t const* data) const override; |
895 | | std::vector<uint8_t> encodeValue() const override; |
896 | | |
897 | | std::vector<std::string> toStringList() const override; |
898 | | |
899 | | private: |
900 | | class BitSet |
901 | | { |
902 | | public: |
903 | 189 | BitSet() = default; |
904 | | explicit BitSet(const std::string& value); |
905 | | BitSet(const uint8_t* data, size_t numBits); |
906 | | |
907 | | BitSet& operator=(const std::string& value); |
908 | | |
909 | | size_t sizeInBytes() const; |
910 | | std::string toString() const; |
911 | | std::vector<uint8_t> toBytes() const; |
912 | | size_t getNumBits() const |
913 | 0 | { |
914 | 0 | return m_NumBits; |
915 | 0 | } |
916 | | |
917 | | private: |
918 | | void initFromString(const std::string& value); |
919 | | |
920 | | std::vector<std::bitset<8>> m_Data; |
921 | | size_t m_NumBits = 0; |
922 | | }; |
923 | | |
924 | 189 | Asn1BitStringRecord() = default; |
925 | | |
926 | | mutable BitSet m_Value; |
927 | | }; |
928 | | } // namespace pcpp |