Coverage Report

Created: 2020-09-16 07:52

/src/botan/build/include/botan/x509_ext.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* X.509 Certificate Extensions
3
* (C) 1999-2007,2012 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#ifndef BOTAN_X509_EXTENSIONS_H_
9
#define BOTAN_X509_EXTENSIONS_H_
10
11
#include <botan/asn1_obj.h>
12
#include <botan/asn1_oid.h>
13
#include <botan/asn1_alt_name.h>
14
#include <botan/cert_status.h>
15
#include <botan/name_constraint.h>
16
#include <botan/key_constraint.h>
17
#include <botan/crl_ent.h>
18
#include <set>
19
20
namespace Botan {
21
22
class Data_Store;
23
class X509_Certificate;
24
25
/**
26
* X.509 Certificate Extension
27
*/
28
class BOTAN_PUBLIC_API(2,0) Certificate_Extension
29
   {
30
   public:
31
      /**
32
      * @return OID representing this extension
33
      */
34
      virtual OID oid_of() const = 0;
35
36
      /*
37
      * @return specific OID name
38
      * If possible OIDS table should match oid_name to OIDS, ie
39
      * OID::from_string(ext->oid_name()) == ext->oid_of()
40
      * Should return empty string if OID is not known
41
      */
42
      virtual std::string oid_name() const = 0;
43
44
      /**
45
      * Make a copy of this extension
46
      * @return copy of this
47
      */
48
      virtual Certificate_Extension* copy() const = 0;
49
50
      /*
51
      * Add the contents of this extension into the information
52
      * for the subject and/or issuer, as necessary.
53
      * @param subject the subject info
54
      * @param issuer the issuer info
55
      */
56
      virtual void contents_to(Data_Store& subject,
57
                               Data_Store& issuer) const = 0;
58
59
      /*
60
      * Callback visited during path validation.
61
      *
62
      * An extension can implement this callback to inspect
63
      * the path during path validation.
64
      *
65
      * If an error occurs during validation of this extension,
66
      * an appropriate status code shall be added to cert_status.
67
      *
68
      * @param subject Subject certificate that contains this extension
69
      * @param issuer Issuer certificate
70
      * @param status Certificate validation status codes for subject certificate
71
      * @param cert_path Certificate path which is currently validated
72
      * @param pos Position of subject certificate in cert_path
73
      */
74
      virtual void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
75
            const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
76
            std::vector<std::set<Certificate_Status_Code>>& cert_status,
77
            size_t pos);
78
79
53.4k
      virtual ~Certificate_Extension() = default;
80
   protected:
81
      friend class Extensions;
82
0
      virtual bool should_encode() const { return true; }
83
      virtual std::vector<uint8_t> encode_inner() const = 0;
84
      virtual void decode_inner(const std::vector<uint8_t>&) = 0;
85
   };
