Botan 3.0.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/secmem.h>
11#include <botan/exceptn.h>
12#include <string_view>
13#include <vector>
14#include <string>
15#include <chrono>
16#include <unordered_map>
17#include <optional>
18#include <iosfwd>
19
20namespace Botan {
21
22class BER_Decoder;
23class DER_Encoder;
24
25/**
26* ASN.1 Class Tags
27*/
28enum class ASN1_Class : uint32_t {
29 Universal = 0b0000'0000,
30 Application = 0b0100'0000,
31 ContextSpecific = 0b1000'0000,
32 Private = 0b1100'0000,
33
34 Constructed = 0b0010'0000,
36
37 NoObject = 0xFF00
38};
39
40/**
41* ASN.1 Type Tags
42*/
43enum class ASN1_Type : uint32_t {
44 Eoc = 0x00,
45 Boolean = 0x01,
46 Integer = 0x02,
47 BitString = 0x03,
48 OctetString = 0x04,
49 Null = 0x05,
50 ObjectId = 0x06,
51 Enumerated = 0x0A,
52 Sequence = 0x10,
53 Set = 0x11,
54
55 Utf8String = 0x0C,
56 NumericString = 0x12,
57 PrintableString = 0x13,
58 TeletexString = 0x14,
59 Ia5String = 0x16,
60 VisibleString = 0x1A,
61 UniversalString = 0x1C,
62 BmpString = 0x1E,
63
64 UtcTime = 0x17,
65 GeneralizedTime = 0x18,
66
67 NoObject = 0xFF00,
68};
69
71 {
72 return static_cast<uint32_t>(x) & static_cast<uint32_t>(y);
73 }
74
76 {
77 return static_cast<ASN1_Type>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
78 }
79
81 {
82 return static_cast<ASN1_Class>(static_cast<uint32_t>(x) | static_cast<uint32_t>(y));
83 }
84
85inline uint32_t operator|(ASN1_Type x, ASN1_Class y)
86 {
87 return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
88 }
89
90inline uint32_t operator|(ASN1_Class x, ASN1_Type y)
91 {
92 return static_cast<uint32_t>(x) | static_cast<uint32_t>(y);
93 }
94
97
98/**
99* Basic ASN.1 Object Interface
100*/
102 {
103 public:
104 /**
105 * Encode whatever this object is into to
106 * @param to the DER_Encoder that will be written to
107 */
108 virtual void encode_into(DER_Encoder& to) const = 0;
109
110 /**
111 * Decode whatever this object is from from
112 * @param from the BER_Decoder that will be read from
113 */
114 virtual void decode_from(BER_Decoder& from) = 0;
115
116 /**
117 * Return the encoding of this object. This is a convenience
118 * method when just one object needs to be serialized. Use
119 * DER_Encoder for complicated encodings.
120 */
121 std::vector<uint8_t> BER_encode() const;
122
123 ASN1_Object() = default;
124 ASN1_Object(const ASN1_Object&) = default;
125 ASN1_Object & operator=(const ASN1_Object&) = default;
126 virtual ~ASN1_Object() = default;
127 };
128
129/**
130* BER Encoded Object
131*/
133 {
134 public:
135 BER_Object() : m_type_tag(ASN1_Type::NoObject), m_class_tag(ASN1_Class::Universal) {}
136
137 BER_Object(const BER_Object& other) = default;
138
139 BER_Object& operator=(const BER_Object& other) = default;
140
141 BER_Object(BER_Object&& other) = default;
142
143 BER_Object& operator=(BER_Object&& other) = default;
144
145 bool is_set() const { return m_type_tag != ASN1_Type::NoObject; }
146
147 uint32_t tagging() const { return type_tag() | class_tag(); }
148
149 ASN1_Type type_tag() const { return m_type_tag; }
150 ASN1_Class class_tag() const { return m_class_tag; }
151
152 ASN1_Type type() const { return m_type_tag; }
153 ASN1_Class get_class() const { return m_class_tag; }
154
155 const uint8_t* bits() const { return m_value.data(); }
156
157 size_t length() const { return m_value.size(); }
158
159 void assert_is_a(ASN1_Type type_tag, ASN1_Class class_tag,
160 std::string_view descr = "object") const;
161
162 bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const;
163
164 bool is_a(int type_tag, ASN1_Class class_tag) const;
165
166 private:
167 ASN1_Type m_type_tag;
168 ASN1_Class m_class_tag;
170
171 friend class BER_Decoder;
172
173 void set_tagging(ASN1_Type type_tag, ASN1_Class class_tag);
174
175 uint8_t* mutable_bits(size_t length)
176 {
177 m_value.resize(length);
178 return m_value.data();
179 }
180 };
181
182/*
183* ASN.1 Utility Functions
184*/
185class DataSource;
186
187namespace ASN1 {
188
189std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& val);
190std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len);
191std::string to_string(const BER_Object& obj);
192
193/**
194* Heuristics tests; is this object possibly BER?
195* @param src a data source that will be peeked at but not modified
196*/
197bool maybe_BER(DataSource& src);
198
199}
200
201/**
202* General BER Decoding Error Exception
203*/
205 {
206 public:
207 explicit BER_Decoding_Error(std::string_view);
208 };
209
210/**
211* Exception For Incorrect BER Taggings
212*/
214 {
215 public:
216 BER_Bad_Tag(std::string_view msg, uint32_t tagging);
217 };
218
219/**
220* This class represents ASN.1 object identifiers.
221*/
223 {
224 public:
225
226 /**
227 * Create an uninitialied OID object
228 */
229 explicit OID() {}
230
231 /**
232 * Construct an OID from a string.
233 * @param str a string in the form "a.b.c" etc., where a,b,c are numbers
234 */
235 explicit OID(std::string_view str);
236
237 /**
238 * Initialize an OID from a sequence of integer values
239 */
240 explicit OID(std::initializer_list<uint32_t> init) : m_id(init)
241 {
242 BOTAN_ARG_CHECK(m_id.size() > 2 && m_id[0] <= 2 && (m_id[0] != 2 || m_id[1] <= 39),
243 "Invalid OID");
244 }
245
246 /**
247 * Initialize an OID from a vector of integer values
248 */
249 explicit OID(std::vector<uint32_t>&& init) : m_id(init)
250 {
251 BOTAN_ARG_CHECK(m_id.size() > 2 && m_id[0] <= 2 && (m_id[0] != 2 || m_id[1] <= 39),
252 "Invalid OID");
253 }
254
255 /**
256 * Construct an OID from a string.
257 * @param str a string in the form "a.b.c" etc., where a,b,c are numbers
258 * or any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier")
259 */
260 static OID from_string(std::string_view str);
261
262 /**
263 * Construct an OID from a name
264 * @param name any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier")
265 */
266 static std::optional<OID> from_name(std::string_view name);
267
268 /**
269 * Register a new OID in the internal table
270 */
271 static void register_oid(const OID& oid, std::string_view name);
272
273 void encode_into(DER_Encoder&) const override;
274 void decode_from(BER_Decoder&) override;
275
276 /**
277 * Find out whether this OID is empty
278 * @return true is no OID value is set
279 */
280 bool empty() const { return m_id.empty(); }
281
282 /**
283 * Find out whether this OID has a value
284 * @return true is this OID has a value
285 */
286 bool has_value() const { return (m_id.empty() == false); }
287
288 /**
289 * Get this OID as list (vector) of its components.
290 * @return vector representing this OID
291 */
292 const std::vector<uint32_t>& get_components() const { return m_id; }
293
294 const std::vector<uint32_t>& get_id() const { return get_components(); }
295
296 /**
297 * Get this OID as a dotted-decimal string
298 * @return string representing this OID
299 */
300 std::string to_string() const;
301
302 /**
303 * If there is a known name associated with this OID, return that.
304 * Otherwise return the result of to_string
305 */
306 std::string to_formatted_string() const;
307
308 /**
309 * If there is a known name associated with this OID, return that.
310 * Otherwise return the empty string.
311 */
312 std::string human_name_or_empty() const;
313
314 /**
315 * Return true if the OID in *this is registered in the internal
316 * set of constants as a known OID.
317 */
318 bool registered_oid() const;
319
320 /**
321 * Compare two OIDs.
322 * @return true if they are equal, false otherwise
323 */
324 bool operator==(const OID& other) const
325 {
326 return m_id == other.m_id;
327 }
328
329 private:
330 std::unordered_map<std::string, std::string> load_oid2str_map();
331 std::unordered_map<std::string, OID> load_str2oid_map();
332
333 std::vector<uint32_t> m_id;
334 };
335
336std::ostream& operator<<(std::ostream& out, const OID& oid);
337
338/**
339* Compare two OIDs.
340* @param a the first OID
341* @param b the second OID
342* @return true if a is not equal to b
343*/
344inline bool operator!=(const OID& a, const OID& b)
345 {
346 return !(a == b);
347 }
348
349/**
350* Compare two OIDs.
351* @param a the first OID
352* @param b the second OID
353* @return true if a is lexicographically smaller than b
354*/
355bool BOTAN_PUBLIC_API(2,0) operator<(const OID& a, const OID& b);
356
357/**
358* Time (GeneralizedTime/UniversalTime)
359*/
361 {
362 public:
363 /// DER encode a ASN1_Time
364 void encode_into(DER_Encoder&) const override;
365
366 // Decode a BER encoded ASN1_Time
367 void decode_from(BER_Decoder&) override;
368
369 /// Return an internal string representation of the time
370 std::string to_string() const;
371
372 /// Returns a human friendly string replesentation of no particular formatting
373 std::string readable_string() const;
374
375 /// Return if the time has been set somehow
376 bool time_is_set() const;
377
378 /// Compare this time against another
379 int32_t cmp(const ASN1_Time& other) const;
380
381 /// Create an invalid ASN1_Time
382 ASN1_Time() = default;
383
384 /// Create a ASN1_Time from a time point
385 explicit ASN1_Time(const std::chrono::system_clock::time_point& time);
386
387 /// Create an ASN1_Time from string
388 ASN1_Time(std::string_view t_spec);
389
390 /// Create an ASN1_Time from string and a specified tagging (Utc or Generalized)
391 ASN1_Time(std::string_view t_spec, ASN1_Type tag);
392
393 /// Returns a STL timepoint object
394 std::chrono::system_clock::time_point to_std_timepoint() const;
395
396 /// Return time since epoch
397 uint64_t time_since_epoch() const;
398
399 private:
400 void set_to(std::string_view t_spec, ASN1_Type type);
401 bool passes_sanity_check() const;
402
403 uint32_t m_year = 0;
404 uint32_t m_month = 0;
405 uint32_t m_day = 0;
406 uint32_t m_hour = 0;
407 uint32_t m_minute = 0;
408 uint32_t m_second = 0;
410 };
411
412/*
413* Comparison Operations
414*/
415bool BOTAN_PUBLIC_API(2,0) operator==(const ASN1_Time&, const ASN1_Time&);
416bool BOTAN_PUBLIC_API(2,0) operator!=(const ASN1_Time&, const ASN1_Time&);
417bool BOTAN_PUBLIC_API(2,0) operator<=(const ASN1_Time&, const ASN1_Time&);
418bool BOTAN_PUBLIC_API(2,0) operator>=(const ASN1_Time&, const ASN1_Time&);
419bool BOTAN_PUBLIC_API(2,0) operator<(const ASN1_Time&, const ASN1_Time&);
420bool BOTAN_PUBLIC_API(2,0) operator>(const ASN1_Time&, const ASN1_Time&);
421
423
424/**
425* ASN.1 string type
426* This class normalizes all inputs to a UTF-8 std::string
427*/
429 {
430 public:
431 void encode_into(DER_Encoder&) const override;
432 void decode_from(BER_Decoder&) override;
433
434 ASN1_Type tagging() const { return m_tag; }
435
436 const std::string& value() const { return m_utf8_str; }
437
438 size_t size() const { return value().size(); }
439
440 bool empty() const { return m_utf8_str.empty(); }
441
442 /**
443 * Return true iff this is a tag for a known string type we can handle.
444 */
445 static bool is_string_type(ASN1_Type tag);
446
447 bool operator==(const ASN1_String& other) const
448 { return value() == other.value(); }
449
450 explicit ASN1_String(std::string_view utf8 = "");
451 ASN1_String(std::string_view utf8, ASN1_Type tag);
452 private:
453 std::vector<uint8_t> m_data;
454 std::string m_utf8_str;
455 ASN1_Type m_tag;
456 };
457
458/**
459* Algorithm Identifier
460*/
462 {
463 public:
464 enum Encoding_Option { USE_NULL_PARAM, USE_EMPTY_PARAM };
465
466 void encode_into(DER_Encoder&) const override;
467 void decode_from(BER_Decoder&) override;
468
470
471 AlgorithmIdentifier(const OID& oid, Encoding_Option enc);
472 AlgorithmIdentifier(std::string_view oid_name, Encoding_Option enc);
473
474 AlgorithmIdentifier(const OID& oid, const std::vector<uint8_t>& params);
475 AlgorithmIdentifier(std::string_view oid_name, const std::vector<uint8_t>& params);
476
477 const OID& oid() const { return m_oid; }
478 const std::vector<uint8_t>& parameters() const { return m_parameters; }
479
480 BOTAN_DEPRECATED("Use AlgorithmIdentifier::oid")
481 const OID& get_oid() const { return m_oid; }
482
483 BOTAN_DEPRECATED("Use AlgorithmIdentifier::parameters")
484 const std::vector<uint8_t>& get_parameters() const { return m_parameters; }
485
486 bool parameters_are_null() const;
487 bool parameters_are_empty() const { return m_parameters.empty(); }
488
490 {
491 return parameters_are_empty() || parameters_are_null();
492 }
493
494 bool empty() const
495 {
496 return m_oid.empty() && m_parameters.empty();
497 }
498
499 private:
500 OID m_oid;
501 std::vector<uint8_t> m_parameters;
502 };
503
504/*
505* Comparison Operations
506*/
507bool BOTAN_PUBLIC_API(2,0) operator==(const AlgorithmIdentifier&,
508 const AlgorithmIdentifier&);
509bool BOTAN_PUBLIC_API(2,0) operator!=(const AlgorithmIdentifier&,
510 const AlgorithmIdentifier&);
511
512}
513
514#endif
static SIMD_4x64 y
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:36
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:436
bool empty() const
Definition: asn1_obj.h:440
size_t size() const
Definition: asn1_obj.h:438
bool operator==(const ASN1_String &other) const
Definition: asn1_obj.h:447
ASN1_Type tagging() const
Definition: asn1_obj.h:434
ASN1_Time()=default
Create an invalid ASN1_Time.
bool parameters_are_empty() const
Definition: asn1_obj.h:487
bool parameters_are_null_or_empty() const
Definition: asn1_obj.h:489
const std::vector< uint8_t > & parameters() const
Definition: asn1_obj.h:478
const OID & oid() const
Definition: asn1_obj.h:477
size_t length() const
Definition: asn1_obj.h:157
BER_Object(BER_Object &&other)=default
const uint8_t * bits() const
Definition: asn1_obj.h:155
BER_Object & operator=(const BER_Object &other)=default
ASN1_Type type_tag() const
Definition: asn1_obj.h:149
uint32_t tagging() const
Definition: asn1_obj.h:147
BER_Object(const BER_Object &other)=default
bool is_set() const
Definition: asn1_obj.h:145
BER_Object & operator=(BER_Object &&other)=default
ASN1_Type type() const
Definition: asn1_obj.h:152
ASN1_Class get_class() const
Definition: asn1_obj.h:153
ASN1_Class class_tag() const
Definition: asn1_obj.h:150
const std::vector< uint32_t > & get_id() const
Definition: asn1_obj.h:294
const std::vector< uint32_t > & get_components() const
Definition: asn1_obj.h:292
OID(std::initializer_list< uint32_t > init)
Definition: asn1_obj.h:240
bool operator==(const OID &other) const
Definition: asn1_obj.h:324
OID(std::vector< uint32_t > &&init)
Definition: asn1_obj.h:249
bool has_value() const
Definition: asn1_obj.h:286
bool empty() const
Definition: asn1_obj.h:280
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
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:192
bool maybe_BER(DataSource &source)
Definition: asn1_obj.cpp:219
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
Definition: alg_id.cpp:12
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:109
ASN1_Class
Definition: asn1_obj.h:28
ASN1_Type
Definition: asn1_obj.h:43
std::ostream & operator<<(std::ostream &out, const OID &oid)
Definition: asn1_oid.cpp:150
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition: alg_id.cpp:81
std::string asn1_class_to_string(ASN1_Class type)
Definition: asn1_obj.cpp:88
bool intersects(ASN1_Class x, ASN1_Class y)
Definition: asn1_obj.h:70
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition: exceptn.cpp:12
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64
Definition: bigint.h:1092