aboutsummaryrefslogtreecommitdiffstats
path: root/doc/x509.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/x509.rst')
-rw-r--r--doc/x509.rst403
1 files changed, 403 insertions, 0 deletions
diff --git a/doc/x509.rst b/doc/x509.rst
new file mode 100644
index 000000000..e7d5c3cdf
--- /dev/null
+++ b/doc/x509.rst
@@ -0,0 +1,403 @@
+
+.. _x509_certificates:
+
+Certificate Handling
+=================================
+
+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, designed by ISO
+and further hacked on by dozens (hundreds?) of other organizations.
+
+When working with certificates, the main class to remember is
+``X509_Certificate``. You can read an object of this type, but you
+can't create one on the fly; a CA object is necessary for making a new
+certificate. So for the most part, you only have to worry about
+reading them in, verifying the signatures, and getting the bits of
+data in them (most commonly the public key, and the information about
+the user of that key). An X.509v3 certificate can contain a literally
+infinite number of items related to all kinds of things. Botan doesn't
+support a lot of them, because nobody uses them and they're an
+impossible mess to work with. This section only documents the most
+commonly used ones of the ones that are supported; for the rest, read
+``x509cert.h`` and ``asn1_obj.h`` (which has the definitions of
+various common ASN.1 constructs used in X.509).
+
+So what's in an X.509 certificate?
+-----------------------------------
+
+Obviously, you want to be able to get the public key. This is achieved
+by calling the member function ``subject_public_key``, which will
+return a ``Public_Key``\*. As to what to do with this, read about
+``load_key`` in :ref:`serializing_public_keys`. In the general case,
+this could be any kind of public key, though 99% of the time it will
+be an RSA key. However, Diffie-Hellman, DSA, and ECDSA keys are also
+supported, so be careful about how you treat this. It is also a wise
+idea to examine the value returned by ``constraints``, to see what
+uses the public key is approved for.
+
+The second major piece of information you'll want is the
+name/email/etc of the person to whom this certificate is
+assigned. Here is where things get a little nasty. X.509v3 has two
+(well, mostly just two...) different places where you can stick
+information about the user: the *subject* field, and in an extension
+called *subjectAlternativeName*. The *subject* field is supposed to
+only included the following information: country, organization, an
+organizational sub-unit name, and a so-called common name. The common
+name is usually the name of the person, or it could be a title
+associated with a position of some sort in the organization. It may
+also include fields for state/province and locality. What a locality
+is, nobody knows, but it's usually given as a city name.
+
+Botan doesn't currently support any of the Unicode variants used in
+ASN.1 (UTF-8, UCS-2, and UCS-4), any of which could be used for the
+fields in the DN. This could be problematic, particularly in Asia and
+other areas where non-ASCII characters are needed for most names. The
+UTF-8 and UCS-2 string types *are* accepted (in fact, UTF-8 is used
+when encoding much of the time), but if any of the characters included
+in the string are not in ISO 8859-1 (ie 0 ... 255), an exception will
+get thrown. Currently the ``ASN1_String`` type holds its data as ISO
+8859-1 internally (regardless of local character set); this would have
+to be changed to hold UCS-2 or UCS-4 in order to support Unicode
+(also, many interfaces in the X.509 code would have to accept or
+return a ``std::wstring`` instead of a ``std::string``).
+
+Like the distinguished names, subject alternative names can contain a lot of
+things that Botan will flat out ignore (most of which you would likely never
+want to use). However, there are three very useful pieces of information that
+this extension might hold: an email address ([email protected]), a DNS name
+(somehost.example.com), or a URI (http://www.example.com).
+
+So, how to get the information? Call ``subject_info`` with the name of
+the piece of information you want, and it will return a
+``std::string`` that is either empty (signifying that the certificate
+doesn't have this information), or has the information
+requested. There are several names for each possible item, but the
+most easily readable ones are: "Name", "Country", "Organization",
+"Organizational Unit", "Locality", "State", "RFC822", "URI", and
+"DNS". These values are returned as a ``std::string``.
+
+You can also get information about the issuer of the certificate in the same
+way, using ``issuer_info``.
+
+X.509v3 Extensions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+X.509v3 specifies a large number of possible extensions. Botan
+supports some, but by no means all of them. This section lists which
+ones 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. The default for a v1/v2 certificate is
+ assume it's a CA if and only if the option "x509/default_to_ca" is set. 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" 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.
+
+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 ``X509_Store`` object
+with
+
+.. cpp:function:: X509_Code X509_Store::add_crl(const X509_CRL& crl)
+
+and all future verifications will take into account the certificates
+listed, assuming ``add_crl`` returns ``VERIFIED``. If it doesn't
+return ``VERIFIED``, then the return value is an error code signifying
+that the CRL could not be processed due to some problem (which could
+be something like the issuing certificate could not being found, an
+invalid signature, or the CRL having some format problem).
+
+Reading Certificates
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``X509_Certificate`` has two constructors, each of which takes a source of
+data; a filename to read, and a ``DataSource&``::
+
+ X509_Certificate cert1("cert1.pem");
+
+ /* This file contains two certificates, concatenated */
+ DataSource_Stream in("certs2_and_3.pem");
+
+ X509_Certificate cert2(in); // read the first cert
+ X509_Certificate cert3(in); // read the second cert
+
+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::vector`` 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 three certificate lookup methods are ``by_SKID`` (Subject Key
+Identifier), ``by_name`` (the CommonName DN entry), and ``by_email``
+(stored in either the distinguished name, or in a
+subjectAlternativeName extension). The name and email versions take a
+``std::string``, while the SKID version takes a
+``secure_vector<byte>`` containing the subject key identifier in raw
+binary. You can choose not to implement ``by_name`` or ``by_email``,
+but ``by_SKID`` is mandatory to implement, and, currently, is the only
+version that is used by ``X509_Store``.
+
+Finally, there is a method for finding CRLs, called ``get_crls_for``,
+that takes an ``X509_Certificate`` object, and returns a
+``std::vector`` of ``X509_CRL``. While normally there will be only one
+CRL, the use of the vector makes it easy to return no CRLs (eg, if the
+certificate store doesn't support retrieving them), or return multiple
+ones (for example, if the certificate store can't determine precisely
+which key was used to sign the certificate). Implementing the function
+is optional, and by default will return no CRLs. If it is available,
+it will be used by ``X509_CRL``.
+
+As for using such a store, you have to tell ``X509_Store`` about it
+with
+
+.. cpp:function:: void X509_Store::add_new_certstore(Certificate_Store* new_store)
+
+ The store object will be owned by (and deleted by) ``X509_Store``,
+ so make sure to allocate it with ``new``.
+
+Path Validation
+----------------------------------------
+
+The process of validating a certfificate 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``.
+
+Certificate Authorities
+---------------------------------
+
+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)
+
+The private key is the private key corresponding to the public key in the
+CA's certificate.
+
+Requests for new certificates are supplied to a CA in the form on 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) const
+
+Here's an example:
+
+.. literalinclude examples/ca.cpp
+
+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(u32bit seconds_to_expiration = 0)
+
+ This function will return a new, empty CRL. The
+ ``seconds_to_expiration`` 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& old_crl, \
+ std::vector<CRL_Entry> new_revoked, size_t seconds_to_expiration = 0)
+
+ Where ``X509_CRL`` is the last CRL this CA issued, and
+ ``new_revoked`` 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<byte>`` 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 ``DELETE_CRL_ENTRY``. 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)
+
+ 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).
+
+An example:
+
+.. literalinclude:: examples/self_sig.cpp
+
+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)
+
+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.
+
+An example:
+
+.. literalinclude:: examples/pkcs10.cpp
+
+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.
+
+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``.
+
+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".
+
+Lastly, 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.
+
+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
+3280), 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.