Botan 3.0.0-alpha0
Crypto and TLS for C&
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/pkix_enums.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
23namespace 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*/
29typedef std::vector<std::set<Certificate_Status_Code>> CertificatePathStatusCodes;
30
31/**
32* Specifies restrictions on the PKIX path validation
33*/
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 */
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 */
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 */
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*/
126 {
127 public:
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<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 */
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 */
196 std::vector<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;
207 std::vector<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*/
226Path_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 = "",
231 Usage_Type usage = Usage_Type::UNSPECIFIED,
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::optional<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*/
248Path_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 = "",
253 Usage_Type usage = Usage_Type::UNSPECIFIED,
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::optional<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*/
270Path_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 = "",
275 Usage_Type usage = Usage_Type::UNSPECIFIED,
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::optional<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*/
292Path_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 = "",
297 Usage_Type usage = Usage_Type::UNSPECIFIED,
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::optional<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*/
309namespace PKIX {
310
312build_all_certificate_paths(std::vector<std::vector<X509_Certificate>>& cert_paths,
313 const std::vector<Certificate_Store*>& trusted_certstores,
314 const std::optional<X509_Certificate>& end_entity,
315 const std::vector<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*/
327BOTAN_PUBLIC_API(2,0) build_certificate_path(std::vector<X509_Certificate>& cert_path_out,
328 const std::vector<Certificate_Store*>& trusted_certstores,
329 const X509_Certificate& end_entity,
330 const std::vector<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*/
350BOTAN_PUBLIC_API(2,0) check_chain(const std::vector<X509_Certificate>& cert_path,
351 std::chrono::system_clock::time_point ref_time,
352 const std::string& hostname,
353 Usage_Type usage,
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*/
369BOTAN_PUBLIC_API(2, 0) check_ocsp(const std::vector<X509_Certificate>& cert_path,
370 const std::vector<std::optional<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*/
385BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<X509_Certificate>& cert_path,
386 const std::vector<std::optional<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*/
398BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<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*/
421BOTAN_PUBLIC_API(2, 0) check_ocsp_online(const std::vector<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*/
443BOTAN_PUBLIC_API(2,0) check_crl_online(const std::vector<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*/
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*/
466 const CertificatePathStatusCodes& crl_status,
467 const CertificatePathStatusCodes& ocsp_status,
468 bool require_rev_on_end_entity,
469 bool require_rev_on_intermediates);
470
471}
472
473}
474
475#endif
bool require_revocation_information() const
Definition: x509path.h:85
const std::set< std::string > & trusted_hashes() const
Definition: x509path.h:98
std::chrono::seconds max_ocsp_age() const
Definition: x509path.h:111
Path_Validation_Restrictions(bool require_rev, size_t minimum_key_strength, bool ocsp_all_intermediates, const std::set< std::string > &trusted_hashes, std::chrono::seconds max_ocsp_age=std::chrono::seconds::zero())
Definition: x509path.h:71
Certificate_Status_Code result() const
Definition: x509path.h:161
Certificate_Status_Code Code
Definition: x509path.h:128
Path_Validation_Result(Certificate_Status_Code status)
Definition: x509path.h:202
const std::vector< X509_Certificate > & cert_path() const
Definition: x509path.h:146
const CertificatePathStatusCodes & all_statuses() const
Definition: x509path.h:166
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
CertificatePathStatusCodes check_chain(const std::vector< X509_Certificate > &cert_path, std::chrono::system_clock::time_point ref_time, const std::string &hostname, Usage_Type usage, size_t min_signature_algo_strength, const std::set< std::string > &trusted_hashes)
Definition: x509path.cpp:32
void merge_revocation_status(CertificatePathStatusCodes &chain_status, const CertificatePathStatusCodes &crl_status, const CertificatePathStatusCodes &ocsp_status, bool require_rev_on_end_entity, bool require_rev_on_intermediates)
Definition: x509path.cpp:771
Certificate_Status_Code build_certificate_path(std::vector< X509_Certificate > &cert_path_out, const std::vector< Certificate_Store * > &trusted_certstores, const X509_Certificate &end_entity, const std::vector< X509_Certificate > &end_entity_extra)
Definition: x509path.cpp:523
CertificatePathStatusCodes check_ocsp(const std::vector< X509_Certificate > &cert_path, const std::vector< std::optional< OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &certstores, std::chrono::system_clock::time_point ref_time, std::chrono::seconds max_ocsp_age=std::chrono::seconds::zero())
Definition: x509path.cpp:213
Certificate_Status_Code overall_status(const CertificatePathStatusCodes &cert_status)
Definition: x509path.cpp:822
Certificate_Status_Code build_all_certificate_paths(std::vector< std::vector< X509_Certificate > > &cert_paths, const std::vector< Certificate_Store * > &trusted_certstores, const std::optional< X509_Certificate > &end_entity, const std::vector< X509_Certificate > &end_entity_extra)
Definition: x509path.cpp:628
CertificatePathStatusCodes check_crl(const std::vector< X509_Certificate > &cert_path, const std::vector< std::optional< X509_CRL > > &crls, std::chrono::system_clock::time_point ref_time)
Definition: x509path.cpp:264
Definition: alg_id.cpp:13
std::vector< std::set< Certificate_Status_Code > > CertificatePathStatusCodes
Definition: x509path.h:29
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::optional< OCSP::Response > > &ocsp_resp)
Definition: x509path.cpp:845
Usage_Type
Definition: x509cert.h:23
Certificate_Status_Code
Definition: pkix_enums.h:17
Definition: bigint.h:1077