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