Botan  2.11.0
Crypto and TLS for C++11
x509path.h
Go to the documentation of this file.
1 /*
2 * X.509 Cert Path Validation
3 * (C) 2010-2011 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #ifndef BOTAN_X509_CERT_PATH_VALIDATION_H_
9 #define BOTAN_X509_CERT_PATH_VALIDATION_H_
10 
11 #include <botan/cert_status.h>
12 #include <botan/x509cert.h>
13 #include <botan/certstor.h>
14 #include <botan/ocsp.h>
15 #include <functional>
16 #include <set>
17 #include <chrono>
18 
19 #if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_HTTP_UTIL)
20  #define BOTAN_HAS_ONLINE_REVOCATION_CHECKS
21 #endif
22 
23 namespace Botan {
24 
25 /**
26 * This type represents the validation status of an entire certificate path.
27 * There is one set of status codes for each certificate in the path.
28 */
29 typedef std::vector<std::set<Certificate_Status_Code>> CertificatePathStatusCodes;
30 
31 /**
32 * Specifies restrictions on the PKIX path validation
33 */
34 class BOTAN_PUBLIC_API(2,0) Path_Validation_Restrictions final
35  {
36  public:
37  /**
38  * @param require_rev if true, revocation information is required
39 
40  * @param minimum_key_strength is the minimum strength (in terms of
41  * operations, eg 80 means 2^80) of a signature. Signatures weaker than
42  * this are rejected. If more than 80, SHA-1 signatures are also
43  * rejected. If possible use at least setting 110.
44  *
45  * 80 bit strength requires 1024 bit RSA
46  * 110 bit strength requires 2k bit RSA
47  * 128 bit strength requires ~3k bit RSA or P-256
48  * @param ocsp_all_intermediates Make OCSP requests for all CAs as
49  * well as end entity (if OCSP enabled in path validation request)
50  * @param max_ocsp_age maximum age of OCSP responses w/o next_update.
51  * If zero, there is no maximum age
52  */
53  Path_Validation_Restrictions(bool require_rev = false,
54  size_t minimum_key_strength = 110,
55  bool ocsp_all_intermediates = false,
56  std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
57 
58  /**
59  * @param require_rev if true, revocation information is required
60  * @param minimum_key_strength is the minimum strength (in terms of
61  * operations, eg 80 means 2^80) of a signature. Signatures
62  * weaker than this are rejected.
63  * @param ocsp_all_intermediates Make OCSP requests for all CAs as
64  * well as end entity (if OCSP enabled in path validation request)
65  * @param trusted_hashes a set of trusted hashes. Any signatures
66  * created using a hash other than one of these will be
67  * rejected.
68  * @param max_ocsp_age maximum age of OCSP responses w/o next_update.
69  * If zero, there is no maximum age
70  */
71  Path_Validation_Restrictions(bool require_rev,
72  size_t minimum_key_strength,
73  bool ocsp_all_intermediates,
74  const std::set<std::string>& trusted_hashes,
75  std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero()) :
76  m_require_revocation_information(require_rev),
77  m_ocsp_all_intermediates(ocsp_all_intermediates),
78  m_trusted_hashes(trusted_hashes),
79  m_minimum_key_strength(minimum_key_strength),
80  m_max_ocsp_age(max_ocsp_age) {}
81 
82  /**
83  * @return whether revocation information is required
84  */
85  bool require_revocation_information() const
86  { return m_require_revocation_information; }
87 
88  /**
89  * @return whether all intermediate CAs should also be OCSPed. If false
90  * then only end entity OCSP is required/requested.
91  */
92  bool ocsp_all_intermediates() const
93  { return m_ocsp_all_intermediates; }
94 
95  /**
96  * @return trusted signature hash functions
97  */
98  const std::set<std::string>& trusted_hashes() const
99  { return m_trusted_hashes; }
100 
101  /**
102  * @return minimum required key strength
103  */
104  size_t minimum_key_strength() const
105  { return m_minimum_key_strength; }
106 
107  /**
108  * @return maximum age of OCSP responses w/o next_update.
109  * If zero, there is no maximum age
110  */
111  std::chrono::seconds max_ocsp_age() const
112  { return m_max_ocsp_age; }
113 
114  private:
115  bool m_require_revocation_information;
116  bool m_ocsp_all_intermediates;
117  std::set<std::string> m_trusted_hashes;
118  size_t m_minimum_key_strength;
119  std::chrono::seconds m_max_ocsp_age;
120  };
121 
122 /**
123 * Represents the result of a PKIX path validation
124 */
125 class BOTAN_PUBLIC_API(2,0) Path_Validation_Result final
126  {
127  public:
128  typedef Certificate_Status_Code Code;
129 
130  /**
131  * @return the set of hash functions you are implicitly
132  * trusting by trusting this result.
133  */
134  std::set<std::string> trusted_hashes() const;
135 
136  /**
137  * @return the trust root of the validation if successful
138  * throws an exception if the validation failed
139  */
140  const X509_Certificate& trust_root() const;
141 
142  /**
143  * @return the full path from subject to trust root
144  * This path may be empty
145  */
146  const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path() const { return m_cert_path; }
147 
148  /**
149  * @return true iff the validation was successful
150  */
151  bool successful_validation() const;
152 
153  /**
154  * @return true iff no warnings occured during validation
155  */
156  bool no_warnings() const;
157 
158  /**
159  * @return overall validation result code
160  */
161  Certificate_Status_Code result() const { return m_overall; }
162 
163  /**
164  * @return a set of status codes for each certificate in the chain
165  */
166  const CertificatePathStatusCodes& all_statuses() const
167  { return m_all_status; }
168 
169  /**
170  * @return the subset of status codes that are warnings
171  */
172  CertificatePathStatusCodes warnings() const;
173 
174  /**
175  * @return string representation of the validation result
176  */
177  std::string result_string() const;
178 
179  /**
180  * @return string representation of the warnings
181  */
182  std::string warnings_string() const;
183 
184  /**
185  * @param code validation status code
186  * @return corresponding validation status message
187  */
188  static const char* status_string(Certificate_Status_Code code);
189 
190  /**
191  * Create a Path_Validation_Result
192  * @param status list of validation status codes
193  * @param cert_chain the certificate chain that was validated
194  */
195  Path_Validation_Result(CertificatePathStatusCodes status,
196  std::vector<std::shared_ptr<const X509_Certificate>>&& cert_chain);
197 
198  /**
199  * Create a Path_Validation_Result
200  * @param status validation status code
201  */
202  explicit Path_Validation_Result(Certificate_Status_Code status) : m_overall(status) {}
203 
204  private:
205  CertificatePathStatusCodes m_all_status;
206  CertificatePathStatusCodes m_warnings;
207  std::vector<std::shared_ptr<const X509_Certificate>> m_cert_path;
208  Certificate_Status_Code m_overall;
209  };
210 
211 /**
212 * PKIX Path Validation
213 * @param end_certs certificate chain to validate (with end entity certificate in end_certs[0])
214 * @param restrictions path validation restrictions
215 * @param trusted_roots list of certificate stores that contain trusted certificates
216 * @param hostname if not empty, compared against the DNS name in end_certs[0]
217 * @param usage if not set to UNSPECIFIED, compared against the key usage in end_certs[0]
218 * @param validation_time what reference time to use for validation
219 * @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
220 * @param ocsp_resp additional OCSP responses to consider (eg from peer)
221 * @return result of the path validation
222 * note: when enabled, OCSP check is softfail by default: if the OCSP server is not
223 * reachable, Path_Validation_Result::successful_validation() will return true.
224 * Hardfail OCSP check can be achieve by also calling Path_Validation_Result::no_warnings().
225 */
226 Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
227  const std::vector<X509_Certificate>& end_certs,
228  const Path_Validation_Restrictions& restrictions,
229  const std::vector<Certificate_Store*>& trusted_roots,
230  const std::string& hostname = "",
232  std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(),
233  std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0),
234  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
235 
236 /**
237 * PKIX Path Validation
238 * @param end_cert certificate to validate
239 * @param restrictions path validation restrictions
240 * @param trusted_roots list of stores that contain trusted certificates
241 * @param hostname if not empty, compared against the DNS name in end_cert
242 * @param usage if not set to UNSPECIFIED, compared against the key usage in end_cert
243 * @param validation_time what reference time to use for validation
244 * @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
245 * @param ocsp_resp additional OCSP responses to consider (eg from peer)
246 * @return result of the path validation
247 */
248 Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
249  const X509_Certificate& end_cert,
250  const Path_Validation_Restrictions& restrictions,
251  const std::vector<Certificate_Store*>& trusted_roots,
252  const std::string& hostname = "",
254  std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(),
255  std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0),
256  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
257 
258 /**
259 * PKIX Path Validation
260 * @param end_cert certificate to validate
261 * @param restrictions path validation restrictions
262 * @param store store that contains trusted certificates
263 * @param hostname if not empty, compared against the DNS name in end_cert
264 * @param usage if not set to UNSPECIFIED, compared against the key usage in end_cert
265 * @param validation_time what reference time to use for validation
266 * @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
267 * @param ocsp_resp additional OCSP responses to consider (eg from peer)
268 * @return result of the path validation
269 */
270 Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
271  const X509_Certificate& end_cert,
272  const Path_Validation_Restrictions& restrictions,
273  const Certificate_Store& store,
274  const std::string& hostname = "",
276  std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(),
277  std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0),
278  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
279 
280 /**
281 * PKIX Path Validation
282 * @param end_certs certificate chain to validate
283 * @param restrictions path validation restrictions
284 * @param store store that contains trusted certificates
285 * @param hostname if not empty, compared against the DNS name in end_certs[0]
286 * @param usage if not set to UNSPECIFIED, compared against the key usage in end_certs[0]
287 * @param validation_time what reference time to use for validation
288 * @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
289 * @param ocsp_resp additional OCSP responses to consider (eg from peer)
290 * @return result of the path validation
291 */
292 Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
293  const std::vector<X509_Certificate>& end_certs,
294  const Path_Validation_Restrictions& restrictions,
295  const Certificate_Store& store,
296  const std::string& hostname = "",
298  std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(),
299  std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0),
300  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
301 
302 
303 /**
304 * namespace PKIX holds the building blocks that are called by x509_path_validate.
305 * This allows custom validation logic to be written by applications and makes
306 * for easier testing, but unless you're positive you know what you're doing you
307 * probably want to just call x509_path_validate instead.
308 */
309 namespace PKIX {
310 
312 build_all_certificate_paths(std::vector<std::vector<std::shared_ptr<const X509_Certificate>>>& cert_paths,
313  const std::vector<Certificate_Store*>& trusted_certstores,
314  const std::shared_ptr<const X509_Certificate>& end_entity,
315  const std::vector<std::shared_ptr<const X509_Certificate>>& end_entity_extra);
316 
317 
318 /**
319 * Build certificate path
320 * @param cert_path_out output parameter, cert_path will be appended to this vector
321 * @param trusted_certstores list of certificate stores that contain trusted certificates
322 * @param end_entity the cert to be validated
323 * @param end_entity_extra optional list of additional untrusted certs for path building
324 * @return result of the path building operation (OK or error)
325 */
327 BOTAN_PUBLIC_API(2,0) build_certificate_path(std::vector<std::shared_ptr<const X509_Certificate>>& cert_path_out,
328  const std::vector<Certificate_Store*>& trusted_certstores,
329  const std::shared_ptr<const X509_Certificate>& end_entity,
330  const std::vector<std::shared_ptr<const X509_Certificate>>& end_entity_extra);
331 
332 /**
333 * Check the certificate chain, but not any revocation data
334 *
335 * @param cert_path path built by build_certificate_path with OK result
336 * @param ref_time whatever time you want to perform the validation
337 * against (normally current system clock)
338 * @param hostname the hostname
339 * @param usage end entity usage checks
340 * @param min_signature_algo_strength 80 or 110 typically
341 * Note 80 allows 1024 bit RSA and SHA-1. 110 allows 2048 bit RSA and SHA-2.
342 * Using 128 requires ECC (P-256) or ~3000 bit RSA keys.
343 * @param trusted_hashes set of trusted hash functions, empty means accept any
344 * hash we have an OID for
345 * @return vector of results on per certificate in the path, each containing a set of
346 * results. If all codes in the set are < Certificate_Status_Code::FIRST_ERROR_STATUS,
347 * then the result for that certificate is successful. If all results are
348 */
350 BOTAN_PUBLIC_API(2,0) check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
351  std::chrono::system_clock::time_point ref_time,
352  const std::string& hostname,
354  size_t min_signature_algo_strength,
355  const std::set<std::string>& trusted_hashes);
356 
357 /**
358 * Check OCSP responses for revocation information
359 * @param cert_path path already validated by check_chain
360 * @param ocsp_responses the OCSP responses to consider
361 * @param certstores trusted roots
362 * @param ref_time whatever time you want to perform the validation against
363 * (normally current system clock)
364 * @param max_ocsp_age maximum age of OCSP responses w/o next_update. If zero,
365 * there is no maximum age
366 * @return revocation status
367 */
369 BOTAN_PUBLIC_API(2, 0) check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
370  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
371  const std::vector<Certificate_Store*>& certstores,
372  std::chrono::system_clock::time_point ref_time,
373  std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
374 
375 /**
376 * Check CRLs for revocation information
377 * @param cert_path path already validated by check_chain
378 * @param crls the list of CRLs to check, it is assumed that crls[i] (if not null)
379 * is the associated CRL for the subject in cert_path[i].
380 * @param ref_time whatever time you want to perform the validation against
381 * (normally current system clock)
382 * @return revocation status
383 */
385 BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
386  const std::vector<std::shared_ptr<const X509_CRL>>& crls,
387  std::chrono::system_clock::time_point ref_time);
388 
389 /**
390 * Check CRLs for revocation information
391 * @param cert_path path already validated by check_chain
392 * @param certstores a list of certificate stores to query for the CRL
393 * @param ref_time whatever time you want to perform the validation against
394 * (normally current system clock)
395 * @return revocation status
396 */
398 BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
399  const std::vector<Certificate_Store*>& certstores,
400  std::chrono::system_clock::time_point ref_time);
401 
402 #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
403 
404 /**
405 * Check OCSP using online (HTTP) access. Current version creates a thread and
406 * network connection per OCSP request made.
407 *
408 * @param cert_path path already validated by check_chain
409 * @param trusted_certstores a list of certstores with trusted certs
410 * @param ref_time whatever time you want to perform the validation against
411 * (normally current system clock)
412 * @param timeout for timing out the responses, though actually this function
413 * may block for up to timeout*cert_path.size()*C for some small C.
414 * @param ocsp_check_intermediate_CAs if true also performs OCSP on any intermediate
415 * CA certificates. If false, only does OCSP on the end entity cert.
416 * @param max_ocsp_age maximum age of OCSP responses w/o next_update. If zero,
417 * there is no maximum age
418 * @return revocation status
419 */
421 BOTAN_PUBLIC_API(2, 0) check_ocsp_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
422  const std::vector<Certificate_Store*>& trusted_certstores,
423  std::chrono::system_clock::time_point ref_time,
424  std::chrono::milliseconds timeout,
425  bool ocsp_check_intermediate_CAs,
426  std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
427 
428 /**
429 * Check CRL using online (HTTP) access. Current version creates a thread and
430 * network connection per CRL access.
431 
432 * @param cert_path path already validated by check_chain
433 * @param trusted_certstores a list of certstores with trusted certs
434 * @param certstore_to_recv_crls optional (nullptr to disable), all CRLs
435 * retreived will be saved to this cert store.
436 * @param ref_time whatever time you want to perform the validation against
437 * (normally current system clock)
438 * @param timeout for timing out the responses, though actually this function
439 * may block for up to timeout*cert_path.size()*C for some small C.
440 * @return revocation status
441 */
443 BOTAN_PUBLIC_API(2,0) check_crl_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
444  const std::vector<Certificate_Store*>& trusted_certstores,
445  Certificate_Store_In_Memory* certstore_to_recv_crls,
446  std::chrono::system_clock::time_point ref_time,
447  std::chrono::milliseconds timeout);
448 
449 #endif
450 
451 /**
452 * Find overall status (OK, error) of a validation
453 * @param cert_status result of merge_revocation_status or check_chain
454 */
455 Certificate_Status_Code BOTAN_PUBLIC_API(2,0) overall_status(const CertificatePathStatusCodes& cert_status);
456 
457 /**
458 * Merge the results from CRL and/or OCSP checks into chain_status
459 * @param chain_status the certificate status
460 * @param crl_status results from check_crl
461 * @param ocsp_status results from check_ocsp
462 * @param require_rev_on_end_entity require valid CRL or OCSP on end-entity cert
463 * @param require_rev_on_intermediates require valid CRL or OCSP on all intermediate certificates
464 */
465 void BOTAN_PUBLIC_API(2,0) merge_revocation_status(CertificatePathStatusCodes& chain_status,
470 
471 }
472 
473 }
474 
475 #endif
Path_Validation_Result const Path_Validation_Restrictions const Certificate_Store & store
Definition: x509path.h:272
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > const std::string Usage_Type std::chrono::system_clock::time_point std::chrono::milliseconds ocsp_timeout
Definition: x509path.h:255
void const CertificatePathStatusCodes & crl_status
Definition: x509path.h:466
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > & trusted_roots
Definition: x509path.h:250
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > const std::string Usage_Type usage
Definition: x509path.h:253
int(* final)(unsigned char *, CTX *)
Definition: bigint.h:1136
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > const std::string & hostname
Definition: x509path.h:252
Path_Validation_Result x509_path_validate(const std::vector< X509_Certificate > &end_certs, const Path_Validation_Restrictions &restrictions, const std::vector< Certificate_Store * > &trusted_roots, const std::string &hostname, Usage_Type usage, std::chrono::system_clock::time_point ref_time, std::chrono::milliseconds ocsp_timeout, const std::vector< std::shared_ptr< const OCSP::Response >> &ocsp_resp)
Definition: x509path.cpp:832
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > const std::string Usage_Type std::chrono::system_clock::time_point std::chrono::milliseconds const std::vector< std::shared_ptr< const OCSP::Response > > & ocsp_resp
Definition: x509path.h:256
Certificate_Status_Code BOTAN_PUBLIC_API(2, 0) build_certificate_path(std CertificatePathStatusCodes BOTAN_PUBLIC_API(2, 0) check_chain(const std CertificatePathStatusCodes BOTAN_PUBLIC_API(2, 0) check_ocsp(const std CertificatePathStatusCodes BOTAN_PUBLIC_API(2, 0) check_crl(const std CertificatePathStatusCodes BOTAN_PUBLIC_API(2, 0) check_crl(const std Certificate_Status_Code BOTAN_PUBLIC_API(2, 0) overall_status(const CertificatePathStatusCodes &cert_status)
void const CertificatePathStatusCodes const CertificatePathStatusCodes bool bool require_rev_on_intermediates
Definition: x509path.h:466
Definition: alg_id.cpp:13
void const CertificatePathStatusCodes const CertificatePathStatusCodes bool require_rev_on_end_entity
Definition: x509path.h:466
Certificate_Status_Code build_all_certificate_paths(std::vector< std::vector< std::shared_ptr< const X509_Certificate >>> &cert_paths, const std::vector< Certificate_Store * > &trusted_certstores, const std::shared_ptr< const X509_Certificate > &end_entity, const std::vector< std::shared_ptr< const X509_Certificate >> &end_entity_extra)
Definition: x509path.cpp:615
class BOTAN_PUBLIC_API(2, 0) AlgorithmIdentifier final bool BOTAN_PUBLIC_API(2, 0) operator
Name Constraints.
Definition: asn1_obj.h:66
std::vector< std::set< Certificate_Status_Code > > CertificatePathStatusCodes
Definition: x509path.h:29
Path_Validation_Result const Path_Validation_Restrictions const std::vector< Certificate_Store * > const std::string Usage_Type std::chrono::system_clock::time_point validation_time
Definition: x509path.h:254
Certificate_Status_Code
Definition: cert_status.h:19
Path_Validation_Result const Path_Validation_Restrictions & restrictions
Definition: x509path.h:250
void const CertificatePathStatusCodes const CertificatePathStatusCodes & ocsp_status
Definition: x509path.h:466
Usage_Type
Definition: x509cert.h:25