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