8#include <botan/der_enc.h>
10#include <botan/asn1_obj.h>
11#include <botan/bigint.h>
12#include <botan/internal/asn1_utils.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/loadstor.h>
16#include <botan/internal/mem_utils.h>
26void encode_tag(std::vector<uint8_t>& encoded_tag,
ASN1_Type type_tag_e,
ASN1_Class class_tag_e) {
27 const uint32_t type_tag =
static_cast<uint32_t
>(type_tag_e);
28 const uint32_t class_tag =
static_cast<uint32_t
>(class_tag_e);
30 if((class_tag | 0xE0) != 0xE0) {
31 throw Encoding_Error(
fmt(
"DER_Encoder: Invalid class tag {}", std::to_string(class_tag)));
35 encoded_tag.push_back(
static_cast<uint8_t
>(type_tag | class_tag));
37 size_t blocks =
high_bit(
static_cast<uint32_t
>(type_tag)) + 6;
38 blocks = (blocks - (blocks % 7)) / 7;
42 encoded_tag.push_back(
static_cast<uint8_t
>(class_tag | 0x1F));
43 for(
size_t i = 0; i != blocks - 1; ++i) {
44 encoded_tag.push_back(0x80 | ((type_tag >> 7 * (blocks - i - 1)) & 0x7F));
46 encoded_tag.push_back(type_tag & 0x7F);
53void encode_length(std::vector<uint8_t>& encoded_length,
size_t length) {
55 encoded_length.push_back(
static_cast<uint8_t
>(length));
59 encoded_length.push_back(
static_cast<uint8_t
>(0x80 | bytes_needed));
61 for(
size_t i =
sizeof(length) - bytes_needed; i <
sizeof(length); ++i) {
72 std::vector<uint8_t> header;
73 header.reserve(2 +
sizeof(contents_len));
75 encode_length(header, contents_len);
82 m_append_output = [&vec](
const uint8_t b[],
size_t l) {
84 vec.insert(vec.end(), b, b + l);
90 m_append_output = [&vec](
const uint8_t b[],
size_t l) {
92 vec.insert(vec.end(), b, b + l);
100void DER_Encoder::DER_Sequence::push_contents(
DER_Encoder& der) {
103 if(m_sort_contents) {
104 std::sort(m_set_contents.begin(), m_set_contents.end());
105 for(
const auto& set_elem : m_set_contents) {
106 m_contents += set_elem;
108 m_set_contents.clear();
111 der.
add_object(m_type_tag, real_class_tag, m_contents.data(), m_contents.size());
118void DER_Encoder::DER_Sequence::add_bytes(
const uint8_t data[],
size_t length) {
119 if(m_sort_contents) {
121 m_set_contents.emplace_back(data, data + length);
123 m_set_contents.emplace_back();
126 m_contents += std::make_pair(data, length);
130void DER_Encoder::DER_Sequence::add_bytes(
const uint8_t hdr[],
size_t hdr_len,
const uint8_t val[],
size_t val_len) {
131 if(m_sort_contents) {
133 m.reserve(hdr_len + val_len);
134 m += std::make_pair(hdr, hdr_len);
135 m += std::make_pair(val, val_len);
136 m_set_contents.push_back(std::move(m));
138 m_contents += std::make_pair(hdr, hdr_len);
139 m_contents += std::make_pair(val, val_len);
146uint32_t DER_Encoder::DER_Sequence::tag_of()
const {
147 return m_type_tag | m_class_tag;
153DER_Encoder::DER_Sequence::DER_Sequence(
ASN1_Type type_tag,
ASN1_Class class_tag,
bool sort_contents) :
154 m_type_tag(type_tag),
155 m_class_tag(class_tag),
162 if(!m_subsequences.empty()) {
163 throw Invalid_State(
"DER_Encoder: Sequence hasn't been marked done");
166 if(m_append_output) {
167 throw Invalid_State(
"DER_Encoder Cannot get contents when using output vector");
171 std::swap(output, m_default_outbuf);
176 if(!m_subsequences.empty()) {
177 throw Invalid_State(
"DER_Encoder: Sequence hasn't been marked done");
180 if(m_append_output) {
181 throw Invalid_State(
"DER_Encoder Cannot get contents when using output vector");
184 std::vector<uint8_t> output(m_default_outbuf.begin(), m_default_outbuf.end());
185 m_default_outbuf.clear();
193 return start_cons(type_tag, class_tag,
false);
201 m_subsequences.push_back(DER_Sequence(type_tag, class_tag, sort_contents));
209 if(m_subsequences.empty()) {
210 throw Invalid_State(
"DER_Encoder::end_cons: No such sequence");
213 DER_Sequence last_seq = std::move(m_subsequences[m_subsequences.size() - 1]);
214 m_subsequences.pop_back();
215 last_seq.push_contents(*
this);
238 if(!m_subsequences.empty()) {
239 m_subsequences[m_subsequences.size() - 1].add_bytes(bytes, length);
240 }
else if(m_append_output) {
241 m_append_output(bytes, length);
243 m_default_outbuf += std::make_pair(bytes, length);
263 if((tlv[0] & 0x1F) == 0x1F) {
264 while(off < tlv.size() && (tlv[off] & 0x80) != 0) {
273 const uint8_t len_byte = tlv[off++];
274 if((len_byte & 0x80) != 0) {
275 off += (len_byte & 0x7F);
279 return add_object(type_tag, class_tag, std::span<const uint8_t>(tlv).subspan(off));
286 std::vector<uint8_t> hdr;
287 encode_tag(hdr, type_tag, class_tag);
288 encode_length(hdr, length);
290 if(!m_subsequences.empty()) {
291 m_subsequences[m_subsequences.size() - 1].add_bytes(hdr.data(), hdr.size(), rep, length);
292 }
else if(m_append_output) {
293 m_append_output(hdr.data(), hdr.size());
294 m_append_output(rep, length);
296 m_default_outbuf += hdr;
297 m_default_outbuf += std::make_pair(rep, length);
342 const uint8_t val = is_true ? 0xFF : 0x00;
343 return add_object(type_tag, class_tag, &val, 1);
366 for(
auto&
byte : contents) {
369 for(
size_t i = contents.size(); i > 0; --i) {
370 if(++contents[i - 1] != 0) {
380 const bool leading_byte_redundant =
381 (contents[0] == 0x00 && (contents[1] & 0x80) == 0) || (contents[0] == 0xFF && (contents[1] & 0x80) != 0);
383 if(leading_byte_redundant) {
384 contents.erase(contents.begin());
407 return add_object(type_tag, class_tag, bytes);
415 if(unused_bits >= 8) {
416 throw Invalid_Argument(
"DER_Encoder: Invalid unused bit count for BIT STRING");
419 if(bits.empty() && unused_bits != 0) {
420 throw Invalid_Argument(
"DER_Encoder: Empty BIT STRING cannot have unused bits");
423 if(unused_bits > 0 && (bits.back() & ((1U << unused_bits) - 1)) != 0) {
428 encoded.reserve(1 + bits.size());
429 encoded.push_back(
static_cast<uint8_t
>(unused_bits));
430 encoded.insert(encoded.end(), bits.begin(), bits.end());
431 return add_object(type_tag, class_tag, encoded);
446 if(width < 64 && (bits >> width) != 0) {
447 throw Invalid_Argument(
"DER_Encoder: Named BIT STRING has bits outside range");
454 const size_t bit_length = width -
ctz(bits);
455 const size_t byte_length = (bit_length + 7) / 8;
456 std::vector<uint8_t> encoded(byte_length);
458 for(
size_t bit = 0; bit != bit_length; ++bit) {
459 if((bits & (uint64_t(1) << (width - 1 - bit))) != 0) {
460 encoded[bit / 8] |=
static_cast<uint8_t
>(0x80 >> (bit % 8));
464 return encode_bitstring(encoded, byte_length * 8 - bit_length, type_tag, class_tag);
483 return add_object(type_tag, class_tag, std::span<const uint8_t>{&rep, 1});
#define BOTAN_ASSERT_NOMSG(expr)
size_t unused_bits() const
std::span< const uint8_t > bytes() const
virtual void encode_into(DER_Encoder &to) const =0
static BigInt from_u64(uint64_t n)
T serialize(size_t len) const
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
secure_vector< uint8_t > get_contents()
DER_Encoder & start_set()
DER_Encoder & end_explicit()
DER_Encoder & start_explicit(uint16_t type_tag)
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
DER_Encoder & encode_null()
std::vector< uint8_t > get_contents_unlocked()
DER_Encoder & encode_bitstring(std::span< const uint8_t > bits, size_t unused_bits=0, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
DER_Encoder & encode(bool b)
DER_Encoder & encode_named_bitstring(uint64_t bits, size_t width, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
std::vector< uint8_t > integer_contents(const BigInt &n)
std::vector< uint8_t > der_sequence_header(size_t contents_len)
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
std::string fmt(std::string_view format, const T &... args)
BOTAN_FORCE_INLINE constexpr size_t significant_bytes(T n)
BOTAN_FORCE_INLINE constexpr size_t high_bit(T n)
std::vector< T, secure_allocator< T > > secure_vector
constexpr uint8_t get_byte_var(size_t byte_num, T input)
std::uint8_t byte
Unsigned 8 bit integer; retained for compatibility with older versions.
BOTAN_FORCE_INLINE constexpr size_t ctz(T n)