Botan: src/asn1/der_enc.cpp Source File

Botan 1.10.17

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