/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 | | /// @class Asn1Record |
113 | | /// Represents an ASN.1 record, as described in ITU-T Recommendation X.680: |
114 | | /// <https://www.itu.int/rec/T-REC-X.680/en> |
115 | | /// <https://en.wikipedia.org/wiki/ASN.1> |
116 | | class Asn1Record |
117 | | { |
118 | | public: |
119 | | /// A static method to decode a byte array into an Asn1Record |
120 | | /// @param data A byte array to decode |
121 | | /// @param dataLen The byte array length |
122 | | /// @param lazy Use lazy decoding, set to true by default. Lazy decoding entails delaying the decoding |
123 | | /// of the record value until it is accessed |
124 | | /// @return A smart pointer to the decoded ASN.1 record. If the byte stream is not a valid ASN.1 record |
125 | | /// an exception is thrown |
126 | | static std::unique_ptr<Asn1Record> decode(const uint8_t* data, size_t dataLen, bool lazy = true); |
127 | | |
128 | | /// Encode this record and convert it to a byte stream |
129 | | /// @return A vector of bytes representing the record |
130 | | std::vector<uint8_t> encode(); |
131 | | |
132 | | /// @return The ASN.1 tag class |
133 | | Asn1TagClass getTagClass() const |
134 | 0 | { |
135 | 0 | return m_TagClass; |
136 | 0 | } |
137 | | |
138 | | /// @return True if it's a constructed record, or false if it's a primitive record |
139 | | bool isConstructed() const |
140 | 0 | { |
141 | 0 | return m_IsConstructed; |
142 | 0 | } |
143 | | |
144 | | /// @return The ASN.1 Universal tag type if the record is of class Universal, otherwise |
145 | | /// Asn1UniversalTagType#NotApplicable |
146 | | Asn1UniversalTagType getUniversalTagType() const; |
147 | | |
148 | | /// @return The ASN.1 tag type value |
149 | | uint8_t getTagType() const |
150 | 27.8k | { |
151 | 27.8k | return m_TagType; |
152 | 27.8k | } |
153 | | |
154 | | /// @return The length of the record value |
155 | | size_t getValueLength() const |
156 | 0 | { |
157 | 0 | return m_ValueLength; |
158 | 0 | } |
159 | | |
160 | | /// @return The total length of the record |
161 | | size_t getTotalLength() const |
162 | 131k | { |
163 | 131k | return m_TotalLength; |
164 | 131k | } |
165 | | |
166 | | /// @return A string representation of the record |
167 | | std::string toString(); |
168 | | |
169 | | /// A templated method that accepts a class derived from Asn1Record as its template argument and attempts |
170 | | /// to cast the current instance to that type |
171 | | /// @tparam Asn1RecordType The type to cast to |
172 | | /// @return A pointer to the type after casting |
173 | | template <class Asn1RecordType> Asn1RecordType* castAs() |
174 | 48.7k | { |
175 | 48.7k | auto result = dynamic_cast<Asn1RecordType*>(this); |
176 | 48.7k | if (result == nullptr) |
177 | 481 | { |
178 | 481 | throw std::bad_cast(); |
179 | 481 | } |
180 | 48.2k | return result; |
181 | 48.7k | } pcpp::Asn1SequenceRecord* pcpp::Asn1Record::castAs<pcpp::Asn1SequenceRecord>() Line | Count | Source | 174 | 33.3k | { | 175 | 33.3k | auto result = dynamic_cast<Asn1RecordType*>(this); | 176 | 33.3k | if (result == nullptr) | 177 | 365 | { | 178 | 365 | throw std::bad_cast(); | 179 | 365 | } | 180 | 33.0k | return result; | 181 | 33.3k | } |
pcpp::Asn1ConstructedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1ConstructedRecord>() Line | Count | Source | 174 | 11.8k | { | 175 | 11.8k | auto result = dynamic_cast<Asn1RecordType*>(this); | 176 | 11.8k | if (result == nullptr) | 177 | 116 | { | 178 | 116 | throw std::bad_cast(); | 179 | 116 | } | 180 | 11.6k | return result; | 181 | 11.8k | } |
Unexecuted instantiation: pcpp::Asn1IntegerRecord* pcpp::Asn1Record::castAs<pcpp::Asn1IntegerRecord>() pcpp::Asn1OctetStringRecord* pcpp::Asn1Record::castAs<pcpp::Asn1OctetStringRecord>() Line | Count | Source | 174 | 640 | { | 175 | 640 | auto result = dynamic_cast<Asn1RecordType*>(this); | 176 | 640 | if (result == nullptr) | 177 | 0 | { | 178 | 0 | throw std::bad_cast(); | 179 | 0 | } | 180 | 640 | return result; | 181 | 640 | } |
pcpp::Asn1EnumeratedRecord* pcpp::Asn1Record::castAs<pcpp::Asn1EnumeratedRecord>() Line | Count | Source | 174 | 2.95k | { | 175 | 2.95k | auto result = dynamic_cast<Asn1RecordType*>(this); | 176 | 2.95k | if (result == nullptr) | 177 | 0 | { | 178 | 0 | throw std::bad_cast(); | 179 | 0 | } | 180 | 2.95k | return result; | 181 | 2.95k | } |
Unexecuted instantiation: pcpp::Asn1GenericRecord* pcpp::Asn1Record::castAs<pcpp::Asn1GenericRecord>() Unexecuted instantiation: pcpp::Asn1BooleanRecord* pcpp::Asn1Record::castAs<pcpp::Asn1BooleanRecord>() Unexecuted instantiation: pcpp::Asn1SetRecord* pcpp::Asn1Record::castAs<pcpp::Asn1SetRecord>() |
182 | | |
183 | 75.9k | virtual ~Asn1Record() = default; |
184 | | |
185 | | protected: |
186 | | Asn1TagClass m_TagClass = Asn1TagClass::Universal; |
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 | 75.9k | 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 | | |
214 | | /// @class Asn1GenericRecord |
215 | | /// Represents a generic ASN.1 record, either of an unknown type or of a known type that doesn't |
216 | | /// have a dedicated parser yet |
217 | | class Asn1GenericRecord : public Asn1Record |
218 | | { |
219 | | friend class Asn1Record; |
220 | | |
221 | | public: |
222 | | /// A constructor to create a generic record |
223 | | /// @param tagClass The record tag class |
224 | | /// @param isConstructed A flag to indicate if the record is constructed or primitive |
225 | | /// @param tagType The record tag type value |
226 | | /// @param value A byte array of the tag value |
227 | | /// @param valueLen The length of the value byte array |
228 | | Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, |
229 | | size_t valueLen); |
230 | | |
231 | | /// A constructor to create a generic record |
232 | | /// @param tagClass The record tag class |
233 | | /// @param isConstructed A flag to indicate if the record is constructed or primitive |
234 | | /// @param tagType The record tag type value |
235 | | /// @param value A string representing the tag value |
236 | | Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const std::string& value); |
237 | | |
238 | | ~Asn1GenericRecord() override; |
239 | | |
240 | | /// @return A pointer to the tag value |
241 | | const uint8_t* getValue() |
242 | 0 | { |
243 | 0 | decodeValueIfNeeded(); |
244 | 0 | return m_Value; |
245 | 0 | } |
246 | | |
247 | | protected: |
248 | 2.38k | 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 | | |
259 | | /// @class Asn1ConstructedRecord |
260 | | /// Represents a constructed ASN.1 record, which is a record that has sub-records |
261 | | class Asn1ConstructedRecord : public Asn1Record |
262 | | { |
263 | | friend class Asn1Record; |
264 | | |
265 | | public: |
266 | | /// A constructor to create a constructed record |
267 | | /// @param tagClass The record tag class |
268 | | /// @param tagType The record tag type value |
269 | | /// @param subRecords A list of sub-records to assign as the record value |
270 | | explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, |
271 | | const std::vector<Asn1Record*>& subRecords); |
272 | | |
273 | | /// A constructor to create a constructed record |
274 | | /// @param tagClass The record tag class |
275 | | /// @param tagType The record tag type value |
276 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
277 | | explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, |
278 | | const PointerVector<Asn1Record>& subRecords); |
279 | | |
280 | | /// @return A reference to the list of sub-records. It's important to note that any modifications made to |
281 | | /// this list will directly affect the internal structure |
282 | | PointerVector<Asn1Record>& getSubRecords() |
283 | 38.4k | { |
284 | 38.4k | decodeValueIfNeeded(); |
285 | 38.4k | return m_SubRecords; |
286 | 38.4k | }; |
287 | | |
288 | | protected: |
289 | 45.8k | 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 | 0 | { |
298 | 0 | m_TagType = tagType; |
299 | 0 | m_TagClass = tagClass; |
300 | 0 | m_IsConstructed = true; |
301 | |
|
302 | 0 | size_t recordValueLength = 0; |
303 | 0 | for (Iterator recordIter = begin; recordIter != end; ++recordIter) |
304 | 0 | { |
305 | 0 | auto encodedRecord = (*recordIter)->encode(); |
306 | 0 | auto copyRecord = Asn1Record::decode(encodedRecord.data(), encodedRecord.size(), false); |
307 | 0 | m_SubRecords.pushBack(std::move(copyRecord)); |
308 | 0 | recordValueLength += encodedRecord.size(); |
309 | 0 | } |
310 | |
|
311 | 0 | m_ValueLength = recordValueLength; |
312 | 0 | m_TotalLength = recordValueLength + 1 + (m_ValueLength < 128 ? 1 : 2); |
313 | 0 | } |
314 | | |
315 | | private: |
316 | | PointerVector<Asn1Record> m_SubRecords; |
317 | | }; |
318 | | |
319 | | /// @class Asn1SequenceRecord |
320 | | /// Represents an ASN.1 record with a value of type Sequence |
321 | | class Asn1SequenceRecord : public Asn1ConstructedRecord |
322 | | { |
323 | | friend class Asn1Record; |
324 | | |
325 | | public: |
326 | | /// A constructor to create a record of type Sequence |
327 | | /// @param subRecords A list of sub-records to assign as the record value |
328 | | explicit Asn1SequenceRecord(const std::vector<Asn1Record*>& subRecords); |
329 | | |
330 | | /// A constructor to create a record of type Sequence |
331 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
332 | | explicit Asn1SequenceRecord(const PointerVector<Asn1Record>& subRecords); |
333 | | |
334 | | private: |
335 | 21.5k | Asn1SequenceRecord() = default; |
336 | | }; |
337 | | |
338 | | /// @class Asn1SetRecord |
339 | | /// Represents an ASN.1 record with a value of type Set |
340 | | class Asn1SetRecord : public Asn1ConstructedRecord |
341 | | { |
342 | | friend class Asn1Record; |
343 | | |
344 | | public: |
345 | | /// A constructor to create a record of type Set |
346 | | /// @param subRecords A list of sub-records to assign as the record value |
347 | | explicit Asn1SetRecord(const std::vector<Asn1Record*>& subRecords); |
348 | | |
349 | | /// A constructor to create a record of type Set |
350 | | /// @param subRecords A PointerVector of sub-records to assign as the record value |
351 | | explicit Asn1SetRecord(const PointerVector<Asn1Record>& subRecords); |
352 | | |
353 | | private: |
354 | 173 | Asn1SetRecord() = default; |
355 | | }; |
356 | | |
357 | | /// @class Asn1PrimitiveRecord |
358 | | /// Represents a primitive ASN.1 record, meaning a record that doesn't have sub-records. |
359 | | /// This is an abstract class that cannot be instantiated |
360 | | class Asn1PrimitiveRecord : public Asn1Record |
361 | | { |
362 | | friend class Asn1Record; |
363 | | |
364 | | protected: |
365 | 24.5k | Asn1PrimitiveRecord() = default; |
366 | | explicit Asn1PrimitiveRecord(Asn1UniversalTagType tagType); |
367 | | }; |
368 | | |
369 | | /// @class Asn1IntegerRecord |
370 | | /// Represents an ASN.1 record with a value of type Integer |
371 | | class Asn1IntegerRecord : public Asn1PrimitiveRecord |
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 | | |
380 | | /// A constructor to create a record of type Integer |
381 | | /// @param value An integer to set as the record value |
382 | | explicit Asn1IntegerRecord(uint64_t value); |
383 | | |
384 | | /// A constructor to create a record of type Integer |
385 | | /// @param value An integer represented as a hex stream to set as the record value |
386 | | /// @throw std::invalid_argument if the value isn't a valid hex stream |
387 | | explicit Asn1IntegerRecord(const std::string& value); |
388 | | |
389 | | /// @return The integer value of this record |
390 | | /// @throw std::invalid_argument if the value doesn't fit the requested integer size |
391 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> T getIntValue() |
392 | 2.95k | { |
393 | 2.95k | decodeValueIfNeeded(); |
394 | 2.95k | return m_Value.getInt<T>(); |
395 | 2.95k | } Unexecuted instantiation: _ZN4pcpp17Asn1IntegerRecord11getIntValueIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Unexecuted instantiation: _ZN4pcpp17Asn1IntegerRecord11getIntValueImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Unexecuted instantiation: _ZN4pcpp17Asn1IntegerRecord11getIntValueItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v _ZN4pcpp17Asn1IntegerRecord11getIntValueIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS4_EE5valueEiE4typeELi0EEES4_v Line | Count | Source | 392 | 2.95k | { | 393 | 2.95k | decodeValueIfNeeded(); | 394 | 2.95k | return m_Value.getInt<T>(); | 395 | 2.95k | } |
|
396 | | |
397 | | /// @deprecated This method is deprecated, please use getIntValue() |
398 | | PCPP_DEPRECATED("Use getIntValue instead") |
399 | | uint32_t getValue() |
400 | 0 | { |
401 | 0 | return getIntValue<uint32_t>(); |
402 | 0 | } |
403 | | |
404 | | /// @return A hex string representation of the record value |
405 | | std::string getValueAsString() |
406 | 0 | { |
407 | 0 | decodeValueIfNeeded(); |
408 | 0 | return m_Value.toString(); |
409 | 0 | } |
410 | | |
411 | | protected: |
412 | 24.1k | 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 | 24.1k | 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 | 0 | { |
435 | 0 | m_Value = initFromInt(value); |
436 | 0 | return *this; |
437 | 0 | } |
438 | | BigInt& operator=(const std::string& value); |
439 | | size_t size() const; |
440 | | |
441 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> T getInt() const |
442 | 2.95k | { |
443 | 2.95k | if (!canFit<T>()) |
444 | 0 | { |
445 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); |
446 | 0 | } |
447 | | |
448 | 2.95k | std::stringstream sstream; |
449 | 2.95k | sstream << std::hex << m_Value; |
450 | | |
451 | 2.95k | uint64_t result; |
452 | 2.95k | sstream >> result; |
453 | 2.95k | return static_cast<T>(result); |
454 | 2.95k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v _ZNK4pcpp17Asn1IntegerRecord6BigInt6getIntIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEES5_v Line | Count | Source | 442 | 2.95k | { | 443 | 2.95k | if (!canFit<T>()) | 444 | 0 | { | 445 | 0 | throw std::overflow_error("Value cannot fit into requested int type"); | 446 | 0 | } | 447 | | | 448 | 2.95k | std::stringstream sstream; | 449 | 2.95k | sstream << std::hex << m_Value; | 450 | | | 451 | 2.95k | uint64_t result; | 452 | 2.95k | sstream >> result; | 453 | 2.95k | return static_cast<T>(result); | 454 | 2.95k | } |
|
455 | | |
456 | | template <typename T, EnableIfUnsignedIntegral<T> = 0> bool canFit() const |
457 | 2.95k | { |
458 | 2.95k | return sizeof(T) >= (m_Value.size() + 1) / 2; |
459 | 2.95k | } Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIjTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitImTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Unexecuted instantiation: _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitItTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv _ZNK4pcpp17Asn1IntegerRecord6BigInt6canFitIhTnNSt3__19enable_ifIXaasr3std11is_integralIT_EE5valuesr3std11is_unsignedIS5_EE5valueEiE4typeELi0EEEbv Line | Count | Source | 457 | 2.95k | { | 458 | 2.95k | return sizeof(T) >= (m_Value.size() + 1) / 2; | 459 | 2.95k | } |
|
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 | 0 | { |
471 | 0 | std::stringstream ss; |
472 | 0 | ss << std::hex << static_cast<uint64_t>(value); |
473 | 0 | return ss.str(); |
474 | 0 | } |
475 | | }; |
476 | | |
477 | | BigInt m_Value; |
478 | | }; |
479 | | |
480 | | /// @class Asn1EnumeratedRecord |
481 | | /// Represents an ASN.1 record with a value of type Enumerated |
482 | | class Asn1EnumeratedRecord : public Asn1IntegerRecord |
483 | | { |
484 | | friend class Asn1Record; |
485 | | |
486 | | public: |
487 | | /// A constructor to create a record of type Enumerated |
488 | | /// @param value An integer to set as the record value |
489 | | explicit Asn1EnumeratedRecord(uint32_t value); |
490 | | |
491 | | private: |
492 | 1.90k | Asn1EnumeratedRecord() = default; |
493 | | }; |
494 | | |
495 | | /// @class Asn1StringRecord |
496 | | /// An abstract class for representing ASN.1 string records. |
497 | | /// This class is not instantiable, users should use the derived classes |
498 | | template <Asn1UniversalTagType TagType> class Asn1StringRecord : public Asn1PrimitiveRecord |
499 | | { |
500 | | public: |
501 | | /// @return The string value of this record |
502 | | std::string getValue() |
503 | 640 | { |
504 | 640 | decodeValueIfNeeded(); |
505 | 640 | return m_Value; |
506 | 640 | }; Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::getValue() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::getValue() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::getValue() pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::getValue() Line | Count | Source | 503 | 640 | { | 504 | 640 | decodeValueIfNeeded(); | 505 | 640 | return m_Value; | 506 | 640 | }; |
|
507 | | |
508 | | protected: |
509 | 3.15k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) |
510 | 3.15k | {} Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::Asn1StringRecord() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::Asn1StringRecord() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::Asn1StringRecord() pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::Asn1StringRecord() Line | Count | Source | 509 | 3.15k | Asn1StringRecord() : Asn1PrimitiveRecord(TagType) | 510 | 3.15k | {} |
|
511 | | |
512 | 0 | explicit Asn1StringRecord(const std::string& value) : Asn1PrimitiveRecord(TagType), m_Value(value) |
513 | 0 | { |
514 | 0 | m_ValueLength = value.size(); |
515 | 0 | m_TotalLength = m_ValueLength + 2; |
516 | 0 | } |
517 | | |
518 | | void decodeValue(uint8_t* data, bool lazy) override |
519 | 306 | { |
520 | 306 | m_Value = std::string(reinterpret_cast<char*>(data), m_ValueLength); |
521 | 306 | } Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::decodeValue(unsigned char*, bool) Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::decodeValue(unsigned char*, bool) Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::decodeValue(unsigned char*, bool) pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::decodeValue(unsigned char*, bool) Line | Count | Source | 519 | 306 | { | 520 | 306 | m_Value = std::string(reinterpret_cast<char*>(data), m_ValueLength); | 521 | 306 | } |
|
522 | | std::vector<uint8_t> encodeValue() const override |
523 | 0 | { |
524 | 0 | return { m_Value.begin(), m_Value.end() }; |
525 | 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 |
526 | | |
527 | | std::vector<std::string> toStringList() override |
528 | 0 | { |
529 | 0 | return { Asn1Record::toStringList().front() + ", Value: " + getValue() }; |
530 | 0 | } Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)4>::toStringList() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)12>::toStringList() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)19>::toStringList() Unexecuted instantiation: pcpp::Asn1StringRecord<(pcpp::Asn1UniversalTagType)22>::toStringList() |
531 | | |
532 | | std::string m_Value; |
533 | | }; |
534 | | |
535 | | /// @class Asn1OctetStringRecord |
536 | | /// Represents an ASN.1 record with a value of type Octet String |
537 | | class Asn1OctetStringRecord : public Asn1StringRecord<Asn1UniversalTagType::OctetString> |
538 | | { |
539 | | friend class Asn1Record; |
540 | | |
541 | | public: |
542 | | using Asn1StringRecord::Asn1StringRecord; |
543 | | |
544 | | /// A constructor to create a record of type Octet String from a non-printable value |
545 | | /// @param value A byte array to set as the record value |
546 | | /// @param valueLength The length of the byte array |
547 | | explicit Asn1OctetStringRecord(const uint8_t* value, size_t valueLength); |
548 | | |
549 | | /// A constructor to create a record from a printable string value |
550 | | /// @param value A string to set as the record value |
551 | | explicit Asn1OctetStringRecord(const std::string& value) : Asn1StringRecord(value) |
552 | 0 | {} |
553 | | |
554 | | protected: |
555 | | void decodeValue(uint8_t* data, bool lazy) override; |
556 | | std::vector<uint8_t> encodeValue() const override; |
557 | | |
558 | | private: |
559 | 3.15k | Asn1OctetStringRecord() = default; |
560 | | |
561 | | bool m_IsPrintable = true; |
562 | | }; |
563 | | |
564 | | /// @class Asn1UTF8StringRecord |
565 | | /// Represents an ASN.1 record with a value of type UTF8 String |
566 | | class Asn1UTF8StringRecord : public Asn1StringRecord<Asn1UniversalTagType::UTF8String> |
567 | | { |
568 | | friend class Asn1Record; |
569 | | |
570 | | public: |
571 | | /// A constructor to create a record from a printable string value |
572 | | /// @param value A string to set as the record value |
573 | | explicit Asn1UTF8StringRecord(const std::string& value) : Asn1StringRecord(value) |
574 | 0 | {} |
575 | | |
576 | | private: |
577 | 0 | Asn1UTF8StringRecord() = default; |
578 | | }; |
579 | | |
580 | | /// @class Asn1PrintableStringRecord |
581 | | /// Represents an ASN.1 record with a value of type Printable String |
582 | | class Asn1PrintableStringRecord : public Asn1StringRecord<Asn1UniversalTagType::PrintableString> |
583 | | { |
584 | | friend class Asn1Record; |
585 | | |
586 | | public: |
587 | | /// A constructor to create a record from a printable string value |
588 | | /// @param value A string to set as the record value |
589 | | explicit Asn1PrintableStringRecord(const std::string& value) : Asn1StringRecord(value) |
590 | 0 | {} |
591 | | |
592 | | private: |
593 | 0 | Asn1PrintableStringRecord() = default; |
594 | | }; |
595 | | |
596 | | /// @class Asn1IA5StringRecord |
597 | | /// Represents an ASN.1 record with a value of type IA5 String |
598 | | class Asn1IA5StringRecord : public Asn1StringRecord<Asn1UniversalTagType::IA5String> |
599 | | { |
600 | | friend class Asn1Record; |
601 | | |
602 | | public: |
603 | | /// A constructor to create a record from a printable string value |
604 | | /// @param value A string to set as the record value |
605 | | explicit Asn1IA5StringRecord(const std::string& value) : Asn1StringRecord(value) |
606 | 0 | {} |
607 | | |
608 | | private: |
609 | 0 | Asn1IA5StringRecord() = default; |
610 | | }; |
611 | | |
612 | | /// @class Asn1BooleanRecord |
613 | | /// Represents an ASN.1 record with a value of type Boolean |
614 | | class Asn1BooleanRecord : public Asn1PrimitiveRecord |
615 | | { |
616 | | friend class Asn1Record; |
617 | | |
618 | | public: |
619 | | /// A constructor to create a record of type Boolean |
620 | | /// @param value A boolean to set as the record value |
621 | | explicit Asn1BooleanRecord(bool value); |
622 | | |
623 | | /// @return The boolean value of this record |
624 | | bool getValue() |
625 | 0 | { |
626 | 0 | decodeValueIfNeeded(); |
627 | 0 | return m_Value; |
628 | 0 | }; |
629 | | |
630 | | protected: |
631 | | void decodeValue(uint8_t* data, bool lazy) override; |
632 | | std::vector<uint8_t> encodeValue() const override; |
633 | | |
634 | | std::vector<std::string> toStringList() override; |
635 | | |
636 | | private: |
637 | 376 | Asn1BooleanRecord() = default; |
638 | | |
639 | | bool m_Value = false; |
640 | | }; |
641 | | |
642 | | /// @class Asn1NullRecord |
643 | | /// Represents an ASN.1 record with a value of type Null |
644 | | class Asn1NullRecord : public Asn1PrimitiveRecord |
645 | | { |
646 | | friend class Asn1Record; |
647 | | |
648 | | public: |
649 | | /// A constructor to create a record of type Null |
650 | | Asn1NullRecord(); |
651 | | |
652 | | protected: |
653 | | void decodeValue(uint8_t* data, bool lazy) override |
654 | 0 | {} |
655 | | std::vector<uint8_t> encodeValue() const override |
656 | 0 | { |
657 | 0 | return {}; |
658 | 0 | } |
659 | | }; |
660 | | |
661 | | /// @class Asn1ObjectIdentifier |
662 | | /// Represents an ASN.1 Object Identifier (OID). |
663 | | class Asn1ObjectIdentifier |
664 | | { |
665 | | friend class Asn1ObjectIdentifierRecord; |
666 | | |
667 | | public: |
668 | | /// Construct an OID from an encoded byte buffer |
669 | | /// @param[in] data The byte buffer of the encoded OID data |
670 | | /// @param[in] dataLen The byte buffer size |
671 | | explicit Asn1ObjectIdentifier(const uint8_t* data, size_t dataLen); |
672 | | |
673 | | /// Construct an OID from its string representation (e.g., "1.2.840.113549"). |
674 | | /// @param[in] oidString The string representation of the OID |
675 | | /// @throws std::invalid_argument if the string is malformed or contains invalid components |
676 | | explicit Asn1ObjectIdentifier(const std::string& oidString); |
677 | | |
678 | | /// @return A const reference to the internal vector of components |
679 | | const std::vector<uint32_t>& getComponents() const |
680 | 0 | { |
681 | 0 | return m_Components; |
682 | 0 | } |
683 | | |
684 | | /// Equality operator to compare two OIDs |
685 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
686 | | bool operator==(const Asn1ObjectIdentifier& other) const |
687 | 0 | { |
688 | 0 | return m_Components == other.m_Components; |
689 | 0 | } |
690 | | |
691 | | /// Inequality operator to compare two OIDs |
692 | | /// @param[in] other Another Asn1ObjectIdentifier instance |
693 | | bool operator!=(const Asn1ObjectIdentifier& other) const |
694 | 0 | { |
695 | 0 | return m_Components != other.m_Components; |
696 | 0 | } |
697 | | |
698 | | /// Convert the OID to its string representation (e.g., "1.2.840.113549") |
699 | | /// @return A string representing the OID |
700 | | std::string toString() const; |
701 | | |
702 | | /// Encode the OID to a byte buffer |
703 | | /// @return A byte buffer containing the encoded OID value |
704 | | std::vector<uint8_t> toBytes() const; |
705 | | |
706 | | friend std::ostream& operator<<(std::ostream& os, const Asn1ObjectIdentifier& oid) |
707 | 0 | { |
708 | 0 | return os << oid.toString(); |
709 | 0 | } |
710 | | |
711 | | protected: |
712 | 20 | Asn1ObjectIdentifier() = default; |
713 | | |
714 | | private: |
715 | | std::vector<uint32_t> m_Components; |
716 | | }; |
717 | | |
718 | | /// @class Asn1ObjectIdentifierRecord |
719 | | /// Represents an ASN.1 record with a value of type ObjectIdentifier |
720 | | class Asn1ObjectIdentifierRecord : public Asn1PrimitiveRecord |
721 | | { |
722 | | friend class Asn1Record; |
723 | | |
724 | | public: |
725 | | /// A constructor to create a ObjectIdentifier record |
726 | | /// @param[in] value The ObjectIdentifier (OID) to set as the record value |
727 | | explicit Asn1ObjectIdentifierRecord(const Asn1ObjectIdentifier& value); |
728 | | |
729 | | /// @return The OID value of this record |
730 | | const Asn1ObjectIdentifier& getValue() |
731 | 0 | { |
732 | 0 | decodeValueIfNeeded(); |
733 | 0 | return m_Value; |
734 | 0 | } |
735 | | |
736 | | protected: |
737 | | void decodeValue(uint8_t* data, bool lazy) override; |
738 | | std::vector<uint8_t> encodeValue() const override; |
739 | | |
740 | | std::vector<std::string> toStringList() override; |
741 | | |
742 | | private: |
743 | | Asn1ObjectIdentifier m_Value; |
744 | | |
745 | 20 | Asn1ObjectIdentifierRecord() = default; |
746 | | }; |
747 | | |
748 | | /// @class Asn1TimeRecord |
749 | | /// An abstract class for representing ASN.1 time records (UTCTime and GeneralizedTime). |
750 | | /// This class is not instantiable, users should use either Asn1UtcTimeRecord or Asn1GeneralizedTimeRecord |
751 | | class Asn1TimeRecord : public Asn1PrimitiveRecord |
752 | | { |
753 | | public: |
754 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
755 | | /// timezones. The default value is UTC |
756 | | /// @return The time-point value of this record |
757 | | /// @throws std::invalid_argument if timezone is not in the correct format |
758 | | std::chrono::system_clock::time_point getValue(const std::string& timezone = "Z") |
759 | 0 | { |
760 | 0 | decodeValueIfNeeded(); |
761 | 0 | return adjustTimezones(m_Value, "Z", timezone); |
762 | 0 | }; |
763 | | |
764 | | /// @param[in] format Requested value format |
765 | | /// @param[in] timezone A timezone string - should be in the format of "Z" for UTC or +=HHMM for other |
766 | | /// timezones. The default value is UTC |
767 | | /// @param[in] includeMilliseconds Should Include milliseconds in the returned string |
768 | | /// @return The value as string |
769 | | /// @throws std::invalid_argument if timezone is not in the correct format |
770 | | std::string getValueAsString(const std::string& format = "%Y-%m-%d %H:%M:%S", const std::string& timezone = "Z", |
771 | | bool includeMilliseconds = false); |
772 | | |
773 | | protected: |
774 | 15 | Asn1TimeRecord() = default; |
775 | | explicit Asn1TimeRecord(Asn1UniversalTagType tagType, const std::chrono::system_clock::time_point& value, |
776 | | const std::string& timezone); |
777 | | |
778 | | std::chrono::system_clock::time_point m_Value; |
779 | | |
780 | | std::vector<std::string> toStringList() override; |
781 | | |
782 | | static void validateTimezone(const std::string& timezone); |
783 | | static std::chrono::system_clock::time_point adjustTimezones(const std::chrono::system_clock::time_point& value, |
784 | | const std::string& fromTimezone, |
785 | | const std::string& toTimezone); |
786 | | }; |
787 | | |
788 | | /// @class Asn1UtcTimeRecord |
789 | | /// Represents an ASN.1 record with a value of type UTCTime |
790 | | class Asn1UtcTimeRecord : public Asn1TimeRecord |
791 | | { |
792 | | friend class Asn1Record; |
793 | | |
794 | | public: |
795 | | /// A constructor to create a record of type UTC time |
796 | | /// @param[in] value A time-point to set as the record value |
797 | | /// @param[in] withSeconds Should write the ASN.1 record with second precision. The default is true |
798 | | explicit Asn1UtcTimeRecord(const std::chrono::system_clock::time_point& value, bool withSeconds = true); |
799 | | |
800 | | protected: |
801 | | void decodeValue(uint8_t* data, bool lazy) override; |
802 | | std::vector<uint8_t> encodeValue() const override; |
803 | | |
804 | | private: |
805 | 5 | Asn1UtcTimeRecord() = default; |
806 | | bool m_WithSeconds = true; |
807 | | }; |
808 | | |
809 | | /// @class Asn1GeneralizedTimeRecord |
810 | | /// Represents an ASN.1 record with a value of type GeneralizedTime |
811 | | class Asn1GeneralizedTimeRecord : public Asn1TimeRecord |
812 | | { |
813 | | friend class Asn1Record; |
814 | | |
815 | | public: |
816 | | /// A constructor to create a record of type generalized time |
817 | | /// @param[in] value A time-point to set as the record value |
818 | | /// @param[in] timezone The time-point's timezone - should be in the format of "Z" for UTC or +=HHMM for other |
819 | | /// timezones. If not provided it's assumed the timezone is UTC |
820 | | /// @throws std::invalid_argument if timezone is not in the correct format |
821 | | explicit Asn1GeneralizedTimeRecord(const std::chrono::system_clock::time_point& value, |
822 | | const std::string& timezone = "Z"); |
823 | | |
824 | | protected: |
825 | | void decodeValue(uint8_t* data, bool lazy) override; |
826 | | std::vector<uint8_t> encodeValue() const override; |
827 | | |
828 | | private: |
829 | 10 | Asn1GeneralizedTimeRecord() = default; |
830 | | std::string m_Timezone; |
831 | | }; |
832 | | |
833 | | /// @class Asn1BitStringRecord |
834 | | /// Represents an ASN.1 record with a value of type BitString |
835 | | class Asn1BitStringRecord : public Asn1PrimitiveRecord |
836 | | { |
837 | | friend class Asn1Record; |
838 | | |
839 | | public: |
840 | | /// A constructor to create a record of type BitString |
841 | | /// @param value A bit string to set as the record value |
842 | | /// @throw std::invalid_argument if the string is not a valid bit string |
843 | | explicit Asn1BitStringRecord(const std::string& value); |
844 | | |
845 | | /// @return The bit string value of this record |
846 | | std::string getValue() |
847 | 0 | { |
848 | 0 | decodeValueIfNeeded(); |
849 | 0 | return m_Value.toString(); |
850 | 0 | }; |
851 | | |
852 | | protected: |
853 | | void decodeValue(uint8_t* data, bool lazy) override; |
854 | | std::vector<uint8_t> encodeValue() const override; |
855 | | |
856 | | std::vector<std::string> toStringList() override; |
857 | | |
858 | | private: |
859 | | class BitSet |
860 | | { |
861 | | public: |
862 | 18 | BitSet() = default; |
863 | | explicit BitSet(const std::string& value); |
864 | | BitSet(const uint8_t* data, size_t numBits); |
865 | | |
866 | | BitSet& operator=(const std::string& value); |
867 | | |
868 | | size_t sizeInBytes() const; |
869 | | std::string toString() const; |
870 | | std::vector<uint8_t> toBytes() const; |
871 | | size_t getNumBits() const |
872 | 0 | { |
873 | 0 | return m_NumBits; |
874 | 0 | } |
875 | | |
876 | | private: |
877 | | void initFromString(const std::string& value); |
878 | | |
879 | | std::vector<std::bitset<8>> m_Data; |
880 | | size_t m_NumBits = 0; |
881 | | }; |
882 | | |
883 | 18 | Asn1BitStringRecord() = default; |
884 | | |
885 | | BitSet m_Value; |
886 | | }; |
887 | | } // namespace pcpp |