summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/doc/api_ref/x509.rst
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/doc/api_ref/x509.rst')
-rw-r--r--comm/third_party/botan/doc/api_ref/x509.rst914
1 files changed, 914 insertions, 0 deletions
diff --git a/comm/third_party/botan/doc/api_ref/x509.rst b/comm/third_party/botan/doc/api_ref/x509.rst
new file mode 100644
index 0000000000..cbf3d531e1
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/x509.rst
@@ -0,0 +1,914 @@
+.. _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.
+
+ .. cpp:function:: std::string PEM_encode() const
+
+ Returns the PEM encoding of the certificate
+
+ .. cpp:function:: std::vector<uint8_t> BER_encode() const
+
+ Returns the DER/BER encoding of 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``.