Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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