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