Coverage Report

Created: 2025-12-05 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/build/include/public/botan/der_enc.h
Line
Count
Source
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
#ifndef BOTAN_DER_ENCODER_H_
9
#define BOTAN_DER_ENCODER_H_
10
11
#include <botan/asn1_obj.h>
12
#include <functional>
13
#include <optional>
14
#include <vector>
15
16
namespace Botan {
17
18
class BigInt;
19
20
/**
21
* General DER Encoding Object
22
*/
23
class BOTAN_PUBLIC_API(2, 0) DER_Encoder final {
24
   public:
25
      typedef std::function<void(const uint8_t[], size_t)> append_fn;
26
27
      /**
28
      * DER encode, writing to an internal buffer
29
      * Use get_contents or get_contents_unlocked to read the results
30
      * after all encoding is completed.
31
      */
32
0
      DER_Encoder() = default;
33
34
      /**
35
      * DER encode, writing to @param vec
36
      * If this constructor is used, get_contents* may not be called.
37
      */
38
      BOTAN_FUTURE_EXPLICIT DER_Encoder(secure_vector<uint8_t>& vec);
39
40
      /**
41
      * DER encode, writing to @param vec
42
      * If this constructor is used, get_contents* may not be called.
43
      */
44
      BOTAN_FUTURE_EXPLICIT DER_Encoder(std::vector<uint8_t>& vec);
45
46
      /**
47
      * DER encode, calling append to write output
48
      * If this constructor is used, get_contents* may not be called.
49
      */
50
0
      BOTAN_FUTURE_EXPLICIT DER_Encoder(append_fn append) : m_append_output(std::move(append)) {}
51
52
      secure_vector<uint8_t> get_contents();
53
54
      /**
55
      * Return the encoded contents as a std::vector
56
      *
57
      * If using this function, instead pass a std::vector to the
58
      * constructor of DER_Encoder where the output will be placed. This
59
      * avoids several unnecessary copies.
60
      */
61
      BOTAN_DEPRECATED("Use DER_Encoder(vector) instead") std::vector<uint8_t> get_contents_unlocked();
62
63
      DER_Encoder& start_cons(ASN1_Type type_tag, ASN1_Class class_tag);
64
65
362k
      DER_Encoder& start_sequence() { return start_cons(ASN1_Type::Sequence, ASN1_Class::Universal); }
66
67
0
      DER_Encoder& start_set() { return start_cons(ASN1_Type::Set, ASN1_Class::Universal); }
68
69
118k
      DER_Encoder& start_context_specific(uint32_t tag) {
70
118k
         return start_cons(ASN1_Type(tag), ASN1_Class::ContextSpecific);
71
118k
      }
72
73
0
      DER_Encoder& start_explicit_context_specific(uint32_t tag) {
74
0
         return start_cons(ASN1_Type(tag), ASN1_Class::ExplicitContextSpecific);
75
0
      }
76
77
      DER_Encoder& end_cons();
78
79
      DER_Encoder& start_explicit(uint16_t type_tag);
80
      DER_Encoder& end_explicit();
81
82
      /**
83
      * Insert raw bytes directly into the output stream
84
      */
85
      DER_Encoder& raw_bytes(const uint8_t val[], size_t len);
86
87
      template <typename Alloc>
88
180k
      DER_Encoder& raw_bytes(const std::vector<uint8_t, Alloc>& val) {
89
180k
         return raw_bytes(val.data(), val.size());
90
180k
      }
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::raw_bytes<Botan::secure_allocator<unsigned char> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
Botan::DER_Encoder& Botan::DER_Encoder::raw_bytes<std::__1::allocator<unsigned char> >(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&)
Line
Count
Source
88
180k
      DER_Encoder& raw_bytes(const std::vector<uint8_t, Alloc>& val) {
89
180k
         return raw_bytes(val.data(), val.size());
90
180k
      }
91
92
      DER_Encoder& encode_null();
93
      DER_Encoder& encode(bool b);
94
      DER_Encoder& encode(size_t s);
95
      DER_Encoder& encode(const BigInt& n);
96
      DER_Encoder& encode(const uint8_t val[], size_t len, ASN1_Type real_type);
97
98
      template <typename Alloc>
99
31.1k
      DER_Encoder& encode(const std::vector<uint8_t, Alloc>& vec, ASN1_Type real_type) {
100
31.1k
         return encode(vec.data(), vec.size(), real_type);
101
31.1k
      }
Botan::DER_Encoder& Botan::DER_Encoder::encode<std::__1::allocator<unsigned char> >(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, Botan::ASN1_Type)
Line
Count
Source
99
31.1k
      DER_Encoder& encode(const std::vector<uint8_t, Alloc>& vec, ASN1_Type real_type) {
100
31.1k
         return encode(vec.data(), vec.size(), real_type);
101
31.1k
      }
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode<Botan::secure_allocator<unsigned char> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&, Botan::ASN1_Type)
102
103
      DER_Encoder& encode(bool b, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
104
105
      DER_Encoder& encode(size_t s, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
106
107
      DER_Encoder& encode(const BigInt& n, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
108
109
      DER_Encoder& encode(const uint8_t v[],
110
                          size_t len,
111
                          ASN1_Type real_type,
112
                          ASN1_Type type_tag,
113
                          ASN1_Class class_tag = ASN1_Class::ContextSpecific);
114
115
      template <typename Alloc>
116
      DER_Encoder& encode(const std::vector<uint8_t, Alloc>& bytes,
117
                          ASN1_Type real_type,
118
                          ASN1_Type type_tag,
119
0
                          ASN1_Class class_tag) {
120
0
         return encode(bytes.data(), bytes.size(), real_type, type_tag, class_tag);
121
0
      }
122
123
      template <typename T>
124
      BOTAN_DEPRECATED("Use the version that takes a std::optional")
125
      DER_Encoder& encode_optional(const T& value, const T& default_value) {
126
         if(value != default_value) {
127
            encode(value);
128
         }
129
         return (*this);
130
      }
131
132
      template <typename T>
133
0
      DER_Encoder& encode_optional(const std::optional<T>& value) {
134
0
         if(value) {
135
0
            encode(*value);
136
0
         }
137
0
         return (*this);
138
0
      }
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_optional<bool>(std::__1::optional<bool> const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_optional<unsigned long>(std::__1::optional<unsigned long> const&)
139
140
      template <typename T>
141
1.58k
      DER_Encoder& encode_list(const std::vector<T>& values) {
142
4.75k
         for(size_t i = 0; i != values.size(); ++i) {
143
3.17k
            encode(values[i]);
144
3.17k
         }
145
1.58k
         return (*this);
146
1.58k
      }
Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::BigInt>(std::__1::vector<Botan::BigInt, std::__1::allocator<Botan::BigInt> > const&)
Line
Count
Source
141
1.58k
      DER_Encoder& encode_list(const std::vector<T>& values) {
142
4.75k
         for(size_t i = 0; i != values.size(); ++i) {
143
3.17k
            encode(values[i]);
144
3.17k
         }
145
1.58k
         return (*this);
146
1.58k
      }
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::OID>(std::__1::vector<Botan::OID, std::__1::allocator<Botan::OID> > const&)
Unexecuted instantiation: x509_ext.cpp:Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::(anonymous namespace)::Policy_Information>(std::__1::vector<Botan::Cert_Extension::(anonymous namespace)::Policy_Information, std::__1::allocator<Botan::Cert_Extension::(anonymous namespace)::Policy_Information> > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::CRL_Distribution_Points::Distribution_Point>(std::__1::vector<Botan::Cert_Extension::CRL_Distribution_Points::Distribution_Point, std::__1::allocator<Botan::Cert_Extension::CRL_Distribution_Points::Distribution_Point> > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::IPAddressBlocks::IPAddressFamily>(std::__1::vector<Botan::Cert_Extension::IPAddressBlocks::IPAddressFamily, std::__1::allocator<Botan::Cert_Extension::IPAddressBlocks::IPAddressFamily> > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)4> >(std::__1::vector<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)4>, std::__1::allocator<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)4> > > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)16> >(std::__1::vector<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)16>, std::__1::allocator<Botan::Cert_Extension::IPAddressBlocks::IPAddressOrRange<(Botan::Cert_Extension::IPAddressBlocks::Version)16> > > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::Cert_Extension::ASBlocks::ASIdOrRange>(std::__1::vector<Botan::Cert_Extension::ASBlocks::ASIdOrRange, std::__1::allocator<Botan::Cert_Extension::ASBlocks::ASIdOrRange> > const&)
Unexecuted instantiation: Botan::DER_Encoder& Botan::DER_Encoder::encode_list<Botan::X509_Certificate>(std::__1::vector<Botan::X509_Certificate, std::__1::allocator<Botan::X509_Certificate> > const&)
147
148
      /*
149
      * Request for an object to encode itself to this stream
150
      */
151
      DER_Encoder& encode(const ASN1_Object& obj);
152
153
      /*
154
      * Conditionally write some values to the stream
155
      */
156
0
      DER_Encoder& encode_if(bool pred, DER_Encoder& enc) {
157
0
         if(pred) {
158
0
            return raw_bytes(enc.get_contents());
159
0
         }
160
0
         return (*this);
161
0
      }
162
163
0
      DER_Encoder& encode_if(bool pred, const ASN1_Object& obj) {
164
0
         if(pred) {
165
0
            encode(obj);
166
0
         }
167
0
         return (*this);
168
0
      }
169
170
0
      DER_Encoder& encode_if(bool pred, size_t num) {
171
0
         if(pred) {
172
0
            encode(num);
173
0
         }
174
0
         return (*this);
175
0
      }
176
177
0
      DER_Encoder& encode_if(bool pred, bool num) {
178
0
         if(pred) {
179
0
            encode(num);
180
0
         }
181
0
         return (*this);
182
0
      }
183
184
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length);
185
186
228k
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::span<const uint8_t> rep) {
187
228k
         return add_object(type_tag, class_tag, rep.data(), rep.size());
188
228k
      }
189
190
197k
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, const std::vector<uint8_t>& rep) {
191
197k
         return add_object(type_tag, class_tag, std::span{rep});
192
197k
      }
193
194
31.1k
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, const secure_vector<uint8_t>& rep) {
195
31.1k
         return add_object(type_tag, class_tag, std::span{rep});
196
31.1k
      }
197
198
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view str);
199
200
      DER_Encoder& add_object(ASN1_Type type_tag, ASN1_Class class_tag, uint8_t val);
