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

randombit / botan / 6052601502

01 Sep 2023 03:07AM UTC coverage: 91.704% (-0.004%) from 91.708%
6052601502

push

github

web-flow
Merge pull request #3673 from falko-strenzke/refact-sha3

Refactoring SHA3: based on new permutation keccak-fips

78576 of 85684 relevant lines covered (91.7%)

8473544.9 hits per line

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

82.39
/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) {
332,751✔
25
   const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
332,751✔
26
   const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
332,751✔
27

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

32
   if(type_tag <= 30) {
332,751✔
33
      encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
331,647✔
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
      }
44
      encoded_tag.push_back(type_tag & 0x7F);
1,104✔
45
   }
46
}
332,751✔
47

48
/*
49
* DER encode an ASN.1 length field
50
*/
51
void encode_length(std::vector<uint8_t>& encoded_length, size_t length) {
332,751✔
52
   if(length <= 127) {
332,751✔
53
      encoded_length.push_back(static_cast<uint8_t>(length));
247,459✔
54
   } else {
55
      const size_t bytes_needed = significant_bytes(length);
85,292✔
56

57
      encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
85,292✔
58

59
      for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i) {
241,253✔
60
         encoded_length.push_back(get_byte_var(i, length));
155,961✔
61
      }
62
   }
63
}
332,751✔
64

65
}  // namespace
66

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

71
DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec) {
130,034✔
72
   m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
390,102✔
73
}
130,034✔
74

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

81
   if(m_type_tag == ASN1_Type::Set) {
178,763✔
82
      std::sort(m_set_contents.begin(), m_set_contents.end());
1,271✔
83
      for(const auto& set_elem : m_set_contents) {
2,542✔
84
         m_contents += set_elem;
1,271✔
85
      }
86
      m_set_contents.clear();
1,271✔
87
   }
88

89
   der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
178,763✔
90
   m_contents.clear();
178,763✔
91
}
178,763✔
92

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

104
void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len) {
198,403✔
105
   if(m_type_tag == ASN1_Type::Set) {
198,403✔
106
      secure_vector<uint8_t> m;
1,116✔
107
      m.reserve(hdr_len + val_len);
1,116✔
108
      m += std::make_pair(hdr, hdr_len);
1,116✔
109
      m += std::make_pair(val, val_len);
1,116✔
110
      m_set_contents.push_back(std::move(m));
1,116✔
111
   } else {
1,116✔
112
      m_contents += std::make_pair(hdr, hdr_len);
197,287✔
113
      m_contents += std::make_pair(val, val_len);
197,287✔
114
   }
115
}
198,403✔
116

117
/*
118
* Return the type and class taggings
119
*/
120
uint32_t DER_Encoder::DER_Sequence::tag_of() const {
×
121
   return m_type_tag | m_class_tag;
×
122
}
123

124
/*
125
* DER_Sequence Constructor
126
*/
127
DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type t1, ASN1_Class t2) : m_type_tag(t1), m_class_tag(t2) {}
178,763✔
128

129
/*
130
* Return the encoded contents
131
*/
132
secure_vector<uint8_t> DER_Encoder::get_contents() {
3,617✔
133
   if(!m_subsequences.empty()) {
3,617✔
134
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
135
   }
136

137
   if(m_append_output) {
3,617✔
138
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
139
   }
140

141
   secure_vector<uint8_t> output;
3,617✔
142
   std::swap(output, m_default_outbuf);
3,617✔
143
   return output;
3,617✔
144
}
145

146
std::vector<uint8_t> DER_Encoder::get_contents_unlocked() {
×
147
   if(!m_subsequences.empty()) {
×
148
      throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
×
149
   }
150

151
   if(m_append_output) {
×
152
      throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
×
153
   }
154

155
   std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
×
156
   m_default_outbuf.clear();
×
157
   return output;
×
158
}
159

160
/*
161
* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
162
*/
163
DER_Encoder& DER_Encoder::start_cons(ASN1_Type type_tag, ASN1_Class class_tag) {
178,763✔
164
   m_subsequences.push_back(DER_Sequence(type_tag, class_tag));
178,763✔
165
   return (*this);
178,763✔
166
}
167

168
/*
169
* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
170
*/
171
DER_Encoder& DER_Encoder::end_cons() {
178,763✔
172
   if(m_subsequences.empty()) {
178,763✔
173
      throw Invalid_State("DER_Encoder::end_cons: No such sequence");
×
174
   }
175

176
   DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
178,763✔
177
   m_subsequences.pop_back();
178,763✔
178
   last_seq.push_contents(*this);
178,763✔
179

180
   return (*this);
178,763✔
181
}
178,763✔
182

183
/*
184
* Start a new ASN.1 EXPLICIT encoding
185
*/
186
DER_Encoder& DER_Encoder::start_explicit(uint16_t type_no) {
718✔
187
   ASN1_Type type_tag = static_cast<ASN1_Type>(type_no);
718✔
188

189
   // This would confuse DER_Sequence
190
   if(type_tag == ASN1_Type::Set) {
718✔
191
      throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");
×
192
   }
193

194
   return start_cons(type_tag, ASN1_Class::ContextSpecific);
718✔
195
}
196

197
/*
198
* Finish the current ASN.1 EXPLICIT encoding
199
*/
200
DER_Encoder& DER_Encoder::end_explicit() {
718✔
201
   return end_cons();
718✔
202
}
203

