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