86
87
/**
88
* X.509 Certificate Extension List
89
*/
90
class BOTAN_PUBLIC_API(2,0) Extensions final : public ASN1_Object
91
   {
92
   public:
93
      /**
94
      * Look up an object in the extensions, based on OID Returns
95
      * nullptr if not set, if the extension was either absent or not
96
      * handled. The pointer returned is owned by the Extensions
97
      * object.
98
      * This would be better with an optional<T> return value
99
      */
100
      const Certificate_Extension* get_extension_object(const OID& oid) const;
101
102
      template<typename T>
103
      const T* get_extension_object_as(const OID& oid = T::static_oid()) const
104
133k
         {
105
133k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
6.52k
            {
107
            // Unknown_Extension oid_name is empty
108
6.52k
            if(extn->oid_name().empty())
109
3.02k
               {
110
3.02k
               return nullptr;
111
3.02k
               }
112
3.50k
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
3.50k
               {
114
3.50k
               return extn_as_T;
115
3.50k
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
126k
            }
121
126k
122
126k
         return nullptr;
123
126k
         }
Botan::Cert_Extension::Key_Usage const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Key_Usage>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
312
            {
107
            // Unknown_Extension oid_name is empty
108
312
            if(extn->oid_name().empty())
109
196
               {
110
196
               return nullptr;
111
196
               }
112
116
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
116
               {
114
116
               return extn_as_T;
115
116
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.3k
            }
121
11.3k
122
11.3k
         return nullptr;
123
11.3k
         }
Botan::Cert_Extension::Subject_Key_ID const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Subject_Key_ID>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
678
            {
107
            // Unknown_Extension oid_name is empty
108
678
            if(extn->oid_name().empty())
109
268
               {
110
268
               return nullptr;
111
268
               }
112
410
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
410
               {
114
410
               return extn_as_T;
115
410
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
10.9k
            }
121
10.9k
122
10.9k
         return nullptr;
123
10.9k
         }
Botan::Cert_Extension::Authority_Key_ID const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Authority_Key_ID>(Botan::OID const&) const
Line
Count
Source
104
12.0k
         {
105
12.0k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
1.05k
            {
107
            // Unknown_Extension oid_name is empty
108
1.05k
            if(extn->oid_name().empty())
109
508
               {
110
508
               return nullptr;
111
508
               }
112
545
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
545
               {
114
545
               return extn_as_T;
115
545
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.0k
            }
121
11.0k
122
11.0k
         return nullptr;
123
11.0k
         }
Botan::Cert_Extension::Name_Constraints const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Name_Constraints>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
217
            {
107
            // Unknown_Extension oid_name is empty
108
217
            if(extn->oid_name().empty())
109
146
               {
110
146
               return nullptr;
111
146
               }
112
71
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
71
               {
114
71
               return extn_as_T;
115
71
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.4k
            }
121
11.4k
122
11.4k
         return nullptr;
123
11.4k
         }
Botan::Cert_Extension::Basic_Constraints const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Basic_Constraints>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
400
            {
107
            // Unknown_Extension oid_name is empty
108
400
            if(extn->oid_name().empty())
109
219
               {
110
219
               return nullptr;
111
219
               }
112
181
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
181
               {
114
181
               return extn_as_T;
115
181
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.2k
            }
121
11.2k
122
11.2k
         return nullptr;
123
11.2k
         }
Botan::Cert_Extension::Issuer_Alternative_Name const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Issuer_Alternative_Name>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
318
            {
107
            // Unknown_Extension oid_name is empty
108
318
            if(extn->oid_name().empty())
109
140
               {
110
140
               return nullptr;
111
140
               }
112
178
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
178
               {
114
178
               return extn_as_T;
115
178
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.3k
            }
121
11.3k
122
11.3k
         return nullptr;
123
11.3k
         }
Botan::Cert_Extension::Subject_Alternative_Name const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Subject_Alternative_Name>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
529
            {
107
            // Unknown_Extension oid_name is empty
108
529
            if(extn->oid_name().empty())
109
220
               {
110
220
               return nullptr;
111
220
               }
112
309
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
309
               {
114
309
               return extn_as_T;
115
309
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.0k
            }
121
11.0k
122
11.0k
         return nullptr;
123
11.0k
         }
Botan::Cert_Extension::Extended_Key_Usage const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Extended_Key_Usage>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
387
            {
107
            // Unknown_Extension oid_name is empty
108
387
            if(extn->oid_name().empty())
109
243
               {
110
243
               return nullptr;
111
243
               }
112
144
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
144
               {
114
144
               return extn_as_T;
115
144
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.2k
            }
121
11.2k
122
11.2k
         return nullptr;
123
11.2k
         }
Botan::Cert_Extension::Certificate_Policies const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Certificate_Policies>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
266
            {
107
            // Unknown_Extension oid_name is empty
108
266
            if(extn->oid_name().empty())
109
169
               {
110
169
               return nullptr;
111
169
               }
112
97
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
97
               {
114
97
               return extn_as_T;
115
97
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.3k
            }
121
11.3k
122
11.3k
         return nullptr;
123
11.3k
         }
Botan::Cert_Extension::Authority_Information_Access const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::Authority_Information_Access>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
176
            {
107
            // Unknown_Extension oid_name is empty
108
176
            if(extn->oid_name().empty())
109
124
               {
110
124
               return nullptr;
111
124
               }
112
52
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
52
               {
114
52
               return extn_as_T;
115
52
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.4k
            }
121
11.4k
122
11.4k
         return nullptr;
123
11.4k
         }
Botan::Cert_Extension::CRL_Distribution_Points const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::CRL_Distribution_Points>(Botan::OID const&) const
Line
Count
Source
104
11.6k
         {
105
11.6k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
232
            {
107
            // Unknown_Extension oid_name is empty
108
232
            if(extn->oid_name().empty())
109
173
               {
110
173
               return nullptr;
111
173
               }
112
59
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
59
               {
114
59
               return extn_as_T;
115
59
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
11.3k
            }
121
11.3k
122
11.3k
         return nullptr;
123
11.3k
         }
Botan::Cert_Extension::CRL_Number const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::CRL_Number>(Botan::OID const&) const
Line
Count
Source
104
471
         {
105
471
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
11
            {
107
            // Unknown_Extension oid_name is empty
108
11
            if(extn->oid_name().empty())
109
10
               {
110
10
               return nullptr;
111
10
               }
112
1
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
1
               {
114
1
               return extn_as_T;
115
1
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
460
            }
121
460
122
460
         return nullptr;
123
460
         }
Botan::Cert_Extension::CRL_Issuing_Distribution_Point const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::CRL_Issuing_Distribution_Point>(Botan::OID const&) const
Line
Count
Source
104
471
         {
105
471
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
14
            {
107
            // Unknown_Extension oid_name is empty
108
14
            if(extn->oid_name().empty())
109
7
               {
110
7
               return nullptr;
111
7
               }
112
7
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
7
               {
114
7
               return extn_as_T;
115
7
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
457
            }
121
457
122
457
         return nullptr;
123
457
         }
Botan::Cert_Extension::CRL_ReasonCode const* Botan::Extensions::get_extension_object_as<Botan::Cert_Extension::CRL_ReasonCode>(Botan::OID const&) const
Line
Count
Source
104
4.11k
         {
105
4.11k
         if(const Certificate_Extension* extn = get_extension_object(oid))
106
1.93k
            {
107
            // Unknown_Extension oid_name is empty
108
1.93k
            if(extn->oid_name().empty())
109
605
               {
110
605
               return nullptr;
111
605
               }
112
1.33k
            else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
113
1.33k
               {
114
1.33k
               return extn_as_T;
115
1.33k
               }
116
0
            else
117
0
               {
118
0
               throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
119
0
               }
120
2.18k
            }
121
2.18k
122
2.18k
         return nullptr;
123
2.18k
         }
124
125
      /**
126
      * Return the set of extensions in the order they appeared in the certificate
127
      * (or as they were added, if constructed)
128
      */
129
      const std::vector<OID>& get_extension_oids() const
130
0
         {
131
0
         return m_extension_oids;
132
0
         }
133
134
      /**
135
      * Return true if an extension was set
136
      */
137
      bool extension_set(const OID& oid) const;
138
139
      /**
140
      * Return true if an extesion was set and marked critical
141
      */
142
      bool critical_extension_set(const OID& oid) const;
143
144
      /**
145
      * Return the raw bytes of the extension
146
      * Will throw if OID was not set as an extension.
147
      */
148
      std::vector<uint8_t> get_extension_bits(const OID& oid) const;
149
150
      void encode_into(class DER_Encoder&) const override;
151
      void decode_from(class BER_Decoder&) override;
152
      void contents_to(Data_Store&, Data_Store&) const;
153
154
      /**
155
      * Adds a new extension to the list.
156
      * @param extn pointer to the certificate extension (Extensions takes ownership)
157
      * @param critical whether this extension should be marked as critical
158
      * @throw Invalid_Argument if the extension is already present in the list
159
      */
160
      void add(Certificate_Extension* extn, bool critical = false);
161
162
      /**
163
      * Adds a new extension to the list unless it already exists. If the extension
164
      * already exists within the Extensions object, the extn pointer will be deleted.
165
      *
166
      * @param extn pointer to the certificate extension (Extensions takes ownership)
167
      * @param critical whether this extension should be marked as critical
168
      * @return true if the object was added false if the extension was already used
169
      */
170
      bool add_new(Certificate_Extension* extn, bool critical = false);
171
172
      /**
173
      * Adds an extension to the list or replaces it.
174
      * @param extn the certificate extension
175
      * @param critical whether this extension should be marked as critical
176
      */
177
      void replace(Certificate_Extension* extn, bool critical = false);
178
179
      /**
180
      * Remove an extension from the list. Returns true if the
181
      * extension had been set, false otherwise.
182
      */
183
      bool remove(const OID& oid);
184
185
      /**
186
      * Searches for an extension by OID and returns the result.
187
      * Only the known extensions types declared in this header
188
      * are searched for by this function.
189
      * @return Copy of extension with oid, nullptr if not found.
190
      * Can avoid creating a copy by using get_extension_object function
191
      */
192
      std::unique_ptr<Certificate_Extension> get(const OID& oid) const;
193
194
      /**
195
      * Searches for an extension by OID and returns the result decoding
196
      * it to some arbitrary extension type chosen by the application.
197
      *
198
      * Only the unknown extensions, that is, extensions types that
199
      * are not declared in this header, are searched for by this
200
      * function.
201
      *
202
      * @return Pointer to new extension with oid, nullptr if not found.
203
      */
204
      template<typename T>
205
      std::unique_ptr<T> get_raw(const OID& oid) const
206
         {
207
         auto extn_info = m_extension_info.find(oid);
208
209
         if(extn_info != m_extension_info.end())
210
            {
211
            // Unknown_Extension oid_name is empty
212
            if(extn_info->second.obj().oid_name() == "")
213
               {
214
               std::unique_ptr<T> ext(new T);
215
               ext->decode_inner(extn_info->second.bits());
216
               return ext;
217
               }
218
            }
219
         return nullptr;
220
         }
221
222
      /**
223
      * Returns a copy of the list of extensions together with the corresponding
224
      * criticality flag. All extensions are encoded as some object, falling back
225
      * to Unknown_Extension class which simply allows reading the bytes as well
226
      * as the criticality flag.
227
      */
228
      std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const;
229
230
      /**
231
      * Returns the list of extensions as raw, encoded bytes
232
      * together with the corresponding criticality flag.
233
      * Contains all extensions, including any extensions encoded as Unknown_Extension
234
      */
235
      std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const;
236
237
32.3k
      Extensions() {}
238
239
0
      Extensions(const Extensions&) = default;
240
21
      Extensions& operator=(const Extensions&) = default;
241
242
      Extensions(Extensions&&) = default;
243
      Extensions& operator=(Extensions&&) = default;
244
245
   private:
246
      static std::unique_ptr<Certificate_Extension>
247
         create_extn_obj(const OID& oid,
248
                         bool critical,
249
                         const std::vector<uint8_t>& body);
250
251
      class Extensions_Info
252
         {
253
         public:
254
            Extensions_Info(bool critical,
255
                            Certificate_Extension* ext) :
256
               m_obj(ext),
257
               m_bits(m_obj->encode_inner()),
258
               m_critical(critical)
259
0
               {
260
0
               }
261
262
            Extensions_Info(bool critical,
263
                            const std::vector<uint8_t>& encoding,
264
                            Certificate_Extension* ext) :
265
               m_obj(ext),
266
               m_bits(encoding),
267
               m_critical(critical)
268
38.8k
               {
269
38.8k
               }
270
271
12.2k
            bool is_critical() const { return m_critical; }
272
0
            const std::vector<uint8_t>& bits() const { return m_bits; }
273
            const Certificate_Extension& obj() const
274
31.0k
               {
275
31.0k
               BOTAN_ASSERT_NONNULL(m_obj.get());
276
31.0k
               return *m_obj.get();
277
31.0k
               }
278
279
         private:
280
            std::shared_ptr<Certificate_Extension> m_obj;
281
            std::vector<uint8_t> m_bits;
282
            bool m_critical = false;
283
         };
284
285
      std::vector<OID> m_extension_oids;
286
      std::map<OID, Extensions_Info> m_extension_info;
287
   };
288
289
namespace Cert_Extension {
290
291
static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
292
293
/**
294
* Basic Constraints Extension
295
*/
296
class BOTAN_PUBLIC_API(2,0) Basic_Constraints final : public Certificate_Extension
297
   {
298
   public:
299
      Basic_Constraints* copy() const override
300
0
         { return new Basic_Constraints(m_is_ca, m_path_limit); }
301
302
      Basic_Constraints(bool ca = false, size_t limit = 0) :
303
1.77k
         m_is_ca(ca), m_path_limit(limit) {}
304
305
181
      bool get_is_ca() const { return m_is_ca; }
306
      size_t get_path_limit() const;
307
308
43.7k
      static OID static_oid() { return OID("2.5.29.19"); }
309
0
      OID oid_of() const override { return static_oid(); }
310
311
   private:
312
      std::string oid_name() const override
313
361
         { return "X509v3.BasicConstraints"; }
314
315
      std::vector<uint8_t> encode_inner() const override;
316
      void decode_inner(const std::vector<uint8_t>&) override;
317
      void contents_to(Data_Store&, Data_Store&) const override;
318
319
      bool m_is_ca;
320
      size_t m_path_limit;
321
   };
322
323
/**
324
* Key Usage Constraints Extension
325
*/
326
class BOTAN_PUBLIC_API(2,0) Key_Usage final : public Certificate_Extension
327
   {
328
   public:
329
0
      Key_Usage* copy() const override { return new Key_Usage(m_constraints); }
330
331
1.25k
      explicit Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : m_constraints(c) {}
332
333
116
      Key_Constraints get_constraints() const { return m_constraints; }
334
335
48.9k
      static OID static_oid() { return OID("2.5.29.15"); }
336
0
      OID oid_of() const override { return static_oid(); }
337
338
   private:
339
221
      std::string oid_name() const override { return "X509v3.KeyUsage"; }
340
341
      bool should_encode() const override
342
0
         { return (m_constraints != NO_CONSTRAINTS); }
343
      std::vector<uint8_t> encode_inner() const override;
344
      void decode_inner(const std::vector<uint8_t>&) override;
345
      void contents_to(Data_Store&, Data_Store&) const override;
346
347
      Key_Constraints m_constraints;
348
   };
349
350
/**
351
* Subject Key Identifier Extension
352
*/
353
class BOTAN_PUBLIC_API(2,0) Subject_Key_ID final : public Certificate_Extension
354
   {
355
   public:
356
1.64k
      Subject_Key_ID() = default;
357
358
0
      explicit Subject_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {}
359
360
      Subject_Key_ID(const std::vector<uint8_t>& public_key,
361
                     const std::string& hash_fn);
362
363
      Subject_Key_ID* copy() const override
364
0
         { return new Subject_Key_ID(m_key_id); }
365
366
410
      const std::vector<uint8_t>& get_key_id() const { return m_key_id; }
367
368
50.6k
      static OID static_oid() { return OID("2.5.29.14"); }
369
0
      OID oid_of() const override { return static_oid(); }
370
371
   private:
372
373
      std::string oid_name() const override
374
820
         { return "X509v3.SubjectKeyIdentifier"; }
375
376
0
      bool should_encode() const override { return (m_key_id.size() > 0); }
377
      std::vector<uint8_t> encode_inner() const override;
378
      void decode_inner(const std::vector<uint8_t>&) override;
379
      void contents_to(Data_Store&, Data_Store&) const override;
380
381
      std::vector<uint8_t> m_key_id;
382
   };
383
384
/**
385
* Authority Key Identifier Extension
386
*/
387
class BOTAN_PUBLIC_API(2,0) Authority_Key_ID final : public Certificate_Extension
388
   {
389
   public:
390
      Authority_Key_ID* copy() const override
391
0
         { return new Authority_Key_ID(m_key_id); }
392
393
1.70k
      Authority_Key_ID() = default;
394
0
      explicit Authority_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {}
395
396
545
      const std::vector<uint8_t>& get_key_id() const { return m_key_id; }
397
398
38.9k
      static OID static_oid() { return OID("2.5.29.35"); }
399
0
      OID oid_of() const override { return static_oid(); }
400
401
   private:
402
      std::string oid_name() const override
403
1.08k
         { return "X509v3.AuthorityKeyIdentifier"; }
404
405
0
      bool should_encode() const override { return (m_key_id.size() > 0); }
406
      std::vector<uint8_t> encode_inner() const override;
407
      void decode_inner(const std::vector<uint8_t>&) override;
408
      void contents_to(Data_Store&, Data_Store&) const override;
409
410
      std::vector<uint8_t> m_key_id;
411
   };
412
413
/**
414
* Subject Alternative Name Extension
415
*/
416
class BOTAN_PUBLIC_API(2,4) Subject_Alternative_Name final : public Certificate_Extension
417
   {
418
   public:
419
616
      const AlternativeName& get_alt_name() const { return m_alt_name; }
420
421
47.7k
      static OID static_oid() { return OID("2.5.29.17"); }
422
0
      OID oid_of() const override { return static_oid(); }
423
424
      Subject_Alternative_Name* copy() const override
425
0
         { return new Subject_Alternative_Name(get_alt_name()); }
426
427
      explicit Subject_Alternative_Name(const AlternativeName& name = AlternativeName()) :
428
2.60k
         m_alt_name(name) {}
429
430
   private:
431
616
      std::string oid_name() const override { return "X509v3.SubjectAlternativeName"; }
432
433
0
      bool should_encode() const override { return m_alt_name.has_items(); }
434
      std::vector<uint8_t> encode_inner() const override;
435
      void decode_inner(const std::vector<uint8_t>&) override;
436
      void contents_to(Data_Store&, Data_Store&) const override;
437
438
      AlternativeName m_alt_name;
439
   };
440
441
/**
442
* Issuer Alternative Name Extension
443
*/
444
class BOTAN_PUBLIC_API(2,0) Issuer_Alternative_Name final : public Certificate_Extension
445
   {
446
   public:
447
355
      const AlternativeName& get_alt_name() const { return m_alt_name; }
448
449
45.1k
      static OID static_oid() { return OID("2.5.29.18"); }
450
0
      OID oid_of() const override { return static_oid(); }
451
452
      Issuer_Alternative_Name* copy() const override
453
0
         { return new Issuer_Alternative_Name(get_alt_name()); }
454
455
      explicit Issuer_Alternative_Name(const AlternativeName& name = AlternativeName()) :
456
1.39k
         m_alt_name(name) {}
457
458
   private:
459
355
      std::string oid_name() const override { return "X509v3.IssuerAlternativeName"; }
460
461
0
      bool should_encode() const override { return m_alt_name.has_items(); }
462
      std::vector<uint8_t> encode_inner() const override;
463
      void decode_inner(const std::vector<uint8_t>&) override;
464
      void contents_to(Data_Store&, Data_Store&) const override;
465
466
      AlternativeName m_alt_name;
467
   };
468
469
/**
470
* Extended Key Usage Extension
471
*/
472
class BOTAN_PUBLIC_API(2,0) Extended_Key_Usage final : public Certificate_Extension
473
   {
474
   public:
475
      Extended_Key_Usage* copy() const override
476
0
         { return new Extended_Key_Usage(m_oids); }
477
478
1.06k
      Extended_Key_Usage() = default;
479
0
      explicit Extended_Key_Usage(const std::vector<OID>& o) : m_oids(o) {}
480
481
144
      const std::vector<OID>& get_oids() const { return m_oids; }
482
483
29.8k
      static OID static_oid() { return OID("2.5.29.37"); }
484
0
      OID oid_of() const override { return static_oid(); }
485
486
   private:
487
287
      std::string oid_name() const override { return "X509v3.ExtendedKeyUsage"; }
488
489
0
      bool should_encode() const override { return (m_oids.size() > 0); }
490
      std::vector<uint8_t> encode_inner() const override;
491
      void decode_inner(const std::vector<uint8_t>&) override;
492
      void contents_to(Data_Store&, Data_Store&) const override;
493
494
      std::vector<OID> m_oids;
495
   };
496
497
/**
498
* Name Constraints
499
*/
500
class BOTAN_PUBLIC_API(2,0) Name_Constraints final : public Certificate_Extension
501
   {
502
   public:
503
      Name_Constraints* copy() const override
504
0
         { return new Name_Constraints(m_name_constraints); }
505
506
3.80k
      Name_Constraints() = default;
507
0
      Name_Constraints(const NameConstraints &nc) : m_name_constraints(nc) {}
508
509
      void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
510
            const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
511
            std::vector<std::set<Certificate_Status_Code>>& cert_status,
512
            size_t pos) override;
513
514
71
      const NameConstraints& get_name_constraints() const { return m_name_constraints; }
515
516
36.7k
      static OID static_oid() { return OID("2.5.29.30"); }
517
0
      OID oid_of() const override { return static_oid(); }
518
519
   private:
520
      std::string oid_name() const override
521
142
         { return "X509v3.NameConstraints"; }
522
523
0
      bool should_encode() const override { return true; }
524
      std::vector<uint8_t> encode_inner() const override;
525
      void decode_inner(const std::vector<uint8_t>&) override;
526
      void contents_to(Data_Store&, Data_Store&) const override;
527
528
      NameConstraints m_name_constraints;
529
   };
530
531
/**
532
* Certificate Policies Extension
533
*/
534
class BOTAN_PUBLIC_API(2,0) Certificate_Policies final : public Certificate_Extension
535
   {
536
   public:
537
      Certificate_Policies* copy() const override
538
0
         { return new Certificate_Policies(m_oids); }
539
540
1.02k
      Certificate_Policies() = default;
541
0
      explicit Certificate_Policies(const std::vector<OID>& o) : m_oids(o) {}
542
543
      BOTAN_DEPRECATED("Use get_policy_oids")
544
0
      std::vector<OID> get_oids() const { return m_oids; }
545
546
97
      const std::vector<OID>& get_policy_oids() const { return m_oids; }
547
548
30.8k
      static OID static_oid() { return OID("2.5.29.32"); }
549
0
      OID oid_of() const override { return static_oid(); }
550
551
      void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
552
            const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
553
            std::vector<std::set<Certificate_Status_Code>>& cert_status,
554
            size_t pos) override;
555
   private:
556
      std::string oid_name() const override
557
192
         { return "X509v3.CertificatePolicies"; }
558
559
0
      bool should_encode() const override { return (m_oids.size() > 0); }
560
      std::vector<uint8_t> encode_inner() const override;
561
      void decode_inner(const std::vector<uint8_t>&) override;
562
      void contents_to(Data_Store&, Data_Store&) const override;
563
564
      std::vector<OID> m_oids;
565
   };
566
567
/**
568
* Authority Information Access Extension
569
*/
570
class BOTAN_PUBLIC_API(2,0) Authority_Information_Access final : public Certificate_Extension
571
   {
572
   public:
573
      Authority_Information_Access* copy() const override
574
0
         { return new Authority_Information_Access(m_ocsp_responder, m_ca_issuers); }
575
576
633
      Authority_Information_Access() = default;
577
578
      explicit Authority_Information_Access(const std::string& ocsp, const std::vector<std::string>& ca_issuers = std::vector<std::string>()) :
579
0
         m_ocsp_responder(ocsp), m_ca_issuers(ca_issuers) {}
580
581
52
      std::string ocsp_responder() const { return m_ocsp_responder; }
582
583
28.7k
      static OID static_oid() { return OID("1.3.6.1.5.5.7.1.1"); }
584
0
      OID oid_of() const override { return static_oid(); }
585
52
      const std::vector<std::string> ca_issuers() const { return m_ca_issuers; }
586
587
   private:
588
      std::string oid_name() const override
589
104
         { return "PKIX.AuthorityInformationAccess"; }
590
591
0
      bool should_encode() const override { return (!m_ocsp_responder.empty()); }
592
593
      std::vector<uint8_t> encode_inner() const override;
594
      void decode_inner(const std::vector<uint8_t>&) override;
595
596
      void contents_to(Data_Store&, Data_Store&) const override;
597
598
      std::string m_ocsp_responder;
599
      std::vector<std::string> m_ca_issuers;
600
   };
601
602
/**
603
* CRL Number Extension
604
*/
605
class BOTAN_PUBLIC_API(2,0) CRL_Number final : public Certificate_Extension
606
   {
607
   public:
608
      CRL_Number* copy() const override;
609
610
665
      CRL_Number() : m_has_value(false), m_crl_number(0) {}
611
0
      CRL_Number(size_t n) : m_has_value(true), m_crl_number(n) {}
612
613
      size_t get_crl_number() const;
614
615
30.7k
      static OID static_oid() { return OID("2.5.29.20"); }
616
0
      OID oid_of() const override { return static_oid(); }
617
618
   private:
619
22
      std::string oid_name() const override { return "X509v3.CRLNumber"; }
620
621
0
      bool should_encode() const override { return m_has_value; }
622
      std::vector<uint8_t> encode_inner() const override;
623
      void decode_inner(const std::vector<uint8_t>&) override;
624
      void contents_to(Data_Store&, Data_Store&) const override;
625
626
      bool m_has_value;
627
      size_t m_crl_number;
628
   };
629
630
/**
631
* CRL Entry Reason Code Extension
632
*/
633
class BOTAN_PUBLIC_API(2,0) CRL_ReasonCode final : public Certificate_Extension
634
   {
635
   public:
636
      CRL_ReasonCode* copy() const override
637
0
         { return new CRL_ReasonCode(m_reason); }
638
639
2.85k
      explicit CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : m_reason(r) {}
640
641
1.33k
      CRL_Code get_reason() const { return m_reason; }
642
643
33.7k
      static OID static_oid() { return OID("2.5.29.21"); }
644
0
      OID oid_of() const override { return static_oid(); }
645
646
   private:
647
1.35k
      std::string oid_name() const override { return "X509v3.ReasonCode"; }
648
649
0
      bool should_encode() const override { return (m_reason != UNSPECIFIED); }
650
      std::vector<uint8_t> encode_inner() const override;
651
      void decode_inner(const std::vector<uint8_t>&) override;
652
      void contents_to(Data_Store&, Data_Store&) const override;
653
654
      CRL_Code m_reason;
655
   };
656
657
/**
658
* CRL Distribution Points Extension
659
* todo enforce restrictions from RFC 5280 4.2.1.13
660
*/
661
class BOTAN_PUBLIC_API(2,0) CRL_Distribution_Points final : public Certificate_Extension
662
   {
663
   public:
664
      class BOTAN_PUBLIC_API(2,0) Distribution_Point final : public ASN1_Object
665
         {
666
         public:
667
            void encode_into(class DER_Encoder&) const override;
668
            void decode_from(class BER_Decoder&) override;
669
670
517
            const AlternativeName& point() const { return m_point; }
671
         private:
672
            AlternativeName m_point;
673
         };
674
675
      CRL_Distribution_Points* copy() const override
676
0
         { return new CRL_Distribution_Points(m_distribution_points); }
677
678
1.61k
      CRL_Distribution_Points() = default;
679
680
      explicit CRL_Distribution_Points(const std::vector<Distribution_Point>& points) :
681
0
         m_distribution_points(points) {}
682
683
      const std::vector<Distribution_Point>& distribution_points() const
684
0
         { return m_distribution_points; }
685
686
      const std::vector<std::string>& crl_distribution_urls() const
687
59
         { return m_crl_distribution_urls; }
688
689
32.9k
      static OID static_oid() { return OID("2.5.29.31"); }
690
0
      OID oid_of() const override { return static_oid(); }
691
692
   private:
693
      std::string oid_name() const override
694
117
         { return "X509v3.CRLDistributionPoints"; }
695
696
      bool should_encode() const override
697
0
         { return !m_distribution_points.empty(); }
698
699
      std::vector<uint8_t> encode_inner() const override;
700
      void decode_inner(const std::vector<uint8_t>&) override;
701
      void contents_to(Data_Store&, Data_Store&) const override;
702
703
      std::vector<Distribution_Point> m_distribution_points;
704
      std::vector<std::string> m_crl_distribution_urls;
705
   };
706
707
/**
708
* CRL Issuing Distribution Point Extension
709
* todo enforce restrictions from RFC 5280 5.2.5
710
*/
711
class CRL_Issuing_Distribution_Point final : public Certificate_Extension
712
   {
713
   public:
714
436
      CRL_Issuing_Distribution_Point() = default;
715
716
      explicit CRL_Issuing_Distribution_Point(const CRL_Distribution_Points::Distribution_Point& distribution_point) :
717
0
         m_distribution_point(distribution_point) {}
718
719
      CRL_Issuing_Distribution_Point* copy() const override
720
0
         { return new CRL_Issuing_Distribution_Point(m_distribution_point); }
721
722
      const AlternativeName& get_point() const
723
7
         { return m_distribution_point.point(); }
724
725
20.1k
      static OID static_oid() { return OID("2.5.29.28"); }
726
0
      OID oid_of() const override { return static_oid(); }
727
728
   private:
729
      std::string oid_name() const override
730
22
         { return "X509v3.CRLIssuingDistributionPoint"; }
731
732
0
      bool should_encode() const override { return true; }
733
      std::vector<uint8_t> encode_inner() const override;
734
      void decode_inner(const std::vector<uint8_t>&) override;
735
      void contents_to(Data_Store&, Data_Store&) const override;
736
737
      CRL_Distribution_Points::Distribution_Point m_distribution_point;
738
   };
739
740
/**
741
* An unknown X.509 extension
742
* Will add a failure to the path validation result, if critical
743
*/
744
class BOTAN_PUBLIC_API(2,4) Unknown_Extension final : public Certificate_Extension
745
   {
746
   public:
747
      Unknown_Extension(const OID& oid, bool critical) :
748
30.9k
         m_oid(oid), m_critical(critical) {}
749
750
      Unknown_Extension* copy() const override
751
0
         { return new Unknown_Extension(m_oid, m_critical); }
752
753
      /**
754
      * Return the OID of this unknown extension
755
      */
756
      OID oid_of() const override
757
0
         { return m_oid; }
758
759
      //static_oid not defined for Unknown_Extension
760
761
      /**
762
      * Return the extension contents
763
      */
764
0
      const std::vector<uint8_t>& extension_contents() const { return m_bytes; }
765
766
      /**
767
      * Return if this extension was marked critical
768
      */
769
0
      bool is_critical_extension() const { return m_critical; }
770
771
      void validate(const X509_Certificate&, const X509_Certificate&,
772
            const std::vector<std::shared_ptr<const X509_Certificate>>&,
773
            std::vector<std::set<Certificate_Status_Code>>& cert_status,
774
            size_t pos) override
775
0
         {
776
0
         if(m_critical)
777
0
            {
778
0
            cert_status.at(pos).insert(Certificate_Status_Code::UNKNOWN_CRITICAL_EXTENSION);
779
0
            }
780
0
         }
781
782
   private:
783
13.0k
      std::string oid_name() const override { return ""; }
784
785
0
      bool should_encode() const override { return true; }
786
      std::vector<uint8_t> encode_inner() const override;
787
      void decode_inner(const std::vector<uint8_t>&) override;
788
      void contents_to(Data_Store&, Data_Store&) const override;
789
790
      OID m_oid;
791
      bool m_critical;
792
      std::vector<uint8_t> m_bytes;
793
   };
794
795
   }
796
797
}
798
799
#endif