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

randombit / botan / 5112587681

29 May 2023 01:55PM UTC coverage: 92.211% (-0.01%) from 92.221%
5112587681

push

github

randombit
Merge GH #3560 Update CI builder to use the macOS 13 image

75573 of 81957 relevant lines covered (92.21%)

12015603.28 hits per line

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

83.12
/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/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
void encode_tag(std::vector<uint8_t>& encoded_tag, ASN1_Type type_tag_e, ASN1_Class class_tag_e) {
299,109✔
25
   const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
299,109✔
26
   const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
299,109✔
27

28
   if((class_tag | 0xE0) != 0xE0) {
299,109✔
29
      throw Encoding_Error(fmt("DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
×
30
   }
31

32
   if(type_tag <= 30) {
299,109✔
33
      encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
298,005✔
34
   } else {
35
      size_t blocks = high_bit(static_cast<uint32_t>(type_tag)) + 6;
1,104✔
36
      blocks = (blocks - (blocks % 7)) / 7;
1,104✔
37

38
      BOTAN_ASSERT_NOMSG(blocks > 0);
1,104✔
39

40
      encoded_tag.push_back(static_cast<uint8_t>(class_tag | 0x1F));
1,104✔
41
      for(size_t i = 0; i != blocks - 1; ++i)
2,263✔
42
         encoded_tag.push_back(0x80 | ((type_tag >> 7 * (blocks - i - 1)) & 0x7F));
1,159✔
43
      encoded_tag.push_back(type_tag & 0x7F);
1,104✔
44
   }
45
}
299,109✔
46

47
/*
48
* DER encode an ASN.1 length field
49
*/
50
void encode_length(std::vector<uint8_t>& encoded_length, size_t length) {
299,109✔
51
   if(length <= 127) {
299,109✔
52
      encoded_length.push_back(static_cast<uint8_t>(length));
216,839✔
53
   } else {
54
      const size_t bytes_needed = significant_bytes(length);
82,270✔
55

56
      encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
82,270✔
57

58
      for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i)
232,497✔
59
         encoded_length.push_back(get_byte_var(i, length));
150,227✔
60
   }
61
}
299,109✔
62

63
}  // namespace
64

65
DER_Encoder::DER_Encoder(secure_vector<uint8_t>& vec) {
×
66
   m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
×
67
}
×
68

69
DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec) {
121,491✔
70
   m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
364,473✔
71
}
121,491✔
72

73
/*
74
* Push the encoded SEQUENCE/SET to the encoder stream
75
*/
76
void DER_Encoder::DER_Sequence::push_contents(DER_Encoder& der) {
157,981✔
77
   const auto real_class_tag = m_class_tag | ASN1_Class::Constructed;
157,981✔
78

79
   if(m_type_tag == ASN1_Type::Set) {
157,981✔
80
      std::sort(m_set_contents.begin(), m_set_contents.end());
1,267✔
81
      for(const auto& set_elem : m_set_contents)
2,534✔
82
         m_contents += set_elem;
1,267✔
83
      m_set_contents.clear();
1,267✔
84
   }
85

86
   der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
157,981✔
87
   m_contents.clear();
157,981✔
88
}
157,981✔
89

90
/*
91
* Add an encoded value to the SEQUENCE/SET
92
*/
93
void DER_Encoder::DER_Sequence::add_bytes(const uint8_t data[], size_t length) {
103,077✔
94
   if(m_type_tag == ASN1_Type::Set)
103,077✔
95
      m_set_contents.push_back(secure_vector<uint8_t>(data, data + length));
308✔
96
   else
97
      m_contents += std::make_pair(data, length);
102,923✔
98
}
103,077✔
99

100
void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len) {
173,467✔
101
   if(m_type_tag == ASN1_Type::Set) {
173,467✔
102
      secure_vector<uint8_t> m;
1,113✔
103
      m.reserve(hdr_len + val_len);
1,113✔
104
      m += std::make_pair(hdr, hdr_len);
1,113✔
105
      m += std::make_pair(val, val_len);
1,113✔
106
      m_set_contents.push_back(std::move(m));
1,113✔
107
   } else {
1,113✔
108
      m_contents += std::make_pair(hdr, hdr_len);
172,354✔
109
      m_contents += std::make_pair(val, val_len);
172,354✔
110
   }
111
}
173,467✔
112

