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