201
202
   private:
203
      class DER_Sequence final {
204
         public:
205
            uint32_t tag_of() const;
206
207
            void push_contents(DER_Encoder& der);
208
209
            void add_bytes(const uint8_t val[], size_t len);
210
211
            void add_bytes(const uint8_t hdr[], size_t hdr_len, const uint8_t val[], size_t val_len);
212
213
            DER_Sequence(ASN1_Type type_tag, ASN1_Class class_tag);
214
215
            DER_Sequence(DER_Sequence&& seq) noexcept :
216
1.11M
                  m_type_tag(seq.m_type_tag),
217
1.11M
                  m_class_tag(seq.m_class_tag),
218
1.11M
                  m_contents(std::move(seq.m_contents)),
219
1.11M
                  m_set_contents(std::move(seq.m_set_contents)) {}
220
221
0
            DER_Sequence& operator=(DER_Sequence&& seq) noexcept {
222
0
               std::swap(m_type_tag, seq.m_type_tag);
223
0
               std::swap(m_class_tag, seq.m_class_tag);
224
0
               std::swap(m_contents, seq.m_contents);
225
0
               std::swap(m_set_contents, seq.m_set_contents);
226
0
               return (*this);
227
0
            }
228
229
            DER_Sequence(const DER_Sequence& seq) = default;
230
            DER_Sequence& operator=(const DER_Sequence& seq) = default;
231
1.59M
            ~DER_Sequence() = default;
232
233
         private:
234
            ASN1_Type m_type_tag;
235
            ASN1_Class m_class_tag;
236
            secure_vector<uint8_t> m_contents;
237
            std::vector<secure_vector<uint8_t>> m_set_contents;
238
      };
239
240
      append_fn m_append_output;
241
      secure_vector<uint8_t> m_default_outbuf;
242
      std::vector<DER_Sequence> m_subsequences;
243
};
244
245
}  // namespace Botan
246
247
#endif