Coverage Report

Created: 2021-11-25 09:31

/src/botan/build/include/botan/x509path.h
Line
Count
Source (jump to first uncovered line)
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
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
0
         m_max_ocsp_age(max_ocsp_age) {}
81
82
      /**
83
      * @return whether revocation information is required
84
      */
85
      bool require_revocation_information() const
86
0
         { 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
0
         { return m_ocsp_all_intermediates; }
94
95
      /**
96
      * @return trusted signature hash functions
97
      */
98
      const std::set<std::string>& trusted_hashes() const
99
0
         { return m_trusted_hashes; }
100
101
      /**
102
      * @return minimum required key strength
103
      */
104
      size_t minimum_key_strength() const
105
0
         { 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
0
         { 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
0
      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
0
      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
0
         { 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<X509_Certificate>&& cert_chain);
197
198
      /**
199
      * Create a Path_Validation_Result
200
      * @param status validation status code
201
      */
202
0
      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<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 = "",
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
*/
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 = "",
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
*/
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 = "",
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
*/
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 = "",
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
*/
309
namespace PKIX {
310
311
Certificate_Status_Code
312
build_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
*/
326
Certificate_Status_Code
327
BOTAN_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
*/
349
CertificatePathStatusCodes
350
BOTAN_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
*/
368
CertificatePathStatusCodes
369
BOTAN_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
*/
384
CertificatePathStatusCodes
385
BOTAN_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
*/
397
CertificatePathStatusCodes
398
BOTAN_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
*/
420
CertificatePathStatusCodes
421
BOTAN_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
*/
442
CertificatePathStatusCodes
443
BOTAN_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
*/
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,
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