• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 4818131743

27 Apr 2023 09:55AM UTC coverage: 92.146%. Remained the same
4818131743

push

github

77594 of 84208 relevant lines covered (92.15%)

11896883.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.82
/src/lib/asn1/der_enc.cpp
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/loadstor.h>
13
#include <botan/internal/bit_ops.h>
14
#include <botan/internal/fmt.h>
15
#include <algorithm>
16

17
namespace Botan {
18

19
namespace {
20

21
/*
22
* DER encode an ASN.1 type tag
23
*/
24
void encode_tag(std::vector<uint8_t>& encoded_tag,
296,757✔
25
                ASN1_Type type_tag_e, ASN1_Class class_tag_e)
26
   {
27
   const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
296,757✔
28
   const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
296,757✔
29

30
   if((class_tag | 0xE0) != 0xE0)
296,757✔
31
      {
32
      throw Encoding_Error(fmt("DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
×
33
      }
34

35
   if(type_tag <= 30)
296,757✔
36
      {
37
      encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
295,653✔
38
      }
39
   else
40
      {
41
      size_t blocks = high_bit(static_cast<uint32_t>(type_tag)) + 6;
1,104✔
42
      blocks = (blocks - (blocks % 7)) / 7;
1,104✔
43

44
      BOTAN_ASSERT_NOMSG(blocks > 0);
1,104✔
45

46
      encoded_tag.push_back(static_cast<uint8_t>(class_tag | 0x1F));
1,104✔
47
      for(size_t i = 0; i != blocks - 1; ++i)
2,263✔
48
         encoded_tag.push_back(0x80 | ((type_tag >> 7*(blocks-i-1)) & 0x7F));
1,159✔
49
      encoded_tag.push_back(type_tag & 0x7F);
1,104✔
50
      }
51
   }
296,757✔
52

53
/*
54
* DER encode an ASN.1 length field
55
*/
56
void encode_length(std::vector<uint8_t>& encoded_length, size_t length)
296,757✔
57
   {
58
   if(length <= 127)
296,757✔
59
      {
60
      encoded_length.push_back(static_cast<uint8_t>(length));
215,678✔
61
      }
62
   else
63
      {
64
      const size_t bytes_needed = significant_bytes(length);
81,079✔
65

66
      encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
81,079✔
67

68
      for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i)
229,039✔
69
         encoded_length.push_back(get_byte_var(i, length));
147,960✔
70
      }
71
   }
296,757✔
72

73
}
74

75
DER_Encoder::DER_Encoder(secure_vector<uint8_t>& vec)
×
76
   {
77
   m_append_output = [&vec](const uint8_t b[], size_t l)
×
78
      {
79
      vec.insert(vec.end(), b, b + l);
×
80
      };
×
81
   }
×
82

83
DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec)
120,249✔
84
   {
85
   m_append_output = [&vec](const uint8_t b[], size_t l)
360,747✔
86
      {
87
      vec.insert(vec.end(), b, b + l);
240,498✔
88
      };
120,249✔
89
   }
120,249✔
90

91
/*
92
* Push the encoded SEQUENCE/SET to the encoder stream
93
*/
94
void DER_Encoder::DER_Sequence::push_contents(DER_Encoder& der)
156,234✔
95
   {
96
   const auto real_class_tag = m_class_tag | ASN1_Class::Constructed;
156,234✔
97

98
   if(m_type_tag == ASN1_Type::Set)
156,234✔
99
      {
100
      std::sort(m_set_contents.begin(), m_set_contents.end());
1,267✔
101
      for(const auto& set_elem : m_set_contents)
2,534✔
102
         m_contents += set_elem;
1,267✔
103
      m_set_contents.clear();
1,267✔
104
      }
105

106
   der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
156,234✔
107
   m_contents.clear();
156,234✔
108
   }
156,234✔
109

110
/*
111
* Add an encoded value to the SEQUENCE/SET
112
*/
113
void DER_Encoder::DER_Sequence::add_bytes(const uint8_t data[], size_t length)
101,640✔
114
   {
115
   if(m_type_tag == ASN1_Type::Set)
101,640✔
116
      m_set_contents.push_back(secure_vector<uint8_t>(data, data + length));
308✔
117
   else
118
      m_contents += std::make_pair(data, length);
101,486✔
119
   }
101,640✔
120

121
void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len,
172,356✔
122
                                          const uint8_t val[], size_t val_len)
123
   {
124
   if(m_type_tag == ASN1_Type::Set)
172,356✔
125
      {
126
      secure_vector<uint8_t> m;
1,113✔
127
      m.reserve(hdr_len + val_len);
1,113✔
128
      m += std::make_pair(hdr, hdr_len);
1,113✔
129
      m += std::make_pair(val, val_len);
1,113✔
130
      m_set_contents.push_back(std::move(m));
1,113✔
131
      }
1,113✔
132
   else
133
      {
134
      m_contents += std::make_pair(hdr, hdr_len);
171,243✔
135
      m_contents += std::make_pair(val, val_len);
171,243✔
136
      }
137
   }
