1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
|
.. _x509_certificates:
X.509 Certificates and CRLs
=================================
A certificate is a binding between some identifying information
(called a *subject*) and a public key. This binding is asserted by a
signature on the certificate, which is placed there by some authority
(the *issuer*) that at least claims that it knows the subject named in
the certificate really "owns" the private key corresponding to the
public key in the certificate.
The major certificate format in use today is X.509v3, used for instance in the
:doc:`tls` protocol. A X.509 certificate is represented by the class
``X509_Certificate``. The data of an X.509 certificate is stored as a
``shared_ptr`` to a structure containing the decoded information. So copying
``X509_Certificate`` objects is quite cheap.
.. cpp:class:: X509_Certificate
.. cpp:function:: X509_Certificate(const std::string& filename)
Load a certificate from a file. PEM or DER is accepted.
.. cpp:function:: X509_Certificate(const std::vector<uint8_t>& in)
Load a certificate from a byte string.
.. cpp:function:: X509_Certificate(DataSource& source)
Load a certificate from an abstract ``DataSource``.
.. cpp:function:: X509_DN subject_dn() const
Returns the distinguished name (DN) of the certificate's subject. This is
the primary place where information about the subject of the certificate is
stored. However "modern" information that doesn't fit in the X.500
framework, such as DNS name, email, IP address, or XMPP address, appears
instead in the subject alternative name.
.. cpp:function:: X509_DN issuer_dn() const
Returns the distinguished name (DN) of the certificate's issuer, ie the CA
that issued this certificate.
.. cpp:function:: const AlternativeName& subject_alt_name() const
Return the subjects alternative name. This is used to store
values like associated URIs, DNS addresses, and email addresses.
.. cpp:function:: const AlternativeName& issuer_alt_name() const
Return alternative names for the issuer.
.. cpp:function:: std::unique_ptr<Public_Key> load_subject_public_key() const
Deserialize the stored public key and return a new object. This
might throw, if it happens that the public key object stored in
the certificate is malformed in some way, or in the case that the
public key algorithm used is not supported by the library.
See :ref:`serializing_public_keys` for more information about what to do
with the returned object. It may be any type of key, in principle, though
RSA and ECDSA are most common.
.. cpp:function:: std::vector<uint8_t> subject_public_key_bits() const
Return the binary encoding of the subject public key. This value (or a hash of
it) is used in various protocols, eg for public key pinning.
.. cpp:function:: AlgorithmIdentifier subject_public_key_algo() const
Return an algorithm identifier that identifies the algorithm used in the
subject's public key.
.. cpp:function:: std::vector<uint8_t> serial_number() const
Return the certificates serial number. The tuple of issuer DN and
serial number should be unique.
.. cpp:function:: std::vector<uint8> raw_subject_dn() const
Return the binary encoding of the subject DN.
.. cpp:function:: std::vector<uint8> raw_issuer_dn() const
Return the binary encoding of the issuer DN.
.. cpp:function:: X509_Time not_before() const
Returns the point in time the certificate becomes valid
.. cpp:function:: X509_Time not_after() const
Returns the point in time the certificate expires
.. cpp:function:: const Extensions& v3_extensions() const
Returns all extensions of this certificate. You can use this
to examine any extension data associated with the certificate,
including custom extensions the library doesn't know about.
.. cpp:function:: std::vector<uint8_t> authority_key_id() const
Return the authority key id, if set. This is an arbitrary string; in the
issuing certificate this will be the subject key id.
.. cpp:function:: std::vector<uint8_t> subject_key_id() const
Return the subject key id, if set.
.. cpp:function:: bool allowed_extended_usage(const OID& usage) const
Return true if and only if the usage OID appears in the extended key usage
extension. Also will return true if the extended key usage extension is
not used in the current certificate.
.. cpp:function: std::vector<OID> extended_key_usage() const
Return the list of extended key usages. May be empty.
.. cpp:function:: std::string fingerprint(const std::string& hash_fn = "SHA-1") const
Return a fingerprint for the certificate, which is basically just a hash
of the binary contents. Normally SHA-1 or SHA-256 is used, but any hash
function is allowed.
.. cpp:function:: Key_Constraints constraints() const
Returns either an enumeration listing key constraints (what the
associated key can be used for) or ``NO_CONSTRAINTS`` if the
relevant extension was not included. Example values are
``DIGITAL_SIGNATURE`` and ``KEY_CERT_SIGN``. More than one value
might be specified.
.. cpp:function:: bool matches_dns_name(const std::string& name) const
Check if the certificate's subject alternative name DNS fields
match ``name``. This function also handles wildcard certificates.
.. cpp:function:: std::string to_string() const
Returns a free-form human readable string describing the certificate.
X.509 Distinguished Names
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. cpp:class:: X509_DN
.. cpp:function:: bool has_field(const std::string& attr) const
Returns true if ``get_attribute`` or ``get_first_attribute`` will return a value.
.. cpp:function:: std::vector<std::string> get_attribute(const std::string& attr) const
Return all attributes associated with a certain attribute type.
.. cpp:function:: std::string get_first_attribute(const std::string& attr) const
Like ``get_attribute`` but returns just the first attribute, or
empty if the DN has no attribute of the specified type.
.. cpp:function:: std::multimap<OID, std::string> get_attributes() const
Get all attributes of the DN. The OID maps to a DN component such as
2.5.4.10 ("Organization"), and the strings are UTF-8 encoded.
.. cpp:function:: std::multimap<std::string, std::string> contents() const
Similar to ``get_attributes``, but the OIDs are decoded to strings.
.. cpp:function:: void add_attribute(const std::string& key, const std::string& val)
Add an attribute to a DN.
.. cpp:function:: void add_attribute(const OID& oid, const std::string& val)
Add an attribute to a DN using an OID instead of string-valued attribute type.
The ``X509_DN`` type also supports iostream extraction and insertion operators,
for formatted input and output.
X.509v3 Extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
X.509v3 specifies a large number of possible extensions. Botan supports some,
but by no means all of them. The following listing lists which X.509v3
extensions are supported and notes areas where there may be problems with the
handling.
- Key Usage and Extended Key Usage: No problems known.
- Basic Constraints: No problems known. A self-signed v1 certificate
is assumed to be a CA, while a v3 certificate is marked as a CA if
and only if the basic constraints extension is present and set for
a CA cert.
- Subject Alternative Names: Only the "rfc822Name", "dNSName", and
"uniformResourceIdentifier" and raw IPv4 fields will be stored; all
others are ignored.
- Issuer Alternative Names: Same restrictions as the Subject
Alternative Names extension. New certificates generated by Botan
never include the issuer alternative name.
- Authority Key Identifier: Only the version using KeyIdentifier is
supported. If the GeneralNames version is used and the extension is
critical, an exception is thrown. If both the KeyIdentifier and GeneralNames
versions are present, then the KeyIdentifier will be used, and the
GeneralNames ignored.
- Subject Key Identifier: No problems known.
- Name Constraints: No problems known (though encoding is not supported).
Any unknown critical extension in a certificate will lead to an
exception during path validation.
Extensions are handled by a special class taking care of encoding
and decoding. It also supports encoding and decoding of custom extensions.
To do this, it internally keeps two lists of extensions. Different lookup
functions are provided to search them.
.. note::
Validation of custom extensions during path validation is currently not supported.
.. cpp:class:: Extensions
.. cpp:function:: void add(Certificate_Extension* extn, bool critical = false)
Adds a new extension to the extensions object. If an extension of the same
type already exists, ``extn`` will replace it. If ``critical`` is true the
extension will be marked as critical in the encoding.
.. cpp:function:: bool add_new(Certificate_Extension* extn, bool critical = false)
Like ``add`` but an existing extension will not be replaced. Returns true if the
extension was used, false if an extension of the same type was already in place.
.. cpp:function:: void replace(Certificate_Extension* extn, bool critical = false)
Adds an extension to the list or replaces it, if the same
extension was already added
.. cpp:function:: std::unique_ptr<Certificate_Extension> get(const OID& oid) const
Searches for an extension by OID and returns the result
.. cpp:function:: template<typename T> \
std::unique_ptr<T> get_raw(const OID& oid)
Searches for an extension by OID and returns the result.
Only the unknown extensions, that is, extensions types that are not
listed above, are searched for by this function.
.. cpp:function:: std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const
Returns the list of extensions together with the corresponding
criticality flag. Only contains the supported extension types
listed above.
.. cpp:function:: std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const
Returns the list of extensions as raw, encoded bytes
together with the corresponding criticality flag.
Contains all extensions, known as well as unknown extensions.
Certificate Revocation Lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It will occasionally happen that a certificate must be revoked before
its expiration date. Examples of this happening include the private
key being compromised, or the user to which it has been assigned
leaving an organization. Certificate revocation lists are an answer to
this problem (though online certificate validation techniques are
starting to become somewhat more popular). Every once in a while the
CA will release a new CRL, listing all certificates that have been
revoked. Also included is various pieces of information like what time
a particular certificate was revoked, and for what reason. In most
systems, it is wise to support some form of certificate revocation,
and CRLs handle this easily.
For most users, processing a CRL is quite easy. All you have to do is
call the constructor, which will take a filename (or a
``DataSource&``). The CRLs can either be in raw BER/DER, or in PEM
format; the constructor will figure out which format without any extra
information. For example::
X509_CRL crl1("crl1.der");
DataSource_Stream in("crl2.pem");
X509_CRL crl2(in);
After that, pass the ``X509_CRL`` object to a ``Certificate_Store`` object
with
.. cpp:function:: void Certificate_Store::add_crl(const X509_CRL& crl)
and all future verifications will take into account the provided CRL.
Certificate Stores
----------------------------------------
An object of type ``Certificate_Store`` is a generalized interface to
an external source for certificates (and CRLs). Examples of such a
store would be one that looked up the certificates in a SQL database,
or by contacting a CGI script running on a HTTP server. There are
currently three mechanisms for looking up a certificate, and one for
retrieving CRLs. By default, most of these mechanisms will return an
empty ``std::shared_ptr`` of ``X509_Certificate``. This storage mechanism
is *only* queried when doing certificate validation: it allows you to
distribute only the root key with an application, and let some online
method handle getting all the other certificates that are needed to
validate an end entity certificate. In particular, the search routines
will not attempt to access the external database.
The certificate lookup methods are ``find_cert`` (by Subject
Distinguished Name and optional Subject Key Identifier) and
``find_cert_by_pubkey_sha1`` (by SHA-1 hash of the certificate's
public key). The Subject Distinguished Name is given as a ``X509_DN``,
while the SKID parameter takes a ``std::vector<uint8_t>`` containing
the subject key identifier in raw binary. Both lookup methods are
mandatory to implement.
Finally, there is a method for finding a CRL, called ``find_crl_for``,
that takes an ``X509_Certificate`` object, and returns a
``std::shared_ptr`` of ``X509_CRL``. The ``std::shared_ptr`` return
type makes it easy to return no CRLs by returning ``nullptr``
(eg, if the certificate store doesn't support retrieving CRLs).
Implementing the function is optional, and by default will return
``nullptr``.
Certificate stores are used in the :doc:`tls` module to store a
list of trusted certificate authorities.
In Memory Certificate Store
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The in memory certificate store keeps all objects in memory only.
Certificates can be loaded from disk initially, but also added
later.
.. cpp:class:: Certificate_Store_In_Memory
.. cpp:function:: Certificate_Store_In_Memory(const std::string& dir)
Attempt to parse all files in ``dir`` (including subdirectories)
as certificates. Ignores errors.
.. cpp:function:: Certificate_Store_In_Memory(const X509_Certificate& cert)
Adds given certificate to the store
.. cpp:function:: Certificate_Store_In_Memory()
Create an empty store
.. cpp:function:: void add_certificate(const X509_Certificate& cert)
Add a certificate to the store
.. cpp:function:: void add_certificate(std::shared_ptr<const X509_Certificate> cert)
Add a certificate already in a shared_ptr to the store
.. cpp:function:: void add_crl(const X509_CRL& crl)
Add a certificate revocation list (CRL) to the store.
.. cpp:function:: void add_crl(std::shared_ptr<const X509_CRL> crl)
Add a certificate revocation list (CRL) to the store as a shared_ptr
SQL-backed Certificate Stores
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The SQL-backed certificate stores store all objects in an SQL database. They
also additionally provide private key storage and revocation of individual
certificates.
.. cpp:class:: Certificate_Store_In_SQL
.. cpp:function:: Certificate_Store_In_SQL(const std::shared_ptr<SQL_Database> db, \
const std::string& passwd, RandomNumberGenerator& rng, const std::string& table_prefix = "")
Create or open an existing certificate store from an SQL database.
The password in ``passwd`` will be used to encrypt private keys.
.. cpp:function:: bool insert_cert(const X509_Certificate& cert)
Inserts ``cert`` into the store. Returns `false` if the certificate is
already known and `true` if insertion was successful.
.. cpp:function:: remove_cert(const X509_Certificate& cert)
Removes ``cert`` from the store. Returns `false` if the certificate could not
be found and `true` if removal was successful.
.. cpp:function:: std::shared_ptr<const Private_Key> find_key(const X509_Certificate&) const
Returns the private key for "cert" or an empty shared_ptr if none was found
.. cpp:function:: std::vector<std::shared_ptr<const X509_Certificate>> \
find_certs_for_key(const Private_Key& key) const
Returns all certificates for private key ``key``
.. cpp:function:: bool insert_key(const X509_Certificate& cert, const Private_Key& key)
Inserts ``key`` for ``cert`` into the store, returns `false` if the key is
already known and `true` if insertion was successful.
.. cpp:function:: void remove_key(const Private_Key& key)
Removes ``key`` from the store
.. cpp:function:: void revoke_cert(const X509_Certificate&, CRL_Code, \
const X509_Time& time = X509_Time())
Marks ``cert`` as revoked starting from ``time``
.. cpp:function:: void affirm_cert(const X509_Certificate&)
Reverses the revocation for ``cert``
.. cpp:function:: std::vector<X509_CRL> generate_crls() const
Generates CRLs for all certificates marked as revoked.
A CRL is returned for each unique issuer DN.
The ``Certificate_Store_In_SQL`` class operates on an abstract ``SQL_Database``
object. If support for sqlite3 was enabled at build time, Botan includes an
implementation of this interface for sqlite3, and a subclass of
``Certificate_Store_In_SQL`` which creates or opens a sqlite3 database.
.. cpp:class:: Certificate_Store_In_SQLite
.. cpp:function:: Certificate_Store_In_SQLite(const std::string& db_path, \
const std::string& passwd, RandomNumberGenerator& rng, const std::string& table_prefix = "")
Create or open an existing certificate store from an sqlite database file.
The password in ``passwd`` will be used to encrypt private keys.
Path Validation
----------------------------------------
The process of validating a certificate chain up to a trusted root is
called `path validation`, and in botan that operation is handled by a
set of functions in ``x509path.h`` named ``x509_path_validate``:
.. cpp:function:: Path_Validation_Result \
x509_path_validate(const X509_Certificate& end_cert, \
const Path_Validation_Restrictions& restrictions, \
const Certificate_Store& store, const std::string& hostname = "", \
Usage_Type usage = Usage_Type::UNSPECIFIED, \
std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(), \
std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0), \
const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp = std::vector<std::shared_ptr<const OCSP::Response>>())
The last five parameters are optional. ``hostname`` specifies a hostname which is
matched against the subject DN in ``end_cert`` according to RFC 6125.
An empty hostname disables hostname validation.
``usage`` specifies key usage restrictions that are compared
to the key usage fields in `end_cert` according to RFC 5280, if not set to
``UNSPECIFIED``. ``validation_time`` allows setting the time point at which all certificates
are validated. This is really only useful for testing. The default is the
current system clock's current time. ``ocsp_timeout`` sets the timeout for
OCSP requests. The default of 0 disables OCSP checks completely.
``ocsp_resp`` allows adding additional OCSP responses retrieved from outside
of the path validation. Note that OCSP online checks are done only
as long as the http_util module was compiled in. Availability of online
OCSP checks can be checked using the macro BOTAN_HAS_ONLINE_REVOCATION_CHECKS.
For the different flavors of ``x509_path_validate``, check ``x509path.h``.
The result of the validation is returned as a class:
.. cpp:class:: Path_Validation_Result
Specifies the result of the validation
.. cpp:function:: bool successful_validation() const
Returns true if a certificate path from *end_cert* to a trusted
root was found and all path validation checks passed.
.. cpp:function:: std::string result_string() const
Returns a descriptive string of the validation status (for
instance "Verified", "Certificate is not yet valid", or
"Signature error"). This is the string value of
the `result` function below.
.. cpp:function:: const X509_Certificate& trust_root() const
If the validation was successful, returns the certificate which
is acting as the trust root for *end_cert*.
.. cpp:function:: const std::vector<X509_Certificate>& cert_path() const
Returns the full certificate path starting with the end entity
certificate and ending in the trust root.
.. cpp:function:: Certificate_Status_Code result() const
Returns the 'worst' error that occurred during validation. For
instance, we do not want an expired certificate with an invalid
signature to be reported to the user as being simply expired (a
relatively innocuous and common error) when the signature isn't
even valid.
.. cpp:function:: const std::vector<std::set<Certificate_Status_Code>>& all_statuses() const
For each certificate in the chain, returns a set of status which
indicate all errors which occurred during validation. This is
primarily useful for diagnostic purposes.
.. cpp:function:: std::set<std::string> trusted_hashes() const
Returns the set of all cryptographic hash functions which are
implicitly trusted for this validation to be correct.
A ``Path_Validation_Restrictions`` is passed to the path
validator and specifies restrictions and options for the validation
step. The two constructors are:
.. cpp:function:: Path_Validation_Restrictions(bool require_rev, \
size_t minimum_key_strength, \
bool ocsp_all_intermediates, \
const std::set<std::string>& trusted_hashes)
If `require_rev` is true, then any path without revocation
information (CRL or OCSP check) is rejected with the code
`NO_REVOCATION_DATA`. The `minimum_key_strength` parameter
specifies the minimum strength of public key signature we will
accept is. The set of hash names `trusted_hashes` indicates which
hash functions we'll accept for cryptographic signatures. Any
untrusted hash will cause the error case `UNTRUSTED_HASH`.
.. cpp:function:: Path_Validation_Restrictions(bool require_rev = false, \
size_t minimum_key_strength = 80, \
bool ocsp_all_intermediates = false)
A variant of the above with some convenient defaults. The current
default `minimum_key_strength` of 80 roughly corresponds to 1024
bit RSA. The set of trusted hashes is set to all SHA-2 variants,
and, if `minimum_key_strength` is less than or equal to 80, then
SHA-1 signatures will also be accepted.
Creating New Certificates
---------------------------------
A CA is represented by the type ``X509_CA``, which can be found in
``x509_ca.h``. A CA always needs its own certificate, which can either
be a self-signed certificate (see below on how to create one) or one
issued by another CA (see the section on PKCS #10 requests). Creating
a CA object is done by the following constructor:
.. cpp:function:: X509_CA::X509_CA(const X509_Certificate& cert, \
const Private_Key& key, \
const std::string& hash_fn, \
RandomNumberGenerator& rng)
The private ``key`` is the private key corresponding to the public key in the
CA's certificate. ``hash_fn`` is the name of the hash function to use
for signing, e.g., `SHA-256`. ``rng`` is queried for random during signing.
There is an alternative constructor that lets you set additional options, namely
the padding scheme that will be used by the X509_CA object to sign certificates
and certificate revocation lists. If the padding is not set explicitly, the CA
will use the padding scheme that was used when signing the CA certificate.
.. cpp:function:: X509_CA::X509_CA(const X509_Certificate& cert, \
const Private_Key& key, \
const std::map<std::string,std::string>& opts, \
const std::string& hash_fn, \
RandomNumberGenerator& rng)
The only option valid at this moment is "padding". The supported padding schemes
can be found in src/lib/pubkey/padding.cpp. Some alternative names for the
padding schemes are understood, as well.
Requests for new certificates are supplied to a CA in the form of PKCS
#10 certificate requests (called a ``PKCS10_Request`` object in
Botan). These are decoded in a similar manner to
certificates/CRLs/etc. A request is vetted by humans (who somehow
verify that the name in the request corresponds to the name of the
entity who requested it), and then signed by a CA key, generating a
new certificate:
.. cpp:function:: X509_Certificate \
X509_CA::sign_request(const PKCS10_Request& req, \
RandomNumberGenerator& rng, \
const X509_Time& not_before, \
const X509_Time& not_after)
Generating CRLs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As mentioned previously, the ability to process CRLs is highly
important in many PKI systems. In fact, according to strict X.509
rules, you must not validate any certificate if the appropriate CRLs
are not available (though hardly any systems are that strict). In any
case, a CA should have a valid CRL available at all times.
Of course, you might be wondering what to do if no certificates have
been revoked. Never fear; empty CRLs, which revoke nothing at all, can
be issued. To generate a new, empty CRL, just call
.. cpp:function:: X509_CRL X509_CA::new_crl(RandomNumberGenerator& rng, \
uint32_t next_update = 0)
This function will return a new, empty CRL. The ``next_update`` parameter is
the number of seconds before the CRL expires. If it is set to the (default)
value of zero, then a reasonable default (currently 7 days) will be used.
On the other hand, you may have issued a CRL before. In that case, you will
want to issue a new CRL that contains all previously revoked
certificates, along with any new ones. This is done by calling
.. cpp:function:: X509_CRL X509_CA::update_crl(const X509_CRL& last_crl, \
std::vector<CRL_Entry> new_entries, RandomNumberGenerator& rng, \
size_t next_update = 0)
Where ``last_crl`` is the last CRL this CA issued, and
``new_entries`` is a list of any newly revoked certificates. The
function returns a new ``X509_CRL`` to make available for
clients.
The ``CRL_Entry`` type is a structure that contains, at a minimum, the serial
number of the revoked certificate. As serial numbers are never repeated, the
pairing of an issuer and a serial number (should) distinctly identify any
certificate. In this case, we represent the serial number as a
``secure_vector<uint8_t>`` called ``serial``. There are two additional (optional)
values, an enumeration called ``CRL_Code`` that specifies the reason for
revocation (``reason``), and an object that represents the time that the
certificate became invalid (if this information is known).
If you wish to remove an old entry from the CRL, insert a new entry for the
same cert, with a ``reason`` code of ``REMOVE_FROM_CRL``. For example, if a
revoked certificate has expired 'normally', there is no reason to continue to
explicitly revoke it, since clients will reject the cert as expired in any
case.
Self-Signed Certificates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generating a new self-signed certificate can often be useful, for
example when setting up a new root CA, or for use in specialized
protocols. The library provides a utility function for this:
.. cpp:function:: X509_Certificate create_self_signed_cert( \
const X509_Cert_Options& opts, const Private_Key& key, \
const std::string& hash_fn, RandomNumberGenerator& rng)
Where ``key`` is the private key you wish to use (the public key,
used in the certificate itself is extracted from the private key),
and ``opts`` is an structure that has various bits of information
that will be used in creating the certificate (this structure, and
its use, is discussed below).
Creating PKCS #10 Requests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Also in ``x509self.h``, there is a function for generating new PKCS #10
certificate requests:
.. cpp:function:: PKCS10_Request create_cert_req( \
const X509_Cert_Options& opts, const Private_Key& key, \
const std::string& hash_fn, RandomNumberGenerator& rng)
This function acts quite similarly to
:cpp:func:`create_self_signed_cert`, except it instead returns a PKCS
#10 certificate request. After creating it, one would typically
transmit it to a CA, who signs it and returns a freshly minted X.509
certificate.
.. cpp:function:: PKCS10_Request PKCS10_Request::create(const Private_Key& key, \
const X509_DN& subject_dn, \
const Extensions& extensions, \
const std::string& hash_fn, \
RandomNumberGenerator& rng, \
const std::string& padding_scheme = "", \
const std::string& challenge = "")
This function (added in 2.5) is similar to ``create_cert_req`` but allows
specifying all the parameters directly. In fact ``create_cert_req`` just
creates the DN and extensions from the options, then uses this call to
actually create the ``PKCS10_Request`` object.
Certificate Options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is this ``X509_Cert_Options`` thing we've been passing around?
It's a class representing a bunch of information that will end up
being stored into the certificate. This information comes in 3 major
flavors: information about the subject (CA or end-user), the validity
period of the certificate, and restrictions on the usage of the
certificate. For special cases, you can also add custom X.509v3
extensions.
First and foremost is a number of ``std::string`` members, which
contains various bits of information about the user: ``common_name``,
``serial_number``, ``country``, ``organization``, ``org_unit``,
``locality``, ``state``, ``email``, ``dns_name``, and ``uri``. As many
of these as possible should be filled it (especially an email
address), though the only required ones are ``common_name`` and
``country``.
Additionally there are a small selection of ``std::vector<std::string>``
members, which allow space for repeating elements:
``more_org_units`` and ``more_dns``.
There is another value that is only useful when creating a PKCS #10
request, which is called ``challenge``. This is a challenge password,
which you can later use to request certificate revocation (*if* the CA
supports doing revocations in this manner).
Then there is the validity period; these are set with ``not_before``
and ``not_after``. Both of these functions also take a
``std::string``, which specifies when the certificate should start
being valid, and when it should stop being valid. If you don't set the
starting validity period, it will automatically choose the current
time. If you don't set the ending time, it will choose the starting
time plus a default time period. The arguments to these functions
specify the time in the following format: "2002/11/27 1:50:14". The
time is in 24-hour format, and the date is encoded as
year/month/day. The date must be specified, but you can omit the time
or trailing parts of it, for example "2002/11/27 1:50" or
"2002/11/27".
Third, you can set constraints on a key. The one you're mostly likely
to want to use is to create (or request) a CA certificate, which can
be done by calling the member function ``CA_key``. This should only be
used when needed.
Moreover, you can specify the padding scheme to be used when digital signatures
are computed by calling function ``set_padding_scheme`` with a string
representing the padding scheme. This way, you can control the padding scheme
for self-signed certificates and PKCS #10 requests. The padding scheme used by
a CA when building a certificate or a certificate revocation list can be set in
the ``X509_CA`` constructor. The supported padding schemes can be found in
src/lib/pubkey/padding.cpp. Some alternative names for the padding schemes are
understood, as well.
Other constraints can be set by calling the member functions
``add_constraints`` and ``add_ex_constraints``. The first takes a
``Key_Constraints`` value, and replaces any previously set value. If
no value is set, then the certificate key is marked as being valid for
any usage. You can set it to any of the following (for more than one
usage, OR them together): ``DIGITAL_SIGNATURE``, ``NON_REPUDIATION``,
``KEY_ENCIPHERMENT``, ``DATA_ENCIPHERMENT``, ``KEY_AGREEMENT``,
``KEY_CERT_SIGN``, ``CRL_SIGN``, ``ENCIPHER_ONLY``,
``DECIPHER_ONLY``. Many of these have quite special semantics, so you
should either consult the appropriate standards document (such as RFC
5280), or just not call ``add_constraints``, in which case the
appropriate values will be chosen for you.
The second function, ``add_ex_constraints``, allows you to specify an
OID that has some meaning with regards to restricting the key to
particular usages. You can, if you wish, specify any OID you like, but
there is a set of standard ones that other applications will be able
to understand. These are the ones specified by the PKIX standard, and
are named "PKIX.ServerAuth" (for TLS server authentication),
"PKIX.ClientAuth" (for TLS client authentication), "PKIX.CodeSigning",
"PKIX.EmailProtection" (most likely for use with S/MIME),
"PKIX.IPsecUser", "PKIX.IPsecTunnel", "PKIX.IPsecEndSystem", and
"PKIX.TimeStamping". You can call "add_ex_constraints" any number of
times - each new OID will be added to the list to include in the
certificate.
Lastly, you can add any X.509v3 extensions in the `extensions` member, which is
useful if you want to encode a custom extension, or encode an extension in a way
differently from how Botan defaults.
OCSP Requests
----------------------------------------
A client makes an OCSP request to what is termed an 'OCSP responder'. This
responder returns a signed response attesting that the certificate in question
has not been revoked. The most recent OCSP specification is as of this
writing :rfc:`6960`.
Normally OCSP validation happens automatically as part of X.509 certificate
validation, as long as OCSP is enabled (by setting a non-zero ``ocsp_timeout``
in the call to ``x509_path_validate``, or for TLS by implementing the related
``tls_verify_cert_chain_ocsp_timeout`` callback and returning a non-zero value
from that). So most applications should not need to directly manipulate OCSP
request and response objects.
For those that do, the primary ocsp interface is in ``ocsp.h``. First a request
must be formed, using information contained in the subject certificate and in
the subject's issuing certificate.
.. cpp:class:: OCSP::Request
.. cpp:function:: OCSP::Request(const X509_Certificate& issuer_cert, \
const BigInt& subject_serial)
Create a new OCSP request
.. cpp:function:: OCSP::Request(const X509_Certificate& issuer_cert, \
const X509_Certificate& subject_cert)
Variant of the above, using serial number from ``subject_cert``.
.. cpp:function:: std::vector<uint8_t> BER_encode() const
Encode the current OCSP request as a binary string.
.. cpp:function:: std::string base64_encode() const
Encode the current OCSP request as a base64 string.
Then the response is parsed and validated, and if valid, can be consulted
for certificate status information.
.. cpp:class:: OCSP::Response
.. cpp:function:: OCSP::Response(const uint8_t response_bits[], size_t response_bits_len)
Attempts to parse ``response_bits`` as an OCSP response. Throws an
exception if parsing fails. Note that this does not verify that the OCSP
response is valid (ie that the signature is correct), merely that the
ASN.1 structure matches an OCSP response.
.. cpp:function:: Certificate_Status_Code check_signature( \
const std::vector<Certificate_Store*>& trust_roots, \
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path = const std::vector<std::shared<const X509_Certificate>>()) const
Find the issuing certificate of the OCSP response, and check the signature.
If possible, pass the full certificate path being validated in
the optional ``cert_path`` argument: this additional information
helps locate the OCSP signer's certificate in some cases. If this
does not return ``Certificate_Status_Code::OCSP_SIGNATURE_OK``,
then the request must not be be used further.
.. cpp:function:: Certificate_Status_Code verify_signature(const X509_Certificate& issuing_cert) const
If the certificate that issued the OCSP response is already known (eg,
because in some specific application all the OCSP responses will always
be signed by a single trusted issuer whose cert is baked into the code)
this provides an alternate version of `check_signature`.
.. cpp:function:: Certificate_Status_Code status_for(const X509_Certificate& issuer, \
const X509_Certificate& subject, \
std::chrono::system_clock::time_point ref_time = std::chrono::system_clock::now()) const
Assuming the signature is valid, returns the status for the subject certificate.
Make sure to get the ordering of the issuer and subject certificates correct.
The ``ref_time`` is normally just the system clock, but can be used if
validation against some other reference time is desired (such as for
testing, to verify an old previously valid OCSP response, or to use an
alternate time source such as the Roughtime protocol instead of the local
client system clock).
.. cpp:function:: const X509_Time& produced_at() const
Return the time this OCSP response was (claimed to be) produced at.
.. cpp:function:: const X509_DN& signer_name() const
Return the distinguished name of the signer. This is used to help
find the issuing certificate.
This field is optional in OCSP responses, and may not be set.
.. cpp:function:: const std::vector<uint8_t>& signer_key_hash() const
Return the SHA-1 hash of the public key of the signer. This is used to
help find the issuing certificate. The ``Certificate_Store`` API
``find_cert_by_pubkey_sha1`` can search on this value.
This field is optional in OCSP responses, and may not be set.
.. cpp:function:: const std::vector<uint8_t>& raw_bits() const
Return the entire raw ASN.1 blob (for debugging or specialized decoding needs)
One common way of making OCSP requests is via HTTP, see :rfc:`2560`
Appendix A for details. A basic implementation of this is the function
``online_check``, which is available as long as the ``http_util`` module
was compiled in; check by testing for the macro ``BOTAN_HAS_HTTP_UTIL``.
.. cpp:function:: OCSP::Response online_check(const X509_Certificate& issuer, \
const BigInt& subject_serial, \
const std::string& ocsp_responder, \
const Certificate_Store* trusted_roots)
Assemble a OCSP request for serial number ``subject_serial`` and attempt to request
it to responder at URI ``ocsp_responder`` over a new HTTP socket, parses and returns
the response. If trusted_roots is not null, then the response is additionally
validated using OCSP response API ``check_signature``. Otherwise, this call must be
performed later by the application.
.. cpp:function:: OCSP::Response online_check(const X509_Certificate& issuer, \
const X509_Certificate& subject, \
const Certificate_Store* trusted_roots)
Variant of the above but uses serial number and OCSP responder URI from ``subject``.
|