/src/PcapPlusPlus/Packet++/header/Asn1Codec.h
Line | Count | Source (jump to first uncovered line) |
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 | 60.1k | { |
165 | 60.1k | return m_TagType; |
166 | 60.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 | 629k | { |
177 | 629k | return m_TotalLength; |
178 | 629k | } |
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 | 100k | { |
189 | 100k | auto result = dynamic_cast<Asn1RecordType*>(this); |
190 | 100k | if (result == nullptr) |
191 | 1.68k | { |
192 | 1.68k | throw std::bad_cast(); |
193 | 1.68k | } |
194 | 98.4k | return result; |
195 | 100k | } pcpp::Asn1SequenceRecord* pcpp::Asn1Record::castAs<pcpp::Asn1SequenceRecord>() Line | Count | Source | 188 | 71.9k | { | 189 | 71.9k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 71.9k | if (result == nullptr) | 191 | 1.50k | { | 192 | 1.50k | throw std::bad_cast(); | 193 | 1.50k | } | 194 | 70.4k | return result; | 195 | 71.9k | } |
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.01k | { | 189 | 1.01k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 1.01k | if (result == nullptr) | 191 | 0 | { | 192 | 0 | throw std::bad_cast(); | 193 | 0 | } | 194 | 1.01k | return result; | 195 | 1.01k | } |
pcpp::Asn1ConstructedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1ConstructedRecord>() Line | Count | Source | 188 | 22.1k | { | 189 | 22.1k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 22.1k | if (result == nullptr) | 191 | 186 | { | 192 | 186 | throw std::bad_cast(); | 193 | 186 | } | 194 | 21.9k | return result; | 195 | 22.1k | } |
pcpp::Asn1EnumeratedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1EnumeratedRecord>() Line | Count | Source | 188 | 5.11k | { | 189 | 5.11k | auto result = dynamic_cast<Asn1RecordType*>(this); | 190 | 5.11k | if (result == nullptr) | 191 | 0 | { | 192 | 0 | throw std::bad_cast(); | 193 | 0 | } | 194 | 5.11k | return result; | 195 | 5.11k | } |
Unexecuted instantiation: pcpp::Asn1GenericRecord* pcpp::Asn1Record::castAs<pcpp::Asn1GenericRecord>() |
196 | | |
197 | 342k | 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 | 342k | 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 | 14.6k | ~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 | 14.6k | 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 | 79.2k | { |
314 | 79.2k | decodeValueIfNeeded(); |
315 | 79.2k | return m_SubRecords; |
316 | 79.2k | }; |
317 | | |
318 | | protected: |
319 | 137k | 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 | 69.3k | 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 | 8.53k | 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 | 80.4k | 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.11k | { |
426 | 5.11k | decodeValueIfNeeded(); |
427 | 5.11k | return m_Value.getInt<T>(); |
428 | 5.11k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord11getIntValueIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v _ZNK4pcpp17Asn1IntegerRecord11getIntValueIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Line | Count | Source | 425 | 5.11k | { | 426 | 5.11k | decodeValueIfNeeded(); | 427 | 5.11k | return m_Value.getInt<T>(); | 428 | 5.11k | } |
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 | | /// @return A hex string representation of the record value |
438 | | std::string getValueAsString() const |
439 | 0 | { |
440 | 0 | decodeValueIfNeeded(); |
441 | 0 | return m_Value.toString(); |
442 | 0 | } |
443 | | |
444 | | protected: |
445 | 76.2k | Asn1IntegerRecord() = default; |
446 | | |
447 | | void decodeValue(uint8_t const* data) const override; |
448 | | std::vector<uint8_t> encodeValue() const override; |
449 | | |
450 | | std::vector<std::string> toStringList() const override; |
451 | | |
452 | | private: |
453 | | class BigInt |
454 | | { |
455 | | public: |
456 | 76.2k | BigInt() = default; |
457 | | |
458 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> explicit BigInt(T value) |
459 | | { |
460 | | m_Value = initFromInt(value); |
461 | | } |
462 | | |
463 | | explicit BigInt(const std::string& value); |
464 | | BigInt(const BigInt& other); |
465 | | |
466 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> BigInt& operator=(T value) |
467 | 0 | { |
468 | 0 | m_Value = initFromInt(value); |
469 | 0 | return *this; |
470 | 0 | } |
471 | | BigInt& operator=(const std::string& value); |
472 | | size_t size() const; |
473 | | |
474 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> T getInt() const |
475 | 5.11k | { |
476 | 5.11k | if (!canFit<T>()) |
477 | 0 | { |
478 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); |
479 | 0 | } |
480 | | |
481 | 5.11k | std::stringstream sstream; |
482 | 5.11k | sstream << std::hex << m_Value; |
483 | | |
484 | 5.11k | uint64_t result; |
485 | 5.11k | sstream >> result; |
486 | 5.11k | return static_cast<T>(result); |
487 | 5.11k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Line | Count | Source | 475 | 5.11k | { | 476 | 5.11k | if (!canFit<T>()) | 477 | 0 | { | 478 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); | 479 | 0 | } | 480 | | | 481 | 5.11k | std::stringstream sstream; | 482 | 5.11k | sstream << std::hex << m_Value; | 483 | | | 484 | 5.11k | uint64_t result; | 485 | 5.11k | sstream >> result; | 486 | 5.11k | return static_cast<T>(result); | 487 | 5.11k | } |
Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v |
488 | | |
489 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> bool canFit() const |
490 | 5.11k | { |
491 | 5.11k | return sizeof(T) >= (m_Value.size() + 1) / 2; |
492 | 5.11k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Line | Count | Source | 490 | 5.11k | { | 491 | 5.11k | return sizeof(T) >= (m_Value.size() + 1) / 2; | 492 | 5.11k | } |
Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv |
493 | | |
494 | | std::string toString() const; |
495 | | std::vector<uint8_t> toBytes() const; |
496 | | |
497 | | private: |
498 | | std::string m_Value; |
499 | | |
500 | | static std::string initFromString(const std::string& value); |
501 | | |
502 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> static std::string initFromInt(T value) |
503 | 0 | { |
504 | 0 | std::stringstream ss; |
505 | 0 | ss << std::hex << static_cast<uint64_t>(value); |
506 | 0 | return ss.str(); |
507 | 0 | } |
508 | | }; |
509 | | |
510 | | mutable BigInt m_Value; |
511 | | }; |
512 | | |
513 | | /// @class Asn1EnumeratedRecord |
514 | | /// Represents an ASN.1 record with a value of type Enumerated |
515 | | class Asn1EnumeratedRecord : public Asn1IntegerRecord |
516 | | { |
517 | | friend class Asn1Record; |
518 | | |
519 | | public: |
520 | | /// A constructor to create a record of type Enumerated |
521 | | /// @param value An integer to set as the record value |
522 | | explicit Asn1EnumeratedRecord(uint32_t value); |
523 | | |
524 | | private: |
525 | 19.3k | Asn1EnumeratedRecord() = default; |
526 | | }; |
527 | | |
528 | | /// @class Asn1StringRecord |
529 | | /// An abstract class for representing ASN.1 string records. |
530 | | /// This class is not instantiable, users should use the derived classes |
531 | | template <Asn1UniversalTagType TagType> class Asn1StringRecord : public Asn1PrimitiveRecord |
532 | | { |
533 | | public: |
534 | | /// @return The string value of this record |
535 | | std::string getValue() const |
536 | 1.01k | { |
537 | 1.01k | decodeValueIfNeeded(); |
538 | 1.01k | return m_Value; |
539 | 1.01k | }; 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 | 536 | 1.01k | { | 537 | 1.01k | decodeValueIfNeeded(); | 538 | 1.01k | return m_Value; | 539 | 1.01k | }; |
|
540 | | |
541 | | protected: |
542 | 109k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) |
543 | 109k | {} pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::Asn1StringRecord() Line | Count | Source | 542 | 118 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 543 | 118 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::Asn1StringRecord() Line | Count | Source | 542 | 15 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 543 | 15 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::Asn1StringRecord() Line | Count | Source | 542 | 24 | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 543 | 24 | {} |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::Asn1StringRecord() Line | Count | Source | 542 | 109k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 543 | 109k | {} |
|
544 | | |
545 | 0 | explicit Asn1StringRecord(const std::string& value) : Asn1PrimitiveRecord(TagType), m_Value(value) |
546 | 0 | { |
547 | 0 | m_ValueLength = value.size(); |
548 | 0 | m_TotalLength = m_ValueLength + 2; |
549 | 0 | } |
550 | | |
551 | | void decodeValue(uint8_t const* data) const override |
552 | 97.6k | { |
553 | 97.6k | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); |
554 | 97.6k | } pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::decodeValue(unsigned char const*) const Line | Count | Source | 552 | 97.5k | { | 553 | 97.5k | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 554 | 97.5k | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::decodeValue(unsigned char const*) const Line | Count | Source | 552 | 38 | { | 553 | 38 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 554 | 38 | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::decodeValue(unsigned char const*) const Line | Count | Source | 552 | 10 | { | 553 | 10 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 554 | 10 | } |
pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::decodeValue(unsigned char const*) const Line | Count | Source | 552 | 17 | { | 553 | 17 | m_Value = std::string(reinterpret_cast<char const*>(data), m_ValueLength); | 554 | 17 | } |
|
555 | | std::vector<uint8_t> encodeValue() const override |
556 | 0 | { |
557 | 0 | return { m_Value.begin(), m_Value.end() }; |
558 | 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 |
559 | | |
560 | | std::vector<std::string> toStringList() const override |
561 | 0 | { |
562 | 0 | return { Asn1Record::toStringList().front() + ", Value: " + getValue() }; |
563 | 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 |
564 | | |
565 | | mutable std::string m_Value; |
566 | | }; |
567 | | |
568 | | /// @class Asn1OctetStringRecord |
569 | | /// Represents an ASN.1 record with a value of type Octet String |
570 | | class Asn1OctetStringRecord : public Asn1StringRecord<Asn1UniversalTagType::OctetString> |
571 | | { |
572 | | friend class Asn1Record; |
573 | | |
574 | | public: |
575 | | using Asn1StringRecord::Asn1StringRecord; |
576 | | |
577 | | /// A constructor to create a record of type Octet String from a non-printable value |
578 | | /// @param value A byte array to set as the record value |
579 | | /// @param valueLength The length of the byte array |
580 | | explicit Asn1OctetStringRecord(const uint8_t* value, size_t valueLength); |
581 | | |
582 | | /// A constructor to create a record from a printable string value |
583 | | /// @param value A string to set as the record value |
584 | | explicit Asn1OctetStringRecord(const std::string& value) : Asn1StringRecord(value) |
585 | 0 | {} |
586 | | |
587 | | protected: |
588 | | void decodeValue(uint8_t const* data) const override; |
589 | | std::vector<uint8_t> encodeValue() const override; |
590 | | |
591 | | private: |
592 | 109k | Asn1OctetStringRecord() = default; |
593 | | |
594 | | mutable bool m_IsPrintable = true; |
595 | | }; |
596 | | |
597 | | /// @class Asn1UTF8StringRecord |
598 | | /// Represents an ASN.1 record with a value of type UTF8 String |
599 | | class Asn1UTF8StringRecord : public Asn1StringRecord<Asn1UniversalTagType::UTF8String> |
600 | | { |
601 | | friend class Asn1Record; |
602 | | |
603 | | public: |
604 | | /// A constructor to create a record from a printable string value |
605 | | /// @param value A string to set as the record value |
606 | | explicit Asn1UTF8StringRecord(const std::string& value) : Asn1StringRecord(value) |
607 | 0 | {} |
608 | | |
609 | | private: |
610 | 118 | Asn1UTF8StringRecord() = default; |
611 | | }; |
612 | | |
613 | | /// @class Asn1PrintableStringRecord |
614 | | /// Represents an ASN.1 record with a value of type Printable String |
615 | | class Asn1PrintableStringRecord : public Asn1StringRecord<Asn1UniversalTagType::PrintableString> |
616 | | { |
617 | | friend class Asn1Record; |
618 | | |
619 | | public: |
620 | | /// A constructor to create a record from a printable string value |
621 | | /// @param value A string to set as the record value |
622 | | explicit Asn1PrintableStringRecord(const std::string& value) : Asn1StringRecord(value) |
623 | 0 | {} |
624 | | |
625 | | private: |
626 | 15 | Asn1PrintableStringRecord() = default; |
627 | | }; |
628 | | |
629 | | /// @class Asn1IA5StringRecord |
630 | | /// Represents an ASN.1 record with a value of type IA5 String |
631 | | class Asn1IA5StringRecord : public Asn1StringRecord<Asn1UniversalTagType::IA5String> |
632 | | { |
633 | | friend class Asn1Record; |
634 | | |
635 | | public: |
636 | | /// A constructor to create a record from a printable string value |
637 | | /// @param value A string to set as the record value |
638 | | explicit Asn1IA5StringRecord(const std::string& value) : Asn1StringRecord(value) |
639 | 0 | {} |
640 | | |
641 | | private: |
642 | 24 | Asn1IA5StringRecord() = default; |
643 | | }; |
644 | | |
645 | | /// @class Asn1BooleanRecord |
646 | | /// Represents an ASN.1 record with a value of type Boolean |
647 | | class Asn1BooleanRecord : public Asn1PrimitiveRecord |
648 | | { |
649 | | friend class Asn1Record; |
650 | | |
651 | | public: |
652 | | /// A constructor to create a record of type Boolean |
653 | | /// @param value A boolean to set as the record value |
654 | | explicit Asn1BooleanRecord(bool value); |
655 | | |
656 | | /// @return The boolean value of this record |
657 | | bool getValue() const |
658 | 0 | { |
659 | 0 | decodeValueIfNeeded(); |
660 | 0 | return m_Value; |
661 | 0 | }; |
662 | | |
663 | | protected: |
664 | | void decodeValue(uint8_t const* data) const override; |
665 | | std::vector<uint8_t> encodeValue() const override; |
666 | | |
667 | | std::vector<std::string> toStringList() const override; |
668 | | |
669 | | private: |
670 | 3.47k | Asn1BooleanRecord() = default; |
671 | | |
672 | | mutable bool m_Value = false; |
673 | | }; |
674 | | |
675 | | /// @class Asn1NullRecord |
676 | | /// Represents an ASN.1 record with a value of type Null |
677 | | class Asn1NullRecord : public Asn1PrimitiveRecord |
678 | | { |
679 | | friend class Asn1Record; |
680 | | |
681 | | public: |
682 | | /// A constructor to create a record of type Null |
683 | | Asn1NullRecord(); |
684 | | |
685 | | protected: |
686 | | void decodeValue(uint8_t const* data) const override |
687 | 120 | {} |
688 | | std::vector<uint8_t> encodeValue() const override |
689 | 0 | { |
690 | 0 | return {}; |
691 | 0 | } |
692 | | }; |
693 | | |
694 | | /// @class Asn1ObjectIdentifier |
695 | | /// Represents an ASN.1 Object Identifier (OID). |
696 | | class Asn1ObjectIdentifier |
697 | | { |
698 | | friend class Asn1ObjectIdentifierRecord; |
699 | | |
700 | | public: |
701 | | /// Construct an OID from an encoded byte buffer |
702 | | /// @param[in] data The byte buffer of the encoded OID data |
703 | | /// @param[in] dataLen The byte buffer size |
704 | | explicit Asn1ObjectIdentifier(const uint8_t* data, size_t dataLen); |
705 | | |
706 | | /// Construct an OID from its string representation (e.g., "1.2.840.113549"). |
707 | | /// @param[in] oidString The string representation of the OID |
708 | | /// @throws std::invalid_argument if the string is malformed or contains invalid components |
709 | | explicit Asn1ObjectIdentifier(const std::string& oidString); |
710 | | |
711 | | /// @return A const reference to the internal vector of components |
712 | | const std::vector<uint32_t>& getComponents() const |
713 | 0 | { |
714 | 0 | return m_Components; |
715 | 0 | } |
716 | | |
717 | | /// Equality operator to compare two OIDs |
718 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
719 | | bool operator==(const Asn1ObjectIdentifier& other) const |
720 | 0 | { |
721 | 0 | return m_Components == other.m_Components; |
722 | 0 | } |
723 | | |
724 | | /// Inequality operator to compare two OIDs |
725 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
726 | | bool operator!=(const Asn1ObjectIdentifier& other) const |
727 | 0 | { |
728 | 0 | return m_Components != other.m_Components; |
729 | 0 | } |
730 | | |
731 | | /// Convert the OID to its string representation (e.g., "1.2.840.113549") |
732 | | /// @return A string representing the OID |
733 | | std::string toString() const; |
734 | | |
735 | | /// Encode the OID to a byte buffer |
736 | | /// @return A byte buffer containing the encoded OID value |
737 | | std::vector<uint8_t> toBytes() const; |
738 | | |
739 | | friend std::ostream& operator<<(std::ostream& os, const Asn1ObjectIdentifier& oid) |
740 | 0 | { |
741 | 0 | return os << oid.toString(); |
742 | 0 | } |
743 | | |
744 | | protected: |
745 | 416 | Asn1ObjectIdentifier() = default; |
746 | | |
747 | | private: |
748 | | std::vector<uint32_t> m_Components; |
749 | | }; |
750 | | |
751 | | /// @class Asn1ObjectIdentifierRecord |
752 | | /// Represents an ASN.1 record with a value of type ObjectIdentifier |
753 | | class Asn1ObjectIdentifierRecord : public Asn1PrimitiveRecord |
754 | | { |
755 | | friend class Asn1Record; |
756 | | |
757 | | public: |
758 | | /// A constructor to create a ObjectIdentifier record |
759 | | /// @param[in] value The ObjectIdentifier (OID) to set as the record value |
760 | | explicit Asn1ObjectIdentifierRecord(const Asn1ObjectIdentifier& value); |
761 | | |
762 | | /// @return The OID value of this record |
763 | | const Asn1ObjectIdentifier& getValue() const |
764 | 0 | { |
765 | 0 | decodeValueIfNeeded(); |
766 | 0 | return m_Value; |
767 | 0 | } |
768 | | |
769 | | protected: |
770 | | void decodeValue(uint8_t const* data) const override; |
771 | | std::vector<uint8_t> encodeValue() const override; |
772 | | |
773 | | std::vector<std::string> toStringList() const override; |
774 | | |
775 | | private: |
776 | | mutable Asn1ObjectIdentifier m_Value; |
777 | | |
778 | 416 | Asn1ObjectIdentifierRecord() = default; |
779 | | }; |
780 | | |
781 | | /// @class Asn1TimeRecord |
782 | | /// An abstract class for representing ASN.1 time records (UTCTime and GeneralizedTime). |
783 | | /// This class is not instantiable, users should use either Asn1UtcTimeRecord or Asn1GeneralizedTimeRecord |
784 | | class Asn1TimeRecord : public Asn1PrimitiveRecord |
785 | | { |
786 | | public: |
787 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
788 | | /// timezones. The default value is UTC |
789 | | /// @return The time-point value of this record |
790 | | /// @throws std::invalid_argument if timezone is not in the correct format |
791 | | std::chrono::system_clock::time_point getValue(const std::string& timezone = "Z") const |
792 | 0 | { |
793 | 0 | decodeValueIfNeeded(); |
794 | 0 | return adjustTimezones(m_Value, "Z", timezone); |
795 | 0 | }; |
796 | | |
797 | | /// @param[in] format Requested value format |
798 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
799 | | /// timezones. The default value is UTC |
800 | | /// @param[in] includeMilliseconds Should Include milliseconds in the returned string |
801 | | /// @return The value as string |
802 | | /// @throws std::invalid_argument if timezone is not in the correct format |
803 | | std::string getValueAsString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z", |
804 | | bool includeMilliseconds = false) const; |
805 | | |
806 | | protected: |
807 | 135 | Asn1TimeRecord() = default; |
808 | | explicit Asn1TimeRecord(Asn1UniversalTagType tagType, const std::chrono::system_clock::time_point& value, |
809 | | const std::string& timezone); |
810 | | |
811 | | mutable std::chrono::system_clock::time_point m_Value; |
812 | | |
813 | | std::vector<std::string> toStringList() const override; |
814 | | |
815 | | static void validateTimezone(const std::string& timezone); |
816 | | static std::chrono::system_clock::time_point adjustTimezones(const std::chrono::system_clock::time_point& value, |
817 | | const std::string& fromTimezone, |
818 | | const std::string& toTimezone); |
819 | | }; |
820 | | |
821 | | /// @class Asn1UtcTimeRecord |
822 | | /// Represents an ASN.1 record with a value of type UTCTime |
823 | | class Asn1UtcTimeRecord : public Asn1TimeRecord |
824 | | { |
825 | | friend class Asn1Record; |
826 | | |
827 | | public: |
828 | | /// A constructor to create a record of type UTC time |
829 | | /// @param[in] value A time-point to set as the record value |
830 | | /// @param[in] withSeconds Should write the ASN.1 record with second precision. The default is true |
831 | | explicit Asn1UtcTimeRecord(const std::chrono::system_clock::time_point& value, bool withSeconds = true); |
832 | | |
833 | | protected: |
834 | | void decodeValue(uint8_t const* data) const override; |
835 | | std::vector<uint8_t> encodeValue() const override; |
836 | | |
837 | | private: |
838 | 20 | Asn1UtcTimeRecord() = default; |
839 | | mutable bool m_WithSeconds = true; |
840 | | }; |
841 | | |
842 | | /// @class Asn1GeneralizedTimeRecord |
843 | | /// Represents an ASN.1 record with a value of type GeneralizedTime |
844 | | class Asn1GeneralizedTimeRecord : public Asn1TimeRecord |
845 | | { |
846 | | friend class Asn1Record; |
847 | | |
848 | | public: |
849 | | /// A constructor to create a record of type generalized time |
850 | | /// @param[in] value A time-point to set as the record value |
851 | | /// @param[in] timezone The time-point's timezone - should be in the format of "Z" for UTC or +=HHMM for other |
852 | | /// timezones. If not provided it's assumed the timezone is UTC |
853 | | /// @throws std::invalid_argument if timezone is not in the correct format |
854 | | explicit Asn1GeneralizedTimeRecord(const std::chrono::system_clock::time_point& value, |
855 | | const std::string& timezone = "Z"); |
856 | | |
857 | | protected: |
858 | | void decodeValue(uint8_t const* data) const override; |
859 | | std::vector<uint8_t> encodeValue() const override; |
860 | | |
861 | | private: |
862 | 115 | Asn1GeneralizedTimeRecord() = default; |
863 | | mutable std::string m_Timezone; |
864 | | }; |
865 | | |
866 | | /// @class Asn1BitStringRecord |
867 | | /// Represents an ASN.1 record with a value of type BitString |
868 | | class Asn1BitStringRecord : public Asn1PrimitiveRecord |
869 | | { |
870 | | friend class Asn1Record; |
871 | | |
872 | | public: |
873 | | /// A constructor to create a record of type BitString |
874 | | /// @param value A bit string to set as the record value |
875 | | /// @throw std::invalid_argument if the string is not a valid bit string |
876 | | explicit Asn1BitStringRecord(const std::string& value); |
877 | | |
878 | | /// @return The bit string value of this record |
879 | | std::string getValue() |
880 | 0 | { |
881 | 0 | decodeValueIfNeeded(); |
882 | 0 | return m_Value.toString(); |
883 | 0 | }; |
884 | | |
885 | | /// @return The byte vector value of this record |
886 | | std::vector<uint8_t> getVecValue() |
887 | 0 | { |
888 | 0 | decodeValueIfNeeded(); |
889 | 0 | return m_Value.toBytes(); |
890 | 0 | } |
891 | | |
892 | | protected: |
893 | | void decodeValue(uint8_t const* data) const override; |
894 | | std::vector<uint8_t> encodeValue() const override; |
895 | | |
896 | | std::vector<std::string> toStringList() const override; |
897 | | |
898 | | private: |
899 | | class BitSet |
900 | | { |
901 | | public: |
902 | 192 | BitSet() = default; |
903 | | explicit BitSet(const std::string& value); |
904 | | BitSet(const uint8_t* data, size_t numBits); |
905 | | |
906 | | BitSet& operator=(const std::string& value); |
907 | | |
908 | | size_t sizeInBytes() const; |
909 | | std::string toString() const; |
910 | | std::vector<uint8_t> toBytes() const; |
911 | | size_t getNumBits() const |
912 | 0 | { |
913 | 0 | return m_NumBits; |
914 | 0 | } |
915 | | |
916 | | private: |
917 | | void initFromString(const std::string& value); |
918 | | |
919 | | std::vector<std::bitset<8>> m_Data; |
920 | | size_t m_NumBits = 0; |
921 | | }; |
922 | | |
923 | 192 | Asn1BitStringRecord() = default; |
924 | | |
925 | | mutable BitSet m_Value; |
926 | | }; |
927 | | } // namespace pcpp |