aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/examples.txt109
-rw-r--r--doc/index.txt5
-rw-r--r--doc/lowlevel.txt258
-rw-r--r--doc/passhash.txt152
-rw-r--r--doc/pubkey.txt365
-rw-r--r--doc/rng.txt112
-rw-r--r--doc/ssl.txt10
-rw-r--r--doc/support.txt19
-rw-r--r--doc/x509.txt10
9 files changed, 634 insertions, 406 deletions
diff --git a/doc/examples.txt b/doc/examples.txt
new file mode 100644
index 000000000..5d4aad8ed
--- /dev/null
+++ b/doc/examples.txt
@@ -0,0 +1,109 @@
+
+Examples
+========================================
+
+RSA Examples
+----------------------------------------
+
+RSA Key Generation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Generate an RSA key of a specified bitlength, and put it into a pair
+of key files. One is the public key in X.509 format (PEM encoded), the
+private key is in PKCS #8 format (also PEM encoded), either encrypted
+or unencrypted depending on if a password was given.
+
+.. literalinclude:: examples/rsa_kgen.cpp
+
+DSA Examples
+----------------------------------------
+
+DSA Key Generation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Generate a 2048 bit DSA key
+
+.. literalinclude:: examples/dsa_kgen.cpp
+
+DSA Signature Generation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Reads a DSA private key and signs the specified file using SHA-1
+
+.. literalinclude:: examples/dsa_sign.cpp
+
+DSA Signature Verification
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Reads a DSA public key and a signature, and checks if the signature
+is valid for the specified file
+
+..literalinclude:: examples/dsa_ver.cpp
+
+X.509 Certificate Examples
+----------------------------------------
+
+PKCS #10 Certificate Requests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. literalinclude:: examples/pkcs10.cpp
+
+Self Signed Certificate
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Generate a 2048 bit RSA key, and then create a self-signed X.509v3
+certificate with that key. If the do_CA variable is set to true, then
+it will be marked for CA use, otherwise it will get extensions
+appropriate for use with a client certificate. The private key is
+stored as an encrypted PKCS #8 object in another file.
+
+.. literalinclude:: examples/self_sig.cpp
+
+Certificate Authority
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implement the functionality of a simple CA: read in a CA certificate,
+the associated private key, and a PKCS #10 certificate request. Sign
+the request and print the new certificate to stdout.
+
+File names are hardcoded for simplicity. The CA certificate is
+expected in "cacert.pem", the private key is expected in
+"caprivate.pem", and "req.pem" is a PKCS #10 certificate request.
+
+.. literalinclude:: examples/ca.cpp
+
+
+Format Preserving Encryption
+----------------------------------------
+
+Format preserving encryption is a way of mapping data with an
+arbitrarly specified format such that the ciphertext has the same
+formatting. This example encrypts a credit card number with a valid
+`Luhn checksum <http://en.wikipedia.org/wiki/Luhn_algorithm>`_ to
+another number with the same format, including a correct checksum.
+
+.. literalinclude:: examples/fpe.cpp
+
+ASN.1 Parsing
+----------------------------------------
+
+This example is a simple ASN.1 parser
+
+.. literalinclude:: examples/asn1.cpp
+
+SSL/TLS
+----------------------------------------
+
+SSL Client
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A simple SSL/TLS client
+
+.. literalinclude:: examples/tls_client.cpp
+
+SSL Server
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A simple SSL/TLS server
+
+.. literalinclude:: examples/tls_server.cpp
diff --git a/doc/index.txt b/doc/index.txt
index 1dfa6abcc..ecbeb8803 100644
--- a/doc/index.txt
+++ b/doc/index.txt
@@ -12,12 +12,17 @@ Contents:
filters
pubkey
x509
+ ssl
lowlevel
+ passhash
+ rng
bigint
+ examples
algos
pgpkeys
license
credits
+ support
log
Indices and tables
diff --git a/doc/lowlevel.txt b/doc/lowlevel.txt
index 4f63948da..d6bf071bc 100644
--- a/doc/lowlevel.txt
+++ b/doc/lowlevel.txt
@@ -216,116 +216,6 @@ away; the key is kept around).
A MAC has the ``SymmetricAlgorithm`` interface in addition to the
``BufferedComputation`` interface.
-Random Number Generators
----------------------------------
-
-The random number generators provided in Botan are meant for creating
-keys, IVs, padding, nonces, and anything else that requires 'random'
-data. It is important to remember that the output of these classes
-will vary, even if they are supplied with ethe same seed (ie, two
-``Randpool`` objects with similar initial states will not produce
-the same output, because the value of high resolution timers is added
-to the state at various points).
-
-To ensure good quality output, a PRNG needs to be seeded with truly
-random data (such as that produced by a hardware RNG). Typically, you
-will use an ``EntropySource`` (see below). To add some (typically
-application specific) entropy to a PRNG, you can use
-
-.. cpp:function:: void add_entropy(const byte* data, size_t length)
-
-Once a PRNG has been initialized, you can get a single byte of random
-data by
-
-.. cpp:function:: byte random()
-
-or get a large block by calling
-
-.. cpp:function:: void randomize(byte* data, size_t length)
-
-Randpool
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-``Randpool`` is the primary PRNG within Botan. In recent versions all
-uses of it have been wrapped by an implementation of the X9.31 PRNG
-(see below). If for some reason you should have cause to create a PRNG
-instead of using the "global" one owned by the library, it would be
-wise to consider the same on the grounds of general caution; while
-``Randpool`` is designed with known attacks and PRNG weaknesses in
-mind, it is not an standard/official PRNG. The remainder of this
-section is a (fairly technical, though high-level) description of the
-algorithms used in this PRNG. Unless you have a specific interest in
-this subject, the rest of this section might prove somewhat
-uninteresting.
-
-``Randpool`` has an internal state called pool, which is 512 bytes
-long. This is where entropy is mixed into and extracted from. There is also a
-small output buffer (called buffer), which holds the data which has already
-been generated but has just not been output yet.
-
-It is based around a MAC and a block cipher (which are currently
-HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it
-should be taken as a multiple of the cipher's block size. For example,
-if a 256-bit block cipher were used instead of AES, all the sizes
-internally would double. Every time some new output is needed, we
-compute the MAC of a counter and a high resolution timer. The
-resulting MAC is XORed into the output buffer (wrapping as needed),
-and the output buffer is then encrypted with AES, producing 16 bytes
-of output.
-
-After 8 blocks (or 128 bytes) have been produced, we mix the pool. To
-do this, we first rekey both the MAC and the cipher; the new MAC key
-is the MAC of the current pool under the old MAC key, while the new
-cipher key is the MAC of the current pool under the just-chosen MAC
-key. We then encrypt the entire pool in CBC mode, using the current
-(unused) output buffer as the IV. We then generate a new output
-buffer, using the mechanism described in the previous paragraph.
-
-To add randomness to the PRNG, we compute the MAC of the input and XOR
-the output into the start of the pool. Then we remix the pool and
-produce a new output buffer. The initial MAC operation should make it
-very hard for chosen inputs to harm the security of ``Randpool``, and
-as HMAC should be able to hold roughly 256 bits of state, it is
-unlikely that we are wasting much input entropy (or, if we are, it
-doesn't matter, because we have a very abundant supply).
-
-ANSI X9.31
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG,
-though using AES-256 instead of 3DES as the block cipher. This PRNG
-implementation has been checked against official X9.31 test vectors.
-
-Internally, the PRNG holds a pointer to another PRNG (typically
-Randpool). This internal PRNG generates the key and seed used by the
-X9.31 algorithm, as well as the date/time vectors. Each time an X9.31
-PRNG object receives entropy, it passes it along to the PRNG it is
-holding, and then pulls out some random bits to generate a new key and
-seed. This PRNG considers itself seeded as soon as the internal PRNG
-is seeded.
-
-
-Entropy Sources
----------------------------------
-
-An ``EntropySource`` is an abstract representation of some method of
-gather "real" entropy. This tends to be very system dependent. The
-*only* way you should use an ``EntropySource`` is to pass it to a PRNG
-that will extract entropy from it -- never use the output directly for
-any kind of key or nonce generation!
-
-``EntropySource`` has a pair of functions for getting entropy from
-some external source, called ``fast_poll`` and ``slow_poll``. These
-pass a buffer of bytes to be written; the functions then return how
-many bytes of entropy were gathered.
-
-Note for writers of ``EntropySource`` subclasses: it isn't necessary
-to use any kind of cryptographic hash on your output. The data
-produced by an EntropySource is only used by an application after it
-has been hashed by the ``RandomNumberGenerator`` that asked for the
-entropy, thus any hashing you do will be wasteful of both CPU cycles
-and entropy.
-
User Interfaces
---------------------------------
@@ -384,154 +274,6 @@ wxWidgets, FOX, etc), and would like to make it available to users in
general (ideally under a permissive license such as public domain or
MIT/BSD), feel free to send in a copy.
-PBKDF Algorithms
----------------------------------
-
-There are various procedures (usually ad-hoc) for turning a
-passphrase into a (mostly) arbitrary length key for a symmetric
-cipher. A general interface for such algorithms is presented in
-``pbkdf.h``. The main function is ``derive_key``, which
-takes a passphrase, a salt, an iteration count, and the desired length
-of the output key, and returns a key of that length, deterministically
-produced from the passphrase and salt. If an algorithm can't produce a
-key of that size, it will throw an exception (most notably, PKCS #5's
-PBKDF1 can only produce strings between 1 and $n$ bytes, where $n$ is
-the output size of the underlying hash function).
-
-The purpose of the iteration count is to make the algorithm take
-longer to compute the final key (reducing the speed of brute-force
-attacks of various kinds). Most standards recommend an iteration count
-of at least 10000. Currently defined PBKDF algorithms are
-"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can
-retrieve any of these using the ``get_pbkdf``, found in
-``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000
-iterations and a 16 byte salt is recommend for new applications.
-
-OpenPGP S2K
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-There are some oddities about OpenPGP's S2K algorithms that are
-documented here. For one thing, it uses the iteration count in a
-strange manner; instead of specifying how many times to iterate the
-hash, it tells how many *bytes* should be hashed in total
-(including the salt). So the exact iteration count will depend on the
-size of the salt (which is fixed at 8 bytes by the OpenPGP standard,
-though the implementation will allow any salt size) and the size of
-the passphrase.
-
-To get what OpenPGP calls "Simple S2K", set iterations to 0, and do
-not specify a salt. To get "Salted S2K", again leave the iteration
-count at 0, but give an 8-byte salt. "Salted and Iterated S2K"
-requires an 8-byte salt and some iteration count (this should be
-significantly larger than the size of the longest passphrase that
-might reasonably be used; somewhere from 1024 to 65536 would probably
-be about right). Using both a reasonably sized salt and a large
-iteration count is highly recommended to prevent password guessing
-attempts.
-
-Password Hashing
----------------------------------
-
-Storing passwords for user authentication purposes in plaintext is the
-simplest but least secure method; when an attacker compromises the
-database in which the passwords are stored, they immediately gain
-access to all of them. Often passwords are reused among multiple
-services or machines, meaning once a password to a single service is
-known an attacker has a substantial head start on attacking other
-machines.
-
-The general approach is to store, instead of the password, the output
-of a one way function of the password. Upon receiving an
-authentication request, the authenticator can recompute the one way
-function and compare the value just computed with the one that was
-stored. If they match, then the authentication request succeeds. But
-when an attacker gains access to the database, they only have the
-output of the one way function, not the original password.
-
-Common hash functions such as SHA-256 are one way, but used alone they
-have problems for this purpose. What an attacker can do, upon gaining
-access to such a stored password database, is hash common dictionary
-words and other possible passwords, storing them in a list. Then he
-can search through his list; if a stored hash and an entry in his list
-match, then he has found the password. Even worse, this can happen
-*offline*: an attacker can begin hashing common passwords days,
-months, or years before ever gaining access to the database. In
-addition, if two users choose the same password, the one way function
-output will be the same for both of them, which will be visible upon
-inspection of the database.
-
-There are two solutions to these problems: salting and
-iteration. Salting refers to including, along with the password, a
-randomly chosen value which perturbs the one way function. Salting can
-reduce the effectivness of offline dictionary generation (because for
-each potential password, an attacker would have to compute the one way
-function output for all possible salts - with a large enough salt,
-this can make the problem quite difficult). It also prevents the same
-password from producing the same output, as long as the salts do not
-collide. With a large salt (say 80 to 128 bits) this will be quite
-unlikely. Iteration refers to the general technique of forcing
-multiple one way function evaluations when computing the output, to
-slow down the operation. For instance if hashing a single password
-requires running SHA-256 100,000 times instead of just once, that will
-slow down user authentication by a factor of 100,000, but user
-authentication happens quite rarely, and usually there are more
-expensive operations that need to occur anyway (network and database
-I/O, etc). On the other hand, an attacker who is attempting to break a
-database full of stolen password hashes will be seriously
-inconvenienced by a factor of 100,000 slowdown; they will be able to
-only test at a rate of .0001% of what they would without iterations
-(or, equivalently, will require 100,000 times as many zombie botnet
-hosts).
-
-There are many different ways of doing this password hashing
-operation, with common ones including Unix's crypt (which is based on
-DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using
-MD5 or SHA-256 are also in use on various systems.
-
-Botan provides two techniques, passhash9 and bcrypt
-
-Passhash9
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Botan provides a password hashing technique called passhash9, in
-``passhash9.h``, which is based on PBKDF2. A usage example can be
-found in ``doc/examples/passhash.cpp``. Three functions are provided
-in this header:
-
-.. cpp:function:: std::string generate_passhash9(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10)
-
- Takes the password to hash, a rng, and a work factor, which tells
- how many iterations to compute. The default work factor is 10
- (which means 100,000 iterations), but any non-zero value is
- accepted.
-
-.. cpp:function:: std::string generate_passhash9(const std::string& password, byte alg_id, RandomNumberGenerator& rng, u16bit work_factor = 10)
-
- Like the other ``generate_passhash9``, but taking a parameter that
- specifies which PRF to use. Currently defined values are 0
- ("HMAC(SHA-1)"), 1 ("HMAC(SHA-256)"), and 2 ("CMAC(Blowfish)").
-
-.. cpp:function:: bool check_passhash9(const std::string& password, const std::string& hash)
-
- Takes a password and a passhash9 output and checks if the password
- is the same as the one that was used to generate the passhash9
- output, returning a boolean true (same) or false (not same).
-
-Bcrypt
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Bcrypt is a password hashing scheme originally designed for use in
-OpenBSD, but numerous other implementations exist. It is made
-available by including ``bcrypt.h``, and provides the functions
-
-.. cpp:function:: std::string generate_bcrypt(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10)
-
-and
-
-.. cpp:function:: bool check_bcrypt(const std::string& password, const std::string& hash)
-
-These work in exactly the same way as the passhash9 password hashing
-functions.
Checksums
---------------------------------
diff --git a/doc/passhash.txt b/doc/passhash.txt
new file mode 100644
index 000000000..a7a18ebb4
--- /dev/null
+++ b/doc/passhash.txt
@@ -0,0 +1,152 @@
+
+.. _pbkdf:
+
+PBKDF Algorithms
+---------------------------------
+
+There are various procedures (usually ad-hoc) for turning a
+passphrase into a (mostly) arbitrary length key for a symmetric
+cipher. A general interface for such algorithms is presented in
+``pbkdf.h``. The main function is ``derive_key``, which
+takes a passphrase, a salt, an iteration count, and the desired length
+of the output key, and returns a key of that length, deterministically
+produced from the passphrase and salt. If an algorithm can't produce a
+key of that size, it will throw an exception (most notably, PKCS #5's
+PBKDF1 can only produce strings between 1 and $n$ bytes, where $n$ is
+the output size of the underlying hash function).
+
+The purpose of the iteration count is to make the algorithm take
+longer to compute the final key (reducing the speed of brute-force
+attacks of various kinds). Most standards recommend an iteration count
+of at least 10000. Currently defined PBKDF algorithms are
+"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can
+retrieve any of these using the ``get_pbkdf``, found in
+``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000
+iterations and a 16 byte salt is recommend for new applications.
+
+OpenPGP S2K
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are some oddities about OpenPGP's S2K algorithms that are
+documented here. For one thing, it uses the iteration count in a
+strange manner; instead of specifying how many times to iterate the
+hash, it tells how many *bytes* should be hashed in total
+(including the salt). So the exact iteration count will depend on the
+size of the salt (which is fixed at 8 bytes by the OpenPGP standard,
+though the implementation will allow any salt size) and the size of
+the passphrase.
+
+To get what OpenPGP calls "Simple S2K", set iterations to 0, and do
+not specify a salt. To get "Salted S2K", again leave the iteration
+count at 0, but give an 8-byte salt. "Salted and Iterated S2K"
+requires an 8-byte salt and some iteration count (this should be
+significantly larger than the size of the longest passphrase that
+might reasonably be used; somewhere from 1024 to 65536 would probably
+be about right). Using both a reasonably sized salt and a large
+iteration count is highly recommended to prevent password guessing
+attempts.
+
+Password Hashing
+---------------------------------
+
+Storing passwords for user authentication purposes in plaintext is the
+simplest but least secure method; when an attacker compromises the
+database in which the passwords are stored, they immediately gain
+access to all of them. Often passwords are reused among multiple
+services or machines, meaning once a password to a single service is
+known an attacker has a substantial head start on attacking other
+machines.
+
+The general approach is to store, instead of the password, the output
+of a one way function of the password. Upon receiving an
+authentication request, the authenticator can recompute the one way
+function and compare the value just computed with the one that was
+stored. If they match, then the authentication request succeeds. But
+when an attacker gains access to the database, they only have the
+output of the one way function, not the original password.
+
+Common hash functions such as SHA-256 are one way, but used alone they
+have problems for this purpose. What an attacker can do, upon gaining
+access to such a stored password database, is hash common dictionary
+words and other possible passwords, storing them in a list. Then he
+can search through his list; if a stored hash and an entry in his list
+match, then he has found the password. Even worse, this can happen
+*offline*: an attacker can begin hashing common passwords days,
+months, or years before ever gaining access to the database. In
+addition, if two users choose the same password, the one way function
+output will be the same for both of them, which will be visible upon
+inspection of the database.
+
+There are two solutions to these problems: salting and
+iteration. Salting refers to including, along with the password, a
+randomly chosen value which perturbs the one way function. Salting can
+reduce the effectivness of offline dictionary generation (because for
+each potential password, an attacker would have to compute the one way
+function output for all possible salts - with a large enough salt,
+this can make the problem quite difficult). It also prevents the same
+password from producing the same output, as long as the salts do not
+collide. With a large salt (say 80 to 128 bits) this will be quite
+unlikely. Iteration refers to the general technique of forcing
+multiple one way function evaluations when computing the output, to
+slow down the operation. For instance if hashing a single password
+requires running SHA-256 100,000 times instead of just once, that will
+slow down user authentication by a factor of 100,000, but user
+authentication happens quite rarely, and usually there are more
+expensive operations that need to occur anyway (network and database
+I/O, etc). On the other hand, an attacker who is attempting to break a
+database full of stolen password hashes will be seriously
+inconvenienced by a factor of 100,000 slowdown; they will be able to
+only test at a rate of .0001% of what they would without iterations
+(or, equivalently, will require 100,000 times as many zombie botnet
+hosts).
+
+There are many different ways of doing this password hashing
+operation, with common ones including Unix's crypt (which is based on
+DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using
+MD5 or SHA-256 are also in use on various systems.
+
+Botan provides two techniques, passhash9 and bcrypt
+
+Passhash9
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Botan provides a password hashing technique called passhash9, in
+``passhash9.h``, which is based on PBKDF2. A usage example can be
+found in ``doc/examples/passhash.cpp``. Three functions are provided
+in this header:
+
+.. cpp:function:: std::string generate_passhash9(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10)
+
+ Takes the password to hash, a rng, and a work factor, which tells
+ how many iterations to compute. The default work factor is 10
+ (which means 100,000 iterations), but any non-zero value is
+ accepted.
+
+.. cpp:function:: std::string generate_passhash9(const std::string& password, byte alg_id, RandomNumberGenerator& rng, u16bit work_factor = 10)
+
+ Like the other ``generate_passhash9``, but taking a parameter that
+ specifies which PRF to use. Currently defined values are 0
+ ("HMAC(SHA-1)"), 1 ("HMAC(SHA-256)"), and 2 ("CMAC(Blowfish)").
+
+.. cpp:function:: bool check_passhash9(const std::string& password, const std::string& hash)
+
+ Takes a password and a passhash9 output and checks if the password
+ is the same as the one that was used to generate the passhash9
+ output, returning a boolean true (same) or false (not same).
+
+Bcrypt
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Bcrypt is a password hashing scheme originally designed for use in
+OpenBSD, but numerous other implementations exist. It is made
+available by including ``bcrypt.h``, and provides the functions
+
+.. cpp:function:: std::string generate_bcrypt(const std::string& password, RandomNumberGenerator& rng, u16bit work_factor = 10)
+
+and
+
+.. cpp:function:: bool check_bcrypt(const std::string& password, const std::string& hash)
+
+These work in exactly the same way as the passhash9 password hashing
+functions.
+
diff --git a/doc/pubkey.txt b/doc/pubkey.txt
index 2b765cc10..1be471e1b 100644
--- a/doc/pubkey.txt
+++ b/doc/pubkey.txt
@@ -4,80 +4,240 @@
Public Key Cryptography
=================================
-Quick Start
----------------------------------
+Public key cryptography (also called assymmetric cryptography) is a
+collection of techniques allowing for encryption, signatures, and key
+agreement.
-Let's create a 2048-bit RSA private key, serialize the public key as a
-PKCS #1 file with PEM encoding (which can be understood by many other
-cryptographic programs), and then load it on another machine::
+Key Objects
+----------------------------------------
- // everyone does:
- AutoSeeded_RNG rng;
+Public and private keys are represented by classes ``Public_Key`` and
+it's subclass ``Private_Key``. The use of inheritence here means that
+a ``Private_Key`` can be converted into a reference to a public key.
- // Alice
- RSA_PrivateKey priv_rsa(rng, 2048 /* bits */);
+None of the functions on ``Public_Key`` and ``Private_Key`` itself are
+particularly useful for users of the library, because 'bare' public key
+operations are *very insecure*. The only purpose of these functions is
+to provide a clean interface that higher level operations can be built
+on. So really the only thing you need to know is that when a function
+takes a reference to a ``Public_Key``, it can take any public key or
+private key, and similiarly for ``Private_Key``.
- std::string alice_pem = X509::PEM_encode(priv_rsa);
+Types of ``Public_Key`` include ``RSA_PublicKey``, ``DSA_PublicKey``,
+``ECDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``,
+``RW_PublicKey``, ``NR_PublicKey``,, and ``GOST_3410_PublicKey``.
+There are cooresponding ``Private_Key`` classes for each of these
+algorithms.
- // send alice_pem to Bob, who does
+.. _creating_new_private_keys:
- // Bob
- std::auto_ptr<Public_Key> alice(load_key(alice_pem));
+Creating New Private Keys
+----------------------------------------
- RSA_PublicKey* alice_rsa = dynamic_cast<RSA_PublicKey>(alice);
- if(alice_rsa)
- {
- /* ... */
- }
+Creating a new private key requires two things: a source of
+random numbers (see :ref:`random_number_generators`) and some
+algorithm specific parameters that define the *security level*
+of the resulting key. For instance, the security level of an RSA
+key is (at least in part) defined by the length of the public key
+modulus in bits. So to create a new RSA private key, you would call
-Creating New Public Key Pairs
----------------------------------
+.. cpp:function:: RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, size_t bits)
+
+ A constructor that creates a new random RSA private key with a modulus
+ of length *bits*.
+
+Algorithms based on the discrete-logarithm problem uses what is called
+a *group*; a group can safely be used with many keys, and for some
+operations, like key agreement, the two keys *must* use the same
+group. There are currently two kinds of discrete logarithm groups
+supported in botan: the integers modulo a prime, represented by
+:ref:`dl_group`, and elliptic curves in GF(p), represented by
+:ref:`ec_dompar`. A rough generalization is that the larger the group
+is, the more secure the algorithm is, but coorespondingly the slower
+the operations will be.
+
+Given a ``DL_Group``, you can create new DSA, Diffie-Hellman, and
+Nyberg-Rueppel key pairs with
+
+.. cpp:function:: DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x = 0)
+
+ The optional *x* parameter to each of these contructors is a private
+ key value. This allows you to create keys where the private key is
+ formed by some special technique; for instance you can use the hash
+ of a password (see :ref:`pbkdf` for how to do that) as a private key
+ value. Normally, you would leave the value as zero, letting the
+ class generate a new random key.
+
+Finally, given an ``EC_Domain_Params`` object, you can create a new
+ECDSA, ECDH, or GOST 34.10 private key with
+
+.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain)
+
+.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain)
+
+.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain)
+
+Unlike the integer modulo a prime key types, the constructor that takes a
+predefined ``BigInt`` private key value is different:
+
+.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(const EC_Domain_Params& domain, const BigInt& x)
+
+.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(const EC_Domain_Params& domain, const BigInt& x)
+
+.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x)
+
+.. note::
+
+ It is likely that these constructors will be removed in a future
+ release, and a third optional parameter will be added to the
+ constructors described above, to match the integer modulo prime
+ versions. Only use them if you really need them.
+
+
+Serializing Private Keys
+----------------------------------------
+
+The standard format for serializing a private key is PKCS #8, the
+operations for which are defined in ``pkcs8.h``. It supports both
+unencrypted and encrypted storage.
+
+.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& password, const std::string& pbe_algo = "")
+
+ Takes any private key object, serializes it, encrypts it using
+ *password*, and returns a binary structure representing the private
+ key.
+
+ The final (optional) argument, *pbe_algo*, specifies a particular
+ password based encryption (or PBE) algorithm. If you don't specify a
+ PBE, a sensible default will be used.
+
+.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "")
+
+ This formats the key in the same manner as ``BER_encode``, but
+ additionally encodes it into a text format with identifying
+ headers. Using PEM encoding is *highly* recommended for many
+ reasons, including compatibility with other software, for
+ transmission over 8-bit unclean channels, because it can be
+ identified by a human without special tools, and because it
+ sometimes allows more sane behavior of tools that process the data.
+
+Unencrypted serialization is also supported.
+
+.. warning::
+
+ In most situations, using unecrypted private key storage is a bad
+ idea, because anyone can come along and grab the private key without
+ having to know any passwords or other secrets. Unless you have very
+ particular security requirements, always use the versions that
+ encrypt the key based on a passphrase, described above.
+
+.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key)
+
+ Serializes the private key and returns the result.
+
+.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key)
+
+ Serializes the private key, base64 encodes it, and returns the
+ result.
+
+Last but not least, there are some functions that will load (and
+decrypt, if necessary) a PKCS #8 private key:
+
+.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, const User_Interface& ui)
+
+.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, std::string passphrase = "")
+
+.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const User_Interface& ui)
+
+.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const std::string& passphrase = "")
+
+The result is an object allocated using ``new``.
+
+The versions that pass the passphrase as a ``std::string`` are
+primarily for compatibility, but they are useful in limited
+circumstances. The ``User_Interface`` versions are how ``load_key`` is
+implemented, and provides for much more flexibility. If the passphrase
+passed in is not correct, then an exception is thrown and that is
+that. However, if you pass in an UI object, then the UI object can
+keep asking the user for the passphrase until they get it right (or
+until they cancel the action, though the UI interface). A
+``User_Interface`` has very little to do with talking to users; it's
+just a way to glue together Botan and whatever user interface you
+happen to be using. You can think of it as a user interface
+interface. The default ``User_Interface`` is rather dumb, and acts
+rather like the versions taking the ``std::string``; it tries the
+passphrase passed in first, and then it cancels.
+
+.. note::
+
+ In a future version, it is likely that ``User_Interface`` will be
+ replaced by a simple callback using ``std::function``.
+
+.. _dl_group:
-The library has interfaces for public key encryption, signatures, and
-key agreement that do not require knowing the exact algorithm in
-use. One place where we *do* need to know exactly what kind of
-algorithm is in use is when we are creating a key.
-
-There are currently three kinds of public key algorithms in Botan:
-ones based on integer factorization (RSA and Rabin-Williams), ones
-based on the discrete logarithm problem in the integers modulo a prime
-(DSA, Diffie-Hellman, Nyberg-Rueppel, and ElGamal), and ones based on
-the discrete logarithm problem in an elliptic curve (ECDSA, ECDH, and
-GOST 34.10). The systems based on discrete logarithms (in either
-regular integers or elliptic curves) use a group (a mathematical
-term), which can be shared among many keys. An elliptic curve group is
-represented by the class ``EC_Domain_Params``, while a modulo-prime
-group is represented by a ``DL_Group``.
-
-There are two ways to create a DL private key (such as
-``DSA_PrivateKey``). One is to pass in just a ``DL_Group`` object -- a
-new key will automatically be generated. The other involves passing in
-a group to use, along with both the public and private values (private
-value first).
-
-Since in integer factorization algorithms, the modulus used isn't
-shared by other keys, we don't use this notion. You can create a new
-key by passing in a ``size_t`` telling how long (in bits) the key
-should be, or you can copy an pre-existing key by passing in the
-appropriate parameters (primes, exponents, etc). For RSA and
-Rabin-Williams (the two IF schemes in Botan), the parameters are all
-``BigInt``: prime 1, prime 2, encryption exponent, decryption
-exponent, modulus. The last two are optional, since they can easily be
-derived from the first three.
-
-Creating a DL_Group
+DL_Group
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-There are quite a few ways to get a ``DL_Group`` object. The best is
-to use the function ``get_dl_group``, which takes a string naming a
-group; it will either return that group, if it knows about it, or
-throw an exception. Names it knows about include "modp/ietf/N" where N
-is 768, 1024, 1536, 2048, 3072, 4096, 6144, and 8192 for
-Diffie-Hellman and ElGamal. DSA-style groups are named "dsa/jce/N" for
-N 512, 768, 1024, and "dsa/botan/N" for 2048 and 3072.
+As described in :ref:`creating_new_private_keys`, a discrete logarithm
+group can be shared among many keys, even keys created by users who do
+not trust each other. However, it is necessary to trust the entity who
+created the group; that is why organization like NIST use algorithms
+which generate groups in a deterministic way such that creating a
+bogus group would require breaking some trusted cryptographic
+primitive like SHA-2.
+
+Instantiating a ``DL_Group`` simply requires calling
+
+.. cpp:function:: DL_Group::DL_Group(const std::string& name)
+
+ The *name* parameter is a specially formatted string that consists
+ of three things, the type of the group ("modp" or "dsa"), the
+ creator of the group, and the size of the group in bits, all
+ delimited by '/' characters.
+
+ Currently all "modp" groups included in botan are ones defined by
+ the Internet Engineering Task Force, so the provider is "ietf", and
+ the strings look like "modp/ietf/N" where N can be any of 768, 1024,
+ 1536, 2048, 3072, 4096, 6144, or 8192. This group type is used
+ for Diffie-Hellman and ElGamal algorithms.
+
+ The other type, "dsa" is used for DSA and Nyberg-Rueppel keys. They
+ can also be used with Diffie-Hellman and ElGamal, but this is less
+ common. The currently available groups are "dsa/jce/N" for N in 512,
+ 768, or 1024, and "dsa/botan/N" with N being 2048 or 3072. The
+ "jce" groups are the standard DSA groups used in the Java
+ Cryptography Extensions, while the "botan" groups were randomly
+ generated using the FIPS 186-3 algorithm by the library maintainers.
+
+You can generate a new random group using
+
+.. cpp:function:: DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits = 0)
-You can also generate a new random group. This is not recommend,
-because it is quite slow, especially for safe primes.
+ The *type* can be either ``Strong``, ``Prime_Subgroup``, or
+ ``DSA_Kosherizer``. *pbits* specifies the size of the prime in
+ bits. If the *type* is ``Prime_Subgroup`` or ``DSA_Kosherizer``,
+ then *qbits* specifies the size of the subgroup.
+
+You can export a ``DL_Group`` using
+
+.. cpp:function:: SecureVector<byte> DL_Group::DER_Encode(Format format)
+
+or
+
+.. cpp:function:: std::string DL_Group::PEM_encode(Format format)
+
+where *format* is any of
+
+.. _ec_dompar:
+
+EC_Domain_Params
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Key Checking
---------------------------------
@@ -291,19 +451,9 @@ To import and export public keys, use:
.. cpp:function:: MemoryVector<byte> X509::BER_encode(const Public_Key& key)
- Takes any public key object, and returns a standard binary structure
- representing the key which can be read by many other crypto
- libraries.
.. cpp:function:: std::string X509::PEM_encode(const Public_Key& key)
- This formats the key the same as ``BER_encode``, but additionally
- encodes it into a text format with identifying headers. Using PEM
- encoding is *highly* recommended for many reasons, including
- compatibility with other software, for transmission over 8-bit
- unclean channels, because it can be identified by a human without
- special tools, and because it sometimes allows more sane behavior of
- tools that process the data.
.. cpp:function:: Public_Key* X509::load_key(DataSource& in)
@@ -325,74 +475,3 @@ To import and export public keys, use:
Importing/Exporting Private Keys
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-There are two different options for private key import/export. The
-first is a plaintext version of the private key. This is supported by
-the following functions:
-
-.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key)
-
-.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key)
-
-These functions are similiar to the X.509 functions described in
-:ref:`import_export_public_keys`. The only difference is that they take
-a ``Private_Key`` object instead. In most situations, using these
-versions is a bad idea, because anyone can come along and grab the
-private key without having to know any passwords or other
-secrets. Unless you have very particular security requirements, always
-use the versions that encrypt the key based on a passphrase described
-below. For importing, the same functions can be used for encrypted and
-unencrypted keys.
-
-The other way to export a PKCS #8 key is to first encode it in the
-same manner as done above, then encrypt it using a passphrase, and
-store the whole thing into another structure. This method is
-definitely preferred, since otherwise the private key is
-unprotected. The algorithms and structures used here are standardized
-by PKCS #5 and PKCS #8, and can be read by many other crypto
-libraries:
-
-.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "")
-
-.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "")
-
-
-There are three new arguments needed here to support the encryption
-process. The first is a ``RandomNumberGenerator``, which is used to
-generate salts to randomize the encryption. The ``pass`` argument is
-the passphrase that will be used to encrypt the key. Both of these are
-required. The final (optional) argument, ``pbe_algo``, specifies a
-particular password based encryption (or PBE) algorithm. If you don't
-specify a PBE, a sensible default will be used.
-
-Last but not least, there are some functions that will load (and
-decrypt, if necessary) a PKCS #8 private key:
-
-.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, const User_Interface& ui)
-
-.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, RandomNumberGenerator& rng, std::string passphrase = "")
-
-.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const User_Interface& ui)
-
-.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, RandomNumberGenerator& rng, const std::string& passphrase = "")
-
-The versions that pass the passphrase as a ``std::string`` are
-primarily for compatibility, but they are useful in limited
-circumstances. The ``User_Interface`` versions are how ``load_key`` is
-implemented, and provides for much more flexibility. If the passphrase
-passed in is not correct, then an exception is thrown and that is
-that. However, if you pass in an UI object, then the UI object can
-keep asking the user for the passphrase until they get it right (or
-until they cancel the action, though the UI interface). A
-``User_Interface`` has very little to do with talking to users; it's
-just a way to glue together Botan and whatever user interface you
-happen to be using. You can think of it as a user interface
-interface. The default ``User_Interface`` is rather dumb, and acts
-rather like the versions taking the ``std::string``; it tries the
-passphrase passed in first, and then it cancels.
-
-All versions need access to a ``RandomNumberGenerator`` in order to
-perform probabilistic tests on the loaded key material.
-
-After loading a key, you can use ``dynamic_cast`` to find out what
-operations it supports, and use it appropriately. Remember to
-``delete`` the object once you are done with it.
diff --git a/doc/rng.txt b/doc/rng.txt
new file mode 100644
index 000000000..756dccfc9
--- /dev/null
+++ b/doc/rng.txt
@@ -0,0 +1,112 @@
+.. _random_number_generators:
+
+Random Number Generators
+---------------------------------
+
+The random number generators provided in Botan are meant for creating
+keys, IVs, padding, nonces, and anything else that requires 'random'
+data. It is important to remember that the output of these classes
+will vary, even if they are supplied with ethe same seed (ie, two
+``Randpool`` objects with similar initial states will not produce
+the same output, because the value of high resolution timers is added
+to the state at various points).
+
+To ensure good quality output, a PRNG needs to be seeded with truly
+random data (such as that produced by a hardware RNG). Typically, you
+will use an ``EntropySource`` (see below). To add some (typically
+application specific) entropy to a PRNG, you can use
+
+.. cpp:function:: void add_entropy(const byte* data, size_t length)
+
+Once a PRNG has been initialized, you can get a single byte of random
+data by
+
+.. cpp:function:: byte random()
+
+or get a large block by calling
+
+.. cpp:function:: void randomize(byte* data, size_t length)
+
+Randpool
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``Randpool`` is the primary PRNG within Botan. In recent versions all
+uses of it have been wrapped by an implementation of the X9.31 PRNG
+(see below). If for some reason you should have cause to create a PRNG
+instead of using the "global" one owned by the library, it would be
+wise to consider the same on the grounds of general caution; while
+``Randpool`` is designed with known attacks and PRNG weaknesses in
+mind, it is not an standard/official PRNG. The remainder of this
+section is a (fairly technical, though high-level) description of the
+algorithms used in this PRNG. Unless you have a specific interest in
+this subject, the rest of this section might prove somewhat
+uninteresting.
+
+``Randpool`` has an internal state called pool, which is 512 bytes
+long. This is where entropy is mixed into and extracted from. There is also a
+small output buffer (called buffer), which holds the data which has already
+been generated but has just not been output yet.
+
+It is based around a MAC and a block cipher (which are currently
+HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it
+should be taken as a multiple of the cipher's block size. For example,
+if a 256-bit block cipher were used instead of AES, all the sizes
+internally would double. Every time some new output is needed, we
+compute the MAC of a counter and a high resolution timer. The
+resulting MAC is XORed into the output buffer (wrapping as needed),
+and the output buffer is then encrypted with AES, producing 16 bytes
+of output.
+
+After 8 blocks (or 128 bytes) have been produced, we mix the pool. To
+do this, we first rekey both the MAC and the cipher; the new MAC key
+is the MAC of the current pool under the old MAC key, while the new
+cipher key is the MAC of the current pool under the just-chosen MAC
+key. We then encrypt the entire pool in CBC mode, using the current
+(unused) output buffer as the IV. We then generate a new output
+buffer, using the mechanism described in the previous paragraph.
+
+To add randomness to the PRNG, we compute the MAC of the input and XOR
+the output into the start of the pool. Then we remix the pool and
+produce a new output buffer. The initial MAC operation should make it
+very hard for chosen inputs to harm the security of ``Randpool``, and
+as HMAC should be able to hold roughly 256 bits of state, it is
+unlikely that we are wasting much input entropy (or, if we are, it
+doesn't matter, because we have a very abundant supply).
+
+ANSI X9.31
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG,
+though using AES-256 instead of 3DES as the block cipher. This PRNG
+implementation has been checked against official X9.31 test vectors.
+
+Internally, the PRNG holds a pointer to another PRNG (typically
+Randpool). This internal PRNG generates the key and seed used by the
+X9.31 algorithm, as well as the date/time vectors. Each time an X9.31
+PRNG object receives entropy, it passes it along to the PRNG it is
+holding, and then pulls out some random bits to generate a new key and
+seed. This PRNG considers itself seeded as soon as the internal PRNG
+is seeded.
+
+
+Entropy Sources
+---------------------------------
+
+An ``EntropySource`` is an abstract representation of some method of
+gather "real" entropy. This tends to be very system dependent. The
+*only* way you should use an ``EntropySource`` is to pass it to a PRNG
+that will extract entropy from it -- never use the output directly for
+any kind of key or nonce generation!
+
+``EntropySource`` has a pair of functions for getting entropy from
+some external source, called ``fast_poll`` and ``slow_poll``. These
+pass a buffer of bytes to be written; the functions then return how
+many bytes of entropy were gathered.
+
+Note for writers of ``EntropySource`` subclasses: it isn't necessary
+to use any kind of cryptographic hash on your output. The data
+produced by an EntropySource is only used by an application after it
+has been hashed by the ``RandomNumberGenerator`` that asked for the
+entropy, thus any hashing you do will be wasteful of both CPU cycles
+and entropy.
+
diff --git a/doc/ssl.txt b/doc/ssl.txt
new file mode 100644
index 000000000..dd206d5fc
--- /dev/null
+++ b/doc/ssl.txt
@@ -0,0 +1,10 @@
+
+SSL/TLS
+========================================
+
+SSL/TLS Clients
+----------------------------------------
+
+
+SSL/TLS Servers
+----------------------------------------
diff --git a/doc/support.txt b/doc/support.txt
new file mode 100644
index 000000000..a341d5830
--- /dev/null
+++ b/doc/support.txt
@@ -0,0 +1,19 @@
+
+Commercial Support Options
+========================================
+
+Commercial support is currently available for Botan from a couple of
+sources. If you provide services related to Botan, email the
+development list and your information can be added here.
+
+ * `FlexSecure GmbH <http://www.flexsecure.de>`_ offers support for
+ both Botan and `InSiTo <http://www.flexsecure.eu/insito/>`_
+ libraries. Developers from FlexSecure have done extensive work
+ with Botan in the past, and many new features to Botan have been
+ implemented and contributed by them. More information at
+ http://www.flexsecure.eu/insito/support.html
+
+ * `Jack Lloyd <http://www.randombit.net>`_ can provide services
+ relating to Botan including performance analysis of application
+ code using Botan, review of cryptographic use and designs for
+ security flaws, and implementing new features.
diff --git a/doc/x509.txt b/doc/x509.txt
index 027548b16..942d27f4c 100644
--- a/doc/x509.txt
+++ b/doc/x509.txt
@@ -187,11 +187,11 @@ Adding Certificates
You can add new certificates to a certificate store using any of these
functions:
-.. cpp:function:: void add_cert(const X509_Certificate& cert, bool trusted = false)
+.. cpp:function:: void X509_Store::add_cert(const X509_Certificate& cert, bool trusted = false)
-.. cpp:function:: void add_cert(DataSource& source)
+.. cpp:function:: void X509_Store::add_cert(DataSource& source)
-.. cpp:function:: void add_trusted_certs(DataSource& source)
+.. cpp:function:: void X509_Store::add_trusted_certs(DataSource& source)
The versions that take a ``DataSource&`` will add all the certificates
that it can find in that source.
@@ -211,7 +211,7 @@ trusted.
Adding CRLs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. cpp:function:: X509_Code add_crl(const X509_CRL& crl)
+.. cpp:function:: X509_Code X509_Store::add_crl(const X509_CRL& crl)
This will process the CRL and mark the revoked certificates. This will
also work if a revoked certificate is added to the store sometime
@@ -277,7 +277,7 @@ Verifying Certificates
There is a single function in ``X509_Store`` related to verifying a
certificate:
-.. .cpp:function:: X509_Code validate_cert(const X509_Certificate& cert, Cert_Usage usage = ANY)
+.. .cpp:function:: X509_Code X509_Store::validate_cert(const X509_Certificate& cert, Cert_Usage usage = ANY)
This function will return ``VERIFIED`` if the certificate can
safely be considered valid for the usage(s) described by ``usage``,