Botan 3.13.0
Crypto and TLS for C&
der_enc.cpp
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#include <botan/der_enc.h>
9
10#include <botan/asn1_obj.h>
11#include <botan/bigint.h>
12#include <botan/internal/asn1_utils.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/loadstor.h>
16#include <botan/internal/mem_utils.h>
17#include <algorithm>
18
19namespace Botan {
20
21namespace {
22
23/*
24* DER encode an ASN.1 type tag
25*/
26void encode_tag(std::vector<uint8_t>& encoded_tag, ASN1_Type type_tag_e, ASN1_Class class_tag_e) {
27 const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
28 const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
29
30 if((class_tag | 0xE0) != 0xE0) {
31 throw Encoding_Error(fmt("DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
32 }
33
34 if(type_tag <= 30) {
35 encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
36 } else {
37 size_t blocks = high_bit(static_cast<uint32_t>(type_tag)) + 6;
38 blocks = (blocks - (blocks % 7)) / 7;
39
40 BOTAN_ASSERT_NOMSG(blocks > 0);
41
42 encoded_tag.push_back(static_cast<uint8_t>(class_tag | 0x1F));
43 for(size_t i = 0; i != blocks - 1; ++i) {
44 encoded_tag.push_back(0x80 | ((type_tag >> 7 * (blocks - i - 1)) & 0x7F));
45 }
46 encoded_tag.push_back(type_tag & 0x7F);
47 }
48}
49
50/*
51* DER encode an ASN.1 length field
52*/
53void encode_length(std::vector<uint8_t>& encoded_length, size_t length) {
54 if(length <= 127) {
55 encoded_length.push_back(static_cast<uint8_t>(length));
56 } else {
57 const size_t bytes_needed = significant_bytes(length);
58
59 encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
60
61 for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i) {
62 encoded_length.push_back(get_byte_var(i, length));
63 }
64 }
65}
66
67} // namespace
68
69namespace ASN1 {
70
71std::vector<uint8_t> der_sequence_header(size_t contents_len) {
72 std::vector<uint8_t> header;
73 header.reserve(2 + sizeof(contents_len));
75 encode_length(header, contents_len);
76 return header;
77}
78
79} // namespace ASN1
80
82 m_append_output = [&vec](const uint8_t b[], size_t l) {
83 if(l > 0) {
84 vec.insert(vec.end(), b, b + l);
85 }
86 };
87}
88
89DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec) {
90 m_append_output = [&vec](const uint8_t b[], size_t l) {
91 if(l > 0) {
92 vec.insert(vec.end(), b, b + l);
93 }
94 };
95}
96
97/*
98* Push the encoded SEQUENCE/SET to the encoder stream
99*/
100void DER_Encoder::DER_Sequence::push_contents(DER_Encoder& der) {
101 const auto real_class_tag = m_class_tag | ASN1_Class::Constructed;
102
103 if(m_sort_contents) {
104 std::sort(m_set_contents.begin(), m_set_contents.end());
105 for(const auto& set_elem : m_set_contents) {
106 m_contents += set_elem;
107 }
108 m_set_contents.clear();
109 }
110
111 der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
112 m_contents.clear();
113}
114
115/*
116* Add an encoded value to the SEQUENCE/SET
117*/
118void DER_Encoder::DER_Sequence::add_bytes(const uint8_t data[], size_t length) {
119 if(m_sort_contents) {
120 if(length > 0) {
121 m_set_contents.emplace_back(data, data + length);
122 } else {
123 m_set_contents.emplace_back();
124 }
125 } else {
126 m_contents += std::make_pair(data, length);
127 }
128}
129
130void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len) {
131 if(m_sort_contents) {
133 m.reserve(hdr_len + val_len);
134 m += std::make_pair(hdr, hdr_len);
135 m += std::make_pair(val, val_len);
136 m_set_contents.push_back(std::move(m));
137 } else {
138 m_contents += std::make_pair(hdr, hdr_len);
139 m_contents += std::make_pair(val, val_len);
140 }
141}
142
143/*
144* Return the type and class taggings
145*/
146uint32_t DER_Encoder::DER_Sequence::tag_of() const {
147 return m_type_tag | m_class_tag;
148}
149
150/*
151* DER_Sequence Constructor
152*/
153DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type type_tag, ASN1_Class class_tag, bool sort_contents) :
154 m_type_tag(type_tag),
155 m_class_tag(class_tag),
156 m_sort_contents(sort_contents || (type_tag == ASN1_Type::Set && class_tag == ASN1_Class::Universal)) {}
157
158/*
159* Return the encoded contents
160*/
162 if(!m_subsequences.empty()) {
163 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
164 }
165
166 if(m_append_output) {
167 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
168 }
169
171 std::swap(output, m_default_outbuf);
172 return output;
173}
174
176 if(!m_subsequences.empty()) {
177 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
178 }
179
180 if(m_append_output) {
181 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
182 }
183
184 std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
185 m_default_outbuf.clear();
186 return output;
187}
188
189/*
190* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
191*/
193 return start_cons(type_tag, class_tag, false);
194}
195
197 return start_cons(type_tag, class_tag, true);
198}
199
200DER_Encoder& DER_Encoder::start_cons(ASN1_Type type_tag, ASN1_Class class_tag, bool sort_contents) {
201 m_subsequences.push_back(DER_Sequence(type_tag, class_tag, sort_contents));
202 return (*this);
203}
204
205/*
206* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
207*/
209 if(m_subsequences.empty()) {
210 throw Invalid_State("DER_Encoder::end_cons: No such sequence");
211 }
212
213 DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
214 m_subsequences.pop_back();
215 last_seq.push_contents(*this);
216
217 return (*this);
218}
219
220/*
221* Start a new ASN.1 EXPLICIT encoding
222*/
224 return start_cons(static_cast<ASN1_Type>(type_no), ASN1_Class::ContextSpecific);
225}
226
227/*
228* Finish the current ASN.1 EXPLICIT encoding
229*/
233
234/*
235* Write raw bytes into the stream
236*/
237DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length) {
238 if(!m_subsequences.empty()) {
239 m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
240 } else if(m_append_output) {
241 m_append_output(bytes, length);
242 } else {
243 m_default_outbuf += std::make_pair(bytes, length);
244 }
245
246 return (*this);
247}
248
249DER_Encoder& DER_Encoder::add_object_tlv(ASN1_Type type_tag, ASN1_Class class_tag, std::vector<uint8_t> tlv) {
250 // `tlv` was just produced by us via DER_Encoder, so it's a single
251 // well-formed TLV. Skip over the tag and length bytes (without
252 // reinterpreting them) to find the body offset.
253 BOTAN_ASSERT_NOMSG(!tlv.empty());
254 class_tag =
255 static_cast<ASN1_Class>(static_cast<uint32_t>(class_tag) & ~static_cast<uint32_t>(ASN1_Class::Constructed));
256 if((tlv[0] & static_cast<uint8_t>(ASN1_Class::Constructed)) != 0) {
257 class_tag = class_tag | ASN1_Class::Constructed;
258 }
259
260 size_t off = 1;
261 // Multi-byte tag form (X.690 8.1.2.4): low 5 bits set to 0x1F, then
262 // continuation bytes whose MSB is 1 except the last.
263 if((tlv[0] & 0x1F) == 0x1F) {
264 while(off < tlv.size() && (tlv[off] & 0x80) != 0) {
265 ++off;
266 }
267 BOTAN_ASSERT_NOMSG(off < tlv.size());
268 ++off;
269 }
270 // Length: short form is one byte; long form (MSB set) names the
271 // number of length-of-length bytes that follow.
272 BOTAN_ASSERT_NOMSG(off < tlv.size());
273 const uint8_t len_byte = tlv[off++];
274 if((len_byte & 0x80) != 0) {
275 off += (len_byte & 0x7F);
276 }
277 BOTAN_ASSERT_NOMSG(off <= tlv.size());
278
279 return add_object(type_tag, class_tag, std::span<const uint8_t>(tlv).subspan(off));
280}
281
282/*
283* Write the encoding of the byte(s)
284*/
285DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length) {
286 std::vector<uint8_t> hdr;
287 encode_tag(hdr, type_tag, class_tag);
288 encode_length(hdr, length);
289
290 if(!m_subsequences.empty()) {
291 m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
292 } else if(m_append_output) {
293 m_append_output(hdr.data(), hdr.size());
294 m_append_output(rep, length);
295 } else {
296 m_default_outbuf += hdr;
297 m_default_outbuf += std::make_pair(rep, length);
298 }
299
300 return (*this);
301}
302
303/*
304* Encode a NULL object
305*/
309
310/*
311* DER encode a BOOLEAN
312*/
316
317/*
318* DER encode a small INTEGER
319*/
323
324/*
325* DER encode a small INTEGER
326*/
330
331/*
332* Encode this object
333*/
334DER_Encoder& DER_Encoder::encode(std::span<const uint8_t> bytes, ASN1_Type real_type) {
335 return encode(bytes, real_type, real_type, ASN1_Class::Universal);
336}
337
338/*
339* DER encode a BOOLEAN
340*/
341DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Type type_tag, ASN1_Class class_tag) {
342 const uint8_t val = is_true ? 0xFF : 0x00;
343 return add_object(type_tag, class_tag, &val, 1);
344}
345
346/*
347* DER encode a small INTEGER
348*/
349DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Type type_tag, ASN1_Class class_tag) {
350 return encode(BigInt::from_u64(n), type_tag, class_tag);
351}
352
353/*
354* DER encode an INTEGER
355*/
356std::vector<uint8_t> ASN1::integer_contents(const BigInt& n) {
357 if(n == 0) {
358 return {0x00};
359 }
360
361 // Serialize magnitude with one extra leading byte
362 auto contents = n.serialize(n.bytes() + 1);
363
364 if(n.signum() < 0) {
365 // Two's complement: bitwise NOT then increment
366 for(auto& byte : contents) {
367 byte = ~byte;
368 }
369 for(size_t i = contents.size(); i > 0; --i) {
370 if(++contents[i - 1] != 0) {
371 break;
372 }
373 }
374 }
375
376 /*
377 * DER requires the leading byte be emitted only if it required
378 */
379 BOTAN_ASSERT_NOMSG(contents.size() >= 2);
380 const bool leading_byte_redundant =
381 (contents[0] == 0x00 && (contents[1] & 0x80) == 0) || (contents[0] == 0xFF && (contents[1] & 0x80) != 0);
382
383 if(leading_byte_redundant) {
384 contents.erase(contents.begin());
385 }
386 return contents;
387}
388
390 return add_object(type_tag, class_tag, ASN1::integer_contents(n));
391}
392
393/*
394* DER encode an OCTET STRING or BIT STRING
395*/
396DER_Encoder& DER_Encoder::encode(std::span<const uint8_t> bytes,
397 ASN1_Type real_type,
398 ASN1_Type type_tag,
399 ASN1_Class class_tag) {
400 if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
401 throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
402 }
403
404 if(real_type == ASN1_Type::BitString) {
405 return encode_bitstring(bytes, 0, type_tag, class_tag);
406 } else {
407 return add_object(type_tag, class_tag, bytes);
408 }
409}
410
411DER_Encoder& DER_Encoder::encode_bitstring(std::span<const uint8_t> bits,
412 size_t unused_bits,
413 ASN1_Type type_tag,
414 ASN1_Class class_tag) {
415 if(unused_bits >= 8) {
416 throw Invalid_Argument("DER_Encoder: Invalid unused bit count for BIT STRING");
417 }
418
419 if(bits.empty() && unused_bits != 0) {
420 throw Invalid_Argument("DER_Encoder: Empty BIT STRING cannot have unused bits");
421 }
422
423 if(unused_bits > 0 && (bits.back() & ((1U << unused_bits) - 1)) != 0) {
424 throw Invalid_Argument("DER_Encoder: BIT STRING unused bits must be zero");
425 }
426
428 encoded.reserve(1 + bits.size());
429 encoded.push_back(static_cast<uint8_t>(unused_bits));
430 encoded.insert(encoded.end(), bits.begin(), bits.end());
431 return add_object(type_tag, class_tag, encoded);
432}
433
435 return encode_bitstring(bits.bytes(), bits.unused_bits(), type_tag, class_tag);
436}
437
439 size_t width,
440 ASN1_Type type_tag,
441 ASN1_Class class_tag) {
442 if(width > 64) {
443 throw Invalid_Argument("DER_Encoder: Named BIT STRING width is too large");
444 }
445
446 if(width < 64 && (bits >> width) != 0) {
447 throw Invalid_Argument("DER_Encoder: Named BIT STRING has bits outside range");
448 }
449
450 if(bits == 0) {
451 return encode_bitstring({}, 0, type_tag, class_tag);
452 }
453
454 const size_t bit_length = width - ctz(bits);
455 const size_t byte_length = (bit_length + 7) / 8;
456 std::vector<uint8_t> encoded(byte_length);
457
458 for(size_t bit = 0; bit != bit_length; ++bit) {
459 if((bits & (uint64_t(1) << (width - 1 - bit))) != 0) {
460 encoded[bit / 8] |= static_cast<uint8_t>(0x80 >> (bit % 8));
461 }
462 }
463
464 return encode_bitstring(encoded, byte_length * 8 - bit_length, type_tag, class_tag);
465}
466
468 obj.encode_into(*this);
469 return (*this);
470}
471
472/*
473* Write the encoding of the byte(s)
474*/
475DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view rep_str) {
476 return add_object(type_tag, class_tag, as_span_of_bytes(rep_str));
477}
478
479/*
480* Write the encoding of the byte
481*/
482DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t rep) {
483 return add_object(type_tag, class_tag, std::span<const uint8_t>{&rep, 1});
484}
485
486} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
size_t unused_bits() const
Definition asn1_obj.h:211
std::span< const uint8_t > bytes() const
Definition asn1_obj.h:206
virtual void encode_into(DER_Encoder &to) const =0
int signum() const
Definition bigint.h:493
static BigInt from_u64(uint64_t n)
Definition bigint.cpp:30
size_t bytes() const
Definition bigint.cpp:294
T serialize(size_t len) const
Definition bigint.h:790
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 & end_explicit()
Definition der_enc.cpp:230
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:223
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_null()
Definition der_enc.cpp:306
DER_Encoder & end_cons()
Definition der_enc.cpp:208
std::vector< uint8_t > get_contents_unlocked()
Definition der_enc.cpp:175
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
DER_Encoder & encode_named_bitstring(uint64_t bits, size_t width, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition der_enc.cpp:438
std::vector< uint8_t > integer_contents(const BigInt &n)
Definition der_enc.cpp:356
std::vector< uint8_t > der_sequence_header(size_t contents_len)
Definition der_enc.cpp:71
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:59
ASN1_Class
Definition asn1_obj.h:32
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:47
BOTAN_FORCE_INLINE constexpr size_t significant_bytes(T n)
Definition bit_ops.h:94
BOTAN_FORCE_INLINE constexpr size_t high_bit(T n)
Definition bit_ops.h:73
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition loadstor.h:69
std::uint8_t byte
Unsigned 8 bit integer; retained for compatibility with older versions.
Definition types.h:112
BOTAN_FORCE_INLINE constexpr size_t ctz(T n)
Definition bit_ops.h:115