Coverage Report

Created: 2025-04-11 06:34

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