/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/pkix_types.h> |
12 | | #include <set> |
13 | | |
14 | | namespace Botan { |
15 | | |
16 | | class X509_Certificate; |
17 | | |
18 | | namespace Cert_Extension { |
19 | | |
20 | | static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0; |
21 | | |
22 | | /** |
23 | | * Basic Constraints Extension |
24 | | */ |
25 | | class BOTAN_PUBLIC_API(2,0) Basic_Constraints final : public Certificate_Extension |
26 | | { |
27 | | public: |
28 | | std::unique_ptr<Certificate_Extension> copy() const override |
29 | 0 | { return std::make_unique<Basic_Constraints>(m_is_ca, m_path_limit); } |
30 | | |
31 | | Basic_Constraints(bool ca = false, size_t limit = 0) : |
32 | 1.90k | m_is_ca(ca), m_path_limit(limit) {} |
33 | | |
34 | 27 | bool get_is_ca() const { return m_is_ca; } |
35 | | size_t get_path_limit() const; |
36 | | |
37 | 44.9k | static OID static_oid() { return OID("2.5.29.19"); } |
38 | 0 | OID oid_of() const override { return static_oid(); } |
39 | | |
40 | | private: |
41 | | std::string oid_name() const override |
42 | 27 | { return "X509v3.BasicConstraints"; } |
43 | | |
44 | | std::vector<uint8_t> encode_inner() const override; |
45 | | void decode_inner(const std::vector<uint8_t>&) override; |
46 | | |
47 | | bool m_is_ca; |
48 | | size_t m_path_limit; |
49 | | }; |
50 | | |
51 | | /** |
52 | | * Key Usage Constraints Extension |
53 | | */ |
54 | | class BOTAN_PUBLIC_API(2,0) Key_Usage final : public Certificate_Extension |
55 | | { |
56 | | public: |
57 | | std::unique_ptr<Certificate_Extension> copy() const override |
58 | 0 | { |
59 | 0 | return std::make_unique<Key_Usage>(m_constraints); |
60 | 0 | } |
61 | | |
62 | 1.93k | explicit Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : m_constraints(c) {} |
63 | | |
64 | 33 | Key_Constraints get_constraints() const { return m_constraints; } |
65 | | |
66 | 49.9k | static OID static_oid() { return OID("2.5.29.15"); } |
67 | 0 | OID oid_of() const override { return static_oid(); } |
68 | | |
69 | | private: |
70 | 33 | std::string oid_name() const override { return "X509v3.KeyUsage"; } |
71 | | |
72 | | bool should_encode() const override |
73 | 0 | { return (m_constraints != NO_CONSTRAINTS); } |
74 | | std::vector<uint8_t> encode_inner() const override; |
75 | | void decode_inner(const std::vector<uint8_t>&) override; |
76 | | |
77 | | Key_Constraints m_constraints; |
78 | | }; |
79 | | |
80 | | /** |
81 | | * Subject Key Identifier Extension |
82 | | */ |
83 | | class BOTAN_PUBLIC_API(2,0) Subject_Key_ID final : public Certificate_Extension |
84 | | { |
85 | | public: |
86 | 1.47k | Subject_Key_ID() = default; |
87 | | |
88 | 0 | explicit Subject_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {} |
89 | | |
90 | | Subject_Key_ID(const std::vector<uint8_t>& public_key, |
91 | | const std::string& hash_fn); |
92 | | |
93 | | std::unique_ptr<Certificate_Extension> copy() const override |
94 | 0 | { return std::make_unique<Subject_Key_ID>(m_key_id); } |
95 | | |
96 | 4 | const std::vector<uint8_t>& get_key_id() const { return m_key_id; } |
97 | | |
98 | 51.4k | static OID static_oid() { return OID("2.5.29.14"); } |
99 | 0 | OID oid_of() const override { return static_oid(); } |
100 | | |
101 | | private: |
102 | | |
103 | | std::string oid_name() const override |
104 | 4 | { return "X509v3.SubjectKeyIdentifier"; } |
105 | | |
106 | 0 | bool should_encode() const override { return (m_key_id.size() > 0); } |
107 | | std::vector<uint8_t> encode_inner() const override; |
108 | | void decode_inner(const std::vector<uint8_t>&) override; |
109 | | |
110 | | std::vector<uint8_t> m_key_id; |
111 | | }; |
112 | | |
113 | | /** |
114 | | * Authority Key Identifier Extension |
115 | | */ |
116 | | class BOTAN_PUBLIC_API(2,0) Authority_Key_ID final : public Certificate_Extension |
117 | | { |
118 | | public: |
119 | | std::unique_ptr<Certificate_Extension> copy() const override |
120 | 0 | { return std::make_unique<Authority_Key_ID>(m_key_id); } |
121 | | |
122 | 756 | Authority_Key_ID() = default; |
123 | 0 | explicit Authority_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {} |
124 | | |
125 | 26 | const std::vector<uint8_t>& get_key_id() const { return m_key_id; } |
126 | | |
127 | 40.5k | static OID static_oid() { return OID("2.5.29.35"); } |
128 | 0 | OID oid_of() const override { return static_oid(); } |
129 | | |
130 | | private: |
131 | | std::string oid_name() const override |
132 | 26 | { return "X509v3.AuthorityKeyIdentifier"; } |
133 | | |
134 | 0 | bool should_encode() const override { return (m_key_id.size() > 0); } |
135 | | std::vector<uint8_t> encode_inner() const override; |
136 | | void decode_inner(const std::vector<uint8_t>&) override; |
137 | | |
138 | | std::vector<uint8_t> m_key_id; |
139 | | }; |
140 | | |
141 | | /** |
142 | | * Subject Alternative Name Extension |
143 | | */ |
144 | | class BOTAN_PUBLIC_API(2,4) Subject_Alternative_Name final : public Certificate_Extension |
145 | | { |
146 | | public: |
147 | 115 | const AlternativeName& get_alt_name() const { return m_alt_name; } |
148 | | |
149 | 48.0k | static OID static_oid() { return OID("2.5.29.17"); } |
150 | 0 | OID oid_of() const override { return static_oid(); } |
151 | | |
152 | | std::unique_ptr<Certificate_Extension> copy() const override |
153 | 0 | { return std::make_unique<Subject_Alternative_Name>(get_alt_name()); } |
154 | | |
155 | | explicit Subject_Alternative_Name(const AlternativeName& name = AlternativeName()) : |
156 | 1.72k | m_alt_name(name) {} |
157 | | |
158 | | private: |
159 | 115 | std::string oid_name() const override { return "X509v3.SubjectAlternativeName"; } |
160 | | |
161 | 0 | bool should_encode() const override { return m_alt_name.has_items(); } |
162 | | std::vector<uint8_t> encode_inner() const override; |
163 | | void decode_inner(const std::vector<uint8_t>&) override; |
164 | | |
165 | | AlternativeName m_alt_name; |
166 | | }; |
167 | | |
168 | | /** |
169 | | * Issuer Alternative Name Extension |
170 | | */ |
171 | | class BOTAN_PUBLIC_API(2,0) Issuer_Alternative_Name final : public Certificate_Extension |
172 | | { |
173 | | public: |
174 | 42 | const AlternativeName& get_alt_name() const { return m_alt_name; } |
175 | | |
176 | 46.3k | static OID static_oid() { return OID("2.5.29.18"); } |
177 | 0 | OID oid_of() const override { return static_oid(); } |
178 | | |
179 | | std::unique_ptr<Certificate_Extension> copy() const override |
180 | 0 | { return std::make_unique<Issuer_Alternative_Name>(get_alt_name()); } |
181 | | |
182 | | explicit Issuer_Alternative_Name(const AlternativeName& name = AlternativeName()) : |
183 | 1.36k | m_alt_name(name) {} |
184 | | |
185 | | private: |
186 | 42 | std::string oid_name() const override { return "X509v3.IssuerAlternativeName"; } |
187 | | |
188 | 0 | bool should_encode() const override { return m_alt_name.has_items(); } |
189 | | std::vector<uint8_t> encode_inner() const override; |
190 | | void decode_inner(const std::vector<uint8_t>&) override; |
191 | | |
192 | | AlternativeName m_alt_name; |
193 | | }; |
194 | | |
195 | | /** |
196 | | * Extended Key Usage Extension |
197 | | */ |
198 | | class BOTAN_PUBLIC_API(2,0) Extended_Key_Usage final : public Certificate_Extension |
199 | | { |
200 | | public: |
201 | | std::unique_ptr<Certificate_Extension> copy() const override |
202 | 0 | { return std::make_unique<Extended_Key_Usage>(m_oids); } |
203 | | |
204 | 1.36k | Extended_Key_Usage() = default; |
205 | 0 | explicit Extended_Key_Usage(const std::vector<OID>& o) : m_oids(o) {} |
206 | | |
207 | 32 | const std::vector<OID>& get_oids() const { return m_oids; } |
208 | | |
209 | 30.1k | static OID static_oid() { return OID("2.5.29.37"); } |
210 | 0 | OID oid_of() const override { return static_oid(); } |
211 | | |
212 | | private: |
213 | 32 | std::string oid_name() const override { return "X509v3.ExtendedKeyUsage"; } |
214 | | |
215 | 0 | bool should_encode() const override { return (m_oids.size() > 0); } |
216 | | std::vector<uint8_t> encode_inner() const override; |
217 | | void decode_inner(const std::vector<uint8_t>&) override; |
218 | | |
219 | | std::vector<OID> m_oids; |
220 | | }; |
221 | | |
222 | | /** |
223 | | * Name Constraints |
224 | | */ |
225 | | class BOTAN_PUBLIC_API(2,0) Name_Constraints final : public Certificate_Extension |
226 | | { |
227 | | public: |
228 | | std::unique_ptr<Certificate_Extension> copy() const override |
229 | 0 | { return std::make_unique<Name_Constraints>(m_name_constraints); } |
230 | | |
231 | 4.01k | Name_Constraints() = default; |
232 | 0 | Name_Constraints(const NameConstraints &nc) : m_name_constraints(nc) {} |
233 | | |
234 | | void validate(const X509_Certificate& subject, const X509_Certificate& issuer, |
235 | | const std::vector<X509_Certificate>& cert_path, |
236 | | std::vector<std::set<Certificate_Status_Code>>& cert_status, |
237 | | size_t pos) override; |
238 | | |
239 | 13 | const NameConstraints& get_name_constraints() const { return m_name_constraints; } |
240 | | |
241 | 39.3k | static OID static_oid() { return OID("2.5.29.30"); } |
242 | 0 | OID oid_of() const override { return static_oid(); } |
243 | | |
244 | | private: |
245 | | std::string oid_name() const override |
246 | 13 | { return "X509v3.NameConstraints"; } |
247 | | |
248 | 0 | bool should_encode() const override { return true; } |
249 | | std::vector<uint8_t> encode_inner() const override; |
250 | | void decode_inner(const std::vector<uint8_t>&) override; |
251 | | |
252 | | NameConstraints m_name_constraints; |
253 | | }; |
254 | | |
255 | | /** |
256 | | * Certificate Policies Extension |
257 | | */ |
258 | | class BOTAN_PUBLIC_API(2,0) Certificate_Policies final : public Certificate_Extension |
259 | | { |
260 | | public: |
261 | | std::unique_ptr<Certificate_Extension> copy() const override |
262 | 0 | { return std::make_unique<Certificate_Policies>(m_oids); } |
263 | | |
264 | 2.23k | Certificate_Policies() = default; |
265 | 0 | explicit Certificate_Policies(const std::vector<OID>& o) : m_oids(o) {} |
266 | | |
267 | 19 | const std::vector<OID>& get_policy_oids() const { return m_oids; } |
268 | | |
269 | 32.3k | static OID static_oid() { return OID("2.5.29.32"); } |
270 | 0 | OID oid_of() const override { return static_oid(); } |
271 | | |
272 | | void validate(const X509_Certificate& subject, const X509_Certificate& issuer, |
273 | | const std::vector<X509_Certificate>& cert_path, |
274 | | std::vector<std::set<Certificate_Status_Code>>& cert_status, |
275 | | size_t pos) override; |
276 | | private: |
277 | | std::string oid_name() const override |
278 | 19 | { return "X509v3.CertificatePolicies"; } |
279 | | |
280 | 0 | bool should_encode() const override { return (m_oids.size() > 0); } |
281 | | std::vector<uint8_t> encode_inner() const override; |
282 | | void decode_inner(const std::vector<uint8_t>&) override; |
283 | | |
284 | | std::vector<OID> m_oids; |
285 | | }; |
286 | | |
287 | | /** |
288 | | * Authority Information Access Extension |
289 | | */ |
290 | | class BOTAN_PUBLIC_API(2,0) Authority_Information_Access final : public Certificate_Extension |
291 | | { |
292 | | public: |
293 | | std::unique_ptr<Certificate_Extension> copy() const override |
294 | 0 | { return std::make_unique<Authority_Information_Access>(m_ocsp_responder, m_ca_issuers); } |
295 | | |
296 | 404 | Authority_Information_Access() = default; |
297 | | |
298 | | explicit Authority_Information_Access(const std::string& ocsp, const std::vector<std::string>& ca_issuers = std::vector<std::string>()) : |
299 | 0 | m_ocsp_responder(ocsp), m_ca_issuers(ca_issuers) {} |
300 | | |
301 | 15 | std::string ocsp_responder() const { return m_ocsp_responder; } |
302 | | |
303 | 28.7k | static OID static_oid() { return OID("1.3.6.1.5.5.7.1.1"); } |
304 | 0 | OID oid_of() const override { return static_oid(); } |
305 | 15 | const std::vector<std::string> ca_issuers() const { return m_ca_issuers; } |
306 | | |
307 | | private: |
308 | | std::string oid_name() const override |
309 | 15 | { return "PKIX.AuthorityInformationAccess"; } |
310 | | |
311 | 0 | bool should_encode() const override { return (!m_ocsp_responder.empty()); } |
312 | | |
313 | | std::vector<uint8_t> encode_inner() const override; |
314 | | void decode_inner(const std::vector<uint8_t>&) override; |
315 | | |
316 | | |
317 | | std::string m_ocsp_responder; |
318 | | std::vector<std::string> m_ca_issuers; |
319 | | }; |
320 | | |
321 | | /** |
322 | | * CRL Number Extension |
323 | | */ |
324 | | class BOTAN_PUBLIC_API(2,0) CRL_Number final : public Certificate_Extension |
325 | | { |
326 | | public: |
327 | | std::unique_ptr<Certificate_Extension> copy() const override; |
328 | | |
329 | 787 | CRL_Number() : m_has_value(false), m_crl_number(0) {} |
330 | 0 | CRL_Number(size_t n) : m_has_value(true), m_crl_number(n) {} |
331 | | |
332 | | size_t get_crl_number() const; |
333 | | |
334 | 34.6k | static OID static_oid() { return OID("2.5.29.20"); } |
335 | 0 | OID oid_of() const override { return static_oid(); } |
336 | | |
337 | | private: |
338 | 3 | std::string oid_name() const override { return "X509v3.CRLNumber"; } |
339 | | |
340 | 0 | bool should_encode() const override { return m_has_value; } |
341 | | std::vector<uint8_t> encode_inner() const override; |
342 | | void decode_inner(const std::vector<uint8_t>&) override; |
343 | | |
344 | | bool m_has_value; |
345 | | size_t m_crl_number; |
346 | | }; |
347 | | |
348 | | /** |
349 | | * CRL Entry Reason Code Extension |
350 | | */ |
351 | | class BOTAN_PUBLIC_API(2,0) CRL_ReasonCode final : public Certificate_Extension |
352 | | { |
353 | | public: |
354 | | std::unique_ptr<Certificate_Extension> copy() const override |
355 | 0 | { return std::make_unique<CRL_ReasonCode>(m_reason); } |
356 | | |
357 | 2.19k | explicit CRL_ReasonCode(CRL_Code r = CRL_Code::UNSPECIFIED) : m_reason(r) {} |
358 | | |
359 | 577 | CRL_Code get_reason() const { return m_reason; } |
360 | | |
361 | 37.8k | static OID static_oid() { return OID("2.5.29.21"); } |
362 | 0 | OID oid_of() const override { return static_oid(); } |
363 | | |
364 | | private: |
365 | 577 | std::string oid_name() const override { return "X509v3.ReasonCode"; } |
366 | | |
367 | 0 | bool should_encode() const override { return (m_reason != CRL_Code::UNSPECIFIED); } |
368 | | std::vector<uint8_t> encode_inner() const override; |
369 | | void decode_inner(const std::vector<uint8_t>&) override; |
370 | | |
371 | | CRL_Code m_reason; |
372 | | }; |
373 | | |
374 | | /** |
375 | | * CRL Distribution Points Extension |
376 | | * todo enforce restrictions from RFC 5280 4.2.1.13 |
377 | | */ |
378 | | class BOTAN_PUBLIC_API(2,0) CRL_Distribution_Points final : public Certificate_Extension |
379 | | { |
380 | | public: |
381 | | class BOTAN_PUBLIC_API(2,0) Distribution_Point final : public ASN1_Object |
382 | | { |
383 | | public: |
384 | | void encode_into(class DER_Encoder&) const override; |
385 | | void decode_from(class BER_Decoder&) override; |
386 | | |
387 | 575 | const AlternativeName& point() const { return m_point; } |
388 | | private: |
389 | | AlternativeName m_point; |
390 | | }; |
391 | | |
392 | | std::unique_ptr<Certificate_Extension> copy() const override |
393 | 0 | { return std::make_unique<CRL_Distribution_Points>(m_distribution_points); } |
394 | | |
395 | 2.40k | CRL_Distribution_Points() = default; |
396 | | |
397 | | explicit CRL_Distribution_Points(const std::vector<Distribution_Point>& points) : |
398 | 0 | m_distribution_points(points) {} |
399 | | |
400 | | const std::vector<Distribution_Point>& distribution_points() const |
401 | 0 | { return m_distribution_points; } |
402 | | |
403 | | const std::vector<std::string>& crl_distribution_urls() const |
404 | 34 | { return m_crl_distribution_urls; } |
405 | | |
406 | 35.3k | static OID static_oid() { return OID("2.5.29.31"); } |
407 | 0 | OID oid_of() const override { return static_oid(); } |
408 | | |
409 | | private: |
410 | | std::string oid_name() const override |
411 | 34 | { return "X509v3.CRLDistributionPoints"; } |
412 | | |
413 | | bool should_encode() const override |
414 | 0 | { return !m_distribution_points.empty(); } |
415 | | |
416 | | std::vector<uint8_t> encode_inner() const override; |
417 | | void decode_inner(const std::vector<uint8_t>&) override; |
418 | | |
419 | | std::vector<Distribution_Point> m_distribution_points; |
420 | | std::vector<std::string> m_crl_distribution_urls; |
421 | | }; |
422 | | |
423 | | /** |
424 | | * CRL Issuing Distribution Point Extension |
425 | | * todo enforce restrictions from RFC 5280 5.2.5 |
426 | | */ |
427 | | class CRL_Issuing_Distribution_Point final : public Certificate_Extension |
428 | | { |
429 | | public: |
430 | 517 | CRL_Issuing_Distribution_Point() = default; |
431 | | |
432 | | explicit CRL_Issuing_Distribution_Point(const CRL_Distribution_Points::Distribution_Point& distribution_point) : |
433 | 0 | m_distribution_point(distribution_point) {} |
434 | | |
435 | | std::unique_ptr<Certificate_Extension> copy() const override |
436 | 0 | { return std::make_unique<CRL_Issuing_Distribution_Point>(m_distribution_point); } |
437 | | |
438 | | const AlternativeName& get_point() const |
439 | 2 | { return m_distribution_point.point(); } |
440 | | |
441 | 24.4k | static OID static_oid() { return OID("2.5.29.28"); } |
442 | 0 | OID oid_of() const override { return static_oid(); } |
443 | | |
444 | | private: |
445 | | std::string oid_name() const override |
446 | 2 | { return "X509v3.CRLIssuingDistributionPoint"; } |
447 | | |
448 | 0 | bool should_encode() const override { return true; } |
449 | | std::vector<uint8_t> encode_inner() const override; |
450 | | void decode_inner(const std::vector<uint8_t>&) override; |
451 | | |
452 | | CRL_Distribution_Points::Distribution_Point m_distribution_point; |
453 | | }; |
454 | | |
455 | | /** |
456 | | * An unknown X.509 extension |
457 | | * Will add a failure to the path validation result, if critical |
458 | | */ |
459 | | class BOTAN_PUBLIC_API(2,4) Unknown_Extension final : public Certificate_Extension |
460 | | { |
461 | | public: |
462 | | Unknown_Extension(const OID& oid, bool critical) : |
463 | 37.1k | m_oid(oid), m_critical(critical) {} |
464 | | |
465 | | std::unique_ptr<Certificate_Extension> copy() const override |
466 | 0 | { return std::make_unique<Unknown_Extension>(m_oid, m_critical); } |
467 | | |
468 | | /** |
469 | | * Return the OID of this unknown extension |
470 | | */ |
471 | | OID oid_of() const override |
472 | 0 | { return m_oid; } |
473 | | |
474 | | //static_oid not defined for Unknown_Extension |
475 | | |
476 | | /** |
477 | | * Return the extension contents |
478 | | */ |
479 | 0 | const std::vector<uint8_t>& extension_contents() const { return m_bytes; } |
480 | | |
481 | | /** |
482 | | * Return if this extension was marked critical |
483 | | */ |
484 | 0 | bool is_critical_extension() const { return m_critical; } |
485 | | |
486 | | void validate(const X509_Certificate&, const X509_Certificate&, |
487 | | const std::vector<X509_Certificate>&, |
488 | | std::vector<std::set<Certificate_Status_Code>>& cert_status, |
489 | | size_t pos) override |
490 | 0 | { |
491 | 0 | if(m_critical) |
492 | 0 | { |
493 | 0 | cert_status.at(pos).insert(Certificate_Status_Code::UNKNOWN_CRITICAL_EXTENSION); |
494 | 0 | } |
495 | 0 | } |
496 | | |
497 | | private: |
498 | 1.95k | std::string oid_name() const override { return ""; } |
499 | | |
500 | 0 | bool should_encode() const override { return true; } |
501 | | std::vector<uint8_t> encode_inner() const override; |
502 | | void decode_inner(const std::vector<uint8_t>&) override; |
503 | | |
504 | | OID m_oid; |
505 | | bool m_critical; |
506 | | std::vector<uint8_t> m_bytes; |
507 | | }; |
508 | | |
509 | | } |
510 | | |
511 | | } |
512 | | |
513 | | #endif |