113
/*
114
* Return the type and class taggings
115
*/
116
uint32_t DER_Encoder::DER_Sequence::tag_of() const { return m_type_tag | m_class_tag; }
×
117

118
/*
119
* DER_Sequence Constructor
120
*/
121
DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type t1, ASN1_Class t2) : m_type_tag(t1), m_class_tag(t2) {}
157,981✔
122

123
/*
124
* Return the encoded contents
125
*/
126
secure_vector<uint8_t> DER_Encoder::get_contents() {
3,457✔
127
   if(!m_subsequences.empty())
3,457✔
128
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
129

130
   if(m_append_output)
3,457✔
131
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
132

133
   secure_vector<uint8_t> output;
3,457✔
134
   std::swap(output, m_default_outbuf);
3,457✔
135
   return output;
3,457✔
136
}
137

138
std::vector<uint8_t> DER_Encoder::get_contents_unlocked() {
×
139
   if(!m_subsequences.empty())
×
140
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
141

142
   if(m_append_output)
×
143
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
144

145
   std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
×
146
   m_default_outbuf.clear();
×
147
   return output;
×
148
}
149

150
/*
151
* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
152
*/
153
DER_Encoder& DER_Encoder::start_cons(ASN1_Type type_tag, ASN1_Class class_tag) {
157,981✔
154
   m_subsequences.push_back(DER_Sequence(type_tag, class_tag));
157,981✔
155
   return (*this);
157,981✔
156
}
157

158
/*
159
* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
160
*/
161
DER_Encoder& DER_Encoder::end_cons() {
157,981✔
162
   if(m_subsequences.empty())
157,981✔
163
      throw Invalid_State("DER_Encoder::end_cons: No such sequence");
×
164

165
   DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
157,981✔
166
   m_subsequences.pop_back();
157,981✔
167
   last_seq.push_contents(*this);
157,981✔
168

169
   return (*this);
157,981✔
170
}
157,981✔
171

172
/*
173
* Start a new ASN.1 EXPLICIT encoding
174
*/
175
DER_Encoder& DER_Encoder::start_explicit(uint16_t type_no) {
713✔
176
   ASN1_Type type_tag = static_cast<ASN1_Type>(type_no);
713✔
177

178
   // This would confuse DER_Sequence
179
   if(type_tag == ASN1_Type::Set)
713✔
180
      throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");
×
181

182
   return start_cons(type_tag, ASN1_Class::ContextSpecific);
713✔
183
}
184

185
/*
186
* Finish the current ASN.1 EXPLICIT encoding
187
*/
188
DER_Encoder& DER_Encoder::end_explicit() { return end_cons(); }
713✔
189

190
/*
191
* Write raw bytes into the stream
192
*/
193
DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length) {
103,077✔
194
   if(!m_subsequences.empty()) {
103,077✔
195
      m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
103,077✔
196
   } else if(m_append_output) {
×
197
      m_append_output(bytes, length);
×
198
   } else {
199
      m_default_outbuf += std::make_pair(bytes, length);
×
200
   }
201

202
   return (*this);
103,077✔
203
}
204

205
/*
206
* Write the encoding of the byte(s)
207
*/
208
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length) {
299,109✔
209
   std::vector<uint8_t> hdr;
299,109✔
210
   encode_tag(hdr, type_tag, class_tag);
299,109✔
211
   encode_length(hdr, length);
299,109✔
212

213
   if(!m_subsequences.empty()) {
299,109✔
214
      m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
173,467✔
215
   } else if(m_append_output) {
125,642✔
216
      m_append_output(hdr.data(), hdr.size());
121,491✔
217
      m_append_output(rep, length);
242,982✔
218
   } else {
219
      m_default_outbuf += hdr;
4,151✔
220
      m_default_outbuf += std::make_pair(rep, length);
4,151✔
221
   }
222

223
   return (*this);
299,109✔
224
}
299,109✔
225

226
/*
227
* Encode a NULL object
228
*/
229
DER_Encoder& DER_Encoder::encode_null() { return add_object(ASN1_Type::Null, ASN1_Class::Universal, nullptr, 0); }
×
230

