monotone

monotone Mtn Source Tree

Root/botan/der_enc.cpp

1/*************************************************
2* DER Encoder Source File *
3* (C) 1999-2005 The Botan Project *
4*************************************************/
5
6#include <botan/der_enc.h>
7#include <botan/bigint.h>
8#include <botan/bit_ops.h>
9#include <botan/parsing.h>
10
11namespace Botan {
12
13namespace {
14
15/*************************************************
16* DER encode an ASN.1 type tag *
17*************************************************/
18SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag)
19 {
20 if((class_tag | 0xE0) != 0xE0)
21 throw Encoding_Error("DER_Encoder: Invalid class tag " +
22 to_string(class_tag));
23
24 SecureVector<byte> encoded_tag;
25 if(type_tag <= 30)
26 encoded_tag.append((byte)(type_tag | class_tag));
27 else
28 {
29 u32bit blocks = high_bit(type_tag) + 6;
30 blocks = (blocks - (blocks % 7)) / 7;
31
32 encoded_tag.append(class_tag | 0x1F);
33 for(u32bit k = 0; k != blocks - 1; k++)
34 encoded_tag.append(0x80 | ((type_tag >> 7*(blocks-k-1)) & 0x7F));
35 encoded_tag.append(type_tag & 0x7F);
36 }
37
38 return encoded_tag;
39 }
40
41/*************************************************
42* DER encode an ASN.1 length field *
43*************************************************/
44SecureVector<byte> encode_length(u32bit length)
45 {
46 SecureVector<byte> encoded_length;
47 if(length <= 127)
48 encoded_length.append((byte)length);
49 else
50 {
51 const u32bit top_byte = significant_bytes(length);
52 encoded_length.append((byte)(0x80 | top_byte));
53 for(u32bit j = 4-top_byte; j != 4; j++)
54 encoded_length.append(get_byte(j, length));
55 }
56 return encoded_length;
57 }
58
59/*************************************************
60* A comparison functor for sorting SET objects *
61*************************************************/
62class DER_Cmp
63 {
64 public:
65 bool operator()(const MemoryRegion<byte>&,
66 const MemoryRegion<byte>&) const;
67 };
68
69/*************************************************
70* Compare two encodings, as specified by X.690 *
71*************************************************/
72bool DER_Cmp::operator()(const MemoryRegion<byte>& a,
73 const MemoryRegion<byte>& b) const
74 {
75 if(a.size() < b.size()) return true;
76 if(a.size() > b.size()) return false;
77
78 for(u32bit j = 0; j != a.size(); j++)
79 {
80 if(a[j] < b[j]) return true;
81 if(a[j] > b[j]) return false;
82 }
83 return false;
84 }
85
86}
87
88/*************************************************
89* Return the encoded SEQUENCE/SET *
90*************************************************/
91SecureVector<byte> DER_Encoder::DER_Sequence::get_contents()
92 {
93 const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED);
94
95 SecureVector<byte> encoded_tag = encode_tag(type_tag, real_class_tag);
96
97 if(is_a_set)
98 {
99 std::sort(set_contents.begin(), set_contents.end(), DER_Cmp());
100 for(u32bit j = 0; j != set_contents.size(); j++)
101 contents.append(set_contents[j]);
102 set_contents.clear();
103 }
104
105 SecureVector<byte> encoded_length = encode_length(contents.size());
106
107 SecureVector<byte> retval;
108 retval.append(encoded_tag);
109 retval.append(encoded_length);
110 retval.append(contents);
111 contents.destroy();
112 return retval;
113 }
114
115/*************************************************
116* Add an encoded value to the SEQUENCE/SET *
117*************************************************/
118void DER_Encoder::DER_Sequence::add_bytes(const byte data[], u32bit length)
119 {
120 if(is_a_set)
121 {
122 set_contents.push_back(SecureVector<byte>(data, length));
123 }
124 else
125 contents.append(data, length);
126 }
127
128/*************************************************
129* Return the type and class taggings *
130*************************************************/
131ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const
132 {
133 return ASN1_Tag(type_tag | class_tag);
134 }
135
136/*************************************************
137* DER_Sequence Constructor *
138*************************************************/
139DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2, bool b) :
140 type_tag(t1), class_tag(t2), is_a_set(b)
141 {
142 }
143
144/*************************************************
145* Return the encoded contents *
146*************************************************/
147SecureVector<byte> DER_Encoder::get_contents()
148 {
149 if(sequence_level != 0)
150 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
151
152 SecureVector<byte> retval;
153 retval = contents;
154 contents.destroy();
155 return retval;
156 }
157
158/*************************************************
159* Start a new ASN.1 SEQUENCE/SET/EXPLICIT *
160*************************************************/
161void DER_Encoder::start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag,
162 bool is_a_set)
163 {
164 sequence_level++;
165 subsequences.push_back(DER_Sequence(type_tag, class_tag, is_a_set));
166 }
167
168/*************************************************
169* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT *
170*************************************************/
171void DER_Encoder::end_cons(ASN1_Tag type_tag, ASN1_Tag class_tag)
172 {
173 if(sequence_level == 0)
174 throw Invalid_State("DER_Encoder::end_cons: No such sequence");
175 sequence_level--;
176 if(subsequences[sequence_level].tag_of() != ASN1_Tag(type_tag | class_tag))
177 throw Invalid_Argument("DER_Encoder::end_cons: Tag mismatch");
178
179 SecureVector<byte> seq = subsequences[sequence_level].get_contents();
180 subsequences.pop_back();
181 add_raw_octets(seq);
182 }
183
184/*************************************************
185* Start a new ASN.1 SEQUENCE *
186*************************************************/
187void DER_Encoder::start_sequence(ASN1_Tag type_tag, ASN1_Tag class_tag)
188 {
189 start_cons(type_tag, class_tag, false);
190 }
191
192/*************************************************
193* Finish the current ASN.1 SEQUENCE *
194*************************************************/
195void DER_Encoder::end_sequence(ASN1_Tag type_tag, ASN1_Tag class_tag)
196 {
197 end_cons(type_tag, class_tag);
198 }
199
200/*************************************************
201* Start a new ASN.1 SET *
202*************************************************/
203void DER_Encoder::start_set(ASN1_Tag type_tag, ASN1_Tag class_tag)
204 {
205 start_cons(type_tag, class_tag, true);
206 }
207
208/*************************************************
209* Finish the current ASN.1 SET *
210*************************************************/
211void DER_Encoder::end_set(ASN1_Tag type_tag, ASN1_Tag class_tag)
212 {
213 end_cons(type_tag, class_tag);
214 }
215
216/*************************************************
217* Start a new ASN.1 SEQUENCE *
218*************************************************/
219void DER_Encoder::start_sequence()
220 {
221 start_sequence(SEQUENCE, UNIVERSAL);
222 }
223
224/*************************************************
225* Finish the current ASN.1 SEQUENCE *
226*************************************************/
227void DER_Encoder::end_sequence()
228 {
229 end_sequence(SEQUENCE, UNIVERSAL);
230 }
231
232/*************************************************
233* Start a new ASN.1 SET *
234*************************************************/
235void DER_Encoder::start_set()
236 {
237 start_set(SET, UNIVERSAL);
238 }
239
240/*************************************************
241* Finish the current ASN.1 SET *
242*************************************************/
243void DER_Encoder::end_set()
244 {
245 end_set(SET, UNIVERSAL);
246 }
247
248/*************************************************
249* Start a new ASN.1 EXPLICIT encoding *
250*************************************************/
251void DER_Encoder::start_explicit(ASN1_Tag type_tag, ASN1_Tag class_tag)
252 {
253 start_cons(type_tag, class_tag, false);
254 }
255
256/*************************************************
257* Finish the current ASN.1 EXPLICIT encoding *
258*************************************************/
259void DER_Encoder::end_explicit(ASN1_Tag type_tag, ASN1_Tag class_tag)
260 {
261 end_cons(type_tag, class_tag);
262 }
263
264/*************************************************
265* Write raw octets into the stream *
266*************************************************/
267void DER_Encoder::add_raw_octets(const MemoryRegion<byte>& octets)
268 {
269 add_raw_octets(octets.begin(), octets.size());
270 }
271
272/*************************************************
273* Write raw octets into the stream *
274*************************************************/
275void DER_Encoder::add_raw_octets(const byte octets[], u32bit length)
276 {
277 if(sequence_level == 0)
278 contents.append(octets, length);
279 else
280 subsequences[sequence_level-1].add_bytes(octets, length);
281 }
282
283/*************************************************
284* Write the encoding of the octet(s) *
285*************************************************/
286void DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
287 const byte rep[], u32bit length)
288 {
289 SecureVector<byte> encoded_tag = encode_tag(type_tag, class_tag);
290 SecureVector<byte> encoded_length = encode_length(length);
291
292 SecureVector<byte> buffer;
293 buffer.append(encoded_tag);
294 buffer.append(encoded_length);
295 buffer.append(rep, length);
296
297 add_raw_octets(buffer);
298 }
299
300/*************************************************
301* Write the encoding of the octet(s) *
302*************************************************/
303void DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
304 const MemoryRegion<byte>& rep_buf)
305 {
306 const byte* rep = rep_buf.begin();
307 const u32bit rep_len = rep_buf.size();
308 add_object(type_tag, class_tag, rep, rep_len);
309 }
310
311/*************************************************
312* Write the encoding of the octet(s) *
313*************************************************/
314void DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
315 const std::string& rep_str)
316 {
317 const byte* rep = (const byte*)rep_str.c_str();
318 const u32bit rep_len = rep_str.size();
319 add_object(type_tag, class_tag, rep, rep_len);
320 }
321
322/*************************************************
323* Write the encoding of the octet *
324*************************************************/
325void DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, byte rep)
326 {
327 add_object(type_tag, class_tag, &rep, 1);
328 }
329
330/*************************************************
331* DER_Encoder Constructor *
332*************************************************/
333DER_Encoder::DER_Encoder()
334 {
335 sequence_level = 0;
336 }
337
338}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status