172,356✔
138

139
/*
140
* Return the type and class taggings
141
*/
142
uint32_t DER_Encoder::DER_Sequence::tag_of() const
×
143
   {
144
   return m_type_tag | m_class_tag;
×
145
   }
146

147
/*
148
* DER_Sequence Constructor
149
*/
150
DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type t1, ASN1_Class t2) :
156,234✔
151
   m_type_tag(t1), m_class_tag(t2)
156,234✔
152
   {
153
   }
156,234✔
154

155
/*
156
* Return the encoded contents
157
*/
158
secure_vector<uint8_t> DER_Encoder::get_contents()
3,458✔
159
   {
160
   if(!m_subsequences.empty())
3,458✔
161
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
162

163
   if(m_append_output)
3,458✔
164
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
165

166
   secure_vector<uint8_t> output;
3,458✔
167
   std::swap(output, m_default_outbuf);
3,458✔
168
   return output;
3,458✔
169
   }
170

171
std::vector<uint8_t> DER_Encoder::get_contents_unlocked()
×
172
   {
173
   if(!m_subsequences.empty())
×
174
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
175

176
   if(m_append_output)
×
177
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
178

179
   std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
×
180
   m_default_outbuf.clear();
×
181
   return output;
×
182
   }
183

184
/*
185
* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
186
*/
187
DER_Encoder& DER_Encoder::start_cons(ASN1_Type type_tag,
156,234✔
188
                                     ASN1_Class class_tag)
189
   {
190
   m_subsequences.push_back(DER_Sequence(type_tag, class_tag));
156,234✔
191
   return (*this);
156,234✔
192
   }
193

194
/*
195
* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
196
*/
197
DER_Encoder& DER_Encoder::end_cons()
156,234✔
198
   {
199
   if(m_subsequences.empty())
156,234✔
200
      throw Invalid_State("DER_Encoder::end_cons: No such sequence");
×
201

202
   DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size()-1]);
156,234✔
203
   m_subsequences.pop_back();
156,234✔
204
   last_seq.push_contents(*this);
156,234✔
205

206
   return (*this);
156,234✔
207
   }
156,234✔
208

209
/*
210
* Start a new ASN.1 EXPLICIT encoding
211
*/
212
DER_Encoder& DER_Encoder::start_explicit(uint16_t type_no)
713✔
213
   {
214
   ASN1_Type type_tag = static_cast<ASN1_Type>(type_no);
713✔
215

216
   // This would confuse DER_Sequence
217
   if(type_tag == ASN1_Type::Set)
713✔
218
      throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");
×
219

220
   return start_cons(type_tag, ASN1_Class::ContextSpecific);
713✔
221
   }
222

223
/*
224
* Finish the current ASN.1 EXPLICIT encoding
225
*/
226
DER_Encoder& DER_Encoder::end_explicit()
713✔
227
   {
228
   return end_cons();
713✔
229
   }
230

231
/*
232
* Write raw bytes into the stream
233
*/
234
DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length)
101,640✔
235
   {
236
   if(!m_subsequences.empty())
101,640✔
237
      {
238
      m_subsequences[m_subsequences.size()-1].add_bytes(bytes, length);
101,640✔
239
      }
240
   else if(m_append_output)
×
241
      {
242
      m_append_output(bytes, length);
×
243
      }
244
   else
245
      {
246
      m_default_outbuf += std::make_pair(bytes, length);
×
247
      }
248

249
   return (*this);
101,640✔
250
   }
251

252
/*
253
* Write the encoding of the byte(s)
254
*/
255
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag,
296,757✔
256
                                     const uint8_t rep[], size_t length)
257
   {
258
   std::vector<uint8_t> hdr;
296,757✔
259
   encode_tag(hdr, type_tag, class_tag);
296,757✔
260
   encode_length(hdr, length);
296,757✔
261

262
   if(!m_subsequences.empty())
296,757✔
263
      {
264
      m_subsequences[m_subsequences.size()-1].add_bytes(hdr.data(), hdr.size(), rep, length);
172,356✔
265
      }
266
   else if(m_append_output)
124,401✔
267
      {
268
      m_append_output(hdr.data(), hdr.size());
120,249✔
269
      m_append_output(rep, length);
240,498✔
270
      }
271
   else
272
      {
273
      m_default_outbuf += hdr;
4,152✔
274
      m_default_outbuf += std::make_pair(rep, length);
4,152✔
275
      }
276

277
   return (*this);
296,757✔
278
   }
296,757✔
279