231
/*
232
* DER encode a BOOLEAN
233
*/
234
DER_Encoder& DER_Encoder::encode(bool is_true) { return encode(is_true, ASN1_Type::Boolean, ASN1_Class::Universal); }
4,182✔
235

236
/*
237
* DER encode a small INTEGER
238
*/
239
DER_Encoder& DER_Encoder::encode(size_t n) {
22,492✔
240
   return encode(BigInt::from_u64(n), ASN1_Type::Integer, ASN1_Class::Universal);
39,529✔
241
}
242

243
/*
244
* DER encode a small INTEGER
245
*/
246
DER_Encoder& DER_Encoder::encode(const BigInt& n) { return encode(n, ASN1_Type::Integer, ASN1_Class::Universal); }
17,994✔
247

248
/*
249
* Encode this object
250
*/
251
DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length, ASN1_Type real_type) {
29,120✔
252
   return encode(bytes, length, real_type, real_type, ASN1_Class::Universal);
29,120✔
253
}
254

255
/*
256
* DER encode a BOOLEAN
257
*/
258
DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Type type_tag, ASN1_Class class_tag) {
4,182✔
259
   uint8_t val = is_true ? 0xFF : 0x00;
4,182✔
260
   return add_object(type_tag, class_tag, &val, 1);
4,182✔
261
}
262

263
/*
264
* DER encode a small INTEGER
265
*/
266
DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Type type_tag, ASN1_Class class_tag) {
23✔
267
   return encode(BigInt::from_u64(n), type_tag, class_tag);
46✔
268
}
269

270
/*
271
* DER encode an INTEGER
272
*/
273
DER_Encoder& DER_Encoder::encode(const BigInt& n, ASN1_Type type_tag, ASN1_Class class_tag) {
40,509✔
274
   if(n == 0)
40,509✔
275
      return add_object(type_tag, class_tag, 0);
5,835✔
276

277
   const size_t extra_zero = (n.bits() % 8 == 0) ? 1 : 0;
34,674✔
278
   secure_vector<uint8_t> contents(extra_zero + n.bytes());
34,674✔
279
   n.binary_encode(&contents[extra_zero]);
34,674✔
280
   if(n < 0) {
34,674✔
281
      for(unsigned char& content : contents)
×
282
         content = ~content;
×
283
      for(size_t i = contents.size(); i > 0; --i)
×
284
         if(++contents[i - 1])
×
285
            break;
286
   }
287

288
   return add_object(type_tag, class_tag, contents);
34,674✔
289
}
40,509✔
290

291
/*
292
* DER encode an OCTET STRING or BIT STRING
293
*/
294
DER_Encoder& DER_Encoder::encode(
29,416✔
295
   const uint8_t bytes[], size_t length, ASN1_Type real_type, ASN1_Type type_tag, ASN1_Class class_tag) {
296
   if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString)
29,416✔
297
      throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
×
298

299
   if(real_type == ASN1_Type::BitString) {
29,416✔
300
      secure_vector<uint8_t> encoded;
18,437✔
301
      encoded.push_back(0);
18,437✔
302
      encoded += std::make_pair(bytes, length);
18,437✔
303
      return add_object(type_tag, class_tag, encoded);
18,437✔
304
   } else
18,437✔
305
      return add_object(type_tag, class_tag, bytes, length);
10,979✔
306
}
307

308
DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) {
69,565✔
309
   obj.encode_into(*this);
69,565✔
310
   return (*this);
69,565✔
311
}
312

313
/*
314
* Write the encoding of the byte(s)
315
*/
316
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view rep_str) {
4,457✔
317
   const uint8_t* rep = cast_char_ptr_to_uint8(rep_str.data());
4,457✔
318
   const size_t rep_len = rep_str.size();
4,457✔
319
   return add_object(type_tag, class_tag, rep, rep_len);
4,457✔
320
}
321

322
/*
323
* Write the encoding of the byte
324
*/
325
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t rep) {
5,835✔
326
   return add_object(type_tag, class_tag, &rep, 1);
5,835✔
327
}
328

329
}  // namespace Botan
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

© 2026 Coveralls, Inc