Botan 3.13.0
Crypto and TLS for C&
der_enc.h
Go to the documentation of this file.
1/*
2* DER Encoder
3* (C) 1999-2007,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_DER_ENCODER_H_
9#define BOTAN_DER_ENCODER_H_
10
11#include <botan/asn1_obj.h>
12#include <botan/secmem.h>
13#include <functional>
14#include <optional>
15#include <span>
16#include <vector>
17
18namespace Botan {
19
20class BigInt;
21
22/**
23* General DER Encoding Object
24*/
25class BOTAN_PUBLIC_API(2, 0) DER_Encoder final {
26 public:
27 /**
28 * Callback type invoked with each chunk of encoded output
29 */
30 typedef std::function<void(const uint8_t[], size_t)> append_fn;
31
32 /**
33 * DER encode, writing to an internal buffer
34 * Use get_contents or get_contents_unlocked to read the results
35 * after all encoding is completed.
36 */
37 DER_Encoder() = default;
38
39 /**
40 * DER encode, writing to @param vec
41 * If this constructor is used, get_contents* may not be called.
42 */
44
45 /**
46 * DER encode, writing to @param vec
47 * If this constructor is used, get_contents* may not be called.
48 */
49 BOTAN_FUTURE_EXPLICIT DER_Encoder(std::vector<uint8_t>& vec);
50
51 /**
52 * DER encode, calling append to write output
53 * If this constructor is used, get_contents* may not be called.
54 */
55 BOTAN_FUTURE_EXPLICIT DER_Encoder(append_fn append) : m_append_output(std::move(append)) {}
56
57 /**
58 * Return the encoded contents
59 *
60 * Throws Invalid_State if any constructed encoding is still open, or if
61 * this encoder was constructed with an output vector or append function.
62 */
63 secure_vector<uint8_t> get_contents();
64
65 /**
66 * Return the encoded contents as a std::vector
67 *
68 * If using this function, instead pass a std::vector to the
69 * constructor of DER_Encoder where the output will be placed. This
70 * avoids several unnecessary copies.
71 */
72 BOTAN_DEPRECATED("Use DER_Encoder(vector) instead") std::vector<uint8_t> get_contents_unlocked();
73
74 /**
75 * Start a constructed encoding with the given tagging. Must be closed with
76 * end_cons(). Contents are emitted in the order they are encoded.
77 *
78 * @param type_tag the type tag of the constructed encoding
79 * @param class_tag the class tag of the constructed encoding
80 */
81 DER_Encoder& start_cons(ASN1_Type type_tag, ASN1_Class class_tag);
82
83 /**
84 * Start a SEQUENCE. Must be closed with end_cons().
85 */
87
88 /**
89 * Start a SET/SET OF. Must be closed with end_cons(). Contents are DER sorted.
90 */
92
93 /**
94 * Start a SET/SET OF with an alternate tag. Contents are still DER sorted.
95 *
96 * @param type_tag the type tag of the constructed encoding
97 * @param class_tag the class tag of the constructed encoding
98 */
99 DER_Encoder& start_set(ASN1_Type type_tag, ASN1_Class class_tag);
100
101 /**
102 * Start a SET/SET OF with a context specific tag. Contents are still DER sorted.
103 *
104 * @param tag the context specific tag number
105 */
107
108 /**
109 * Start an IMPLICIT context specific constructed encoding
110 *
111 * @param tag the context specific tag number
112 */
116
117 /**
118 * Start an EXPLICIT context specific constructed encoding
119 *
120 * @param tag the context specific tag number
121 */
125
126 /**
127 * Finish the innermost open constructed encoding
128 *
129 * Throws Invalid_State if no constructed encoding is open.
130 */
131 DER_Encoder& end_cons();
132
133 /**
134 * Start a context specific constructed encoding, an alias for
135 * start_context_specific()
136 *
137 * @param type_tag the context specific tag number
138 */
139 DER_Encoder& start_explicit(uint16_t type_tag);
140
141 /**
142 * Finish the innermost open constructed encoding, an alias for end_cons()
143 */
144 DER_Encoder& end_explicit();
145
146 /**
147 * Insert raw bytes directly into the output stream
148 */
149 DER_Encoder& raw_bytes(const uint8_t val[], size_t len);
150
151 /**
152 * Insert raw bytes directly into the output stream
153 */
154 DER_Encoder& raw_bytes(std::span<const uint8_t> val) { return raw_bytes(val.data(), val.size()); }
155
156 /**
157 * Encode a NULL
158 */
159 DER_Encoder& encode_null();
160
161 /**
162 * Encode a BOOLEAN
163 */
164 DER_Encoder& encode(bool b);
165
166 /**
167 * Encode an INTEGER
168 */
169 DER_Encoder& encode(size_t s);
170
171 /**
172 * Encode an INTEGER
173 */
174 DER_Encoder& encode(const BigInt& n);
175
176 /**
177 * Encode an OCTET STRING or an octet aligned BIT STRING
178 *
179 * @param val the contents of the object
180 * @param real_type either ASN1_Type::OctetString or ASN1_Type::BitString
181 */
182 DER_Encoder& encode(std::span<const uint8_t> val, ASN1_Type real_type);
183
184 /**
185 * Encode a BIT STRING, with `bits` not including the initial unused-bits octet.
186 */
187 DER_Encoder& encode_bitstring(std::span<const uint8_t> bits,
188 size_t unused_bits = 0,
191
192 /**
193 * Encode a BIT STRING
194 *
195 * @param bits the value to encode
196 * @param type_tag the type tag to encode with
197 * @param class_tag the class tag to encode with
198 */
199 DER_Encoder& encode_bitstring(const ASN1_BitString& bits,
202
203 /**
204 * Encode a BIT STRING with no unused bits
205 *
206 * @param bytes the bits to encode
207 * @param type_tag the type tag to encode with
208 * @param class_tag the class tag to encode with
209 */
210 DER_Encoder& encode_octet_aligned_bitstring(std::span<const uint8_t> bytes,
212 ASN1_Class class_tag = ASN1_Class::Universal) {
213 return encode_bitstring(bytes, 0, type_tag, class_tag);
214 }
215
216 /**
217 * Helper for encoding BIT STRING elements that are actually bit sets, rather
218 * than being OCTET STRINGS with the wrong type.
219 */
220 DER_Encoder& encode_named_bitstring(uint64_t bits,
221 size_t width,
224
225 /**
226 * Encode an OCTET STRING or an octet aligned BIT STRING
227 *
228 * @param val the contents of the object
229 * @param len the length of val in bytes
230 * @param real_type either ASN1_Type::OctetString or ASN1_Type::BitString
231 */
232 DER_Encoder& encode(const uint8_t val[], size_t len, ASN1_Type real_type) {
233 return this->encode(std::span{val, len}, real_type);
234 }
235
236 /**
237 * Encode a BOOLEAN with an IMPLICIT tagging
238 *
239 * @param b the value to encode
240 * @param type_tag the type tag to encode with
241 * @param class_tag the class tag to encode with
242 */
243 DER_Encoder& encode(bool b, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
244
245 /**
246 * Encode an INTEGER with an IMPLICIT tagging
247 *
248 * @param s the value to encode
249 * @param type_tag the type tag to encode with
250 * @param class_tag the class tag to encode with
251 */
252 DER_Encoder& encode(size_t s, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
253
254 /**
255 * Encode an INTEGER with an IMPLICIT tagging
256 *
257 * @param n the value to encode
258 * @param type_tag the type tag to encode with
259 * @param class_tag the class tag to encode with
260 */
261 DER_Encoder& encode(const BigInt& n, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
262
263 /**
264 * Encode an OCTET STRING or octet aligned BIT STRING with an IMPLICIT tagging
265 *
266 * @param value the contents of the object
267 * @param real_type either ASN1_Type::OctetString or ASN1_Type::BitString
268 * @param type_tag the type tag to encode with
269 * @param class_tag the class tag to encode with
270 */
271 DER_Encoder& encode(std::span<const uint8_t> value,
272 ASN1_Type real_type,
273 ASN1_Type type_tag,
275
276 /**
277 * Encode an OCTET STRING or octet aligned BIT STRING with an IMPLICIT tagging
278 *
279 * @param v the contents of the object
280 * @param len the length of v in bytes
281 * @param real_type either ASN1_Type::OctetString or ASN1_Type::BitString
282 * @param type_tag the type tag to encode with
283 * @param class_tag the class tag to encode with
284 */
285 DER_Encoder& encode(const uint8_t v[],
286 size_t len,
287 ASN1_Type real_type,
288 ASN1_Type type_tag,
290 return encode(std::span{v, len}, real_type, type_tag, class_tag);
291 }
292
293 /**
294 * Encode a value unless it is equal to the DEFAULT
295 *
296 * @param value the value to encode
297 * @param default_value the value which should be omitted
298 */
299 template <typename T>
300 BOTAN_DEPRECATED("Use the version that takes a std::optional")
301 DER_Encoder& encode_optional(const T& value, const T& default_value) {
302 if(value != default_value) {
303 encode(value);
304 }
305 return (*this);
306 }
307
308 /**
309 * Encode a value if it is set, otherwise write nothing
310 *
311 * @param value the value to encode
312 */
313 template <typename T>
314 DER_Encoder& encode_optional(const std::optional<T>& value) {
315 if(value) {
316 encode(*value);
317 }
318 return (*this);
319 }
320
321 /**
322 * Encode each element of the vector in turn
323 *
324 * @param values the values to encode
325 */
326 template <typename T>
327 DER_Encoder& encode_list(const std::vector<T>& values) {
328 for(size_t i = 0; i != values.size(); ++i) {
329 encode(values[i]);
330 }
331 return (*this);
332 }
333
334 /**
335 * Request for an object to encode itself to this stream
336 *
337 * @param obj the object to encode
338 */
339 DER_Encoder& encode(const ASN1_Object& obj);
340
341 /**
342 * Write the contents of another encoder to this stream if pred is true
343 *
344 * @param pred if false nothing is written
345 * @param enc the encoder whose contents are written
346 */
348 if(pred) {
349 return raw_bytes(enc.get_contents());
350 }
351 return (*this);
352 }
353
354 /**
355 * Encode an object if pred is true
356 *
357 * @param pred if false nothing is written
358 * @param obj the object to encode
359 */
360 DER_Encoder& encode_if(bool pred, const ASN1_Object& obj) {
361 if(pred) {
362 encode(obj);
363 }
364 return (*this);
365 }
366
367 /**
368 * Encode an INTEGER if pred is true
369 *
370 * @param pred if false nothing is written
371 * @param num the value to encode
372 */
373 DER_Encoder& encode_if(bool pred, size_t num) {
374 if(pred) {
375 encode(num);
376 }
377 return (*this);
378 }
379
380 /**
381 * Encode a BOOLEAN if pred is true
382 *
383 * @param pred if false nothing is written
384 * @param num the value to encode
385 */
386 DER_Encoder& encode_if(bool pred, bool num) {
387 if(pred) {
388 encode(num);
389 }
390 return (*this);
391 }
392
393 /**
394 * Write a tag and length header followed by the given contents
395 *
396 * @param type_tag the type tag to encode with
397 * @param class_tag the class tag to encode with
398 * @param rep the contents of the object
399 * @param length the length of rep in bytes
400 */
401 DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length);
402
403 /**
404 * Write a tag and length header followed by the given contents
405 *
406 * @param type_tag the type tag to encode with
407 * @param class_tag the class tag to encode with
408 * @param rep the contents of the object
409 */
410 DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::span<const uint8_t> rep) {
411 return add_object(type_tag, class_tag, rep.data(), rep.size());
412 }
413
414 /**
415 * Write a tag and length header followed by the given contents
416 *
417 * @param type_tag the type tag to encode with
418 * @param class_tag the class tag to encode with
419 * @param rep the contents of the object
420 */
421 DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, const std::vector<uint8_t>& rep) {
422 return add_object(type_tag, class_tag, std::span{rep});
423 }
424
425 /**
426 * Write a tag and length header followed by the given contents
427 *
428 * @param type_tag the type tag to encode with
429 * @param class_tag the class tag to encode with
430 * @param rep the contents of the object
431 */
433 return add_object(type_tag, class_tag, std::span{rep});
434 }
435
436 /**
437 * Write a tag and length header followed by the given contents
438 *
439 * @param type_tag the type tag to encode with
440 * @param class_tag the class tag to encode with
441 * @param str the contents of the object
442 */
443 DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view str);
444
445 /**
446 * Write a tag and length header followed by a single byte of contents
447 *
448 * @param type_tag the type tag to encode with
449 * @param class_tag the class tag to encode with
450 * @param val the contents of the object
451 */
452 DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t val);
453
454 /**
455 * Encode `value` and emit just its body bytes under an IMPLICIT
456 * `type_tag`/`class_tag` (e.g. for `[N] IMPLICIT OBJECT IDENTIFIER` where the
457 * body is an OID's arc bytes but the tag must be `[N]`). The
458 * primitive/constructed bit is copied from `value`.
459 */
460 template <typename T>
462 ASN1_Type type_tag,
464 std::vector<uint8_t> tlv;
465 DER_Encoder(tlv).encode(value);
466 return add_object_tlv(type_tag, class_tag, std::move(tlv));
467 }
468
469 private:
470 DER_Encoder& add_object_tlv(ASN1_Type type_tag, ASN1_Class class_tag, std::vector<uint8_t> tlv);
471
472 DER_Encoder& start_cons(ASN1_Type type_tag, ASN1_Class class_tag, bool sort_contents);
473
474 class DER_Sequence final {
475 public:
476 uint32_t tag_of() const;
477
478 void push_contents(DER_Encoder& der);
479
480 void add_bytes(const uint8_t val[], size_t len);
481
482 void add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len);
483
484 DER_Sequence(ASN1_Type type_tag, ASN1_Class class_tag, bool sort_contents);
485
486 DER_Sequence(DER_Sequence&& seq) noexcept :
487 m_type_tag(seq.m_type_tag),
488 m_class_tag(seq.m_class_tag),
489 m_sort_contents(seq.m_sort_contents),
490 m_contents(std::move(seq.m_contents)),
491 m_set_contents(std::move(seq.m_set_contents)) {}
492
493 DER_Sequence& operator=(DER_Sequence&& seq) noexcept {
494 std::swap(m_type_tag, seq.m_type_tag);
495 std::swap(m_class_tag, seq.m_class_tag);
496 std::swap(m_sort_contents, seq.m_sort_contents);
497 std::swap(m_contents, seq.m_contents);
498 std::swap(m_set_contents, seq.m_set_contents);
499 return (*this);
500 }
501
502 DER_Sequence(const DER_Sequence& seq) = default;
503 DER_Sequence& operator=(const DER_Sequence& seq) = default;
504 ~DER_Sequence() = default;
505
506 private:
507 ASN1_Type m_type_tag;
508 ASN1_Class m_class_tag;
509 bool m_sort_contents;
510 secure_vector<uint8_t> m_contents;
511 std::vector<secure_vector<uint8_t>> m_set_contents;
512 };
513
514 append_fn m_append_output;
515 secure_vector<uint8_t> m_default_outbuf;
516 std::vector<DER_Sequence> m_subsequences;
517};
518
519} // namespace Botan
520
521#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
#define BOTAN_FUTURE_EXPLICIT
Definition api.h:52
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
Definition der_enc.cpp:285
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:161
DER_Encoder & start_set()
Definition der_enc.h:91
DER_Encoder & encode_implicit(const T &value, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition der_enc.h:461
DER_Encoder & encode_if(bool pred, bool num)
Definition der_enc.h:386
DER_Encoder & encode_octet_aligned_bitstring(std::span< const uint8_t > bytes, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition der_enc.h:210
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const std::vector< uint8_t > &rep)
Definition der_enc.h:421
DER_Encoder & encode_optional(const T &value, const T &default_value)
Definition der_enc.h:301
DER_Encoder & encode_list(const std::vector< T > &values)
Definition der_enc.h:327
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::span< const uint8_t > rep)
Definition der_enc.h:410
DER_Encoder & encode_if(bool pred, const ASN1_Object &obj)
Definition der_enc.h:360
DER_Encoder & start_set(uint32_t tag)
Definition der_enc.h:106
DER_Encoder & start_explicit_context_specific(uint32_t tag)
Definition der_enc.h:122
DER_Encoder & start_context_specific(uint32_t tag)
Definition der_enc.h:113
DER_Encoder & encode_optional(const std::optional< T > &value)
Definition der_enc.h:314
DER_Encoder & encode(const uint8_t val[], size_t len, ASN1_Type real_type)
Definition der_enc.h:232
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const secure_vector< uint8_t > &rep)
Definition der_enc.h:432
DER_Encoder & encode(const uint8_t v[], size_t len, ASN1_Type real_type, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition der_enc.h:285
DER_Encoder & start_sequence()
Definition der_enc.h:86
DER_Encoder & encode_if(bool pred, DER_Encoder &enc)
Definition der_enc.h:347
DER_Encoder & raw_bytes(std::span< const uint8_t > val)
Definition der_enc.h:154
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition der_enc.cpp:192
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition der_enc.cpp:237
DER_Encoder & encode_if(bool pred, size_t num)
Definition der_enc.h:373
BOTAN_FUTURE_EXPLICIT DER_Encoder(append_fn append)
Definition der_enc.h:55
DER_Encoder & encode_bitstring(std::span< const uint8_t > bits, size_t unused_bits=0, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition der_enc.cpp:411
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
DER_Encoder()=default
std::function< void(const uint8_t[], size_t)> append_fn
Definition der_enc.h:30
ASN1_Class
Definition asn1_obj.h:32
ASN1_Type
Definition asn1_obj.h:47
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128