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
16namespace Botan {
17
18namespace {
19
20/*
21* DER encode an ASN.1 type tag
22*/
23SecureVector<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*/
49SecureVector<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*/
71SecureVector<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*/
95void 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*/
106ASN1_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*/
114DER_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*/
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*/
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*/
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*/
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*/
173 {
174 return end_cons();
175 }
176
177/*
178* Write raw bytes into the stream
179*/
181 {
182 return raw_bytes(&val[0], val.size());
183 }
184
185/*
186* Write raw bytes into the stream
187*/
188DER_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*/
205
206/*
207* DER encode a BOOLEAN
208*/
210 {
211 return encode(is_true, BOOLEAN, UNIVERSAL);
212 }
213
214/*
215* DER encode a small INTEGER
216*/
218 {
219 return encode(BigInt(n), INTEGER, UNIVERSAL);
220 }
221
222/*
223* DER encode a small INTEGER
224*/
226 {
227 return encode(n, INTEGER, UNIVERSAL);
228 }
229
230/*
231* DER encode an OCTET STRING or BIT STRING
232*/
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*/
243DER_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*/
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*/
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*/
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*/
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*/
306DER_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*/
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*/
338 {
339 obj.encode_into(*this);
340 return (*this);
341 }
342
343/*
344* Write the encoding of the byte(s)
345*/
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*/
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*/
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*/
383 ASN1_Tag class_tag, byte rep)
384 {
385 return add_object(type_tag, class_tag, &rep, 1);
386 }
387
388}
virtual void encode_into(class DER_Encoder &to) const =0
static SecureVector< byte > encode(const BigInt &n, Base base=Binary)
Definition big_code.cpp:64
size_t bits() const
Definition bigint.cpp:254
size_t bytes() const
Definition bigint.cpp:246
DER_Encoder & end_explicit()
Definition der_enc.cpp:172
DER_Encoder & start_explicit(u16bit type_tag)
Definition der_enc.cpp:159
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const byte rep[], size_t length)
Definition der_enc.cpp:346
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition der_enc.cpp:135
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition der_enc.cpp:188
DER_Encoder & encode_if(bool pred, DER_Encoder &enc)
Definition der_enc.cpp:327
DER_Encoder & encode_null()
Definition der_enc.cpp:201
SecureVector< byte > get_contents()
Definition der_enc.cpp:122
DER_Encoder & end_cons()
Definition der_enc.cpp:145
DER_Encoder & encode(bool b)
Definition der_enc.cpp:209
size_t size() const
Definition secmem.h:29
void push_back(T x)
Definition secmem.h:149
byte get_byte(size_t byte_num, T input)
Definition get_byte.h:21
std::string to_string(u64bit n, size_t min_len)
Definition parsing.cpp:42
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
ASN1_Tag
Definition asn1_int.h:19
@ CONSTRUCTED
Definition asn1_int.h:25
@ BIT_STRING
Definition asn1_int.h:30
@ BOOLEAN
Definition asn1_int.h:28
@ CONTEXT_SPECIFIC
Definition asn1_int.h:22
@ OCTET_STRING
Definition asn1_int.h:31
@ NULL_TAG
Definition asn1_int.h:32
@ UNIVERSAL
Definition asn1_int.h:20
@ SET
Definition asn1_int.h:36
@ INTEGER
Definition asn1_int.h:29
unsigned short u16bit
Definition types.h:27
size_t significant_bytes(T n)
Definition bit_ops.h:62
size_t high_bit(T n)
Definition bit_ops.h:33
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition secmem.h:438
Encoding_Error(const std::string &name)
Definition exceptn.h:131