204
/*
205
* Write raw bytes into the stream
206
*/
207
DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length) {
113,414✔
208
   if(!m_subsequences.empty()) {
113,414✔
209
      m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
113,414✔
210
   } else if(m_append_output) {
×
211
      m_append_output(bytes, length);
×
212
   } else {
213
      m_default_outbuf += std::make_pair(bytes, length);
×
214
   }
215

216
   return (*this);
113,414✔
217
}
218

219
/*
220
* Write the encoding of the byte(s)
221
*/
222
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length) {
332,751✔
223
   std::vector<uint8_t> hdr;
332,751✔
224
   encode_tag(hdr, type_tag, class_tag);
332,751✔
225
   encode_length(hdr, length);
332,751✔
226

227
   if(!m_subsequences.empty()) {
332,751✔
228
      m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
198,403✔
229
   } else if(m_append_output) {
134,348✔
230
      m_append_output(hdr.data(), hdr.size());
130,034✔
231
      m_append_output(rep, length);
260,068✔
232
   } else {
233
      m_default_outbuf += hdr;
4,314✔
234
      m_default_outbuf += std::make_pair(rep, length);
4,314✔
235
   }
236

237
   return (*this);
332,751✔
238
}
332,751✔
239

240
/*
241
* Encode a NULL object
242
*/
243
DER_Encoder& DER_Encoder::encode_null() {
×
244
   return add_object(ASN1_Type::Null, ASN1_Class::Universal, nullptr, 0);
×
245
}
246

247
/*
248
* DER encode a BOOLEAN
249
*/
250
DER_Encoder& DER_Encoder::encode(bool is_true) {
4,189✔
251
   return encode(is_true, ASN1_Type::Boolean, ASN1_Class::Universal);
4,189✔
252
}
253

254
/*
255
* DER encode a small INTEGER
256
*/
257
DER_Encoder& DER_Encoder::encode(size_t n) {
26,370✔
258
   return encode(BigInt::from_u64(n), ASN1_Type::Integer, ASN1_Class::Universal);
47,125✔
259
}
260

261
/*
262
* DER encode a small INTEGER
263
*/
264
DER_Encoder& DER_Encoder::encode(const BigInt& n) {
18,785✔
265
   return encode(n, ASN1_Type::Integer, ASN1_Class::Universal);
18,785✔
266
}
267

268
/*
269
* Encode this object
270
*/
271
DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length, ASN1_Type real_type) {
30,330✔
272
   return encode(bytes, length, real_type, real_type, ASN1_Class::Universal);
30,330✔
273
}
274

275
/*
276
* DER encode a BOOLEAN
277
*/
278
DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Type type_tag, ASN1_Class class_tag) {
4,189✔
279
   uint8_t val = is_true ? 0xFF : 0x00;
4,189✔
280
   return add_object(type_tag, class_tag, &val, 1);
4,189✔
281
}
282

283
/*
284
* DER encode a small INTEGER
285
*/
286
DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Type type_tag, ASN1_Class class_tag) {
23✔
287
   return encode(BigInt::from_u64(n), type_tag, class_tag);
46✔
288
}
289

290
/*
291
* DER encode an INTEGER
292
*/
293
DER_Encoder& DER_Encoder::encode(const BigInt& n, ASN1_Type type_tag, ASN1_Class class_tag) {
45,178✔
294
   if(n == 0) {
45,178✔
295
      return add_object(type_tag, class_tag, 0);
5,995✔
296
   }
297

298
   const size_t extra_zero = (n.bits() % 8 == 0) ? 1 : 0;
39,183✔
299
   secure_vector<uint8_t> contents(extra_zero + n.bytes());
39,183✔
300
   n.binary_encode(&contents[extra_zero]);
39,183✔
301
   if(n < 0) {
39,183✔
302
      for(unsigned char& content : contents) {
×
303
         content = ~content;
×
304
      }
305
      for(size_t i = contents.size(); i > 0; --i) {
×
306
         if(++contents[i - 1]) {
×
307
            break;
308
         }
309
      }
310
   }
311

312
   return add_object(type_tag, class_tag, contents);
39,183✔
313
}
45,178✔
314

315
/*
316
* DER encode an OCTET STRING or BIT STRING
317
*/
318
DER_Encoder& DER_Encoder::encode(
30,628✔
319
   const uint8_t bytes[], size_t length, ASN1_Type real_type, ASN1_Type type_tag, ASN1_Class class_tag) {
320
   if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
30,628✔
321
      throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
×
322
   }
323

324
   if(real_type == ASN1_Type::BitString) {
30,628✔
325
      secure_vector<uint8_t> encoded;
19,254✔
326
      encoded.push_back(0);
19,254✔
327
      encoded += std::make_pair(bytes, length);
19,254✔
328
      return add_object(type_tag, class_tag, encoded);
19,254✔
329
   } else {
19,254✔
330
      return add_object(type_tag, class_tag, bytes, length);
11,374✔
331
   }
332
}
333

334
DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) {
82,554✔
335
   obj.encode_into(*this);
82,554✔
336
   return (*this);
82,554✔
337
}
338

339
/*
340
* Write the encoding of the byte(s)
341
*/
342
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view rep_str) {
4,464✔
343
   const uint8_t* rep = cast_char_ptr_to_uint8(rep_str.data());
4,464✔
344
   const size_t rep_len = rep_str.size();
4,464✔
345
   return add_object(type_tag, class_tag, rep, rep_len);
4,464✔
346
}
347

348
/*
349
* Write the encoding of the byte
350
*/
351
DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t rep) {
5,995✔
352
   return add_object(type_tag, class_tag, &rep, 1);
5,995✔
353
}
354

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

© 2025 Coveralls, Inc