Coverage Report

Created: 2020-06-30 13:58

/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
}