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