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