Coverage Report

Created: 2026-02-07 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/build/include/public/botan/asn1_obj.h
Line
Count
Source
1
/*
2
* (C) 1999-2007,2018,2020 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef BOTAN_ASN1_OBJECT_TYPES_H_
8
#define BOTAN_ASN1_OBJECT_TYPES_H_
9
10
#include <botan/exceptn.h>
11
#include <botan/secmem.h>
12
#include <iosfwd>
13
#include <optional>
14
#include <span>
15
#include <string>
16
#include <string_view>
17
#include <vector>
18
19
namespace Botan {
20
21
class BER_Decoder;
22
class DER_Encoder;
23
class ASN1_Time;  // in asn1_time.h
24
typedef ASN1_Time X509_Time;
25
26
/**
27
* ASN.1 Class Tags
28
*/
29
enum class ASN1_Class : uint32_t /* NOLINT(performance-enum-size) */ {
30
   Universal = 0b0000'0000,
31
   Application = 0b0100'0000,
32
   ContextSpecific = 0b1000'0000,
33
   Private = 0b1100'0000,
34
35
   Constructed = 0b0010'0000,
36
   ExplicitContextSpecific = Constructed | ContextSpecific,
37
38
   NoObject = 0xFF00
39
};
40
41
/**
42
* ASN.1 Type Tags
43
*/
44
enum class ASN1_Type : uint32_t /* NOLINT(performance-enum-size) */ {
45
   Eoc = 0x00,
46
   Boolean = 0x01,
47
   Integer = 0x02,
48
   BitString = 0x03,
49
   OctetString = 0x04,
50
   Null = 0x05,
51
   ObjectId = 0x06,
52
   Enumerated = 0x0A,
53
   Sequence = 0x10,
54
   Set = 0x11,
55
56
   Utf8String = 0x0C,
57
   NumericString = 0x12,
58
   PrintableString = 0x13,
59
   TeletexString = 0x14,
60
   Ia5String = 0x16,
61
   VisibleString = 0x1A,
62
   UniversalString = 0x1C,
63
   BmpString = 0x1E,
64
65
   UtcTime = 0x17,
66
   GeneralizedTime = 0x18,
67
68
   NoObject = 0xFF00,
69
};
70
71
0
inline bool intersects(ASN1_Class x, ASN1_Class y) {
72
0
   return (static_cast<uint32_t>(x) & static_cast<uint32_t>(y)) != 0;
73
0
}
74
75
0
inline ASN1_Type operator|(ASN1_Type x, ASN1_Type y) {
76
0
   return static_cast<ASN1_Type>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
77
0
}
78
79
734
inline ASN1_Class operator|(ASN1_Class x, ASN1_Class y) {
80
734
   return static_cast<ASN1_Class>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
81
734
}
82
83
1.10k
inline uint32_t operator|(ASN1_Type x, ASN1_Class y) {
84
1.10k
   return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
85
1.10k
}
86
87
0
inline uint32_t operator|(ASN1_Class x, ASN1_Type y) {
88
0
   return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
89
0
}
90
91
std::string BOTAN_UNSTABLE_API asn1_tag_to_string(ASN1_Type type);
92
std::string BOTAN_UNSTABLE_API asn1_class_to_string(ASN1_Class type);
93
94
/**
95
* Basic ASN.1 Object Interface
96
*/
97
class BOTAN_PUBLIC_API(2, 0) ASN1_Object {
98
   public:
99
      /**
100
      * Encode whatever this object is into to
101
      * @param to the DER_Encoder that will be written to
102
      */
103
      virtual void encode_into(DER_Encoder& to) const = 0;
104
105
      /**
106
      * Decode whatever this object is from from
107
      * @param from the BER_Decoder that will be read from
108
      */
109
      virtual void decode_from(BER_Decoder& from) = 0;
110
111
      /**
112
      * Return the encoding of this object. This is a convenience
113
      * method when just one object needs to be serialized. Use
114
      * DER_Encoder for complicated encodings.
115
      */
116
      std::vector<uint8_t> BER_encode() const;
117
118
3.27k
      ASN1_Object() = default;
119
70
      ASN1_Object(const ASN1_Object&) = default;
120
0
      ASN1_Object& operator=(const ASN1_Object&) = default;
121
8.94k
      ASN1_Object(ASN1_Object&&) = default;
122
0
      ASN1_Object& operator=(ASN1_Object&&) = default;
123
12.2k
      virtual ~ASN1_Object() = default;
124
};
125
126
/**
127
* BER Encoded Object
128
*/
129
class BOTAN_PUBLIC_API(2, 0) BER_Object final {
130
   public:
131
1.83k
      BER_Object() = default;
132
133
      BER_Object(const BER_Object& other) = default;
134
367
      BER_Object(BER_Object&& other) = default;
135
0
      BER_Object& operator=(const BER_Object& other) = default;
136
0
      BER_Object& operator=(BER_Object&& other) = default;
137
2.20k
      ~BER_Object() = default;
138
139
2.56k
      bool is_set() const { return m_type_tag != ASN1_Type::NoObject; }
140
141
1.10k
      uint32_t tagging() const { return type_tag() | class_tag(); }
142
143
1.10k
      ASN1_Type type_tag() const { return m_type_tag; }
144
145
1.10k
      ASN1_Class class_tag() const { return m_class_tag; }
146
147
0
      ASN1_Type type() const { return m_type_tag; }
148
149
0
      ASN1_Class get_class() const { return m_class_tag; }
150
151
2.93k
      const uint8_t* bits() const { return m_value.data(); }
152
153
7.70k
      size_t length() const { return m_value.size(); }
154
155
734
      std::span<const uint8_t> data() const { return std::span{m_value}; }
156
157
      void assert_is_a(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view descr = "object") const;
158
159
      bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const;
160
161
      bool is_a(int type_tag, ASN1_Class class_tag) const;
162
163
   private:
164
      ASN1_Type m_type_tag = ASN1_Type::NoObject;
165
      ASN1_Class m_class_tag = ASN1_Class::Universal;
166
      secure_vector<uint8_t> m_value;
167
168
      friend class BER_Decoder;
169
170
      void set_tagging(ASN1_Type type_tag, ASN1_Class class_tag);
171
172
1.10k
      uint8_t* mutable_bits(size_t length) {
173
1.10k
         m_value.resize(length);
174
1.10k
         return m_value.data();
175
1.10k
      }
176
};
177
178
/*
179
* ASN.1 Utility Functions
180
*/
181
class DataSource;
182
183
namespace ASN1 {
184
185
std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& val);
186
std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len);
187
std::string to_string(const BER_Object& obj);
188
189
/**
190
* Heuristics tests; is this object possibly BER?
191
* @param src a data source that will be peeked at but not modified
192
*/
193
bool maybe_BER(DataSource& src);
194
195
}  // namespace ASN1
196
197
/**
198
* General BER Decoding Error Exception
199
*/
200
class BOTAN_PUBLIC_API(2, 0) BER_Decoding_Error : public Decoding_Error {
201
   public:
202
      explicit BER_Decoding_Error(std::string_view err);
203
};
204
205
/**
206
* Exception For Incorrect BER Taggings
207
*/
208
class BOTAN_PUBLIC_API(2, 0) BER_Bad_Tag final : public BER_Decoding_Error {
209
   public:
210
      BER_Bad_Tag(std::string_view msg, uint32_t tagging);
211
};
212
213
/**
214
* This class represents ASN.1 object identifiers.
215
*/
216
class BOTAN_PUBLIC_API(2, 0) OID final : public ASN1_Object {
217
   public:
218
      /**
219
      * Create an uninitialised OID object
220
      */
221
0
      explicit OID() = default;
222
223
      /**
224
      * Construct an OID from a string.
225
      * @param str a string in the form "a.b.c" etc., where a,b,c are integers
226
      *
227
      * Note: it is currently required that each integer fit into 32 bits
228
      */
229
      explicit OID(std::string_view str);
230
231
      /**
232
      * Initialize an OID from a sequence of integer values
233
      */
234
      OID(std::initializer_list<uint32_t> init);
235
236
      /**
237
      * Initialize an OID from a vector of integer values
238
      */
239
      explicit OID(std::vector<uint32_t>&& init);
240
241
      /**
242
      * Construct an OID from a string.
243
      * @param str a string in the form "a.b.c" etc., where a,b,c are numbers
244
      *        or any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier")
245
      */
246
      static OID from_string(std::string_view str);
247
248
      /**
249
      * Construct an OID from a name
250
      * @param name any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier")
251
      */
252
      static std::optional<OID> from_name(std::string_view name);
253
254
      /**
255
      * Register a new OID in the internal table
256
      */
257
      static void register_oid(const OID& oid, std::string_view name);
258
259
      void encode_into(DER_Encoder& to) const override;
260
      void decode_from(BER_Decoder& from) override;
261
262
      /**
263
      * Find out whether this OID is empty
264
      * @return true is no OID value is set
265
      */
266
7.89k
      bool empty() const { return m_id.empty(); }
267
268
      /**
269
      * Find out whether this OID has a value
270
      * @return true is this OID has a value
271
      */
272
5.94k
      bool has_value() const { return !empty(); }
273
274
      /**
275
      * Get this OID as a dotted-decimal string
276
      * @return string representing this OID
277
      */
278
      std::string to_string() const;
279
280
      /**
281
      * If there is a known name associated with this OID, return that.
282
      * Otherwise return the result of to_string
283
      */
284
      std::string to_formatted_string() const;
285
286
      /**
287
      * If there is a known name associated with this OID, return that.
288
      * Otherwise return the empty string.
289
      */
290
      std::string human_name_or_empty() const;
291
292
      /**
293
      * Return true if the OID in *this is registered in the internal
294
      * set of constants as a known OID.
295
      */
296
      bool registered_oid() const;
297
298
      /**
299
      * Compare two OIDs.
300
      * @return true if they are equal, false otherwise
301
      */
302
16.4k
      bool operator==(const OID& other) const { return m_id == other.m_id; }
303
304
      /**
305
      * Return a hash code for this OID
306
      *
307
      * This value is only meant as a std::unordered_map hash and
308
      * can change value from release to release.
309
      */
310
      uint64_t hash_code() const;
311
312
      /**
313
      * Check if this OID matches the provided value
314
      */
315
      bool matches(std::initializer_list<uint32_t> other) const;
316
317
      /**
318
      * Get this OID as list (vector) of its components.
319
      * @return vector representing this OID
320
      */
321
      BOTAN_DEPRECATED("Do not access the integer values, use eg to_string")
322
0
      const std::vector<uint32_t>& get_components() const {
323
0
         return m_id;
324
0
      }
325
326
      BOTAN_DEPRECATED("Do not access the integer values, use eg to_string")
327
0
      const std::vector<uint32_t>& get_id() const {
328
0
         return m_id;
329
0
      }
330
331
   private:
332
      std::vector<uint32_t> m_id;
333
};
334
335
BOTAN_PUBLIC_API(3, 0) std::ostream& operator<<(std::ostream& out, const OID& oid);
336
337
/**
338
* Compare two OIDs.
339
* @param a the first OID
340
* @param b the second OID
341
* @return true if a is not equal to b
342
*/
343
0
inline bool operator!=(const OID& a, const OID& b) {
344
0
   return !(a == b);
345
0
}
346
347
/**
348
* Compare two OIDs.
349
* @param a the first OID
350
* @param b the second OID
351
* @return true if a is lexicographically smaller than b
352
*/
353
BOTAN_PUBLIC_API(2, 0) bool operator<(const OID& a, const OID& b);
354
355
/**
356
* ASN.1 string type
357
* This class normalizes all inputs to a UTF-8 std::string
358
*/
359
class BOTAN_PUBLIC_API(2, 0) ASN1_String final : public ASN1_Object {
360
   public:
361
      void encode_into(DER_Encoder& to) const override;
362
      void decode_from(BER_Decoder& from) override;
363
364
0
      ASN1_Type tagging() const { return m_tag; }
365
366
0
      const std::string& value() const { return m_utf8_str; }
367
368
0
      size_t size() const { return value().size(); }
369
370
0
      bool empty() const { return m_utf8_str.empty(); }
371
372
      /**
373
      * Return true iff this is a tag for a known string type we can handle.
374
      */
375
      static bool is_string_type(ASN1_Type tag);
376
377
0
      bool operator==(const ASN1_String& other) const { return value() == other.value(); }
378
379
0
      friend bool operator<(const ASN1_String& a, const ASN1_String& b) { return a.value() < b.value(); }
380
381
      explicit ASN1_String(std::string_view utf8 = "");
382
      ASN1_String(std::string_view utf8, ASN1_Type tag);
383
384
   private:
385
      std::vector<uint8_t> m_data;
386
      std::string m_utf8_str;
387
      ASN1_Type m_tag;
388
};
389
390
/**
391
* Algorithm Identifier
392
*/
393
class BOTAN_PUBLIC_API(2, 0) AlgorithmIdentifier final : public ASN1_Object {
394
   public:
395
      enum Encoding_Option : uint8_t { USE_NULL_PARAM, USE_EMPTY_PARAM }; /* NOLINT(*-use-enum-class) */
396
397
      void encode_into(DER_Encoder& to) const override;
398
      void decode_from(BER_Decoder& from) override;
399
400
      AlgorithmIdentifier() = default;
401
402
      AlgorithmIdentifier(const OID& oid, Encoding_Option enc);
403
      AlgorithmIdentifier(std::string_view oid_name, Encoding_Option enc);
404
405
      AlgorithmIdentifier(const OID& oid, const std::vector<uint8_t>& params);
406
      AlgorithmIdentifier(std::string_view oid_name, const std::vector<uint8_t>& params);
407
408
0
      const OID& oid() const { return m_oid; }
409
410
0
      const std::vector<uint8_t>& parameters() const { return m_parameters; }
411
412
0
      BOTAN_DEPRECATED("Use AlgorithmIdentifier::oid") const OID& get_oid() const { return m_oid; }
413
414
0
      BOTAN_DEPRECATED("Use AlgorithmIdentifier::parameters") const std::vector<uint8_t>& get_parameters() const {
415
0
         return m_parameters;
416
0
      }
417
418
      bool parameters_are_null() const;
419
420
0
      bool parameters_are_empty() const { return m_parameters.empty(); }
421
422
0
      bool parameters_are_null_or_empty() const { return parameters_are_empty() || parameters_are_null(); }
423
424
0
      bool empty() const { return m_oid.empty() && m_parameters.empty(); }
425
426
   private:
427
      OID m_oid;
428
      std::vector<uint8_t> m_parameters;
429
};
430
431
/*
432
* Comparison Operations
433
*/
434
BOTAN_PUBLIC_API(2, 0) bool operator==(const AlgorithmIdentifier& x, const AlgorithmIdentifier& y);
435
BOTAN_PUBLIC_API(2, 0) bool operator!=(const AlgorithmIdentifier& x, const AlgorithmIdentifier& y);
436
437
}  // namespace Botan
438
439
template <>
440
class std::hash<Botan::OID> {
441
   public:
442
32
      size_t operator()(const Botan::OID& oid) const noexcept { return static_cast<size_t>(oid.hash_code()); }
443
};
444
445
/*
446
In 3.11 ASN1_Time was split out to its own header as <chrono> is huge in C++20
447
However we continue to include this header (when not building the library),
448
to avoid breaking applications which would expect it to still be available.
449
450
TODO(Botan4) remove this
451
*/
452
#if defined(BOTAN_AMALGAMATION_H_) || (!defined(BOTAN_IS_BEING_BUILT) && !defined(__clang_analyzer__))
453
   #include <botan/asn1_time.h>
454
#endif
455
456
#endif