/src/botan/build/include/botan/asn1_obj.h
Line | Count | Source (jump to first uncovered line) |
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 <vector> |
13 | | #include <string> |
14 | | #include <chrono> |
15 | | |
16 | | namespace Botan { |
17 | | |
18 | | class BER_Decoder; |
19 | | class DER_Encoder; |
20 | | |
21 | | /** |
22 | | * ASN.1 Type and Class Tags |
23 | | * This will become an enum class in a future major release |
24 | | */ |
25 | | enum ASN1_Tag : uint32_t { |
26 | | UNIVERSAL = 0x00, |
27 | | APPLICATION = 0x40, |
28 | | CONTEXT_SPECIFIC = 0x80, |
29 | | |
30 | | CONSTRUCTED = 0x20, |
31 | | |
32 | | PRIVATE = CONSTRUCTED | CONTEXT_SPECIFIC, |
33 | | |
34 | | EOC = 0x00, |
35 | | BOOLEAN = 0x01, |
36 | | INTEGER = 0x02, |
37 | | BIT_STRING = 0x03, |
38 | | OCTET_STRING = 0x04, |
39 | | NULL_TAG = 0x05, |
40 | | OBJECT_ID = 0x06, |
41 | | ENUMERATED = 0x0A, |
42 | | SEQUENCE = 0x10, |
43 | | SET = 0x11, |
44 | | |
45 | | UTF8_STRING = 0x0C, |
46 | | NUMERIC_STRING = 0x12, |
47 | | PRINTABLE_STRING = 0x13, |
48 | | T61_STRING = 0x14, |
49 | | IA5_STRING = 0x16, |
50 | | VISIBLE_STRING = 0x1A, |
51 | | UNIVERSAL_STRING = 0x1C, |
52 | | BMP_STRING = 0x1E, |
53 | | |
54 | | UTC_TIME = 0x17, |
55 | | GENERALIZED_TIME = 0x18, |
56 | | UTC_OR_GENERALIZED_TIME = 0x19, |
57 | | |
58 | | NO_OBJECT = 0xFF00, |
59 | | DIRECTORY_STRING = 0xFF01 |
60 | | }; |
61 | | |
62 | | std::string BOTAN_UNSTABLE_API asn1_tag_to_string(ASN1_Tag type); |
63 | | std::string BOTAN_UNSTABLE_API asn1_class_to_string(ASN1_Tag type); |
64 | | |
65 | | /** |
66 | | * Basic ASN.1 Object Interface |
67 | | */ |
68 | | class BOTAN_PUBLIC_API(2,0) ASN1_Object |
69 | | { |
70 | | public: |
71 | | /** |
72 | | * Encode whatever this object is into to |
73 | | * @param to the DER_Encoder that will be written to |
74 | | */ |
75 | | virtual void encode_into(DER_Encoder& to) const = 0; |
76 | | |
77 | | /** |
78 | | * Decode whatever this object is from from |
79 | | * @param from the BER_Decoder that will be read from |
80 | | */ |
81 | | virtual void decode_from(BER_Decoder& from) = 0; |
82 | | |
83 | | /** |
84 | | * Return the encoding of this object. This is a convenience |
85 | | * method when just one object needs to be serialized. Use |
86 | | * DER_Encoder for complicated encodings. |
87 | | */ |
88 | | std::vector<uint8_t> BER_encode() const; |
89 | | |
90 | 1.28M | ASN1_Object() = default; |
91 | 1.55M | ASN1_Object(const ASN1_Object&) = default; |
92 | 5.84k | ASN1_Object & operator=(const ASN1_Object&) = default; |
93 | 2.83M | virtual ~ASN1_Object() = default; |
94 | | }; |
95 | | |
96 | | /** |
97 | | * BER Encoded Object |
98 | | */ |
99 | | class BOTAN_PUBLIC_API(2,0) BER_Object final |
100 | | { |
101 | | public: |
102 | 2.27M | BER_Object() : m_type_tag(NO_OBJECT), m_class_tag(UNIVERSAL) {} |
103 | | |
104 | | BER_Object(const BER_Object& other) = default; |
105 | | |
106 | 7.02k | BER_Object& operator=(const BER_Object& other) = default; |
107 | | |
108 | 611k | BER_Object(BER_Object&& other) = default; |
109 | | |
110 | 332k | BER_Object& operator=(BER_Object&& other) = default; |
111 | | |
112 | 3.41M | bool is_set() const { return m_type_tag != NO_OBJECT; } |
113 | | |
114 | 1.64M | ASN1_Tag tagging() const { return ASN1_Tag(type() | get_class()); } |
115 | | |
116 | 0 | ASN1_Tag type_tag() const { return m_type_tag; } |
117 | 0 | ASN1_Tag class_tag() const { return m_class_tag; } |
118 | | |
119 | 2.01M | ASN1_Tag type() const { return m_type_tag; } |
120 | 1.71M | ASN1_Tag get_class() const { return m_class_tag; } |
121 | | |
122 | 16.3M | const uint8_t* bits() const { return m_value.data(); } |
123 | | |
124 | 34.4M | size_t length() const { return m_value.size(); } |
125 | | |
126 | | void assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag, |
127 | | const std::string& descr = "object") const; |
128 | | |
129 | | bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const; |
130 | | |
131 | | bool is_a(int type_tag, ASN1_Tag class_tag) const; |
132 | | |
133 | | private: |
134 | | ASN1_Tag m_type_tag, m_class_tag; |
135 | | secure_vector<uint8_t> m_value; |
136 | | |
137 | | friend class BER_Decoder; |
138 | | |
139 | | void set_tagging(ASN1_Tag type_tag, ASN1_Tag class_tag); |
140 | | |
141 | | uint8_t* mutable_bits(size_t length) |
142 | 1.39M | { |
143 | 1.39M | m_value.resize(length); |
144 | 1.39M | return m_value.data(); |
145 | 1.39M | } |
146 | | }; |
147 | | |
148 | | /* |
149 | | * ASN.1 Utility Functions |
150 | | */ |
151 | | class DataSource; |
152 | | |
153 | | namespace ASN1 { |
154 | | |
155 | | std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& val); |
156 | | std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len); |
157 | | std::string to_string(const BER_Object& obj); |
158 | | |
159 | | /** |
160 | | * Heuristics tests; is this object possibly BER? |
161 | | * @param src a data source that will be peeked at but not modified |
162 | | */ |
163 | | bool maybe_BER(DataSource& src); |
164 | | |
165 | | } |
166 | | |
167 | | /** |
168 | | * General BER Decoding Error Exception |
169 | | */ |
170 | | class BOTAN_PUBLIC_API(2,0) BER_Decoding_Error : public Decoding_Error |
171 | | { |
172 | | public: |
173 | | explicit BER_Decoding_Error(const std::string&); |
174 | | }; |
175 | | |
176 | | /** |
177 | | * Exception For Incorrect BER Taggings |
178 | | */ |
179 | | class BOTAN_PUBLIC_API(2,0) BER_Bad_Tag final : public BER_Decoding_Error |
180 | | { |
181 | | public: |
182 | | BER_Bad_Tag(const std::string& msg, ASN1_Tag tag); |
183 | | BER_Bad_Tag(const std::string& msg, ASN1_Tag tag1, ASN1_Tag tag2); |
184 | | }; |
185 | | |
186 | | /** |
187 | | * This class represents ASN.1 object identifiers. |
188 | | */ |
189 | | class BOTAN_PUBLIC_API(2,0) OID final : public ASN1_Object |
190 | | { |
191 | | public: |
192 | | |
193 | | /** |
194 | | * Create an uninitialied OID object |
195 | | */ |
196 | 264k | explicit OID() {} |
197 | | |
198 | | /** |
199 | | * Construct an OID from a string. |
200 | | * @param str a string in the form "a.b.c" etc., where a,b,c are numbers |
201 | | */ |
202 | | explicit OID(const std::string& str); |
203 | | |
204 | | /** |
205 | | * Initialize an OID from a sequence of integer values |
206 | | */ |
207 | 24.9k | explicit OID(std::initializer_list<uint32_t> init) : m_id(init) {} |
208 | | |
209 | | /** |
210 | | * Initialize an OID from a vector of integer values |
211 | | */ |
212 | 0 | explicit OID(std::vector<uint32_t>&& init) : m_id(init) {} |
213 | | |
214 | | /** |
215 | | * Construct an OID from a string. |
216 | | * @param str a string in the form "a.b.c" etc., where a,b,c are numbers |
217 | | * or any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier") |
218 | | */ |
219 | | static OID from_string(const std::string& str); |
220 | | |
221 | | void encode_into(class DER_Encoder&) const override; |
222 | | void decode_from(class BER_Decoder&) override; |
223 | | |
224 | | /** |
225 | | * Find out whether this OID is empty |
226 | | * @return true is no OID value is set |
227 | | */ |
228 | 21.8k | bool empty() const { return m_id.empty(); } |
229 | | |
230 | | /** |
231 | | * Find out whether this OID has a value |
232 | | * @return true is this OID has a value |
233 | | */ |
234 | 38.0k | bool has_value() const { return (m_id.empty() == false); } |
235 | | |
236 | | /** |
237 | | * Get this OID as list (vector) of its components. |
238 | | * @return vector representing this OID |
239 | | */ |
240 | 1.39M | const std::vector<uint32_t>& get_components() const { return m_id; } |
241 | | |
242 | 0 | const std::vector<uint32_t>& get_id() const { return get_components(); } |
243 | | |
244 | | /** |
245 | | * Get this OID as a dotted-decimal string |
246 | | * @return string representing this OID |
247 | | */ |
248 | | std::string to_string() const; |
249 | | |
250 | | /** |
251 | | * If there is a known name associated with this OID, return that. |
252 | | * Otherwise return the result of to_string |
253 | | */ |
254 | | std::string to_formatted_string() const; |
255 | | |
256 | | /** |
257 | | * Compare two OIDs. |
258 | | * @return true if they are equal, false otherwise |
259 | | */ |
260 | | bool operator==(const OID& other) const |
261 | 631k | { |
262 | 631k | return m_id == other.m_id; |
263 | 631k | } |
264 | | |
265 | | private: |
266 | | std::vector<uint32_t> m_id; |
267 | | }; |
268 | | |
269 | | /** |
270 | | * Append another component onto the OID. |
271 | | * @param oid the OID to add the new component to |
272 | | * @param new_comp the new component to add |
273 | | */ |
274 | | OID BOTAN_PUBLIC_API(2,0) operator+(const OID& oid, uint32_t new_comp); |
275 | | |
276 | | /** |
277 | | * Compare two OIDs. |
278 | | * @param a the first OID |
279 | | * @param b the second OID |
280 | | * @return true if a is not equal to b |
281 | | */ |
282 | | inline bool operator!=(const OID& a, const OID& b) |
283 | 87.5k | { |
284 | 87.5k | return !(a == b); |
285 | 87.5k | } |
286 | | |
287 | | /** |
288 | | * Compare two OIDs. |
289 | | * @param a the first OID |
290 | | * @param b the second OID |
291 | | * @return true if a is lexicographically smaller than b |
292 | | */ |
293 | | bool BOTAN_PUBLIC_API(2,0) operator<(const OID& a, const OID& b); |
294 | | |
295 | | /** |
296 | | * Time (GeneralizedTime/UniversalTime) |
297 | | */ |
298 | | class BOTAN_PUBLIC_API(2,0) ASN1_Time final : public ASN1_Object |
299 | | { |
300 | | public: |
301 | | /// DER encode a ASN1_Time |
302 | | void encode_into(DER_Encoder&) const override; |
303 | | |
304 | | // Decode a BER encoded ASN1_Time |
305 | | void decode_from(BER_Decoder&) override; |
306 | | |
307 | | /// Return an internal string representation of the time |
308 | | std::string to_string() const; |
309 | | |
310 | | /// Returns a human friendly string replesentation of no particular formatting |
311 | | std::string readable_string() const; |
312 | | |
313 | | /// Return if the time has been set somehow |
314 | | bool time_is_set() const; |
315 | | |
316 | | /// Compare this time against another |
317 | | int32_t cmp(const ASN1_Time& other) const; |
318 | | |
319 | | /// Create an invalid ASN1_Time |
320 | 60.1k | ASN1_Time() = default; |
321 | | |
322 | | /// Create a ASN1_Time from a time point |
323 | | explicit ASN1_Time(const std::chrono::system_clock::time_point& time); |
324 | | |
325 | | /// Create an ASN1_Time from string |
326 | | ASN1_Time(const std::string& t_spec, ASN1_Tag tag); |
327 | | |
328 | | /// Returns a STL timepoint object |
329 | | std::chrono::system_clock::time_point to_std_timepoint() const; |
330 | | |
331 | | /// Return time since epoch |
332 | | uint64_t time_since_epoch() const; |
333 | | |
334 | | private: |
335 | | void set_to(const std::string& t_spec, ASN1_Tag); |
336 | | bool passes_sanity_check() const; |
337 | | |
338 | | uint32_t m_year = 0; |
339 | | uint32_t m_month = 0; |
340 | | uint32_t m_day = 0; |
341 | | uint32_t m_hour = 0; |
342 | | uint32_t m_minute = 0; |
343 | | uint32_t m_second = 0; |
344 | | ASN1_Tag m_tag = NO_OBJECT; |
345 | | }; |
346 | | |
347 | | /* |
348 | | * Comparison Operations |
349 | | */ |
350 | | bool BOTAN_PUBLIC_API(2,0) operator==(const ASN1_Time&, const ASN1_Time&); |
351 | | bool BOTAN_PUBLIC_API(2,0) operator!=(const ASN1_Time&, const ASN1_Time&); |
352 | | bool BOTAN_PUBLIC_API(2,0) operator<=(const ASN1_Time&, const ASN1_Time&); |
353 | | bool BOTAN_PUBLIC_API(2,0) operator>=(const ASN1_Time&, const ASN1_Time&); |
354 | | bool BOTAN_PUBLIC_API(2,0) operator<(const ASN1_Time&, const ASN1_Time&); |
355 | | bool BOTAN_PUBLIC_API(2,0) operator>(const ASN1_Time&, const ASN1_Time&); |
356 | | |
357 | | typedef ASN1_Time X509_Time; |
358 | | |
359 | | /** |
360 | | * ASN.1 string type |
361 | | * This class normalizes all inputs to a UTF-8 std::string |
362 | | */ |
363 | | class BOTAN_PUBLIC_API(2,0) ASN1_String final : public ASN1_Object |
364 | | { |
365 | | public: |
366 | | void encode_into(class DER_Encoder&) const override; |
367 | | void decode_from(class BER_Decoder&) override; |
368 | | |
369 | 954 | ASN1_Tag tagging() const { return m_tag; } |
370 | | |
371 | 189k | const std::string& value() const { return m_utf8_str; } |
372 | | |
373 | 0 | size_t size() const { return value().size(); } |
374 | | |
375 | 110k | bool empty() const { return m_utf8_str.empty(); } |
376 | | |
377 | | /** |
378 | | * Return true iff this is a tag for a known string type we can handle. |
379 | | * This ignores string types that are not supported, eg teletexString |
380 | | */ |
381 | | static bool is_string_type(ASN1_Tag tag); |
382 | | |
383 | | bool operator==(const ASN1_String& other) const |
384 | 0 | { return value() == other.value(); } |
385 | | |
386 | | explicit ASN1_String(const std::string& utf8 = ""); |
387 | | ASN1_String(const std::string& utf8, ASN1_Tag tag); |
388 | | private: |
389 | | std::vector<uint8_t> m_data; |
390 | | std::string m_utf8_str; |
391 | | ASN1_Tag m_tag; |
392 | | }; |
393 | | |
394 | | /** |
395 | | * Algorithm Identifier |
396 | | */ |
397 | | class BOTAN_PUBLIC_API(2,0) AlgorithmIdentifier final : public ASN1_Object |
398 | | { |
399 | | public: |
400 | | enum Encoding_Option { USE_NULL_PARAM, USE_EMPTY_PARAM }; |
401 | | |
402 | | void encode_into(class DER_Encoder&) const override; |
403 | | void decode_from(class BER_Decoder&) override; |
404 | | |
405 | 84.5k | AlgorithmIdentifier() = default; |
406 | | |
407 | | AlgorithmIdentifier(const OID& oid, Encoding_Option enc); |
408 | | AlgorithmIdentifier(const std::string& oid_name, Encoding_Option enc); |
409 | | |
410 | | AlgorithmIdentifier(const OID& oid, const std::vector<uint8_t>& params); |
411 | | AlgorithmIdentifier(const std::string& oid_name, const std::vector<uint8_t>& params); |
412 | | |
413 | 11.6k | const OID& oid() const { return m_oid; } |
414 | 12.1k | const std::vector<uint8_t>& parameters() const { return m_parameters; } |
415 | | |
416 | 84.3k | const OID& get_oid() const { return m_oid; } |
417 | 5.11k | const std::vector<uint8_t>& get_parameters() const { return m_parameters; } |
418 | | |
419 | | bool parameters_are_null() const; |
420 | 49.9k | bool parameters_are_empty() const { return m_parameters.empty(); } |
421 | | |
422 | | bool parameters_are_null_or_empty() const |
423 | 49.8k | { |
424 | 49.8k | return parameters_are_empty() || parameters_are_null(); |
425 | 49.8k | } |
426 | | |
427 | | private: |
428 | | OID m_oid; |
429 | | std::vector<uint8_t> m_parameters; |
430 | | }; |
431 | | |
432 | | /* |
433 | | * Comparison Operations |
434 | | */ |
435 | | bool BOTAN_PUBLIC_API(2,0) operator==(const AlgorithmIdentifier&, |
436 | | const AlgorithmIdentifier&); |
437 | | bool BOTAN_PUBLIC_API(2,0) operator!=(const AlgorithmIdentifier&, |
438 | | const AlgorithmIdentifier&); |
439 | | |
440 | | } |
441 | | |
442 | | #endif |