Botan 3.5.0
Crypto and TLS for C&
asn1_obj.h
Go to the documentation of this file.
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 <chrono>
13#include <iosfwd>
14#include <optional>
15#include <span>
16#include <string>
17#include <string_view>
18#include <unordered_map>
19#include <vector>
20
21namespace Botan {
22
23class BER_Decoder;
24class DER_Encoder;
25
26/**
27* ASN.1 Class Tags
28*/
29enum class ASN1_Class : uint32_t {
30 Universal = 0b0000'0000,
31 Application = 0b0100'0000,
32 ContextSpecific = 0b1000'0000,
33 Private = 0b1100'0000,
34
35 Constructed = 0b0010'0000,
37
38 NoObject = 0xFF00
39};
40
41/**
42* ASN.1 Type Tags
43*/
44enum class ASN1_Type : uint32_t {
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
71inline bool intersects(ASN1_Class x, ASN1_Class y) {
72 return static_cast<uint32_t>(x) & static_cast<uint32_t>(y);
73}
74
76 return static_cast<ASN1_Type>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
77}
78
80 return static_cast<ASN1_Class>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
81}
82
83inline uint32_t operator|(ASN1_Type x, ASN1_Class y) {
84 return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
85}
86
87inline uint32_t operator|(ASN1_Class x, ASN1_Type y) {
88 return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
89}
90
93
94/**
95* Basic ASN.1 Object Interface
96*/
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 ASN1_Object() = default;
119 ASN1_Object(const ASN1_Object&) = default;
121 virtual ~ASN1_Object() = default;
122};
123
124/**
125* BER Encoded Object
126*/
128 public:
129 BER_Object() : m_type_tag(ASN1_Type::NoObject), m_class_tag(ASN1_Class::Universal) {}
130
131 BER_Object(const BER_Object& other) = default;
132
133 BER_Object& operator=(const BER_Object& other) = default;
134
135 BER_Object(BER_Object&& other) = default;
136
137 BER_Object& operator=(BER_Object&& other) = default;
138
139 bool is_set() const { return m_type_tag != ASN1_Type::NoObject; }
140
141 uint32_t tagging() const { return type_tag() | class_tag(); }
142
143 ASN1_Type type_tag() const { return m_type_tag; }
144
145 ASN1_Class class_tag() const { return m_class_tag; }
146
147 ASN1_Type type() const { return m_type_tag; }
148
149 ASN1_Class get_class() const { return m_class_tag; }
150
151 const uint8_t* bits() const { return m_value.data(); }
152
153 size_t length() const { return m_value.size(); }
154
155 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;
165 ASN1_Class m_class_tag;
167
168 friend class BER_Decoder;
169
170 void set_tagging(ASN1_Type type_tag, ASN1_Class class_tag);
171
172 uint8_t* mutable_bits(size_t length) {
173 m_value.resize(length);
174 return m_value.data();
175 }
176};
177
178/*
179* ASN.1 Utility Functions
180*/
181class DataSource;
182
183namespace ASN1 {
184
185std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& val);
186std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len);
187std::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*/
193bool maybe_BER(DataSource& src);
194
195} // namespace ASN1
196
197/**
198* General BER Decoding Error Exception
199*/
201 public:
202 explicit BER_Decoding_Error(std::string_view);
203};
204
205/**
206* Exception For Incorrect BER Taggings
207*/
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*/
216class BOTAN_PUBLIC_API(2, 0) OID final : public ASN1_Object {
217 public:
218 /**
219 * Create an uninitialied OID object
220 */
221 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 explicit OID(std::initializer_list<uint32_t> init);
235
236 /**
237 * Initialize an OID from a vector of integer values
238 */
239 BOTAN_DEPRECATED("Use another contructor") 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&) const override;
260 void decode_from(BER_Decoder&) override;
261
262 /**
263 * Find out whether this OID is empty
264 * @return true is no OID value is set
265 */
266 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 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 bool operator==(const OID& other) const { return m_id == other.m_id; }
303
304 /**
305 * Get this OID as list (vector) of its components.
306 * @return vector representing this OID
307 */
308 BOTAN_DEPRECATED("Do not access the integer values, use eg to_string")
309 const std::vector<uint32_t>& get_components() const {
310 return m_id;
311 }
312
313 BOTAN_DEPRECATED("Do not access the integer values, use eg to_string")
314 const std::vector<uint32_t>& get_id() const {
315 return m_id;
316 }
317
318 private:
319 std::vector<uint32_t> m_id;
320};
321
322inline std::ostream& operator<<(std::ostream& out, const OID& oid) {
323 out << oid.to_string();
324 return out;
325}
326
327/**
328* Compare two OIDs.
329* @param a the first OID
330* @param b the second OID
331* @return true if a is not equal to b
332*/
333inline bool operator!=(const OID& a, const OID& b) {
334 return !(a == b);
335}
336
337/**
338* Compare two OIDs.
339* @param a the first OID
340* @param b the second OID
341* @return true if a is lexicographically smaller than b
342*/
343BOTAN_PUBLIC_API(2, 0) bool operator<(const OID& a, const OID& b);
344
345/**
346* Time (GeneralizedTime/UniversalTime)
347*/
349 public:
350 /// DER encode a ASN1_Time
351 void encode_into(DER_Encoder&) const override;
352
353 // Decode a BER encoded ASN1_Time
354 void decode_from(BER_Decoder&) override;
355
356 /// Return an internal string representation of the time
357 std::string to_string() const;
358
359 /// Returns a human friendly string replesentation of no particular formatting
360 std::string readable_string() const;
361
362 /// Return if the time has been set somehow
363 bool time_is_set() const;
364
365 /// Compare this time against another
366 int32_t cmp(const ASN1_Time& other) const;
367
368 /// Create an invalid ASN1_Time
369 ASN1_Time() = default;
370
371 /// Create a ASN1_Time from a time point
372 explicit ASN1_Time(const std::chrono::system_clock::time_point& time);
373
374 /// Create an ASN1_Time from string
375 ASN1_Time(std::string_view t_spec);
376
377 /// Create an ASN1_Time from string and a specified tagging (Utc or Generalized)
378 ASN1_Time(std::string_view t_spec, ASN1_Type tag);
379
380 /// Returns a STL timepoint object
381 std::chrono::system_clock::time_point to_std_timepoint() const;
382
383 /// Return time since epoch
384 uint64_t time_since_epoch() const;
385
386 private:
387 void set_to(std::string_view t_spec, ASN1_Type type);
388 bool passes_sanity_check() const;
389
390 uint32_t m_year = 0;
391 uint32_t m_month = 0;
392 uint32_t m_day = 0;
393 uint32_t m_hour = 0;
394 uint32_t m_minute = 0;
395 uint32_t m_second = 0;
397};
398
399/*
400* Comparison Operations
401*/
402BOTAN_PUBLIC_API(2, 0) bool operator==(const ASN1_Time&, const ASN1_Time&);
403BOTAN_PUBLIC_API(2, 0) bool operator!=(const ASN1_Time&, const ASN1_Time&);
404BOTAN_PUBLIC_API(2, 0) bool operator<=(const ASN1_Time&, const ASN1_Time&);
405BOTAN_PUBLIC_API(2, 0) bool operator>=(const ASN1_Time&, const ASN1_Time&);
406BOTAN_PUBLIC_API(2, 0) bool operator<(const ASN1_Time&, const ASN1_Time&);
407BOTAN_PUBLIC_API(2, 0) bool operator>(const ASN1_Time&, const ASN1_Time&);
408
410
411/**
412* ASN.1 string type
413* This class normalizes all inputs to a UTF-8 std::string
414*/
416 public:
417 void encode_into(DER_Encoder&) const override;
418 void decode_from(BER_Decoder&) override;
419
420 ASN1_Type tagging() const { return m_tag; }
421
422 const std::string& value() const { return m_utf8_str; }
423
424 size_t size() const { return value().size(); }
425
426 bool empty() const { return m_utf8_str.empty(); }
427
428 /**
429 * Return true iff this is a tag for a known string type we can handle.
430 */
431 static bool is_string_type(ASN1_Type tag);
432
433 bool operator==(const ASN1_String& other) const { return value() == other.value(); }
434
435 friend bool operator<(const ASN1_String& a, const ASN1_String& b) { return a.value() < b.value(); }
436
437 explicit ASN1_String(std::string_view utf8 = "");
438 ASN1_String(std::string_view utf8, ASN1_Type tag);
439
440 private:
441 std::vector<uint8_t> m_data;
442 std::string m_utf8_str;
443 ASN1_Type m_tag;
444};
445
446/**
447* Algorithm Identifier
448*/
450 public:
451 enum Encoding_Option { USE_NULL_PARAM, USE_EMPTY_PARAM };
452
453 void encode_into(DER_Encoder&) const override;
454 void decode_from(BER_Decoder&) override;
455
457
458 AlgorithmIdentifier(const OID& oid, Encoding_Option enc);
459 AlgorithmIdentifier(std::string_view oid_name, Encoding_Option enc);
460
461 AlgorithmIdentifier(const OID& oid, const std::vector<uint8_t>& params);
462 AlgorithmIdentifier(std::string_view oid_name, const std::vector<uint8_t>& params);
463
464 const OID& oid() const { return m_oid; }
465
466 const std::vector<uint8_t>& parameters() const { return m_parameters; }
467
468 BOTAN_DEPRECATED("Use AlgorithmIdentifier::oid") const OID& get_oid() const { return m_oid; }
469
470 BOTAN_DEPRECATED("Use AlgorithmIdentifier::parameters") const std::vector<uint8_t>& get_parameters() const {
471 return m_parameters;
472 }
473
474 bool parameters_are_null() const;
475
476 bool parameters_are_empty() const { return m_parameters.empty(); }
477
478 bool parameters_are_null_or_empty() const { return parameters_are_empty() || parameters_are_null(); }
479
480 bool empty() const { return m_oid.empty() && m_parameters.empty(); }
481
482 private:
483 OID m_oid;
484 std::vector<uint8_t> m_parameters;
485};
486
487/*
488* Comparison Operations
489*/
490BOTAN_PUBLIC_API(2, 0) bool operator==(const AlgorithmIdentifier&, const AlgorithmIdentifier&);
491BOTAN_PUBLIC_API(2, 0) bool operator!=(const AlgorithmIdentifier&, const AlgorithmIdentifier&);
492
493} // namespace Botan
494
495#endif
ASN1_Object & operator=(const ASN1_Object &)=default
ASN1_Object(const ASN1_Object &)=default
virtual ~ASN1_Object()=default
virtual void decode_from(BER_Decoder &from)=0
ASN1_Object()=default
virtual void encode_into(DER_Encoder &to) const =0
const std::string & value() const
Definition asn1_obj.h:422
bool empty() const
Definition asn1_obj.h:426
size_t size() const
Definition asn1_obj.h:424
bool operator==(const ASN1_String &other) const
Definition asn1_obj.h:433
friend bool operator<(const ASN1_String &a, const ASN1_String &b)
Definition asn1_obj.h:435
ASN1_Type tagging() const
Definition asn1_obj.h:420
ASN1_Time()=default
Create an invalid ASN1_Time.
bool parameters_are_empty() const
Definition asn1_obj.h:476
bool parameters_are_null_or_empty() const
Definition asn1_obj.h:478
const std::vector< uint8_t > & parameters() const
Definition asn1_obj.h:466
const OID & oid() const
Definition asn1_obj.h:464
size_t length() const
Definition asn1_obj.h:153
BER_Object(BER_Object &&other)=default
const uint8_t * bits() const
Definition asn1_obj.h:151
BER_Object & operator=(const BER_Object &other)=default
ASN1_Type type_tag() const
Definition asn1_obj.h:143
uint32_t tagging() const
Definition asn1_obj.h:141
BER_Object(const BER_Object &other)=default
bool is_set() const
Definition asn1_obj.h:139
std::span< const uint8_t > data() const
Definition asn1_obj.h:155
BER_Object & operator=(BER_Object &&other)=default
ASN1_Type type() const
Definition asn1_obj.h:147
ASN1_Class get_class() const
Definition asn1_obj.h:149
ASN1_Class class_tag() const
Definition asn1_obj.h:145
bool operator==(const OID &other) const
Definition asn1_obj.h:302
OID()=default
bool has_value() const
Definition asn1_obj.h:272
bool empty() const
Definition asn1_obj.h:266
std::string to_string() const
Definition asn1_oid.cpp:125
int(* init)(CTX *)
std::string name
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition compiler.h:31
#define BOTAN_UNSTABLE_API
Definition compiler.h:44
#define BOTAN_DEPRECATED(msg)
Definition compiler.h:125
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:172
bool maybe_BER(DataSource &source)
Definition asn1_obj.cpp:192
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:185
ASN1_Type operator|(ASN1_Type x, ASN1_Type y)
Definition asn1_obj.h:75
std::string asn1_tag_to_string(ASN1_Type type)
Definition asn1_obj.cpp:93
ASN1_Class
Definition asn1_obj.h:29
ASN1_Type
Definition asn1_obj.h:44
std::ostream & operator<<(std::ostream &out, const OID &oid)
Definition asn1_obj.h:322
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition alg_id.cpp:69
std::string asn1_class_to_string(ASN1_Class type)
Definition asn1_obj.cpp:74
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
bool intersects(ASN1_Class x, ASN1_Class y)
Definition asn1_obj.h:71
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition exceptn.cpp:13