Botan 3.4.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/bit_ops.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/loadstor.h>
15#include <algorithm>
16
17namespace Botan {
18
19namespace {
20
21/*
22* DER encode an ASN.1 type tag
23*/
24void encode_tag(std::vector<uint8_t>& encoded_tag, ASN1_Type type_tag_e, ASN1_Class class_tag_e) {
25 const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
26 const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
27
28 if((class_tag | 0xE0) != 0xE0) {
29 throw Encoding_Error(fmt("DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
30 }
31
32 if(type_tag <= 30) {
33 encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
34 } else {
35 size_t blocks = high_bit(static_cast<uint32_t>(type_tag)) + 6;
36 blocks = (blocks - (blocks % 7)) / 7;
37
38 BOTAN_ASSERT_NOMSG(blocks > 0);
39
40 encoded_tag.push_back(static_cast<uint8_t>(class_tag | 0x1F));
41 for(size_t i = 0; i != blocks - 1; ++i) {
42 encoded_tag.push_back(0x80 | ((type_tag >> 7 * (blocks - i - 1)) & 0x7F));
43 }
44 encoded_tag.push_back(type_tag & 0x7F);
45 }
46}
47
48/*
49* DER encode an ASN.1 length field
50*/
51void encode_length(std::vector<uint8_t>& encoded_length, size_t length) {
52 if(length <= 127) {
53 encoded_length.push_back(static_cast<uint8_t>(length));
54 } else {
55 const size_t bytes_needed = significant_bytes(length);
56
57 encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
58
59 for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i) {
60 encoded_length.push_back(get_byte_var(i, length));
61 }
62 }
63}
64
65} // namespace
66
68 m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
69}
70
71DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec) {
72 m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
73}
74
75/*
76* Push the encoded SEQUENCE/SET to the encoder stream
77*/
78void DER_Encoder::DER_Sequence::push_contents(DER_Encoder& der) {
79 const auto real_class_tag = m_class_tag | ASN1_Class::Constructed;
80
81 if(m_type_tag == ASN1_Type::Set) {
82 std::sort(m_set_contents.begin(), m_set_contents.end());
83 for(const auto& set_elem : m_set_contents) {
84 m_contents += set_elem;
85 }
86 m_set_contents.clear();
87 }
88
89 der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
90 m_contents.clear();
91}
92
93/*
94* Add an encoded value to the SEQUENCE/SET
95*/
96void DER_Encoder::DER_Sequence::add_bytes(const uint8_t data[], size_t length) {
97 if(m_type_tag == ASN1_Type::Set) {
98 m_set_contents.push_back(secure_vector<uint8_t>(data, data + length));
99 } else {
100 m_contents += std::make_pair(data, length);
101 }
102}
103
104void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len) {
105 if(m_type_tag == ASN1_Type::Set) {
106 secure_vector<uint8_t> m;
107 m.reserve(hdr_len + val_len);
108 m += std::make_pair(hdr, hdr_len);
109 m += std::make_pair(val, val_len);
110 m_set_contents.push_back(std::move(m));
111 } else {
112 m_contents += std::make_pair(hdr, hdr_len);
113 m_contents += std::make_pair(val, val_len);
114 }
115}
116
117/*
118* Return the type and class taggings
119*/
120uint32_t DER_Encoder::DER_Sequence::tag_of() const {
121 return m_type_tag | m_class_tag;
122}
123
124/*
125* DER_Sequence Constructor
126*/
127DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type t1, ASN1_Class t2) : m_type_tag(t1), m_class_tag(t2) {}
128
129/*
130* Return the encoded contents
131*/
133 if(!m_subsequences.empty()) {
134 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
135 }
136
137 if(m_append_output) {
138 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
139 }
140
142 std::swap(output, m_default_outbuf);
143 return output;
144}
145
147 if(!m_subsequences.empty()) {
148 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
149 }
150
151 if(m_append_output) {
152 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
153 }
154
155 std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
156 m_default_outbuf.clear();
157 return output;
158}
159
160/*
161* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
162*/
164 m_subsequences.push_back(DER_Sequence(type_tag, class_tag));
165 return (*this);
166}
167
168/*
169* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
170*/
172 if(m_subsequences.empty()) {
173 throw Invalid_State("DER_Encoder::end_cons: No such sequence");
174 }
175
176 DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
177 m_subsequences.pop_back();
178 last_seq.push_contents(*this);
179
180 return (*this);
181}
182
183/*
184* Start a new ASN.1 EXPLICIT encoding
185*/
187 ASN1_Type type_tag = static_cast<ASN1_Type>(type_no);
188
189 // This would confuse DER_Sequence
190 if(type_tag == ASN1_Type::Set) {
191 throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");
192 }
193
194 return start_cons(type_tag, ASN1_Class::ContextSpecific);
195}
196
197/*
198* Finish the current ASN.1 EXPLICIT encoding
199*/
203
204/*
205* Write raw bytes into the stream
206*/
207DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length) {
208 if(!m_subsequences.empty()) {
209 m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
210 } else if(m_append_output) {
211 m_append_output(bytes, length);
212 } else {
213 m_default_outbuf += std::make_pair(bytes, length);
214 }
215
216 return (*this);
217}
218
219/*
220* Write the encoding of the byte(s)
221*/
222DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length) {
223 std::vector<uint8_t> hdr;
224 encode_tag(hdr, type_tag, class_tag);
225 encode_length(hdr, length);
226
227 if(!m_subsequences.empty()) {
228 m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
229 } else if(m_append_output) {
230 m_append_output(hdr.data(), hdr.size());
231 m_append_output(rep, length);
232 } else {
233 m_default_outbuf += hdr;
234 m_default_outbuf += std::make_pair(rep, length);
235 }
236
237 return (*this);
238}
239
240/*
241* Encode a NULL object
242*/
246
247/*
248* DER encode a BOOLEAN
249*/
253
254/*
255* DER encode a small INTEGER
256*/
260
261/*
262* DER encode a small INTEGER
263*/
267
268/*
269* Encode this object
270*/
271DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length, ASN1_Type real_type) {
272 return encode(bytes, length, real_type, real_type, ASN1_Class::Universal);
273}
274
275/*
276* DER encode a BOOLEAN
277*/
278DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Type type_tag, ASN1_Class class_tag) {
279 uint8_t val = is_true ? 0xFF : 0x00;
280 return add_object(type_tag, class_tag, &val, 1);
281}
282
283/*
284* DER encode a small INTEGER
285*/
286DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Type type_tag, ASN1_Class class_tag) {
287 return encode(BigInt::from_u64(n), type_tag, class_tag);
288}
289
290/*
291* DER encode an INTEGER
292*/
294 if(n == 0) {
295 return add_object(type_tag, class_tag, 0);
296 }
297
298 const size_t extra_zero = (n.bits() % 8 == 0) ? 1 : 0;
299 secure_vector<uint8_t> contents(extra_zero + n.bytes());
300 n.binary_encode(&contents[extra_zero]);
301 if(n < 0) {
302 for(unsigned char& content : contents) {
303 content = ~content;
304 }
305 for(size_t i = contents.size(); i > 0; --i) {
306 if(++contents[i - 1]) {
307 break;
308 }
309 }
310 }
311
312 return add_object(type_tag, class_tag, contents);
313}
314
315/*
316* DER encode an OCTET STRING or BIT STRING
317*/
319 const uint8_t bytes[], size_t length, ASN1_Type real_type, ASN1_Type type_tag, ASN1_Class class_tag) {
320 if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
321 throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
322 }
323
324 if(real_type == ASN1_Type::BitString) {
326 encoded.push_back(0);
327 encoded += std::make_pair(bytes, length);
328 return add_object(type_tag, class_tag, encoded);
329 } else {
330 return add_object(type_tag, class_tag, bytes, length);
331 }
332}
333
335 obj.encode_into(*this);
336 return (*this);
337}
338
339/*
340* Write the encoding of the byte(s)
341*/
342DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view rep_str) {
343 const uint8_t* rep = cast_char_ptr_to_uint8(rep_str.data());
344 const size_t rep_len = rep_str.size();
345 return add_object(type_tag, class_tag, rep, rep_len);
346}
347
348/*
349* Write the encoding of the byte
350*/
351DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t rep) {
352 return add_object(type_tag, class_tag, &rep, 1);
353}
354
355} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
virtual void encode_into(DER_Encoder &to) const =0
void binary_encode(uint8_t buf[]) const
Definition bigint.cpp:375
size_t bits() const
Definition bigint.cpp:290
static BigInt from_u64(uint64_t n)
Definition bigint.cpp:28
size_t bytes() const
Definition bigint.cpp:277
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
Definition der_enc.cpp:222
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:132
DER_Encoder & end_explicit()
Definition der_enc.cpp:200
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:186
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition der_enc.cpp:163
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition der_enc.cpp:207
DER_Encoder & encode_null()
Definition der_enc.cpp:243
DER_Encoder & end_cons()
Definition der_enc.cpp:171
std::vector< uint8_t > get_contents_unlocked()
Definition der_enc.cpp:146
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
DER_Encoder()=default
ASN1_Class
Definition asn1_obj.h:28
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:43
constexpr size_t high_bit(T n)
Definition bit_ops.h:58
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition loadstor.h:65
constexpr size_t significant_bytes(T n)
Definition bit_ops.h:80
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition mem_ops.h:275