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