280
/*
281
* Encode a NULL object
282
*/
283
DER_Encoder& DER_Encoder::encode_null()
×
284
   {
285
   return add_object(ASN1_Type::Null, ASN1_Class::Universal, nullptr, 0);
×
286
   }
287

288
/*
289
* DER encode a BOOLEAN
290
*/
291
DER_Encoder& DER_Encoder::encode(bool is_true)
4,185✔
292
   {
293
   return encode(is_true, ASN1_Type::Boolean, ASN1_Class::Universal);
4,185✔
294
   }
295

296
/*
297
* DER encode a small INTEGER
298
*/
299
DER_Encoder& DER_Encoder::encode(size_t n)
22,497✔
300
   {
301
   return encode(BigInt::from_u64(n), ASN1_Type::Integer, ASN1_Class::Universal);
39,535✔
302
   }
303

304
/*
305
* DER encode a small INTEGER
306
*/
307
DER_Encoder& DER_Encoder::encode(const BigInt& n)
17,892✔
308
   {
309
   return encode(n, ASN1_Type::Integer, ASN1_Class::Universal);
17,892✔
310
   }
311

312
/*
313
* Encode this object
314
*/
315
DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length,
28,863✔
316
                                 ASN1_Type real_type)
317
   {
318
   return encode(bytes, length, real_type, real_type, ASN1_Class::Universal);
28,863✔
319
   }
320

321
/*
322
* DER encode a BOOLEAN
323
*/
324
DER_Encoder& DER_Encoder::encode(bool is_true,
4,185✔
325
                                 ASN1_Type type_tag, ASN1_Class class_tag)
326
   {
327
   uint8_t val = is_true ? 0xFF : 0x00;
4,185✔
328
   return add_object(type_tag, class_tag, &val, 1);
4,185✔
329
   }
330

331
/*
332
* DER encode a small INTEGER
333
*/
334
DER_Encoder& DER_Encoder::encode(size_t n,
23✔
335
                                 ASN1_Type type_tag, ASN1_Class class_tag)
336
   {
337
   return encode(BigInt::from_u64(n), type_tag, class_tag);
46✔
338
   }
339

340
/*
341
* DER encode an INTEGER
342
*/
343
DER_Encoder& DER_Encoder::encode(const BigInt& n,
40,412✔
344
                                 ASN1_Type type_tag, ASN1_Class class_tag)
345
   {
346
   if(n == 0)
40,412✔
347
      return add_object(type_tag, class_tag, 0);
5,839✔
348

349
   const size_t extra_zero = (n.bits() % 8 == 0) ? 1 : 0;
34,573✔
350
   secure_vector<uint8_t> contents(extra_zero + n.bytes());
34,573✔
351
   n.binary_encode(&contents[extra_zero]);
34,573✔
352
   if(n < 0)
34,573✔
353
      {
354
      for(unsigned char & content : contents)
×
355
         content = ~content;
×
356
      for(size_t i = contents.size(); i > 0; --i)
×
357
         if(++contents[i-1])
×
358
            break;
359
      }
360

361
   return add_object(type_tag, class_tag, contents);
34,573✔
362
   }
40,412✔
363

364
/*
365
* DER encode an OCTET STRING or BIT STRING
366
*/
367
DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length,
29,159✔
368
                                 ASN1_Type real_type,
369
                                 ASN1_Type type_tag, ASN1_Class class_tag)
370
   {
371
   if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString)
29,159✔
372
      throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
×
373

374
   if(real_type == ASN1_Type::BitString)
29,159✔
375
      {
376
      secure_vector<uint8_t> encoded;
18,191✔
377
      encoded.push_back(0);
18,191✔
378
      encoded += std::make_pair(bytes, length);
18,191✔
379
      return add_object(type_tag, class_tag, encoded);
18,191✔
380
      }
18,191✔
381
   else
382
      return add_object(type_tag, class_tag, bytes, length);
10,968✔
383
   }
384

385
DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj)
69,058✔
386
   {
387
   obj.encode_into(*this);
69,058✔
388
   return (*this);
69,058✔
389
   }
390

391
/*
392
* Write the encoding of the byte(s)
393
*/
394
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag,
4,459✔
395
                                     std::string_view rep_str)
396
   {
397
   const uint8_t* rep = cast_char_ptr_to_uint8(rep_str.data());
4,459✔
398
   const size_t rep_len = rep_str.size();
4,459✔
399
   return add_object(type_tag, class_tag, rep, rep_len);
4,459✔
400
   }
401

402
/*
403
* Write the encoding of the byte
404
*/
405
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag,
5,839✔
406
                                     ASN1_Class class_tag, uint8_t rep)
407
   {
408
   return add_object(type_tag, class_tag, &rep, 1);
5,839✔
409
   }
410

411
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc