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