Botan  2.1.0
Crypto and TLS for C++11
x509_ext.h
Go to the documentation of this file.
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/datastor.h>
16 #include <botan/name_constraint.h>
17 #include <botan/key_constraint.h>
18 #include <botan/crl_ent.h>
19 
20 namespace Botan {
21 
22 class X509_Certificate;
23 
24 /**
25 * X.509 Certificate Extension
26 */
27 class BOTAN_DLL Certificate_Extension
28  {
29  public:
30  /**
31  * @return OID representing this extension
32  */
33  virtual OID oid_of() const;
34 
35  /**
36  * Make a copy of this extension
37  * @return copy of this
38  */
39  virtual Certificate_Extension* copy() const = 0;
40 
41  /*
42  * Add the contents of this extension into the information
43  * for the subject and/or issuer, as necessary.
44  * @param subject the subject info
45  * @param issuer the issuer info
46  */
47  virtual void contents_to(Data_Store& subject,
48  Data_Store& issuer) const = 0;
49 
50  /*
51  * @return specific OID name
52  */
53  virtual std::string oid_name() const = 0;
54 
55  /*
56  * Callback visited during path validation.
57  *
58  * An extension can implement this callback to inspect
59  * the path during path validation.
60  *
61  * If an error occurs during validation of this extension,
62  * an appropriate status code shall be added to cert_status.
63  *
64  * @param subject Subject certificate that contains this extension
65  * @param issuer Issuer certificate
66  * @param status Certificate validation status codes for subject certificate
67  * @param cert_path Certificate path which is currently validated
68  * @param pos Position of subject certificate in cert_path
69  */
70  virtual void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
71  const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
72  std::vector<std::set<Certificate_Status_Code>>& cert_status,
73  size_t pos);
74 
75  virtual ~Certificate_Extension() = default;
76  protected:
77  friend class Extensions;
78  virtual bool should_encode() const { return true; }
79  virtual std::vector<uint8_t> encode_inner() const = 0;
80  virtual void decode_inner(const std::vector<uint8_t>&) = 0;
81  };
82 
83 /**
84 * X.509 Certificate Extension List
85 */
86 class BOTAN_DLL Extensions : public ASN1_Object
87  {
88  public:
89  void encode_into(class DER_Encoder&) const override;
90  void decode_from(class BER_Decoder&) override;
91  void contents_to(Data_Store&, Data_Store&) const;
92 
93  /**
94  * Adds a new extension to the list.
95  * @param extn the certificate extension
96  * @param critical whether this extension should be marked as critical
97  * @throw Invalid_Argument if the extension is already present in the list
98  */
99  void add(Certificate_Extension* extn, bool critical = false);
100 
101  /**
102  * Adds an extension to the list or replaces it.
103  * @param extn the certificate extension
104  * @param critical whether this extension should be marked as critical
105  */
106  void replace(Certificate_Extension* extn, bool critical = false);
107 
108  /**
109  * Searches for an extension by OID and returns the result.
110  * Only the known extensions types declared in this header
111  * are searched for by this function.
112  * @return Pointer to extension with oid, nullptr if not found.
113  */
114  std::unique_ptr<Certificate_Extension> get(const OID& oid) const;
115 
116  /**
117  * Searches for an extension by OID and returns the result.
118  * Only the unknown extensions, that is, extensions
119  * types that are not declared in this header, are searched
120  * for by this function.
121  * @return Pointer to extension with oid, nullptr if not found.
122  */
123  template<typename T>
124  std::unique_ptr<T> get_raw(const OID& oid)
125  {
126  try
127  {
128  if(m_extensions_raw.count(oid) > 0)
129  {
130  std::unique_ptr<T> ext(new T);
131  ext->decode_inner(m_extensions_raw[oid].first);
132  return std::move(ext);
133  }
134  }
135  catch(std::exception& e)
136  {
137  throw Decoding_Error("Exception while decoding extension " +
138  oid.as_string() + ": " + e.what());
139  }
140  return nullptr;
141  }
142 
143  /**
144  * Returns the list of extensions together with the corresponding
145  * criticality flag. Only contains the known extensions
146  * types declared in this header.
147  */
148  std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const;
149 
150  /**
151  * Returns the list of extensions as raw, encoded bytes
152  * together with the corresponding criticality flag.
153  * Contains all extensions, known as well as unknown extensions.
154  */
155  std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const;
156 
157  Extensions& operator=(const Extensions&);
158 
159  Extensions(const Extensions&);
160 
161  /**
162  * @param st whether to throw an exception when encountering an unknown
163  * extension type during decoding
164  */
165  explicit Extensions(bool st = true) : m_throw_on_unknown_critical(st) {}
166 
167  private:
168  static Certificate_Extension* create_extension(const OID&, bool);
169 
170  std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> m_extensions;
171  bool m_throw_on_unknown_critical;
172  std::map<OID, std::pair<std::vector<uint8_t>, bool>> m_extensions_raw;
173  };
174 
175 namespace Cert_Extension {
176 
177 static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
178 
179 /**
180 * Basic Constraints Extension
181 */
182 class BOTAN_DLL Basic_Constraints final : public Certificate_Extension
183  {
184  public:
185  Basic_Constraints* copy() const override
186  { return new Basic_Constraints(m_is_ca, m_path_limit); }
187 
188  Basic_Constraints(bool ca = false, size_t limit = 0) :
189  m_is_ca(ca), m_path_limit(limit) {}
190 
191  bool get_is_ca() const { return m_is_ca; }
192  size_t get_path_limit() const;
193 
194  private:
195  std::string oid_name() const override
196  { return "X509v3.BasicConstraints"; }
197 
198  std::vector<uint8_t> encode_inner() const override;
199  void decode_inner(const std::vector<uint8_t>&) override;
200  void contents_to(Data_Store&, Data_Store&) const override;
201 
202  bool m_is_ca;
203  size_t m_path_limit;
204  };
205 
206 /**
207 * Key Usage Constraints Extension
208 */
209 class BOTAN_DLL Key_Usage final : public Certificate_Extension
210  {
211  public:
212  Key_Usage* copy() const override { return new Key_Usage(m_constraints); }
213 
214  explicit Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : m_constraints(c) {}
215 
216  Key_Constraints get_constraints() const { return m_constraints; }
217 
218  private:
219  std::string oid_name() const override { return "X509v3.KeyUsage"; }
220 
221  bool should_encode() const override
222  { return (m_constraints != NO_CONSTRAINTS); }
223  std::vector<uint8_t> encode_inner() const override;
224  void decode_inner(const std::vector<uint8_t>&) override;
225  void contents_to(Data_Store&, Data_Store&) const override;
226 
227  Key_Constraints m_constraints;
228  };
229 
230 /**
231 * Subject Key Identifier Extension
232 */
233 class BOTAN_DLL Subject_Key_ID final : public Certificate_Extension
234  {
235  public:
236  Subject_Key_ID* copy() const override
237  { return new Subject_Key_ID(m_key_id); }
238 
239  Subject_Key_ID() = default;
240  explicit Subject_Key_ID(const std::vector<uint8_t>&);
241 
242  std::vector<uint8_t> get_key_id() const { return m_key_id; }
243  private:
244  std::string oid_name() const override
245  { return "X509v3.SubjectKeyIdentifier"; }
246 
247  bool should_encode() const override { return (m_key_id.size() > 0); }
248  std::vector<uint8_t> encode_inner() const override;
249  void decode_inner(const std::vector<uint8_t>&) override;
250  void contents_to(Data_Store&, Data_Store&) const override;
251 
252  std::vector<uint8_t> m_key_id;
253  };
254 
255 /**
256 * Authority Key Identifier Extension
257 */
258 class BOTAN_DLL Authority_Key_ID final : public Certificate_Extension
259  {
260  public:
261  Authority_Key_ID* copy() const override
262  { return new Authority_Key_ID(m_key_id); }
263 
264  Authority_Key_ID() = default;
265  explicit Authority_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {}
266 
267  std::vector<uint8_t> get_key_id() const { return m_key_id; }
268 
269  private:
270  std::string oid_name() const override
271  { return "X509v3.AuthorityKeyIdentifier"; }
272 
273  bool should_encode() const override { return (m_key_id.size() > 0); }
274  std::vector<uint8_t> encode_inner() const override;
275  void decode_inner(const std::vector<uint8_t>&) override;
276  void contents_to(Data_Store&, Data_Store&) const override;
277 
278  std::vector<uint8_t> m_key_id;
279  };
280 
281 /**
282 * Alternative Name Extension Base Class
283 */
284 class BOTAN_DLL Alternative_Name : public Certificate_Extension
285  {
286  public:
287  AlternativeName get_alt_name() const { return m_alt_name; }
288 
289  protected:
290  Alternative_Name(const AlternativeName&, const std::string& oid_name);
291 
292  Alternative_Name(const std::string&, const std::string&);
293 
294  private:
295  std::string oid_name() const override { return m_oid_name_str; }
296 
297  bool should_encode() const override { return m_alt_name.has_items(); }
298  std::vector<uint8_t> encode_inner() const override;
299  void decode_inner(const std::vector<uint8_t>&) override;
300  void contents_to(Data_Store&, Data_Store&) const override;
301 
302  std::string m_oid_name_str;
303  AlternativeName m_alt_name;
304  };
305 
306 /**
307 * Subject Alternative Name Extension
308 */
310  {
311  public:
312  Subject_Alternative_Name* copy() const override
313  { return new Subject_Alternative_Name(get_alt_name()); }
314 
316  };
317 
318 /**
319 * Issuer Alternative Name Extension
320 */
322  {
323  public:
324  Issuer_Alternative_Name* copy() const override
325  { return new Issuer_Alternative_Name(get_alt_name()); }
326 
328  };
329 
330 /**
331 * Extended Key Usage Extension
332 */
333 class BOTAN_DLL Extended_Key_Usage final : public Certificate_Extension
334  {
335  public:
336  Extended_Key_Usage* copy() const override
337  { return new Extended_Key_Usage(m_oids); }
338 
339  Extended_Key_Usage() = default;
340  explicit Extended_Key_Usage(const std::vector<OID>& o) : m_oids(o) {}
341 
342  std::vector<OID> get_oids() const { return m_oids; }
343 
344  private:
345  std::string oid_name() const override
346  { return "X509v3.ExtendedKeyUsage"; }
347 
348  bool should_encode() const override { return (m_oids.size() > 0); }
349  std::vector<uint8_t> encode_inner() const override;
350  void decode_inner(const std::vector<uint8_t>&) override;
351  void contents_to(Data_Store&, Data_Store&) const override;
352 
353  std::vector<OID> m_oids;
354  };
355 
356 /**
357 * Name Constraints
358 */
359 class BOTAN_DLL Name_Constraints : public Certificate_Extension
360  {
361  public:
362  Name_Constraints* copy() const override
363  { return new Name_Constraints(m_name_constraints); }
364 
365  Name_Constraints() = default;
366  Name_Constraints(const NameConstraints &nc) : m_name_constraints(nc) {}
367 
368  void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
369  const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
370  std::vector<std::set<Certificate_Status_Code>>& cert_status,
371  size_t pos) override;
372 
373  private:
374  std::string oid_name() const override
375  { return "X509v3.NameConstraints"; }
376 
377  bool should_encode() const override { return true; }
378  std::vector<uint8_t> encode_inner() const override;
379  void decode_inner(const std::vector<uint8_t>&) override;
380  void contents_to(Data_Store&, Data_Store&) const override;
381 
382  NameConstraints m_name_constraints;
383  };
384 
385 /**
386 * Certificate Policies Extension
387 */
388 class BOTAN_DLL Certificate_Policies final : public Certificate_Extension
389  {
390  public:
391  Certificate_Policies* copy() const override
392  { return new Certificate_Policies(m_oids); }
393 
394  Certificate_Policies() = default;
395  explicit Certificate_Policies(const std::vector<OID>& o) : m_oids(o) {}
396 
397  std::vector<OID> get_oids() const { return m_oids; }
398 
399  private:
400  std::string oid_name() const override
401  { return "X509v3.CertificatePolicies"; }
402 
403  bool should_encode() const override { return (m_oids.size() > 0); }
404  std::vector<uint8_t> encode_inner() const override;
405  void decode_inner(const std::vector<uint8_t>&) override;
406  void contents_to(Data_Store&, Data_Store&) const override;
407 
408  std::vector<OID> m_oids;
409  };
410 
412  {
413  public:
415  { return new Authority_Information_Access(m_ocsp_responder); }
416 
417  Authority_Information_Access() = default;
418 
419  explicit Authority_Information_Access(const std::string& ocsp) :
420  m_ocsp_responder(ocsp) {}
421 
422  private:
423  std::string oid_name() const override
424  { return "PKIX.AuthorityInformationAccess"; }
425 
426  bool should_encode() const override { return (!m_ocsp_responder.empty()); }
427 
428  std::vector<uint8_t> encode_inner() const override;
429  void decode_inner(const std::vector<uint8_t>&) override;
430 
431  void contents_to(Data_Store&, Data_Store&) const override;
432 
433  std::string m_ocsp_responder;
434  };
435 
436 /**
437 * CRL Number Extension
438 */
439 class BOTAN_DLL CRL_Number final : public Certificate_Extension
440  {
441  public:
442  CRL_Number* copy() const override;
443 
444  CRL_Number() : m_has_value(false), m_crl_number(0) {}
445  CRL_Number(size_t n) : m_has_value(true), m_crl_number(n) {}
446 
447  size_t get_crl_number() const;
448 
449  private:
450  std::string oid_name() const override { return "X509v3.CRLNumber"; }
451 
452  bool should_encode() const override { return m_has_value; }
453  std::vector<uint8_t> encode_inner() const override;
454  void decode_inner(const std::vector<uint8_t>&) override;
455  void contents_to(Data_Store&, Data_Store&) const override;
456 
457  bool m_has_value;
458  size_t m_crl_number;
459  };
460 
461 /**
462 * CRL Entry Reason Code Extension
463 */
464 class BOTAN_DLL CRL_ReasonCode final : public Certificate_Extension
465  {
466  public:
467  CRL_ReasonCode* copy() const override
468  { return new CRL_ReasonCode(m_reason); }
469 
470  explicit CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : m_reason(r) {}
471 
472  CRL_Code get_reason() const { return m_reason; }
473 
474  private:
475  std::string oid_name() const override { return "X509v3.ReasonCode"; }
476 
477  bool should_encode() const override { return (m_reason != UNSPECIFIED); }
478  std::vector<uint8_t> encode_inner() const override;
479  void decode_inner(const std::vector<uint8_t>&) override;
480  void contents_to(Data_Store&, Data_Store&) const override;
481 
482  CRL_Code m_reason;
483  };
484 
485 /**
486 * CRL Distribution Points Extension
487 */
488 class BOTAN_DLL CRL_Distribution_Points final : public Certificate_Extension
489  {
490  public:
491  class BOTAN_DLL Distribution_Point final : public ASN1_Object
492  {
493  public:
494  void encode_into(class DER_Encoder&) const override;
495  void decode_from(class BER_Decoder&) override;
496 
497  const AlternativeName& point() const { return m_point; }
498  private:
499  AlternativeName m_point;
500  };
501 
502  CRL_Distribution_Points* copy() const override
503  { return new CRL_Distribution_Points(m_distribution_points); }
504 
505  CRL_Distribution_Points() = default;
506 
507  explicit CRL_Distribution_Points(const std::vector<Distribution_Point>& points) :
508  m_distribution_points(points) {}
509 
510  std::vector<Distribution_Point> distribution_points() const
511  { return m_distribution_points; }
512 
513  private:
514  std::string oid_name() const override
515  { return "X509v3.CRLDistributionPoints"; }
516 
517  bool should_encode() const override
518  { return !m_distribution_points.empty(); }
519 
520  std::vector<uint8_t> encode_inner() const override;
521  void decode_inner(const std::vector<uint8_t>&) override;
522  void contents_to(Data_Store&, Data_Store&) const override;
523 
524  std::vector<Distribution_Point> m_distribution_points;
525  };
526 
527 /**
528 * An unknown X.509 extension marked as critical
529 * Will always add a failure to the path validation result.
530 */
531 class BOTAN_DLL Unknown_Critical_Extension final : public Certificate_Extension
532  {
533  public:
534  explicit Unknown_Critical_Extension(OID oid) : m_oid(oid) {}
535 
537  { return new Unknown_Critical_Extension(m_oid); }
538 
539  OID oid_of() const override
540  { return m_oid; }
541 
543  const std::vector<std::shared_ptr<const X509_Certificate>>&,
544  std::vector<std::set<Certificate_Status_Code>>& cert_status,
545  size_t pos) override
546  {
547  cert_status.at(pos).insert(Certificate_Status_Code::UNKNOWN_CRITICAL_EXTENSION);
548  }
549 
550  private:
551  std::string oid_name() const override
552  { return "Unknown OID name"; }
553 
554  bool should_encode() const override { return false; }
555  std::vector<uint8_t> encode_inner() const override;
556  void decode_inner(const std::vector<uint8_t>&) override;
557  void contents_to(Data_Store&, Data_Store&) const override;
558 
559  OID m_oid;
560  };
561 
562 }
563 
564 }
565 
566 #endif
CRL_Distribution_Points * copy() const override
Definition: x509_ext.h:502
std::vector< uint8_t > get_key_id() const
Definition: x509_ext.h:267
std::vector< uint8_t > get_key_id() const
Definition: x509_ext.h:242
Key_Usage * copy() const override
Definition: x509_ext.h:212
OID m_oid
Definition: x509_ext.cpp:682
Authority_Information_Access(const std::string &ocsp)
Definition: x509_ext.h:419
Key_Constraints get_constraints() const
Definition: x509_ext.h:216
void validate(const X509_Certificate &, const X509_Certificate &, const std::vector< std::shared_ptr< const X509_Certificate >> &, std::vector< std::set< Certificate_Status_Code >> &cert_status, size_t pos) override
Definition: x509_ext.h:542
Subject_Alternative_Name * copy() const override
Definition: x509_ext.h:312
Authority_Key_ID(const std::vector< uint8_t > &k)
Definition: x509_ext.h:265
Certificate_Policies(const std::vector< OID > &o)
Definition: x509_ext.h:395
Basic_Constraints(bool ca=false, size_t limit=0)
Definition: x509_ext.h:188
std::vector< OID > get_oids() const
Definition: x509_ext.h:397
CRL_ReasonCode * copy() const override
Definition: x509_ext.h:467
Name_Constraints * copy() const override
Definition: x509_ext.h:362
CRL_Distribution_Points(const std::vector< Distribution_Point > &points)
Definition: x509_ext.h:507
virtual bool should_encode() const
Definition: x509_ext.h:78
Basic_Constraints * copy() const override
Definition: x509_ext.h:185
std::vector< OID > get_oids() const
Definition: x509_ext.h:342
Definition: alg_id.cpp:13
std::vector< Distribution_Point > distribution_points() const
Definition: x509_ext.h:510
Extended_Key_Usage(const std::vector< OID > &o)
Definition: x509_ext.h:340
Name_Constraints(const NameConstraints &nc)
Definition: x509_ext.h:366
Extensions(bool st=true)
Definition: x509_ext.h:165
AlternativeName get_alt_name() const
Definition: x509_ext.h:287
std::string as_string() const
Definition: asn1_oid.cpp:50
Key_Usage(Key_Constraints c=NO_CONSTRAINTS)
Definition: x509_ext.h:214
std::unique_ptr< T > get_raw(const OID &oid)
Definition: x509_ext.h:124
CRL_Code
Definition: crl_ent.h:20
Issuer_Alternative_Name * copy() const override
Definition: x509_ext.h:324
CRL_ReasonCode(CRL_Code r=UNSPECIFIED)
Definition: x509_ext.h:470
Extended_Key_Usage * copy() const override
Definition: x509_ext.h:336
Authority_Information_Access * copy() const override
Definition: x509_ext.h:414
Unknown_Critical_Extension * copy() const override
Definition: x509_ext.h:536
Authority_Key_ID * copy() const override
Definition: x509_ext.h:261
Subject_Key_ID * copy() const override
Definition: x509_ext.h:236
Certificate_Policies * copy() const override
Definition: x509_ext.h:391
Name Constraints.