Botan 3.0.0
Crypto and TLS for C&
pkix_types.h
Go to the documentation of this file.
1/*
2* (C) 1999-2010,2012,2018,2020 Jack Lloyd
3* (C) 2007 Yves Jerschow
4* (C) 2015 Kai Michaelis
5* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
6* (C) 2017 Fabian Weissberg, Rohde & Schwarz Cybersecurity
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#ifndef BOTAN_PKIX_TYPES_H_
12#define BOTAN_PKIX_TYPES_H_
13
14#include <botan/asn1_obj.h>
15#include <botan/pkix_enums.h>
16#include <vector>
17#include <string>
18#include <string_view>
19#include <iosfwd>
20#include <map>
21#include <set>
22
23namespace Botan {
24
25class X509_Certificate;
26class Public_Key;
27
28BOTAN_DEPRECATED("Use Key_Constraints::to_string")
30 {
31 return c.to_string();
32 }
33
34/**
35* Distinguished Name
36*/
38 {
39 public:
40 X509_DN() = default;
41
42 explicit X509_DN(const std::multimap<OID, std::string>& args)
43 {
44 for(auto i : args)
45 add_attribute(i.first, i.second);
46 }
47
48 explicit X509_DN(const std::multimap<std::string, std::string>& args)
49 {
50 for(auto i : args)
51 add_attribute(i.first, i.second);
52 }
53
54 void encode_into(DER_Encoder&) const override;
55 void decode_from(BER_Decoder&) override;
56
57 bool has_field(const OID& oid) const;
58 ASN1_String get_first_attribute(const OID& oid) const;
59
60 /*
61 * Return the BER encoded data, if any
62 */
63 const std::vector<uint8_t>& get_bits() const { return m_dn_bits; }
64
65 std::vector<uint8_t> DER_encode() const;
66
67 bool empty() const { return m_rdn.empty(); }
68
69 std::string to_string() const;
70
71 const std::vector<std::pair<OID,ASN1_String>>& dn_info() const { return m_rdn; }
72
73 std::multimap<OID, std::string> get_attributes() const;
74 std::multimap<std::string, std::string> contents() const;
75
76 bool has_field(std::string_view attr) const;
77 std::vector<std::string> get_attribute(std::string_view attr) const;
78 std::string get_first_attribute(std::string_view attr) const;
79
80 void add_attribute(std::string_view key, std::string_view val);
81
82 void add_attribute(const OID& oid, std::string_view val)
83 {
84 add_attribute(oid, ASN1_String(val));
85 }
86
87 void add_attribute(const OID& oid, const ASN1_String& val);
88
89 static std::string deref_info_field(std::string_view key);
90
91 /**
92 * Lookup upper bounds in characters for the length of distinguished name fields
93 * as given in RFC 5280, Appendix A.
94 *
95 * @param oid the oid of the DN to lookup
96 * @return the upper bound, or zero if no ub is known to Botan
97 */
98 static size_t lookup_ub(const OID& oid);
99
100 private:
101 std::vector<std::pair<OID,ASN1_String>> m_rdn;
102 std::vector<uint8_t> m_dn_bits;
103 };
104
105bool BOTAN_PUBLIC_API(2,0) operator==(const X509_DN& dn1, const X509_DN& dn2);
106bool BOTAN_PUBLIC_API(2,0) operator!=(const X509_DN& dn1, const X509_DN& dn2);
107
108/*
109The ordering here is arbitrary and may change from release to release.
110It is intended for allowing DNs as keys in std::map and similiar containers
111*/
112bool BOTAN_PUBLIC_API(2,0) operator<(const X509_DN& dn1, const X509_DN& dn2);
113
114BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& out, const X509_DN& dn);
115BOTAN_PUBLIC_API(2,0) std::istream& operator>>(std::istream& in, X509_DN& dn);
116
117/**
118* Alternative Name
119*/
121 {
122 public:
123 void encode_into(DER_Encoder&) const override;
124 void decode_from(BER_Decoder&) override;
125
126 std::multimap<std::string, std::string> contents() const;
127
128 bool has_field(std::string_view attr) const;
129 std::vector<std::string> get_attribute(std::string_view attr) const;
130
131 std::string get_first_attribute(std::string_view attr) const;
132
133 void add_attribute(std::string_view type, std::string_view value);
134 void add_othername(const OID& oid, std::string_view value, ASN1_Type type);
135
136 const std::multimap<std::string, std::string, std::less<>>& get_attributes() const
137 {
138 return m_alt_info;
139 }
140
141 const std::multimap<OID, ASN1_String>& get_othernames() const
142 {
143 return m_othernames;
144 }
145
146 X509_DN dn() const;
147
148 bool has_items() const;
149
150 AlternativeName(std::string_view email_addr = "",
151 std::string_view uri = "",
152 std::string_view dns = "",
153 std::string_view ip_address = "");
154 private:
155 std::multimap<std::string, std::string, std::less<>> m_alt_info;
156 std::multimap<OID, ASN1_String> m_othernames;
157 };
158
159/**
160* Attribute
161*/
163 {
164 public:
165 void encode_into(DER_Encoder& to) const override;
166 void decode_from(BER_Decoder& from) override;
167
168 Attribute() = default;
169 Attribute(const OID& oid, const std::vector<uint8_t>& params);
170 Attribute(std::string_view oid_str, const std::vector<uint8_t>& params);
171
172 const OID& oid() const { return m_oid; }
173 const std::vector<uint8_t>& parameters() const { return m_parameters; }
174
175 const OID& object_identifier() const { return m_oid; }
176 const std::vector<uint8_t>& get_parameters() const { return m_parameters; }
177
178 private:
179 OID m_oid;
180 std::vector<uint8_t> m_parameters;
181 };
182
183/**
184* @brief X.509 GeneralName Type
185*
186* Handles parsing GeneralName types in their BER and canonical string
187* encoding. Allows matching GeneralNames against each other using
188* the rules laid out in the RFC 5280, sec. 4.2.1.10 (Name Contraints).
189*/
191 {
192 public:
193 enum MatchResult : int
194 {
200 };
201
202 /**
203 * Creates an empty GeneralName.
204 */
205 GeneralName() = default;
206
207 /**
208 * Creates a new GeneralName for its string format.
209 * @param str type and name, colon-separated, e.g., "DNS:google.com"
210 */
211 GeneralName(const std::string& str);
212
213 void encode_into(DER_Encoder&) const override;
214
215 void decode_from(BER_Decoder&) override;
216
217 /**
218 * @return Type of the name. Can be DN, DNS, IP, RFC822 or URI.
219 */
220 const std::string& type() const { return m_type; }
221
222 /**
223 * @return The name as string. Format depends on type.
224 */
225 const std::string& name() const { return m_name; }
226
227 /**
228 * Checks whether a given certificate (partially) matches this name.
229 * @param cert certificate to be matched
230 * @return the match result
231 */
232 MatchResult matches(const X509_Certificate& cert) const;
233
234 private:
235 std::string m_type;
236 std::string m_name;
237
238 bool matches_dns(const std::string&) const;
239 bool matches_dn(const std::string&) const;
240 bool matches_ip(const std::string&) const;
241 };
242
243std::ostream& operator<<(std::ostream& os, const GeneralName& gn);
244
245/**
246* @brief A single Name Constraint
247*
248* The Name Constraint extension adds a minimum and maximum path
249* length to a GeneralName to form a constraint. The length limits
250* are currently unused.
251*/
253 {
254 public:
255 /**
256 * Creates an empty name constraint.
257 */
258 GeneralSubtree() : m_base(), m_minimum(0), m_maximum(std::numeric_limits<std::size_t>::max())
259 {}
260
261 /***
262 * Creates a new name constraint.
263 * @param base name
264 * @param min minimum path length
265 * @param max maximum path length
266 */
267 GeneralSubtree(const GeneralName& base, size_t min, size_t max)
268 : m_base(base), m_minimum(min), m_maximum(max)
269 {}
270
271 /**
272 * Creates a new name constraint for its string format.
273 * @param str name constraint
274 */
275 GeneralSubtree(const std::string& str);
276
277 void encode_into(DER_Encoder&) const override;
278
279 void decode_from(BER_Decoder&) override;
280
281 /**
282 * @return name
283 */
284 const GeneralName& base() const { return m_base; }
285
286 /**
287 * @return minimum path length
288 */
289 size_t minimum() const { return m_minimum; }
290
291 /**
292 * @return maximum path length
293 */
294 size_t maximum() const { return m_maximum; }
295
296 private:
297 GeneralName m_base;
298 size_t m_minimum;
299 size_t m_maximum;
300 };
301
302std::ostream& operator<<(std::ostream& os, const GeneralSubtree& gs);
303
304/**
305* @brief Name Constraints
306*
307* Wraps the Name Constraints associated with a certificate.
308*/
310 {
311 public:
312 /**
313 * Creates an empty name NameConstraints.
314 */
315 NameConstraints() : m_permitted_subtrees(), m_excluded_subtrees() {}
316
317 /**
318 * Creates NameConstraints from a list of permitted and excluded subtrees.
319 * @param permitted_subtrees names for which the certificate is permitted
320 * @param excluded_subtrees names for which the certificate is not permitted
321 */
322 NameConstraints(std::vector<GeneralSubtree>&& permitted_subtrees,
323 std::vector<GeneralSubtree>&& excluded_subtrees)
324 : m_permitted_subtrees(permitted_subtrees), m_excluded_subtrees(excluded_subtrees)
325 {}
326
327 /**
328 * @return permitted names
329 */
330 const std::vector<GeneralSubtree>& permitted() const { return m_permitted_subtrees; }
331
332 /**
333 * @return excluded names
334 */
335 const std::vector<GeneralSubtree>& excluded() const { return m_excluded_subtrees; }
336
337 private:
338 std::vector<GeneralSubtree> m_permitted_subtrees;
339 std::vector<GeneralSubtree> m_excluded_subtrees;
340 };
341
342/**
343* X.509 Certificate Extension
344*/
346 {
347 public:
348 /**
349 * @return OID representing this extension
350 */
351 virtual OID oid_of() const = 0;
352
353 /*
354 * @return specific OID name
355 * If possible OIDS table should match oid_name to OIDS, ie
356 * OID::from_string(ext->oid_name()) == ext->oid_of()
357 * Should return empty string if OID is not known
358 */
359 virtual std::string oid_name() const = 0;
360
361 /**
362 * Make a copy of this extension
363 * @return copy of this
364 */
365
366 virtual std::unique_ptr<Certificate_Extension> copy() const = 0;
367
368 /*
369 * Callback visited during path validation.
370 *
371 * An extension can implement this callback to inspect
372 * the path during path validation.
373 *
374 * If an error occurs during validation of this extension,
375 * an appropriate status code shall be added to cert_status.
376 *
377 * @param subject Subject certificate that contains this extension
378 * @param issuer Issuer certificate
379 * @param status Certificate validation status codes for subject certificate
380 * @param cert_path Certificate path which is currently validated
381 * @param pos Position of subject certificate in cert_path
382 */
383 virtual void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
384 const std::vector<X509_Certificate>& cert_path,
385 std::vector<std::set<Certificate_Status_Code>>& cert_status,
386 size_t pos);
387
388 virtual ~Certificate_Extension() = default;
389 protected:
390 friend class Extensions;
391 virtual bool should_encode() const { return true; }
392 virtual std::vector<uint8_t> encode_inner() const = 0;
393 virtual void decode_inner(const std::vector<uint8_t>&) = 0;
394 };
395
396/**
397* X.509 Certificate Extension List
398*/
400 {
401 public:
402 /**
403 * Look up an object in the extensions, based on OID Returns
404 * nullptr if not set, if the extension was either absent or not
405 * handled. The pointer returned is owned by the Extensions
406 * object.
407 * This would be better with an optional<T> return value
408 */
409 const Certificate_Extension* get_extension_object(const OID& oid) const;
410
411 template<typename T>
412 const T* get_extension_object_as(const OID& oid = T::static_oid()) const
413 {
414 if(const Certificate_Extension* extn = get_extension_object(oid))
415 {
416 // Unknown_Extension oid_name is empty
417 if(extn->oid_name().empty())
418 {
419 return nullptr;
420 }
421 else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
422 {
423 return extn_as_T;
424 }
425 else
426 {
427 throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
428 }
429 }
430
431 return nullptr;
432 }
433
434 /**
435 * Return the set of extensions in the order they appeared in the certificate
436 * (or as they were added, if constructed)
437 */
438 const std::vector<OID>& get_extension_oids() const
439 {
440 return m_extension_oids;
441 }
442
443 /**
444 * Return true if an extension was set
445 */
446 bool extension_set(const OID& oid) const;
447
448 /**
449 * Return true if an extesion was set and marked critical
450 */
451 bool critical_extension_set(const OID& oid) const;
452
453 /**
454 * Return the raw bytes of the extension
455 * Will throw if OID was not set as an extension.
456 */
457 std::vector<uint8_t> get_extension_bits(const OID& oid) const;
458
459 void encode_into(DER_Encoder&) const override;
460 void decode_from(BER_Decoder&) override;
461
462 /**
463 * Adds a new extension to the list.
464 * @param extn pointer to the certificate extension (Extensions takes ownership)
465 * @param critical whether this extension should be marked as critical
466 * @throw Invalid_Argument if the extension is already present in the list
467 */
468 void add(std::unique_ptr<Certificate_Extension> extn, bool critical = false);
469
470 /**
471 * Adds a new extension to the list unless it already exists. If the extension
472 * already exists within the Extensions object, the extn pointer will be deleted.
473 *
474 * @param extn pointer to the certificate extension (Extensions takes ownership)
475 * @param critical whether this extension should be marked as critical
476 * @return true if the object was added false if the extension was already used
477 */
478 bool add_new(std::unique_ptr<Certificate_Extension> extn, bool critical = false);
479
480 /**
481 * Adds an extension to the list or replaces it.
482 * @param extn the certificate extension
483 * @param critical whether this extension should be marked as critical
484 */
485 void replace(std::unique_ptr<Certificate_Extension> extn, bool critical = false);
486
487 /**
488 * Remove an extension from the list. Returns true if the
489 * extension had been set, false otherwise.
490 */
491 bool remove(const OID& oid);
492
493 /**
494 * Searches for an extension by OID and returns the result.
495 * Only the known extensions types declared in this header
496 * are searched for by this function.
497 * @return Copy of extension with oid, nullptr if not found.
498 * Can avoid creating a copy by using get_extension_object function
499 */
500 std::unique_ptr<Certificate_Extension> get(const OID& oid) const;
501
502 /**
503 * Searches for an extension by OID and returns the result decoding
504 * it to some arbitrary extension type chosen by the application.
505 *
506 * Only the unknown extensions, that is, extensions types that
507 * are not declared in this header, are searched for by this
508 * function.
509 *
510 * @return Pointer to new extension with oid, nullptr if not found.
511 */
512 template<typename T>
513 std::unique_ptr<T> get_raw(const OID& oid) const
514 {
515 auto extn_info = m_extension_info.find(oid);
516
517 if(extn_info != m_extension_info.end())
518 {
519 // Unknown_Extension oid_name is empty
520 if(extn_info->second.obj().oid_name() == "")
521 {
522 auto ext = std::make_unique<T>();
523 ext->decode_inner(extn_info->second.bits());
524 return ext;
525 }
526 }
527 return nullptr;
528 }
529
530 /**
531 * Returns a copy of the list of extensions together with the corresponding
532 * criticality flag. All extensions are encoded as some object, falling back
533 * to Unknown_Extension class which simply allows reading the bytes as well
534 * as the criticality flag.
535 */
536 std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const;
537
538 /**
539 * Returns the list of extensions as raw, encoded bytes
540 * together with the corresponding criticality flag.
541 * Contains all extensions, including any extensions encoded as Unknown_Extension
542 */
543 std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const;
544
546
547 Extensions(const Extensions&) = default;
548 Extensions& operator=(const Extensions&) = default;
549
550 Extensions(Extensions&&) = default;
552
553 private:
554 static std::unique_ptr<Certificate_Extension>
555 create_extn_obj(const OID& oid,
556 bool critical,
557 const std::vector<uint8_t>& body);
558
559 class Extensions_Info
560 {
561 public:
562 Extensions_Info(bool critical,
563 std::unique_ptr<Certificate_Extension> ext) :
564 m_obj(std::move(ext)),
565 m_bits(m_obj->encode_inner()),
566 m_critical(critical)
567 {
568 }
569
570 Extensions_Info(bool critical,
571 const std::vector<uint8_t>& encoding,
572 std::unique_ptr<Certificate_Extension> ext) :
573 m_obj(std::move(ext)),
574 m_bits(encoding),
575 m_critical(critical)
576 {
577 }
578
579 bool is_critical() const { return m_critical; }
580 const std::vector<uint8_t>& bits() const { return m_bits; }
581 const Certificate_Extension& obj() const
582 {
583 BOTAN_ASSERT_NONNULL(m_obj.get());
584 return *m_obj.get();
585 }
586
587 private:
588 std::shared_ptr<Certificate_Extension> m_obj;
589 std::vector<uint8_t> m_bits;
590 bool m_critical = false;
591 };
592
593 std::vector<OID> m_extension_oids;
594 std::map<OID, Extensions_Info> m_extension_info;
595 };
596
597}
598
599#endif
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106
const std::multimap< std::string, std::string, std::less<> > & get_attributes() const
Definition: pkix_types.h:136
const std::multimap< OID, ASN1_String > & get_othernames() const
Definition: pkix_types.h:141
const std::vector< uint8_t > & parameters() const
Definition: pkix_types.h:173
const OID & object_identifier() const
Definition: pkix_types.h:175
const OID & oid() const
Definition: pkix_types.h:172
Attribute()=default
const std::vector< uint8_t > & get_parameters() const
Definition: pkix_types.h:176
virtual bool should_encode() const
Definition: pkix_types.h:391
virtual std::string oid_name() const =0
virtual OID oid_of() const =0
virtual std::unique_ptr< Certificate_Extension > copy() const =0
virtual std::vector< uint8_t > encode_inner() const =0
virtual ~Certificate_Extension()=default
virtual void decode_inner(const std::vector< uint8_t > &)=0
std::unique_ptr< T > get_raw(const OID &oid) const
Definition: pkix_types.h:513
Extensions & operator=(const Extensions &)=default
Extensions(const Extensions &)=default
Extensions(Extensions &&)=default
const std::vector< OID > & get_extension_oids() const
Definition: pkix_types.h:438
const T * get_extension_object_as(const OID &oid=T::static_oid()) const
Definition: pkix_types.h:412
Extensions & operator=(Extensions &&)=default
X.509 GeneralName Type.
Definition: pkix_types.h:191
GeneralName()=default
const std::string & type() const
Definition: pkix_types.h:220
const std::string & name() const
Definition: pkix_types.h:225
A single Name Constraint.
Definition: pkix_types.h:253
size_t maximum() const
Definition: pkix_types.h:294
GeneralSubtree(const GeneralName &base, size_t min, size_t max)
Definition: pkix_types.h:267
size_t minimum() const
Definition: pkix_types.h:289
const GeneralName & base() const
Definition: pkix_types.h:284
Name Constraints.
Definition: pkix_types.h:310
NameConstraints(std::vector< GeneralSubtree > &&permitted_subtrees, std::vector< GeneralSubtree > &&excluded_subtrees)
Definition: pkix_types.h:322
const std::vector< GeneralSubtree > & permitted() const
Definition: pkix_types.h:330
const std::vector< GeneralSubtree > & excluded() const
Definition: pkix_types.h:335
void add_attribute(const OID &oid, std::string_view val)
Definition: pkix_types.h:82
X509_DN()=default
X509_DN(const std::multimap< OID, std::string > &args)
Definition: pkix_types.h:42
const std::vector< std::pair< OID, ASN1_String > > & dn_info() const
Definition: pkix_types.h:71
X509_DN(const std::multimap< std::string, std::string > &args)
Definition: pkix_types.h:48
bool empty() const
Definition: pkix_types.h:67
const std::vector< uint8_t > & get_bits() const
Definition: pkix_types.h:63
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
FE_25519 T
Definition: ge.cpp:36
Definition: alg_id.cpp:12
ASN1_Type
Definition: asn1_obj.h:43
std::ostream & operator<<(std::ostream &out, const OID &oid)
Definition: asn1_oid.cpp:150
std::string key_constraints_to_string(Key_Constraints c)
Definition: pkix_types.h:29
Definition: bigint.h:1092