Botan 3.9.0
Crypto and TLS for C&
der_enc.cpp
Go to the documentation of this file.
1/*
2* DER Encoder
3* (C) 1999-2007,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/der_enc.h>
9
10#include <botan/asn1_obj.h>
11#include <botan/bigint.h>
12#include <botan/internal/bit_ops.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/loadstor.h>
15#include <botan/internal/mem_utils.h>
16#include <algorithm>
17
18namespace Botan {
19
20namespace {
21
22/*
23* DER encode an ASN.1 type tag
24*/
25void encode_tag(std::vector<uint8_t>& encoded_tag, ASN1_Type type_tag_e, ASN1_Class class_tag_e) {
26 const uint32_t type_tag = static_cast<uint32_t>(type_tag_e);
27 const uint32_t class_tag = static_cast<uint32_t>(class_tag_e);
28
29 if((class_tag | 0xE0) != 0xE0) {
30 throw Encoding_Error(fmt("DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
31 }
32
33 if(type_tag <= 30) {
34 encoded_tag.push_back(static_cast<uint8_t>(type_tag | class_tag));
35 } else {
36 size_t blocks = high_bit(static_cast<uint32_t>(type_tag)) + 6;
37 blocks = (blocks - (blocks % 7)) / 7;
38
39 BOTAN_ASSERT_NOMSG(blocks > 0);
40
41 encoded_tag.push_back(static_cast<uint8_t>(class_tag | 0x1F));
42 for(size_t i = 0; i != blocks - 1; ++i) {
43 encoded_tag.push_back(0x80 | ((type_tag >> 7 * (blocks - i - 1)) & 0x7F));
44 }
45 encoded_tag.push_back(type_tag & 0x7F);
46 }
47}
48
49/*
50* DER encode an ASN.1 length field
51*/
52void encode_length(std::vector<uint8_t>& encoded_length, size_t length) {
53 if(length <= 127) {
54 encoded_length.push_back(static_cast<uint8_t>(length));
55 } else {
56 const size_t bytes_needed = significant_bytes(length);
57
58 encoded_length.push_back(static_cast<uint8_t>(0x80 | bytes_needed));
59
60 for(size_t i = sizeof(length) - bytes_needed; i < sizeof(length); ++i) {
61 encoded_length.push_back(get_byte_var(i, length));
62 }
63 }
64}
65
66} // namespace
67
69 m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
70}
71
72DER_Encoder::DER_Encoder(std::vector<uint8_t>& vec) {
73 m_append_output = [&vec](const uint8_t b[], size_t l) { vec.insert(vec.end(), b, b + l); };
74}
75
76/*
77* Push the encoded SEQUENCE/SET to the encoder stream
78*/
79void DER_Encoder::DER_Sequence::push_contents(DER_Encoder& der) {
80 const auto real_class_tag = m_class_tag | ASN1_Class::Constructed;
81
82 if(m_type_tag == ASN1_Type::Set) {
83 std::sort(m_set_contents.begin(), m_set_contents.end());
84 for(const auto& set_elem : m_set_contents) {
85 m_contents += set_elem;
86 }
87 m_set_contents.clear();
88 }
89
90 der.add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
91 m_contents.clear();
92}
93
94/*
95* Add an encoded value to the SEQUENCE/SET
96*/
97void DER_Encoder::DER_Sequence::add_bytes(const uint8_t data[], size_t length) {
98 if(m_type_tag == ASN1_Type::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
105void DER_Encoder::DER_Sequence::add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len) {
106 if(m_type_tag == ASN1_Type::Set) {
108 m.reserve(hdr_len + val_len);
109 m += std::make_pair(hdr, hdr_len);
110 m += std::make_pair(val, val_len);
111 m_set_contents.push_back(std::move(m));
112 } else {
113 m_contents += std::make_pair(hdr, hdr_len);
114 m_contents += std::make_pair(val, val_len);
115 }
116}
117
118/*
119* Return the type and class taggings
120*/
121uint32_t DER_Encoder::DER_Sequence::tag_of() const {
122 return m_type_tag | m_class_tag;
123}
124
125/*
126* DER_Sequence Constructor
127*/
128DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Type type_tag, ASN1_Class class_tag) :
129 m_type_tag(type_tag), m_class_tag(class_tag) {}
130
131/*
132* Return the encoded contents
133*/
135 if(!m_subsequences.empty()) {
136 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
137 }
138
139 if(m_append_output) {
140 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
141 }
142
144 std::swap(output, m_default_outbuf);
145 return output;
146}
147
149 if(!m_subsequences.empty()) {
150 throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
151 }
152
153 if(m_append_output) {
154 throw Invalid_State("DER_Encoder Cannot get contents when using output vector");
155 }
156
157 std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
158 m_default_outbuf.clear();
159 return output;
160}
161
162/*
163* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
164*/
166 m_subsequences.push_back(DER_Sequence(type_tag, class_tag));
167 return (*this);
168}
169
170/*
171* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
172*/
174 if(m_subsequences.empty()) {
175 throw Invalid_State("DER_Encoder::end_cons: No such sequence");
176 }
177
178 DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
179 m_subsequences.pop_back();
180 last_seq.push_contents(*this);
181
182 return (*this);
183}
184
185/*
186* Start a new ASN.1 EXPLICIT encoding
187*/
189 ASN1_Type type_tag = static_cast<ASN1_Type>(type_no);
190
191 // This would confuse DER_Sequence
192 if(type_tag == ASN1_Type::Set) {
193 throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");
194 }
195
196 return start_cons(type_tag, ASN1_Class::ContextSpecific);
197}
198
199/*
200* Finish the current ASN.1 EXPLICIT encoding
201*/
205
206/*
207* Write raw bytes into the stream
208*/
209DER_Encoder& DER_Encoder::raw_bytes(const uint8_t bytes[], size_t length) {
210 if(!m_subsequences.empty()) {
211 m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
212 } else if(m_append_output) {
213 m_append_output(bytes, length);
214 } else {
215 m_default_outbuf += std::make_pair(bytes, length);
216 }
217
218 return (*this);
219}
220
221/*
222* Write the encoding of the byte(s)
223*/
224DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length) {
225 std::vector<uint8_t> hdr;
226 encode_tag(hdr, type_tag, class_tag);
227 encode_length(hdr, length);
228
229 if(!m_subsequences.empty()) {
230 m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
231 } else if(m_append_output) {
232 m_append_output(hdr.data(), hdr.size());
233 m_append_output(rep, length);
234 } else {
235 m_default_outbuf += hdr;
236 m_default_outbuf += std::make_pair(rep, length);
237 }
238
239 return (*this);
240}
241
242/*
243* Encode a NULL object
244*/
248
249/*
250* DER encode a BOOLEAN
251*/
255
256/*
257* DER encode a small INTEGER
258*/
262
263/*
264* DER encode a small INTEGER
265*/
269
270/*
271* Encode this object
272*/
273DER_Encoder& DER_Encoder::encode(const uint8_t bytes[], size_t length, ASN1_Type real_type) {
274 return encode(bytes, length, real_type, real_type, ASN1_Class::Universal);
275}
276
277/*
278* DER encode a BOOLEAN
279*/
280DER_Encoder& DER_Encoder::encode(bool is_true, ASN1_Type type_tag, ASN1_Class class_tag) {
281 uint8_t val = is_true ? 0xFF : 0x00;
282 return add_object(type_tag, class_tag, &val, 1);
283}
284
285/*
286* DER encode a small INTEGER
287*/
288DER_Encoder& DER_Encoder::encode(size_t n, ASN1_Type type_tag, ASN1_Class class_tag) {
289 return encode(BigInt::from_u64(n), type_tag, class_tag);
290}
291
292/*
293* DER encode an INTEGER
294*/
296 if(n == 0) {
297 return add_object(type_tag, class_tag, 0);
298 }
299
300 const size_t extra_zero = (n.bits() % 8 == 0) ? 1 : 0;
301
302 auto contents = n.serialize(n.bytes() + extra_zero);
303 if(n < 0) {
304 for(unsigned char& content : contents) {
305 content = ~content;
306 }
307 for(size_t i = contents.size(); i > 0; --i) {
308 contents[i - 1] += 1;
309 if(contents[i - 1] != 0) {
310 break;
311 }
312 }
313 }
314
315 return add_object(type_tag, class_tag, contents);
316}
317
318/*
319* DER encode an OCTET STRING or BIT STRING
320*/
322 const uint8_t bytes[], size_t length, ASN1_Type real_type, ASN1_Type type_tag, ASN1_Class class_tag) {
323 if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
324 throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
325 }
326
327 if(real_type == ASN1_Type::BitString) {
329 encoded.push_back(0);
330 encoded += std::make_pair(bytes, length);
331 return add_object(type_tag, class_tag, encoded);
332 } else {
333 return add_object(type_tag, class_tag, bytes, length);
334 }
335}
336
338 obj.encode_into(*this);
339 return (*this);
340}
341
342/*
343* Write the encoding of the byte(s)
344*/
345DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view rep_str) {
346 return add_object(type_tag, class_tag, as_span_of_bytes(rep_str));
347}
348
349/*
350* Write the encoding of the byte
351*/
352DER_Encoder& DER_Encoder::add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t rep) {
353 return add_object(type_tag, class_tag, std::span<const uint8_t>{&rep, 1});
354}
355
356} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
virtual void encode_into(DER_Encoder &to) const =0
size_t bits() const
Definition bigint.cpp:311
static BigInt from_u64(uint64_t n)
Definition bigint.cpp:29
size_t bytes() const
Definition bigint.cpp:298
T serialize(size_t len) const
Definition bigint.h:711
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
Definition der_enc.cpp:224
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:134
DER_Encoder & end_explicit()
Definition der_enc.cpp:202
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:188
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition der_enc.cpp:165
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition der_enc.cpp:209
DER_Encoder & encode_null()
Definition der_enc.cpp:245
DER_Encoder & end_cons()
Definition der_enc.cpp:173
std::vector< uint8_t > get_contents_unlocked()
Definition der_enc.cpp:148
DER_Encoder & encode(bool b)
Definition der_enc.cpp:252
DER_Encoder()=default
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:28
ASN1_Class
Definition asn1_obj.h:28
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:43
BOTAN_FORCE_INLINE constexpr size_t significant_bytes(T n)
Definition bit_ops.h:76
BOTAN_FORCE_INLINE constexpr size_t high_bit(T n)
Definition bit_ops.h:56
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition loadstor.h:69