summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/doc/api_ref
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/doc/api_ref')
-rw-r--r--comm/third_party/botan/doc/api_ref/bigint.rst279
-rw-r--r--comm/third_party/botan/doc/api_ref/block_cipher.rst364
-rw-r--r--comm/third_party/botan/doc/api_ref/cipher_modes.rst384
-rw-r--r--comm/third_party/botan/doc/api_ref/compression.rst90
-rw-r--r--comm/third_party/botan/doc/api_ref/contents.rst39
-rw-r--r--comm/third_party/botan/doc/api_ref/credentials_manager.rst186
-rw-r--r--comm/third_party/botan/doc/api_ref/cryptobox.rst32
-rw-r--r--comm/third_party/botan/doc/api_ref/ecc.rst284
-rw-r--r--comm/third_party/botan/doc/api_ref/env_vars.rst20
-rw-r--r--comm/third_party/botan/doc/api_ref/ffi.rst1203
-rw-r--r--comm/third_party/botan/doc/api_ref/filters.rst733
-rw-r--r--comm/third_party/botan/doc/api_ref/fpe.rst98
-rw-r--r--comm/third_party/botan/doc/api_ref/hash.rst351
-rw-r--r--comm/third_party/botan/doc/api_ref/kdf.rst109
-rw-r--r--comm/third_party/botan/doc/api_ref/keywrap.rst60
-rw-r--r--comm/third_party/botan/doc/api_ref/message_auth_codes.rst268
-rw-r--r--comm/third_party/botan/doc/api_ref/otp.rst98
-rw-r--r--comm/third_party/botan/doc/api_ref/passhash.rst219
-rw-r--r--comm/third_party/botan/doc/api_ref/pbkdf.rst190
-rw-r--r--comm/third_party/botan/doc/api_ref/pkcs11.rst1419
-rw-r--r--comm/third_party/botan/doc/api_ref/psk_db.rst110
-rw-r--r--comm/third_party/botan/doc/api_ref/pubkey.rst954
-rw-r--r--comm/third_party/botan/doc/api_ref/python.rst668
-rw-r--r--comm/third_party/botan/doc/api_ref/rng.rst281
-rw-r--r--comm/third_party/botan/doc/api_ref/roughtime.rst6
-rw-r--r--comm/third_party/botan/doc/api_ref/secmem.rst31
-rw-r--r--comm/third_party/botan/doc/api_ref/srp.rst77
-rw-r--r--comm/third_party/botan/doc/api_ref/stream_ciphers.rst211
-rw-r--r--comm/third_party/botan/doc/api_ref/tls.rst1926
-rw-r--r--comm/third_party/botan/doc/api_ref/tpm.rst113
-rw-r--r--comm/third_party/botan/doc/api_ref/tss.rst45
-rw-r--r--comm/third_party/botan/doc/api_ref/versions.rst100
-rw-r--r--comm/third_party/botan/doc/api_ref/x509.rst914
33 files changed, 11862 insertions, 0 deletions
diff --git a/comm/third_party/botan/doc/api_ref/bigint.rst b/comm/third_party/botan/doc/api_ref/bigint.rst
new file mode 100644
index 0000000000..364844fb53
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/bigint.rst
@@ -0,0 +1,279 @@
+BigInt
+========================================
+
+``BigInt`` is Botan's implementation of a multiple-precision integer. Thanks to
+C++'s operator overloading features, using ``BigInt`` is often quite similar to
+using a native integer type. The number of functions related to ``BigInt`` is
+quite large, and not all of them are documented here. You can find the complete
+declarations in ``botan/bigint.h`` and ``botan/numthry.h``.
+
+.. cpp:class:: BigInt
+
+ .. cpp:function:: BigInt()
+
+ Create a BigInt with value zero
+
+ .. cpp:function:: BigInt(uint64_t n)
+
+ Create a BigInt with value *n*
+
+ .. cpp:function:: BigInt(const std::string& str)
+
+ Create a BigInt from a string. By default decimal is expected. With an 0x
+ prefix instead it is treated as hexadecimal.
+
+ .. cpp:function:: BigInt(const uint8_t buf[], size_t length)
+
+ Create a BigInt from a binary array (big-endian encoding).
+
+ .. cpp:function:: BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit = true)
+
+ Create a random BigInt of the specified size.
+
+ .. cpp:function:: BigInt operator+(const BigInt& x, const BigInt& y)
+
+ Add ``x`` and ``y`` and return result.
+
+ .. cpp:function:: BigInt operator+(const BigInt& x, word y)
+
+ Add ``x`` and ``y`` and return result.
+
+ .. cpp:function:: BigInt operator+(word x, const BigInt& y)
+
+ Add ``x`` and ``y`` and return result.
+
+ .. cpp:function:: BigInt operator-(const BigInt& x, const BigInt& y)
+
+ Subtract ``y`` from ``x`` and return result.
+
+ .. cpp:function:: BigInt operator-(const BigInt& x, word y)
+
+ Subtract ``y`` from ``x`` and return result.
+
+ .. cpp:function:: BigInt operator*(const BigInt& x, const BigInt& y)
+
+ Multiply ``x`` and ``y`` and return result.
+
+ .. cpp:function:: BigInt operator/(const BigInt& x, const BigInt& y)
+
+ Divide ``x`` by ``y`` and return result.
+
+ .. cpp:function:: BigInt operator%(const BigInt& x, const BigInt& y)
+
+ Divide ``x`` by ``y`` and return remainder.
+
+ .. cpp:function:: word operator%(const BigInt& x, word y)
+
+ Divide ``x`` by ``y`` and return remainder.
+
+ .. cpp:function:: word operator<<(const BigInt& x, size_t n)
+
+ Left shift ``x`` by ``n`` and return result.
+
+ .. cpp:function:: word operator>>(const BigInt& x, size_t n)
+
+ Right shift ``x`` by ``n`` and return result.
+
+ .. cpp:function:: BigInt& operator+=(const BigInt& y)
+
+ Add y to ``*this``
+
+ .. cpp:function:: BigInt& operator+=(word y)
+
+ Add y to ``*this``
+
+ .. cpp:function:: BigInt& operator-=(const BigInt& y)
+
+ Subtract y from ``*this``
+
+ .. cpp:function:: BigInt& operator-=(word y)
+
+ Subtract y from ``*this``
+
+ .. cpp:function:: BigInt& operator*=(const BigInt& y)
+
+ Multiply ``*this`` with y
+
+ .. cpp:function:: BigInt& operator*=(word y)
+
+ Multiply ``*this`` with y
+
+ .. cpp:function:: BigInt& operator/=(const BigInt& y)
+
+ Divide ``*this`` by y
+
+ .. cpp:function:: BigInt& operator%=(const BigInt& y)
+
+ Divide ``*this`` by y and set ``*this`` to the remainder.
+
+ .. cpp:function:: word operator%=(word y)
+
+ Divide ``*this`` by y and set ``*this`` to the remainder.
+
+ .. cpp:function:: word operator<<=(size_t shift)
+
+ Left shift ``*this`` by *shift* bits
+
+ .. cpp:function:: word operator>>=(size_t shift)
+
+ Right shift ``*this`` by *shift* bits
+
+ .. cpp:function:: BigInt& operator++()
+
+ Increment ``*this`` by 1
+
+ .. cpp:function:: BigInt& operator--()
+
+ Decrement ``*this`` by 1
+
+ .. cpp:function:: BigInt operator++(int)
+
+ Postfix increment ``*this`` by 1
+
+ .. cpp:function:: BigInt operator--(int)
+
+ Postfix decrement ``*this`` by 1
+
+ .. cpp:function:: BigInt operator-() const
+
+ Negation operator
+
+ .. cpp:function:: bool operator !() const
+
+ Return true unless ``*this`` is zero
+
+ .. cpp:function:: void clear()
+
+ Set ``*this`` to zero
+
+ .. cpp:function:: size_t bytes() const
+
+ Return number of bytes need to represent value of ``*this``
+
+ .. cpp:function:: size_t bits() const
+
+ Return number of bits need to represent value of ``*this``
+
+ .. cpp:function:: bool is_even() const
+
+ Return true if ``*this`` is even
+
+ .. cpp:function:: bool is_odd() const
+
+ Return true if ``*this`` is odd
+
+ .. cpp:function:: bool is_nonzero() const
+
+ Return true if ``*this`` is not zero
+
+ .. cpp:function:: bool is_zero() const
+
+ Return true if ``*this`` is zero
+
+ .. cpp:function:: void set_bit(size_t n)
+
+ Set bit *n* of ``*this``
+
+ .. cpp:function:: void clear_bit(size_t n)
+
+ Clear bit *n* of ``*this``
+
+ .. cpp:function:: bool get_bit(size_t n) const
+
+ Get bit *n* of ``*this``
+
+ .. cpp:function:: uint32_t to_u32bit() const
+
+ Return value of ``*this`` as a 32-bit integer, if possible.
+ If the integer is negative or not in range, an exception is thrown.
+
+ .. cpp:function:: bool is_negative() const
+
+ Return true if ``*this`` is negative
+
+ .. cpp:function:: bool is_positive() const
+
+ Return true if ``*this`` is negative
+
+ .. cpp:function:: BigInt abs() const
+
+ Return absolute value of ``*this``
+
+ .. cpp:function:: void binary_encode(uint8_t buf[]) const
+
+ Encode this BigInt as a big-endian integer. The sign is ignored.
+
+ .. cpp:function:: void binary_encode(uint8_t buf[], size_t len) const
+
+ Encode this BigInt as a big-endian integer. The sign is ignored.
+ If ``len`` is less than ``bytes()`` then only the low ``len``
+ bytes are output. If ``len`` is greater than ``bytes()`` then
+ the output is padded with leading zeros.
+
+ .. cpp:function:: void binary_decode(uint8_t buf[])
+
+ Decode this BigInt as a big-endian integer.
+
+ .. cpp:function:: std::string to_dec_string() const
+
+ Encode the integer as a decimal string.
+
+ .. cpp:function:: std::string to_hex_string() const
+
+ Encode the integer as a hexadecimal string.
+
+Number Theory
+----------------------------------------
+
+Number theoretic functions available include:
+
+.. cpp:function:: BigInt gcd(BigInt x, BigInt y)
+
+ Returns the greatest common divisor of x and y
+
+.. cpp:function:: BigInt lcm(BigInt x, BigInt y)
+
+ Returns an integer z which is the smallest integer such that z % x
+ == 0 and z % y == 0
+
+.. cpp:function:: BigInt jacobi(BigInt a, BigInt n)
+
+ Return Jacobi symbol of (a|n).
+
+.. cpp:function:: BigInt inverse_mod(BigInt x, BigInt m)
+
+ Returns the modular inverse of x modulo m, that is, an integer
+ y such that (x*y) % m == 1. If no such y exists, returns zero.
+
+.. cpp:function:: BigInt power_mod(BigInt b, BigInt x, BigInt m)
+
+ Returns b to the xth power modulo m. If you are doing many
+ exponentiations with a single fixed modulus, it is faster to use a
+ ``Power_Mod`` implementation.
+
+.. cpp:function:: BigInt ressol(BigInt x, BigInt p)
+
+ Returns the square root modulo a prime, that is, returns a number y
+ such that (y*y) % p == x. Returns -1 if no such integer exists.
+
+.. cpp:function:: bool is_prime(BigInt n, RandomNumberGenerator& rng, \
+ size_t prob = 56, double is_random = false)
+
+ Test *n* for primality using a probabilistic algorithm (Miller-Rabin). With
+ this algorithm, there is some non-zero probability that true will be returned
+ even if *n* is actually composite. Modifying *prob* allows you to decrease the
+ chance of such a false positive, at the cost of increased runtime. Sufficient
+ tests will be run such that the chance *n* is composite is no more than 1 in
+ 2\ :sup:`prob`. Set *is_random* to true if (and only if) *n* was randomly
+ chosen (ie, there is no danger it was chosen maliciously) as far fewer tests
+ are needed in that case.
+
+.. cpp:function:: BigInt random_prime(RandomNumberGenerator& rng, \
+ size_t bits, \
+ BigInt coprime = 1, \
+ size_t equiv = 1, \
+ size_t equiv_mod = 2)
+
+ Return a random prime number of ``bits`` bits long that is
+ relatively prime to ``coprime``, and equivalent to ``equiv`` modulo
+ ``equiv_mod``.
diff --git a/comm/third_party/botan/doc/api_ref/block_cipher.rst b/comm/third_party/botan/doc/api_ref/block_cipher.rst
new file mode 100644
index 0000000000..fc2b26e1d3
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/block_cipher.rst
@@ -0,0 +1,364 @@
+Block Ciphers
+=======================
+
+Block ciphers are a n-bit permutation for some small n, typically 64 or 128
+bits. They are a cryptographic primitive used to generate higher level
+operations such as authenticated encryption.
+
+.. warning::
+
+ In almost all cases, a bare block cipher is not what you should be using.
+ You probably want an authenticated cipher mode instead (see :ref:`cipher_modes`)
+ This interface is used to build higher level operations (such as cipher
+ modes or MACs), or in the very rare situation where ECB is required,
+ eg for compatibility with an existing system.
+
+.. cpp:class:: BlockCipher
+
+ .. cpp:function:: static std::unique_ptr<BlockCipher> create(const std::string& algo_spec, \
+ const std::string& provider = "")
+
+ Create a new block cipher object, or else return null.
+
+ .. cpp:function:: static std::unique_ptr<BlockCipher> create_or_throw(const std::string& algo_spec, \
+ const std::string& provider = "")
+
+ Like ``create``, except instead of returning null an exception is thrown
+ if the cipher is not known.
+
+ .. cpp:function:: void set_key(const uint8_t* key, size_t length)
+
+ This sets the key to the value specified. Most algorithms only accept keys
+ of certain lengths. If you attempt to call ``set_key`` with a key length
+ that is not supported, the exception ``Invalid_Key_Length`` will be
+ thrown.
+
+ In all cases, ``set_key`` must be called on an object before any data
+ processing (encryption, decryption, etc) is done by that object. If this
+ is not done, an exception will be thrown.
+ thrown.
+
+ .. cpp:function:: bool valid_keylength(size_t length) const
+
+ This function returns true if and only if *length* is a valid keylength for
+ this algorithm.
+
+ .. cpp:function:: size_t minimum_keylength() const
+
+ Return the smallest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: std::string name() const
+
+ Return a human readable name for this algorithm. This is guaranteed to round-trip with
+ ``create`` and ``create_or_throw`` calls, ie create("Foo")->name() == "Foo"
+
+ .. cpp:function:: void clear()
+
+ Zero out the key. The key must be reset before the cipher object can be used.
+
+ .. cpp:function:: BlockCipher* clone() const
+
+ Return a newly allocated BlockCipher object of the same type as this one.
+
+ .. cpp:function:: size_t block_size() const
+
+ Return the size (in *bytes*) of the cipher.
+
+ .. cpp:function:: size_t parallelism() const
+
+ Return the parallelism underlying this implementation of the cipher. This
+ value can vary across versions and machines. A return value of N means that
+ encrypting or decrypting with N blocks can operate in parallel.
+
+ .. cpp:function:: size_t parallel_bytes() const
+
+ Returns ``parallelism`` multiplied by the block size as well as a small
+ fudge factor. That's because even ciphers that have no implicit parallelism
+ typically see a small speedup for being called with several blocks due to
+ caching effects.
+
+ .. cpp:function:: std::string provider() const
+
+ Return the provider type. Default value is "base" but can be any arbitrary string.
+ Other example values are "sse2", "avx2", "openssl".
+
+ .. cpp:function:: void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
+
+ Encrypt *blocks* blocks of data, taking the input from the array *in* and
+ placing the ciphertext into *out*. The two pointers may be identical, but
+ should not overlap ranges.
+
+ .. cpp:function:: void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
+
+ Decrypt *blocks* blocks of data, taking the input from the array *in* and
+ placing the plaintext into *out*. The two pointers may be identical, but
+ should not overlap ranges.
+
+ .. cpp:function:: void encrypt(const uint8_t in[], uint8_t out[]) const
+
+ Encrypt a single block. Equivalent to :cpp:func:`encrypt_n`\ (in, out, 1).
+
+ .. cpp:function:: void encrypt(uint8_t block[]) const
+
+ Encrypt a single block. Equivalent to :cpp:func:`encrypt_n`\ (block, block, 1)
+
+ .. cpp:function:: void decrypt(const uint8_t in[], uint8_t out[]) const
+
+ Decrypt a single block. Equivalent to :cpp:func:`decrypt_n`\ (in, out, 1)
+
+ .. cpp:function:: void decrypt(uint8_t block[]) const
+
+ Decrypt a single block. Equivalent to :cpp:func:`decrypt_n`\ (block, block, 1)
+
+ .. cpp:function:: template<typename Alloc> void encrypt(std::vector<uint8_t, Alloc>& block) const
+
+ Assumes ``block`` is of a multiple of the block size.
+
+ .. cpp:function:: template<typename Alloc> void decrypt(std::vector<uint8_t, Alloc>& block) const
+
+ Assumes ``block`` is of a multiple of the block size.
+
+Code Example
+-----------------
+
+For sheer demonstrative purposes, the following code encrypts a provided single
+block of plaintext with AES-256 using two different keys.
+
+.. code-block:: cpp
+
+ #include <botan/block_cipher.h>
+ #include <botan/hex.h>
+ #include <iostream>
+ int main ()
+ {
+ std::vector<uint8_t> key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
+ std::vector<uint8_t> block = Botan::hex_decode("00112233445566778899AABBCCDDEEFF");
+ std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create("AES-256"));
+ cipher->set_key(key);
+ cipher->encrypt(block);
+ std::cout << std::endl <<cipher->name() << "single block encrypt: " << Botan::hex_encode(block);
+
+ //clear cipher for 2nd encryption with other key
+ cipher->clear();
+ key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337");
+ cipher->set_key(key);
+ cipher->encrypt(block);
+
+ std::cout << std::endl << cipher->name() << "single block encrypt: " << Botan::hex_encode(block);
+ return 0;
+ }
+
+Available Ciphers
+---------------------
+
+Botan includes a number of block ciphers that are specific to particular countries, as
+well as a few that are included mostly due to their use in specific protocols such as PGP
+but not widely used elsewhere. If you are developing new code and have no particular
+opinion, use AES-256. If you desire an alternative to AES, consider Serpent, SHACAL2 or
+Threefish.
+
+.. warning:: Avoid any 64-bit block cipher in new designs. There are
+ combinatoric issues that affect any 64-bit cipher that render it
+ insecure when large amounts of data are processed.
+
+AES
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Comes in three variants, AES-128, AES-192, and AES-256.
+
+The standard 128-bit block cipher. Many modern platforms offer hardware
+acceleration. However, on platforms without hardware support, AES
+implementations typically are vulnerable to side channel attacks. For x86
+systems with SSSE3 but without AES-NI, Botan has an implementation which avoids
+known side channels.
+
+Available if ``BOTAN_HAS_AES`` is defined.
+
+ARIA
+~~~~~~
+
+South Korean cipher used in industry there. No reason to use it otherwise.
+
+Available if ``BOTAN_HAS_ARIA`` is defined.
+
+Blowfish
+~~~~~~~~~
+
+A 64-bit cipher popular in the pre-AES era. Very slow key setup. Also used (with
+bcrypt) for password hashing.
+
+Available if ``BOTAN_HAS_BLOWFISH`` is defined.
+
+CAST-128
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 64-bit cipher, commonly used in OpenPGP.
+
+Available if ``BOTAN_HAS_CAST128`` is defined.
+
+CAST-256
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 128-bit cipher that was a contestant in the NIST AES competition.
+Almost never used in practice. Prefer AES or Serpent.
+
+Available if ``BOTAN_HAS_CAST256`` is defined.
+
+.. warning::
+ Support for CAST-256 is deprecated and will be removed in a future major release.
+
+Camellia
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Comes in three variants, Camellia-128, Camellia-192, and Camellia-256.
+
+A Japanese design standardized by ISO, NESSIE and CRYPTREC.
+Rarely used outside of Japan.
+
+Available if ``BOTAN_HAS_CAMELLIA`` is defined.
+
+Cascade
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Creates a block cipher cascade, where each block is encrypted by two ciphers
+with independent keys. Useful if you're very paranoid. In practice any single
+good cipher (such as Serpent, SHACAL2, or AES-256) is more than sufficient.
+
+Available if ``BOTAN_HAS_CASCADE`` is defined.
+
+DES, 3DES, DESX
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Originally designed by IBM and NSA in the 1970s. Today, DES's 56-bit key renders
+it insecure to any well-resourced attacker. DESX and 3DES extend the key length,
+and are still thought to be secure, modulo the limitation of a 64-bit block.
+All are somewhat common in some industries such as finance. Avoid in new code.
+
+.. warning::
+ Support for DESX is deprecated and it will be removed in a future major release.
+
+Available if ``BOTAN_HAS_DES`` is defined.
+
+GOST-28147-89
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Aka "Magma". An old 64-bit Russian cipher. Possible security issues, avoid
+unless compatibility is needed.
+
+Available if ``BOTAN_HAS_GOST_28147_89`` is defined.
+
+.. warning::
+ Support for this cipher is deprecated and will be removed in a future major release.
+
+IDEA
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+An older but still unbroken 64-bit cipher with a 128-bit key. Somewhat common
+due to its use in PGP. Avoid in new designs.
+
+Available if ``BOTAN_HAS_IDEA`` is defined.
+
+Kasumi
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 64-bit cipher used in 3GPP mobile phone protocols. There is no reason to use
+it outside of this context.
+
+Available if ``BOTAN_HAS_KASUMI`` is defined.
+
+.. warning::
+ Support for Kasumi is deprecated and will be removed in a future major release.
+
+Lion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A "block cipher construction" which can encrypt blocks of nearly arbitrary
+length. Built from a stream cipher and a hash function. Useful in certain
+protocols where being able to encrypt large or arbitrary length blocks is
+necessary.
+
+Available if ``BOTAN_HAS_LION`` is defined.
+
+MISTY1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 64-bit Japanese cipher standardized by NESSIE and ISO. Seemingly secure, but
+quite slow and saw little adoption. No reason to use it in new code.
+
+Available if ``BOTAN_HAS_MISTY1`` is defined.
+
+.. warning::
+ Support for MISTY1 is deprecated and will be removed in a future major release.
+
+Noekeon
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A fast 128-bit cipher by the designers of AES. Easily secured against side
+channels.
+
+Available if ``BOTAN_HAS_NOEKEON`` is defined.
+
+.. warning::
+ Support for Noekeon is deprecated and will be removed in a future major release.
+
+SEED
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A older South Korean cipher, widely used in industry there. No reason to choose it otherwise.
+
+Available if ``BOTAN_HAS_SEED`` is defined.
+
+SHACAL2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 256-bit block cipher used inside SHA-256. Accepts up to a 512-bit key.
+Fast, especially when SIMD or SHA-2 acceleration instructions are available.
+Standardized by NESSIE but otherwise obscure.
+
+Available if ``BOTAN_HAS_SHACAL2`` is defined.
+
+SM4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 128-bit Chinese national cipher, required for use in certain commercial
+applications in China. Quite slow. Probably no reason to use it outside of legal
+requirements.
+
+Available if ``BOTAN_HAS_SM4`` is defined.
+
+Serpent
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+An AES contender. Widely considered the most conservative design. Fairly slow
+unless SIMD instructions are available.
+
+Available if ``BOTAN_HAS_SERPENT`` is defined.
+
+Threefish-512
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 512-bit tweakable block cipher that was used in the Skein hash function.
+Very fast on 64-bit processors.
+
+Available if ``BOTAN_HAS_THREEFISH_512`` is defined.
+
+Twofish
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 128-bit block cipher that was one of the AES finalists. Has a somewhat complicated key
+setup and a "kitchen sink" design.
+
+Available if ``BOTAN_HAS_TWOFISH`` is defined.
+
+XTEA
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A 64-bit cipher popular for its simple implementation. Avoid in new code.
+
+Available if ``BOTAN_HAS_XTEA`` is defined.
diff --git a/comm/third_party/botan/doc/api_ref/cipher_modes.rst b/comm/third_party/botan/doc/api_ref/cipher_modes.rst
new file mode 100644
index 0000000000..413db70b57
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/cipher_modes.rst
@@ -0,0 +1,384 @@
+.. _cipher_modes:
+
+Cipher Modes
+=====================
+
+A block cipher by itself, is only able to securely encrypt a single data block.
+To be able to securely encrypt data of arbitrary length, a mode of operation
+applies the block cipher's single block operation repeatedly to encrypt
+an entire message.
+
+All cipher mode implementations are are derived from the base class
+:cpp:class:`Cipher_Mode`, which is declared in ``botan/cipher_mode.h``.
+
+.. warning::
+ Using an unauthenticted cipher mode without combining it with a
+ :ref:`mac` is insecure. Prefer using an :ref:`aead`.
+
+.. cpp:class:: Cipher_Mode
+
+ .. cpp:function:: void set_key(const uint8_t* key, size_t length)
+
+ Set the symmetric key to be used.
+
+ .. cpp:function:: bool valid_keylength(size_t length) const
+
+ This function returns true if and only if *length* is a valid
+ keylength for the algorithm.
+
+ .. cpp:function:: size_t minimum_keylength() const
+
+ Return the smallest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: size_t default_nonce_length() const
+
+ Return the default (preferable) nonce size for this cipher mode.
+
+ .. cpp:function:: bool valid_nonce_length(size_t nonce_len) const
+
+ Return true if *nonce_len* is a valid length for a nonce with this
+ algorithm.
+
+ .. cpp:function:: bool authenticated() const
+
+ Return true if this cipher mode is authenticated
+
+ .. cpp:function:: size_t tag_size() const
+
+ Return the length in bytes of the authentication tag this algorithm
+ generates. If the mode is not authenticated, this will return 0. If the mode
+ is authenticated, it will return some positive value (typically somewhere
+ between 8 and 16).
+
+ .. cpp:function:: void clear()
+
+ Clear all internal state. The object will act exactly like one which was
+ just allocated.
+
+ .. cpp:function:: void reset()
+
+ Reset all message state. For example if you called :cpp:func:`start_msg`,
+ then :cpp:func:`process` to process some ciphertext, but then encounter an
+ IO error and must abandon the current message, you can call `reset`. The
+ object will retain the key (unlike calling :cpp:func:`clear` which also
+ resets the key) but the nonce and current message state will be erased.
+
+ .. cpp:function:: void start_msg(const uint8_t* nonce, size_t nonce_len)
+
+ Set up for processing a new message. This function must be called with a new
+ random value for each message. For almost all modes (excepting SIV), if the
+ same nonce is ever used twice with the same key, the encryption scheme loses
+ its confidentiality and/or authenticity properties.
+
+ .. cpp:function:: void start(const std::vector<uint8_t> nonce)
+
+ Acts like :cpp:func:`start_msg`\ (nonce.data(), nonce.size()).
+
+ .. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len)
+
+ Acts like :cpp:func:`start_msg`\ (nonce, nonce_len).
+
+ .. cpp:function:: virtual size_t update_granularity() const
+
+ The :cpp:class:`Cipher_Mode` interface requires message processing in multiples of the block size.
+ Returns size of required blocks to update and 1, if the mode can process messages of any length.
+
+ .. cpp:function:: virtual size_t process(uint8_t* msg, size_t msg_len)
+
+ Process msg in place and returns the number of bytes written. *msg* must
+ be a multiple of :cpp:func:`update_granularity`.
+
+ .. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0)
+
+ Continue processing a message in the buffer in place. The passed buffer's
+ size must be a multiple of :cpp:func:`update_granularity`. The first
+ *offset* bytes of the buffer will be ignored.
+
+ .. cpp:function:: size_t minimum_final_size() const
+
+ Returns the minimum size needed for :cpp:func:`finish`.
+
+ .. cpp:function:: void finish(secure_vector<uint8_t>& final_block, size_t offset = 0)
+
+ Finalize the message processing with a final block of at least :cpp:func:`minimum_final_size` size.
+ The first *offset* bytes of the passed final block will be ignored.
+
+Code Example
+---------------------
+
+The following code encrypts the specified plaintext using AES-128/CBC
+with PKCS#7 padding.
+
+.. warning::
+ This example ignores the requirement to authenticate the ciphertext
+
+.. note::
+ Simply replacing the string "AES-128/CBC/PKCS7" string in the example below
+ with "AES-128/GCM" suffices to use authenticated encryption.
+
+.. code-block:: cpp
+
+ #include <botan/rng.h>
+ #include <botan/auto_rng.h>
+ #include <botan/cipher_mode.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ Botan::AutoSeeded_RNG rng;
+
+ const std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's.");
+ const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C");
+
+ std::unique_ptr<Botan::Cipher_Mode> enc = Botan::Cipher_Mode::create("AES-128/CBC/PKCS7", Botan::ENCRYPTION);
+ enc->set_key(key);
+
+ //generate fresh nonce (IV)
+ Botan::secure_vector<uint8_t> iv = rng.random_vec(enc->default_nonce_length());
+
+ // Copy input data to a buffer that will be encrypted
+ Botan::secure_vector<uint8_t> pt(plaintext.data(), plaintext.data()+plaintext.length());
+
+ enc->start(iv);
+ enc->finish(pt);
+
+ std::cout << enc->name() << " with iv " << Botan::hex_encode(iv) << " " << Botan::hex_encode(pt) << "\n";
+ return 0;
+ }
+
+
+Available Unauthenticated Cipher Modes
+-----------------------------------------
+
+.. note::
+ CTR and OFB modes are also implemented, but these are treated as
+ :cpp:class:`Stream_Cipher`\s instead.
+
+CBC
+~~~~~~~~~~~~
+
+Available if ``BOTAN_HAS_MODE_CBC`` is defined.
+
+CBC requires the plaintext be padded using a reversible rule. The following
+padding schemes are implemented
+
+PKCS#7 (RFC5652)
+ The last byte in the padded block defines the padding length p, the remaining padding bytes are set to p as well.
+ANSI X9.23
+ The last byte in the padded block defines the padding length, the remaining padding is filled with 0x00.
+OneAndZeros (ISO/IEC 7816-4)
+ The first padding byte is set to 0x80, the remaining padding bytes are set to 0x00.
+
+Ciphertext stealing (CTS) is also implemented. This scheme allows the
+ciphertext to have the same length as the plaintext, however using CTS
+requires the input be at least one full block plus one byte. It is
+also less commonly implemented.
+
+CFB
+~~~~~~~~~~~~
+
+Available if ``BOTAN_HAS_MODE_CFB`` is defined.
+
+CFB uses a block cipher to create a self-synchronizing stream cipher. It is used
+for example in the OpenPGP protocol. There is no reason to prefer it, as it has
+worse performance characteristics than modes such as CTR or CBC.
+
+XTS
+~~~~~~~~~
+
+Available if ``BOTAN_HAS_MODE_XTS`` is defined.
+
+XTS is a mode specialized for encrypting disk or database storage
+where ciphertext expansion is not possible. XTS requires all inputs be
+at least one full block (16 bytes for AES), however for any acceptable
+input length, there is no ciphertext expansion.
+
+.. _aead:
+
+AEAD Mode
+---------------------------
+
+AEAD (Authenticated Encryption with Associated Data) modes provide message
+encryption, message authentication, and the ability to authenticate additional
+data that is not included in the ciphertext (such as a sequence number or
+header). It is a subclass of :cpp:class:`Cipher_Mode`.
+
+.. cpp:class:: AEAD_Mode
+
+ .. cpp:function:: void set_key(const SymmetricKey& key)
+
+ Set the key
+
+ .. cpp:function:: Key_Length_Specification key_spec() const
+
+ Return the key length specification
+
+ .. cpp:function:: void set_associated_data(const uint8_t ad[], size_t ad_len)
+
+ Set any associated data for this message. For maximum portability between
+ different modes, this must be called after :cpp:func:`set_key` and before
+ :cpp:func:`start`.
+
+ If the associated data does not change, it is not necessary to call this
+ function more than once, even across multiple calls to :cpp:func:`start`
+ and :cpp:func:`finish`.
+
+ .. cpp:function:: void start(const uint8_t nonce[], size_t nonce_len)
+
+ Start processing a message, using *nonce* as the unique per-message
+ value. It does not need to be random, simply unique (per key).
+
+ .. warning::
+ With almost all AEADs, if the same nonce is ever used to encrypt two
+ different messages under the same key, all security is lost. If
+ reliably generating unique nonces is difficult in your environment,
+ use SIV mode which retains security even if nonces are repeated.
+
+ .. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0)
+
+ Continue processing a message. The *buffer* is an in/out parameter and
+ may be resized. In particular, some modes require that all input be
+ consumed before any output is produced; with these modes, *buffer* will
+ be returned empty.
+
+ On input, the buffer must be sized in blocks of size
+ :cpp:func:`update_granularity`. For instance if the update granularity
+ was 64, then *buffer* could be 64, 128, 192, ... bytes.
+
+ The first *offset* bytes of *buffer* will be ignored (this allows in
+ place processing of a buffer that contains an initial plaintext header)
+
+ .. cpp:function:: void finish(secure_vector<uint8_t>& buffer, size_t offset = 0)
+
+ Complete processing a message with a final input of *buffer*, which is
+ treated the same as with :cpp:func:`update`. It must contain at least
+ :cpp:func:`final_minimum_size` bytes.
+
+ Note that if you have the entire message in hand, calling finish without
+ ever calling update is both efficient and convenient.
+
+ .. note::
+
+ During decryption, if the supplied authentication tag does not
+ validate, finish will throw an instance of Invalid_Authentication_Tag
+ (aka Integrity_Failure, which was the name for this exception in
+ versions before 2.10, a typedef is included for compatability).
+
+ If this occurs, all plaintext previously output via calls to update
+ must be destroyed and not used in any way that an attacker could
+ observe the effects of. This could be anything from echoing the
+ plaintext back (perhaps in an error message), or by making an external
+ RPC whose destination or contents depend on the plaintext. The only
+ thing you can do is buffer it, and in the event of an invalid tag,
+ erase the previously decrypted content from memory.
+
+ One simply way to assure this could never happen is to never
+ call update, and instead always marshal the entire message
+ into a single buffer and call finish on it when decrypting.
+
+ .. cpp:function:: size_t update_granularity() const
+
+ The AEAD interface requires :cpp:func:`update` be called with blocks of
+ this size. This will be 1, if the mode can process any length inputs.
+
+ .. cpp:function:: size_t final_minimum_size() const
+
+ The AEAD interface requires :cpp:func:`finish` be called with at least
+ this many bytes (which may be zero, or greater than
+ :cpp:func:`update_granularity`)
+
+ .. cpp:function:: bool valid_nonce_length(size_t nonce_len) const
+
+ Returns true if *nonce_len* is a valid nonce length for this scheme. For
+ EAX and GCM, any length nonces are allowed. OCB allows any value between
+ 8 and 15 bytes.
+
+ .. cpp:function:: size_t default_nonce_length() const
+
+ Returns a reasonable length for the nonce, typically either 96
+ bits, or the only supported length for modes which don't
+ support 96 bit nonces.
+
+
+Available AEAD Modes
+-------------------------
+
+If in doubt about what to use, pick ChaCha20Poly1305, AES-256/GCM, or AES-256/SIV.
+Both ChaCha20Poly1305 and AES with GCM are widely implemented. SIV is somewhat
+more obscure (and is slower than either GCM or ChaCha20Poly1305), but has
+excellent security properties.
+
+ChaCha20Poly1305
+~~~~~~~~~~~~~~~~~~
+
+Available if ``BOTAN_HAS_AEAD_CHACHA20_POLY1305`` is defined.
+
+Unlike the other AEADs which are based on block ciphers, this mode is based on
+the ChaCha stream cipher and the Poly1305 authentication code. It is very fast
+on all modern platforms.
+
+ChaCha20Poly1305 supports 64-bit, 96-bit, and (since 2.8) 192-bit nonces. 64-bit nonces
+are the "classic" ChaCha20Poly1305 design. 96-bit nonces are used by the IETF standard
+version of ChaCha20Poly1305. And 192-bit nonces is the XChaCha20Poly1305 construction,
+which is somewhat less common.
+
+For best interop use the IETF version with 96-bit nonces. However 96 bits is small enough
+that it can be dangerous to generate nonces randomly if more than ~ 2^32 messages are
+encrypted under a single key, since if a nonce is ever reused ChaCha20Poly1305 becomes
+insecure. It is better to use a counter for the nonce in this case.
+
+If you are encrypting many messages under a single key and cannot maintain a counter for
+the nonce, prefer XChaCha20Poly1305 since a 192 bit nonce is large enough that randomly
+chosen nonces are extremely unlikely to repeat.
+
+GCM
+~~~~~
+
+Available if ``BOTAN_HAS_AEAD_GCM`` is defined.
+
+NIST standard, commonly used. Requires a 128-bit block cipher. Fairly slow,
+unless hardware support for carryless multiplies is available.
+
+OCB
+~~~~~
+
+Available if ``BOTAN_HAS_AEAD_OCB`` is defined.
+
+A block cipher based AEAD. Supports 128-bit, 256-bit and 512-bit block ciphers.
+This mode is very fast and easily secured against side channels. Adoption has
+been poor because it is patented in the United States, though a license is
+available allowing it to be freely used by open source software.
+
+EAX
+~~~~~
+
+Available if ``BOTAN_HAS_AEAD_EAX`` is defined.
+
+A secure composition of CTR mode and CMAC. Supports 128-bit, 256-bit and 512-bit
+block ciphers.
+
+SIV
+~~~~~~
+
+Available if ``BOTAN_HAS_AEAD_SIV`` is defined.
+
+Requires a 128-bit block cipher. Unlike other AEADs, SIV is "misuse resistant";
+if a nonce is repeated, SIV retains security, with the exception that if the
+same nonce is used to encrypt the same message multiple times, an attacker can
+detect the fact that the message was duplicated (this is simply because if both
+the nonce and the message are reused, SIV will output identical ciphertexts).
+
+CCM
+~~~~~
+
+Available if ``BOTAN_HAS_AEAD_CCM`` is defined.
+
+A composition of CTR mode and CBC-MAC. Requires a 128-bit block cipher. This is
+a NIST standard mode, but that is about all to recommend it. Prefer EAX.
diff --git a/comm/third_party/botan/doc/api_ref/compression.rst b/comm/third_party/botan/doc/api_ref/compression.rst
new file mode 100644
index 0000000000..5637a5a682
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/compression.rst
@@ -0,0 +1,90 @@
+Lossless Data Compression
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Some lossless data compression algorithms are available in botan, currently all
+via third party libraries - these include zlib (including deflate and gzip
+formats), bzip2, and lzma. Support for these must be enabled at build time;
+you can check for them using the macros ``BOTAN_HAS_ZLIB``, ``BOTAN_HAS_BZIP2``,
+and ``BOTAN_HAS_LZMA``.
+
+.. note::
+ You should always compress *before* you encrypt, because encryption seeks to
+ hide the redundancy that compression is supposed to try to find and remove.
+
+Compression is done through the ``Compression_Algorithm`` and
+``Decompression_Algorithm`` classes, both defined in `compression.h`
+
+Compression and decompression both work in three stages: starting a
+message (``start``), continuing to process it (``update``), and then
+finally completing processing the stream (``finish``).
+
+.. cpp:class:: Compression_Algorithm
+
+ .. cpp:function:: void start(size_t level)
+
+ Initialize the compression engine. This must be done before calling
+ ``update`` or ``finish``. The meaning of the `level` parameter varies by
+ the algorithm but generally takes a value between 1 and 9, with higher
+ values implying typically better compression from and more memory and/or
+ CPU time consumed by the compression process. The decompressor can always
+ handle input from any compressor.
+
+ .. cpp:function:: void update(secure_vector<uint8_t>& buf, \
+ size_t offset = 0, bool flush = false)
+
+ Compress the material in the in/out parameter ``buf``. The leading
+ ``offset`` bytes of ``buf`` are ignored and remain untouched; this can be
+ useful for ignoring packet headers. If ``flush`` is true, the
+ compression state is flushed, allowing the decompressor to recover the
+ entire message up to this point without having the see the rest of the
+ compressed stream.
+
+ .. cpp::function:: void finish(secure_vector<uint8_t>& buf, size_t offset = 0)
+
+ Finish compressing a message. The ``buf`` and ``offset`` parameters are
+ treated as in ``update``. It is acceptable to call ``start`` followed by
+ ``finish`` with the entire message, without any intervening call to
+ ``update``.
+
+.. cpp:class:: Decompression_Algorithm
+
+ .. cpp:function:: void start()
+
+ Initialize the decompression engine. This must be done before calling
+ ``update`` or ``finish``. No level is provided here; the decompressor
+ can accept input generated by any compression parameters.
+
+ .. cpp:function:: void update(secure_vector<uint8_t>& buf, \
+ size_t offset = 0)
+
+ Decompress the material in the in/out parameter ``buf``. The leading
+ ``offset`` bytes of ``buf`` are ignored and remain untouched; this can be
+ useful for ignoring packet headers.
+
+ This function may throw if the data seems to be invalid.
+
+ .. cpp::function:: void finish(secure_vector<uint8_t>& buf, size_t offset = 0)
+
+ Finish decompressing a message. The ``buf`` and ``offset`` parameters are
+ treated as in ``update``. It is acceptable to call ``start`` followed by
+ ``finish`` with the entire message, without any intervening call to
+ ``update``.
+
+ This function may throw if the data seems to be invalid.
+
+The easiest way to get a compressor is via the functions
+
+.. cpp:function:: Compression_Algorithm* make_compressor(std::string type)
+.. cpp:function:: Decompression_Algorithm* make_decompressor(std::string type)
+
+Supported values for `type` include `zlib` (raw zlib with no checksum),
+`deflate` (zlib's deflate format), `gzip`, `bz2`, and `lzma`. A null pointer
+will be returned if the algorithm is unavailable.
+
+To use a compression algorithm in a `Pipe` use the adapter types
+`Compression_Filter` and `Decompression_Filter` from `comp_filter.h`. The
+constructors of both filters take a `std::string` argument (passed to
+`make_compressor` or `make_decompressor`), the compression filter also takes a
+`level` parameter. Finally both constructors have a parameter `buf_sz` which
+specifies the size of the internal buffer that will be used - inputs will be
+broken into blocks of this size. The default is 4096.
diff --git a/comm/third_party/botan/doc/api_ref/contents.rst b/comm/third_party/botan/doc/api_ref/contents.rst
new file mode 100644
index 0000000000..24fb274808
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/contents.rst
@@ -0,0 +1,39 @@
+
+API Reference
+===================
+
+.. toctree::
+ :maxdepth: 1
+
+ versions
+ secmem
+ rng
+ hash
+ block_cipher
+ stream_ciphers
+ message_auth_codes
+ cipher_modes
+ pubkey
+ x509
+ tls
+ credentials_manager
+ bigint
+ kdf
+ pbkdf
+ keywrap
+ passhash
+ cryptobox
+ srp
+ psk_db
+ filters
+ fpe
+ tss
+ ecc
+ compression
+ pkcs11
+ tpm
+ otp
+ roughtime
+ ffi
+ env_vars
+ python
diff --git a/comm/third_party/botan/doc/api_ref/credentials_manager.rst b/comm/third_party/botan/doc/api_ref/credentials_manager.rst
new file mode 100644
index 0000000000..8f78970dbf
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/credentials_manager.rst
@@ -0,0 +1,186 @@
+
+Credentials Manager
+==================================================
+
+A ``Credentials_Manager`` is a way to abstract how the application
+stores credentials. The main user is the :doc:`tls` implementation.
+
+.. cpp:class:: Credentials_Manager
+
+ .. cpp:function:: std::vector<Certificate_Store*> \
+ trusted_certificate_authorities( \
+ const std::string& type, \
+ const std::string& context)
+
+ Return the list of certificate stores, each of which is assumed
+ to contain (only) trusted certificate authorities. The
+ ``Credentials_Manager`` retains ownership of the
+ Certificate_Store pointers.
+
+ .. note::
+
+ It would have been a better API to return a vector of
+ ``shared_ptr`` here. This may change in a future major release.
+
+ When *type* is "tls-client", *context* will be the hostname of
+ the server, or empty if the hostname is not known. This allows
+ using a different set of certificate stores in different contexts,
+ for example using the system certificate store unless contacting
+ one particular server which uses a cert issued by an internal CA.
+
+ When *type* is "tls-server", the *context* will again be the
+ hostname of the server, or empty if the client did not send a
+ server name indicator. For TLS servers, these CAs are the ones
+ trusted for signing of client certificates. If you do not want
+ the TLS server to ask for a client cert,
+ ``trusted_certificate_authorities`` should return an empty list
+ for *type* "tls-server".
+
+ The default implementation returns an empty list.
+
+ .. cpp:function:: std::vector<X509_Certificate> find_cert_chain( \
+ const std::vector<std::string>& cert_key_types, \
+ const std::vector<X509_DN>& acceptable_CAs, \
+ const std::string& type, \
+ const std::string& context)
+
+ Return the certificate chain to use to identify ourselves. The
+ ``acceptable_CAs`` parameter gives a list of CAs the peer trusts.
+ This may be empty.
+
+ .. warning::
+ If this function returns a certificate that is not one of the
+ types given in ``cert_key_types`` confusing handshake
+ failures will result.
+
+ .. cpp:function:: std::vector<X509_Certificate> cert_chain( \
+ const std::vector<std::string>& cert_key_types, \
+ const std::string& type, \
+ const std::string& context)
+
+ Return the certificate chain to use to identify ourselves. Starting in
+ 2.5, prefer ``find_cert_chain`` which additionally provides the CA list.
+
+ .. cpp:function:: std::vector<X509_Certificate> cert_chain_single_type( \
+ const std::string& cert_key_type, \
+ const std::string& type, \
+ const std::string& context)
+
+ Return the certificate chain to use to identifier ourselves, if
+ we have one of type *cert_key_type* and we would like to use a
+ certificate in this *type*/*context*.
+
+ .. cpp:function:: Private_Key* private_key_for(const X509_Certificate& cert, \
+ const std::string& type, \
+ const std::string& context)
+
+ Return the private key for this certificate. The *cert* will be
+ the leaf cert of a chain returned previously by ``cert_chain``
+ or ``cert_chain_single_type``.
+
+In versions before 1.11.34, there was an additional function on `Credentials_Manager`
+
+ .. cpp::function:: void verify_certificate_chain( \
+ const std::string& type, \
+ const std::string& hostname, \
+ const std::vector<X509_Certificate>& cert_chain)
+
+This function has been replaced by `TLS::Callbacks::tls_verify_cert_chain`.
+
+SRP Authentication
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``Credentials_Manager`` contains the hooks used by TLS clients and
+servers for SRP authentication.
+
+.. note::
+
+ Support for TLS-SRP is deprecated, and will be removed in a future
+ major release. When that occurs these APIs will be removed. Prefer
+ instead performing a standard TLS handshake, then perform a PAKE
+ authentication inside of (and cryptographically bound to) the TLS
+ channel.
+
+.. cpp:function:: bool attempt_srp(const std::string& type, \
+ const std::string& context)
+
+ Returns if we should consider using SRP for authentication
+
+.. cpp:function:: std::string srp_identifier(const std::string& type, \
+ const std::string& context)
+
+ Returns the SRP identifier we'd like to use (used by client)
+
+.. cpp:function:: std::string srp_password(const std::string& type, \
+ const std::string& context, \
+ const std::string& identifier)
+
+ Returns the password for *identifier* (used by client)
+
+.. cpp:function:: bool srp_verifier(const std::string& type, \
+ const std::string& context, \
+ const std::string& identifier, \
+ std::string& group_name, \
+ BigInt& verifier, \
+ std::vector<uint8_t>& salt, \
+ bool generate_fake_on_unknown)
+
+ Returns the SRP verifier information for *identifier* (used by server)
+
+Preshared Keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+TLS supports the use of pre shared keys for authentication.
+
+.. cpp:function:: SymmetricKey psk(const std::string& type, \
+ const std::string& context, \
+ const std::string& identity)
+
+ Return a symmetric key for use with *identity*
+
+ One important special case for ``psk`` is where *type* is
+ "tls-server", *context* is "session-ticket" and *identity* is an
+ empty string. If a key is returned for this case, a TLS server
+ will offer session tickets to clients who can use them, and the
+ returned key will be used to encrypt the ticket. The server is
+ allowed to change the key at any time (though changing the key
+ means old session tickets can no longer be used for resumption,
+ forcing a full re-handshake when the client next connects). One
+ simple approach to add support for session tickets in your server
+ is to generate a random key the first time ``psk`` is called to
+ retrieve the session ticket key, cache it for later use in the
+ ``Credentials_Manager``, and simply let it be thrown away when the
+ process terminates. See :rfc:`4507` for more information about TLS
+ session tickets.
+
+ A similar special case exists for DTLS cookie verification. In
+ this case *type* will be "tls-server" and *context* is
+ "dtls-cookie-secret". If no key is returned, then DTLS cookies are
+ not used. Similar to the session ticket key, the DTLS cookie
+ secret can be chosen during server startup and rotated at any time
+ with no ill effect.
+
+ .. warning::
+
+ If DTLS cookies are not used then the server is prone to be
+ abused as a DoS amplifier, where the attacker sends a
+ relatively small client hello in a UDP packet with a forged
+ return address, and then the server replies to the victim with
+ several messages that are larger. This not only hides the
+ attackers address from the victim, but increases their
+ effective bandwidth. This is not an issue when using DTLS over
+ SCTP or TCP.
+
+.. cpp:function:: std::string psk_identity_hint(const std::string& type, \
+ const std::string& context)
+
+ Returns an identity hint which may be provided to the client. This
+ can help a client understand what PSK to use.
+
+.. cpp:function:: std::string psk_identity(const std::string& type, \
+ const std::string& context, \
+ const std::string& identity_hint)
+
+ Returns the identity we would like to use given this *type* and
+ *context* and the optional *identity_hint*. Not all servers or
+ protocols will provide a hint.
diff --git a/comm/third_party/botan/doc/api_ref/cryptobox.rst b/comm/third_party/botan/doc/api_ref/cryptobox.rst
new file mode 100644
index 0000000000..dbade88af5
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/cryptobox.rst
@@ -0,0 +1,32 @@
+
+Cryptobox
+========================================
+
+Encryption using a passphrase
+----------------------------------------
+
+.. versionadded:: 1.8.6
+
+This is a set of simple routines that encrypt some data using a
+passphrase. There are defined in the header `cryptobox.h`, inside
+namespace `Botan::CryptoBox`.
+
+It generates cipher and MAC keys using 8192 iterations of PBKDF2 with
+HMAC(SHA-512), then encrypts using Serpent in CTR mode and authenticates using a
+HMAC(SHA-512) mac of the ciphertext, truncated to 160 bits.
+
+ .. cpp:function:: std::string encrypt(const uint8_t input[], size_t input_len, \
+ const std::string& passphrase, \
+ RandomNumberGenerator& rng)
+
+ Encrypt the contents using *passphrase*.
+
+ .. cpp:function:: std::string decrypt(const uint8_t input[], size_t input_len, \
+ const std::string& passphrase)
+
+ Decrypts something encrypted with encrypt.
+
+ .. cpp:function:: std::string decrypt(const std::string& input, \
+ const std::string& passphrase)
+
+ Decrypts something encrypted with encrypt.
diff --git a/comm/third_party/botan/doc/api_ref/ecc.rst b/comm/third_party/botan/doc/api_ref/ecc.rst
new file mode 100644
index 0000000000..f522bbe3df
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/ecc.rst
@@ -0,0 +1,284 @@
+Elliptic Curve Operations
+============================
+
+In addition to high level operations for signatures, key agreement,
+and message encryption using elliptic curve cryptography, the library
+contains lower level interfaces for performing operations such as
+elliptic curve point multiplication.
+
+Only curves over prime fields are supported.
+
+Many of these functions take a workspace, either a vector of words or
+a vector of BigInts. These are used to minimize memory allocations
+during common operations.
+
+.. warning::
+ You should only use these interfaces if you know what you are doing.
+
+.. cpp:class:: EC_Group
+
+ .. cpp:function:: EC_Group(const OID& oid)
+
+ Initialize an ``EC_Group`` using an OID referencing the curve
+ parameters.
+
+ .. cpp:function:: EC_Group(const std::string& name)
+
+ Initialize an ``EC_Group`` using a name or OID (for example
+ "secp256r1", or "1.2.840.10045.3.1.7")
+
+ .. cpp:function:: EC_Group(const BigInt& p, \
+ const BigInt& a, \
+ const BigInt& b, \
+ const BigInt& base_x, \
+ const BigInt& base_y, \
+ const BigInt& order, \
+ const BigInt& cofactor, \
+ const OID& oid = OID())
+
+ Initialize an elliptic curve group from the relevant parameters. This
+ is used for example to create custom (application-specific) curves.
+
+ .. cpp:function:: EC_Group(const std::vector<uint8_t>& ber_encoding)
+
+ Initialize an ``EC_Group`` by decoding a DER encoded parameter block.
+
+ .. cpp:function:: std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const
+
+ Return the DER encoding of this group.
+
+ .. cpp:function:: std::string PEM_encode() const
+
+ Return the PEM encoding of this group (base64 of DER encoding plus
+ header/trailer).
+
+ .. cpp:function:: bool a_is_minus_3() const
+
+ Return true if the ``a`` parameter is congruent to -3 mod p.
+
+ .. cpp:function:: bool a_is_zero() const
+
+ Return true if the ``a`` parameter is congruent to 0 mod p.
+
+ .. cpp:function:: size_t get_p_bits() const
+
+ Return size of the prime in bits.
+
+ .. cpp:function:: size_t get_p_bytes() const
+
+ Return size of the prime in bytes.
+
+ .. cpp:function:: size_t get_order_bits() const
+
+ Return size of the group order in bits.
+
+ .. cpp:function:: size_t get_order_bytes() const
+
+ Return size of the group order in bytes.
+
+ .. cpp:function:: const BigInt& get_p() const
+
+ Return the prime modulus.
+
+ .. cpp:function:: const BigInt& get_a() const
+
+ Return the ``a`` parameter of the elliptic curve equation.
+
+ .. cpp:function:: const BigInt& get_b() const
+
+ Return the ``b`` parameter of the elliptic curve equation.
+
+ .. cpp:function:: const PointGFp& get_base_point() const
+
+ Return the groups base point element.
+
+ .. cpp:function:: const BigInt& get_g_x() const
+
+ Return the x coordinate of the base point element.
+
+ .. cpp:function:: const BigInt& get_g_y() const
+
+ Return the y coordinate of the base point element.
+
+ .. cpp:function:: const BigInt& get_order() const
+
+ Return the order of the group generated by the base point.
+
+ .. cpp:function:: const BigInt& get_cofactor() const
+
+ Return the cofactor of the curve. In most cases this will be 1.
+
+ .. cpp:function:: BigInt mod_order(const BigInt& x) const
+
+ Reduce argument ``x`` modulo the curve order.
+
+ .. cpp:function:: BigInt inverse_mod_order(const BigInt& x) const
+
+ Return inverse of argument ``x`` modulo the curve order.
+
+ .. cpp:function:: BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const
+
+ Multiply ``x`` and ``y`` and reduce the result modulo the curve order.
+
+ .. cpp:function:: bool verify_public_element(const PointGFp& y) const
+
+ Return true if ``y`` seems to be a valid group element.
+
+ .. cpp:function:: const OID& get_curve_oid() const
+
+ Return the OID used to identify the curve. May be empty.
+
+ .. cpp:function:: PointGFp point(const BigInt& x, const BigInt& y) const
+
+ Create and return a point with affine elements ``x`` and ``y``. Note
+ this function *does not* verify that ``x`` and ``y`` satisfy the curve
+ equation.
+
+ .. cpp:function:: PointGFp point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const
+
+ Multi-exponentiation. Returns base_point*x + pt*y. Not constant time.
+ (Ordinarily used for signature verification.)
+
+ .. cpp:function:: PointGFp blinded_base_point_multiply(const BigInt& k, \
+ RandomNumberGenerator& rng, \
+ std::vector<BigInt>& ws) const
+
+ Return ``base_point*k`` in a way that attempts to resist side channels.
+
+ .. cpp:function:: BigInt blinded_base_point_multiply_x(const BigInt& k, \
+ RandomNumberGenerator& rng, \
+ std::vector<BigInt>& ws) const
+
+ Like `blinded_base_point_multiply` but returns only the x coordinate.
+
+ .. cpp:function:: PointGFp blinded_var_point_multiply(const PointGFp& point, \
+ const BigInt& k, \
+ RandomNumberGenerator& rng, \
+ std::vector<BigInt>& ws) const
+
+ Return ``point*k`` in a way that attempts to resist side channels.
+
+ .. cpp:function:: BigInt random_scalar(RandomNumberGenerator& rng) const
+
+ Return a random scalar (ie an integer between 1 and the group order).
+
+ .. cpp:function:: PointGFp zero_point() const
+
+ Return the zero point (aka the point at infinity).
+
+ .. cpp:function:: PointGFp OS2ECP(const uint8_t bits[], size_t len) const
+
+ Decode a point from the binary encoding. This function verifies that
+ the decoded point is a valid element on the curve.
+
+ .. cpp:function:: bool verify_group(RandomNumberGenerator& rng, bool strong = false) const
+
+ Attempt to verify the group seems valid.
+
+ .. cpp:function:: static const std::set<std::string>& known_named_groups()
+
+ Return a list of known groups, ie groups for which ``EC_Group(name)``
+ will succeed.
+
+.. cpp:class:: PointGFp
+
+ Stores elliptic curve points in Jacobian representation.
+
+ .. cpp:function:: std::vector<uint8_t> encode(PointGFp::Compression_Type format) const
+
+ Encode a point in a way that can later be decoded with `EC_Group::OS2ECP`.
+
+ .. cpp:function:: PointGFp& operator+=(const PointGFp& rhs)
+
+ Point addition.
+
+ .. cpp:function:: PointGFp& operator-=(const PointGFp& rhs)
+
+ Point subtraction.
+
+ .. cpp:function:: PointGFp& operator*=(const BigInt& scalar)
+
+ Point multiplication using Montgomery ladder.
+
+ .. warning::
+ Prefer the blinded functions in ``EC_Group``
+
+ .. cpp:function:: PointGFp& negate()
+
+ Negate this point.
+
+ .. cpp:function:: BigInt get_affine_x() const
+
+ Return the affine ``x`` coordinate of the point.
+
+ .. cpp:function:: BigInt get_affine_y() const
+
+ Return the affine ``y`` coordinate of the point.
+
+ .. cpp:function:: void force_affine()
+
+ Convert the point to its equivalent affine coordinates. Throws
+ if this is the point at infinity.
+
+ .. cpp:function:: static void force_all_affine(std::vector<PointGFp>& points, \
+ secure_vector<word>& ws)
+
+ Force several points to be affine at once. Uses Montgomery's
+ trick to reduce number of inversions required, so this is much
+ faster than calling ``force_affine`` on each point in sequence.
+
+ .. cpp:function:: bool is_affine() const
+
+ Return true if this point is in affine coordinates.
+
+ .. cpp:function:: bool is_zero() const
+
+ Return true if this point is zero (aka point at infinity).
+
+ .. cpp:function:: bool on_the_curve() const
+
+ Return true if this point is on the curve.
+
+ .. cpp:function:: void randomize_repr(RandomNumberGenerator& rng)
+
+ Randomize the point representation.
+
+ .. cpp:function:: bool operator==(const PointGFp& other) const
+
+ Point equality. This compares the affine representations.
+
+ .. cpp:function:: void add(const PointGFp& other, std::vector<BigInt>& workspace)
+
+ Point addition, taking a workspace.
+
+ .. cpp:function:: void add_affine(const PointGFp& other, std::vector<BigInt>& workspace)
+
+ Mixed (Jacobian+affine) addition, taking a workspace.
+
+ .. warning::
+
+ This function assumes that ``other`` is affine, if this is
+ not correct the result will be invalid.
+
+ .. cpp:function:: void mult2(std::vector<BigInt>& workspace)
+
+ Point doubling.
+
+ .. cpp:function:: void mult2i(size_t i, std::vector<BigInt>& workspace)
+
+ Repeated point doubling.
+
+ .. cpp:function:: PointGFp plus(const PointGFp& other, std::vector<BigInt>& workspace) const
+
+ Point addition, returning the result.
+
+ .. cpp:function:: PointGFp double_of(std::vector<BigInt>& workspace) const
+
+ Point doubling, returning the result.
+
+ .. cpp:function:: PointGFp zero() const
+
+ Return the point at infinity
+
+
+
diff --git a/comm/third_party/botan/doc/api_ref/env_vars.rst b/comm/third_party/botan/doc/api_ref/env_vars.rst
new file mode 100644
index 0000000000..221a225453
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/env_vars.rst
@@ -0,0 +1,20 @@
+Environment Variables
+======================
+
+Certain environment variables can affect or tune the behavior of the
+library. The variables and their behavior are described here.
+
+* ``BOTAN_THREAD_POOL_SIZE`` controls the number of threads which will be
+ created for a thread pool used for some purposes within the library. If not
+ set then it defaults to the number of CPUs available on the system.
+
+* ``BOTAN_MLOCK_POOL_SIZE`` controls the total amount of memory which will be
+ locked in memory using ``mlock`` or ``VirtualLock`` and managed in a memory
+ pool. If set to ``0`` (or indeed any value smaller than the system page size),
+ then the memory pool is disabled.
+
+* ``BOTAN_FFI_PRINT_EXCEPTIONS`` if this variable is set (to any value), then
+ if an exception is caught by the FFI layer, before returning an error code, it
+ will print the text message of the exception to stderr. This is primarily
+ intended for debugging.
+
diff --git a/comm/third_party/botan/doc/api_ref/ffi.rst b/comm/third_party/botan/doc/api_ref/ffi.rst
new file mode 100644
index 0000000000..faee6e23d3
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/ffi.rst
@@ -0,0 +1,1203 @@
+
+FFI (C Binding)
+========================================
+
+.. versionadded:: 1.11.14
+
+Botan's ffi module provides a C89 binding intended to be easily usable with other
+language's foreign function interface (FFI) libraries. For instance the included
+Python wrapper uses Python's ``ctypes`` module and the C89 API. This API is of
+course also useful for programs written directly in C.
+
+Code examples can be found in
+`the tests <https://github.com/randombit/botan/blob/master/src/tests/test_ffi.cpp>`_.
+
+Return Codes
+---------------
+
+Almost all functions in the Botan C interface return an ``int`` error code. The
+only exceptions are a handful of functions (like
+:cpp:func:`botan_ffi_api_version`) which cannot fail in any circumstances.
+
+The FFI functions return a non-negative integer (usually 0) to indicate success,
+or a negative integer to represent an error. A few functions (like
+:cpp:func:`botan_block_cipher_block_size`) return positive integers instead of
+zero on success.
+
+The error codes returned in certain error situations may change over time. This
+especially applies to very generic errors like
+:cpp:enumerator:`BOTAN_FFI_ERROR_EXCEPTION_THROWN` and
+:cpp:enumerator:`BOTAN_FFI_ERROR_UNKNOWN_ERROR`. For instance, before 2.8, setting
+an invalid key length resulted in :cpp:enumerator:`BOTAN_FFI_ERROR_EXCEPTION_THROWN`
+but now this is specially handled and returns
+:cpp:enumerator:`BOTAN_FFI_ERROR_INVALID_KEY_LENGTH` instead.
+
+The following enum values are defined in the FFI header:
+
+.. cpp:enumerator:: BOTAN_FFI_SUCCESS = 0
+
+ Generally returned to indicate success
+
+.. cpp:enumerator:: BOTAN_FFI_INVALID_VERIFIER = 1
+
+ Note this value is positive, but still represents an error condition. In
+ indicates that the function completed successfully, but the value provided
+ was not correct. For example :cpp:func:`botan_bcrypt_is_valid` returns this
+ value if the password did not match the hash.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_INVALID_INPUT = -1
+
+ The input was invalid. (Currently this error return is not used.)
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_BAD_MAC = -2
+
+ While decrypting in an AEAD mode, the tag failed to verify.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE = -10
+
+ Functions which write a variable amount of space return this if the indicated
+ buffer length was insufficient to write the data. In that case, the output
+ length parameter is set to the size that is required.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_EXCEPTION_THROWN = -20
+
+ An exception was thrown while processing this request, but no further
+ details are available.
+
+ .. note::
+
+ If the environment variable ``BOTAN_FFI_PRINT_EXCEPTIONS`` is set to any
+ non-empty value, then any exception which is caught by the FFI layer will
+ first print the exception message to stderr before returning an
+ error. This is sometimes useful for debugging.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_OUT_OF_MEMORY = -21
+
+ Memory allocation failed
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_BAD_FLAG = -30
+
+ A value provided in a `flag` variable was unknown.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_NULL_POINTER = -31
+
+ A null pointer was provided as an argument where that is not allowed.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_BAD_PARAMETER = -32
+
+ An argument did not match the function.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_KEY_NOT_SET = -33
+
+ An object that requires a key normally must be keyed before use (eg before
+ encrypting or MACing data). If this is not done, the operation will fail and
+ return this error code.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_INVALID_KEY_LENGTH = -34
+
+ An invalid key length was provided with a call to ``x_set_key``.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_NOT_IMPLEMENTED = -40
+
+ This is returned if the functionality is not available for some reason. For
+ example if you call :cpp:func:`botan_hash_init` with a named hash function
+ which is not enabled, this error is returned.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_INVALID_OBJECT = -50
+
+ This is used if an object provided did not match the function. For example
+ calling :cpp:func:`botan_hash_destroy` on a ``botan_rng_t`` object will cause
+ this return.
+
+.. cpp:enumerator:: BOTAN_FFI_ERROR_UNKNOWN_ERROR = -100
+
+ Something bad happened, but we are not sure why or how.
+
+Versioning
+----------------------------------------
+
+.. cpp:function:: uint32_t botan_ffi_api_version()
+
+ Returns the version of the currently supported FFI API. This is
+ expressed in the form YYYYMMDD of the release date of this version
+ of the API.
+
+.. cpp:function:: int botan_ffi_supports_api(uint32_t version)
+
+ Returns 0 iff the FFI version specified is supported by this
+ library. Otherwise returns -1. The expression
+ botan_ffi_supports_api(botan_ffi_api_version()) will always
+ evaluate to 0. A particular version of the library may also support
+ other (older) versions of the FFI API.
+
+.. cpp:function:: const char* botan_version_string()
+
+ Returns a free-form string describing the version. The return
+ value is a statically allocated string.
+
+.. cpp:function:: uint32_t botan_version_major()
+
+ Returns the major version of the library
+
+.. cpp:function:: uint32_t botan_version_minor()
+
+ Returns the minor version of the library
+
+.. cpp:function:: uint32_t botan_version_patch()
+
+ Returns the patch version of the library
+
+.. cpp:function:: uint32_t botan_version_datestamp()
+
+ Returns the date this version was released as an integer YYYYMMDD,
+ or 0 if an unreleased version
+
+
+FFI Versions
+^^^^^^^^^^^^^
+
+This maps the FFI API version to the first version of the library that
+supported it.
+
+============== ===================
+FFI Version Supported Starting
+============== ===================
+20191214 2.13.0
+20180713 2.8.0
+20170815 2.3.0
+20170327 2.1.0
+20150515 2.0.0
+============== ===================
+
+Utility Functions
+----------------------------------------
+
+.. const char* botan_error_description(int err)
+
+ Return a string representation of the provided error code. If the error code
+ is unknown, returns the string "Unknown error". The return values are static
+ constant strings and should not be freed.
+
+.. cpp:function:: int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
+
+ Returns 0 if `x[0..len] == y[0..len]`, -1 otherwise.
+
+.. cpp:function:: int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags)
+
+ Performs hex encoding of binary data in *x* of size *len* bytes.
+ The output buffer *out* must be of at least *x*2* bytes in size.
+ If *flags* contains ``BOTAN_FFI_HEX_LOWER_CASE``, hex encoding
+ will only contain lower-case letters, upper-case letters otherwise.
+ Returns 0 on success, 1 otherwise.
+
+.. cpp:function:: int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len)
+
+ Hex decode some data
+
+Random Number Generators
+----------------------------------------
+
+.. cpp:type:: opaque* botan_rng_t
+
+ An opaque data type for a random number generator. Don't mess with it.
+
+.. cpp:function:: int botan_rng_init(botan_rng_t* rng, const char* rng_type)
+
+ Initialize a random number generator object from the given
+ *rng_type*: "system" (or ``nullptr``): ``System_RNG``,
+ "user": ``AutoSeeded_RNG``,
+ "user-threadsafe": serialized ``AutoSeeded_RNG``,
+ "null": ``Null_RNG`` (always fails),
+ "hwrnd" or "rdrand": ``Processor_RNG`` (if available)
+
+.. cpp:function:: int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len)
+
+ Get random bytes from a random number generator.
+
+.. cpp:function:: int botan_rng_reseed(botan_rng_t rng, size_t bits)
+
+ Reseeds the random number generator with *bits* number of bits
+ from the `System_RNG`.
+
+.. cpp:function:: int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t src, size_t bits)
+
+ Reseeds the random number generator with *bits* number of bits
+ taken from the given source RNG.
+
+.. cpp:function:: int botan_rng_add_entropy(botan_rng_t rng, const uint8_t seed[], size_t len)
+
+ Adds the provided seed material to the internal RNG state.
+
+ This call may be ignored by certain RNG instances (such as RDRAND
+ or, on some systems, the system RNG).
+
+.. cpp:function:: int botan_rng_destroy(botan_rng_t rng)
+
+ Destroy the object created by :cpp:func:`botan_rng_init`.
+
+Block Ciphers
+----------------------------------------
+
+.. versionadded:: 2.1.0
+
+This is a 'raw' interface to ECB mode block ciphers. Most applications
+want the higher level cipher API which provides authenticated
+encryption. This API exists as an escape hatch for applications which
+need to implement custom primitives using a PRP.
+
+.. cpp:type:: opaque* botan_block_cipher_t
+
+ An opaque data type for a block cipher. Don't mess with it.
+
+.. cpp:function:: int botan_block_cipher_init(botan_block_cipher_t* bc, const char* cipher_name)
+
+ Create a new cipher mode object, `cipher_name` should be for example "AES-128" or "Threefish-512"
+
+.. cpp:function:: int botan_block_cipher_block_size(botan_block_cipher_t bc)
+
+ Return the block size of this cipher.
+
+.. cpp:function:: int botan_block_cipher_name(botan_block_cipher_t cipher, \
+ char* name, size_t* name_len)
+
+ Return the name of this block cipher algorithm, which may nor may not exactly
+ match what was passed to :cpp:func:`botan_block_cipher_init`.
+
+.. cpp:function:: int botan_block_cipher_get_keyspec(botan_block_cipher_t cipher, \
+ size_t* out_minimum_keylength, \
+ size_t* out_maximum_keylength, \
+ size_t* out_keylength_modulo)
+
+ Return the limits on the key which can be provided to this cipher. If any of the
+ parameters are null, no output is written to that field. This allows retrieving only
+ (say) the maximum supported keylength, if that is the only information needed.
+
+.. cpp:function:: int botan_block_cipher_clear(botan_block_cipher_t bc)
+
+ Clear the internal state (such as keys) of this cipher object, but do not deallocate it.
+
+.. cpp:function:: int botan_block_cipher_set_key(botan_block_cipher_t bc, const uint8_t key[], size_t key_len)
+
+ Set the cipher key, which is required before encrypting or decrypting.
+
+.. cpp:function:: int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc, const uint8_t in[], uint8_t out[], size_t blocks)
+
+ The key must have been set first with :cpp:func:`botan_block_cipher_set_key`.
+ Encrypt *blocks* blocks of data stored in *in* and place the ciphertext into *out*.
+ The two parameters may be the same buffer, but must not overlap.
+
+.. cpp:function:: int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc, const uint8_t in[], uint8_t out[], size_t blocks)
+
+ The key must have been set first with :cpp:func:`botan_block_cipher_set_key`.
+ Decrypt *blocks* blocks of data stored in *in* and place the ciphertext into *out*.
+ The two parameters may be the same buffer, but must not overlap.
+
+.. cpp:function:: int botan_block_cipher_destroy(botan_block_cipher_t rng)
+
+ Destroy the object created by :cpp:func:`botan_block_cipher_init`.
+
+
+Hash Functions
+----------------------------------------
+
+.. cpp:type:: opaque* botan_hash_t
+
+ An opaque data type for a hash. Don't mess with it.
+
+.. cpp:function:: botan_hash_t botan_hash_init(const char* hash, uint32_t flags)
+
+ Creates a hash of the given name, e.g., "SHA-384".
+ Returns null on failure. Flags should always be zero in this version of the API.
+
+.. cpp:function:: int botan_hash_destroy(botan_hash_t hash)
+
+ Destroy the object created by :cpp:func:`botan_hash_init`.
+
+.. cpp:function:: int botan_hash_name(botan_hash_t hash, char* name, size_t* name_len)
+
+ Write the name of the hash function to the provided buffer.
+
+.. cpp:function:: int botan_hash_copy_state(botan_hash_t* dest, const botan_hash_t source)
+
+ Copies the state of the hash object to a new hash object.
+
+.. cpp:function:: int botan_hash_clear(botan_hash_t hash)
+
+ Reset the state of this object back to clean, as if no input has
+ been supplied.
+
+.. cpp:function:: size_t botan_hash_output_length(botan_hash_t hash)
+
+ Return the output length of the hash function.
+
+.. cpp:function:: int botan_hash_update(botan_hash_t hash, const uint8_t* input, size_t len)
+
+ Add input to the hash computation.
+
+.. cpp:function:: int botan_hash_final(botan_hash_t hash, uint8_t out[])
+
+ Finalize the hash and place the output in out. Exactly
+ :cpp:func:`botan_hash_output_length` bytes will be written.
+
+Message Authentication Codes
+----------------------------------------
+.. cpp:type:: opaque* botan_mac_t
+
+ An opaque data type for a MAC. Don't mess with it, but do remember
+ to set a random key first.
+
+.. cpp:function:: botan_mac_t botan_mac_init(const char* mac, uint32_t flags)
+
+ Creates a MAC of the given name, e.g., "HMAC(SHA-384)".
+ Returns null on failure. Flags should always be zero in this version of the API.
+
+.. cpp:function:: int botan_mac_destroy(botan_mac_t mac)
+
+ Destroy the object created by :cpp:func:`botan_mac_init`.
+
+.. cpp:function:: int botan_mac_clear(botan_mac_t mac)
+
+ Reset the state of this object back to clean, as if no key and input have
+ been supplied.
+
+.. cpp:function:: size_t botan_mac_output_length(botan_mac_t mac)
+
+ Return the output length of the MAC.
+
+.. cpp:function:: int botan_mac_set_key(botan_mac_t mac, const uint8_t* key, size_t key_len)
+
+ Set the random key.
+
+.. cpp:function:: int botan_mac_update(botan_mac_t mac, uint8_t buf[], size_t len)
+
+ Add input to the MAC computation.
+
+.. cpp:function:: int botan_mac_final(botan_mac_t mac, uint8_t out[], size_t* out_len)
+
+ Finalize the MAC and place the output in out. Exactly
+ :cpp:func:`botan_mac_output_length` bytes will be written.
+
+Symmetric Ciphers
+----------------------------------------
+
+.. cpp:type:: opaque* botan_cipher_t
+
+ An opaque data type for a symmetric cipher object. Don't mess with it, but do remember
+ to set a random key first. And please use an AEAD.
+
+.. cpp:function:: botan_cipher_t botan_cipher_init(const char* cipher_name, uint32_t flags)
+
+ Create a cipher object from a name such as "AES-256/GCM" or "Serpent/OCB".
+
+ Flags is a bitfield; the low bitof ``flags`` specifies if encrypt or decrypt,
+ ie use 0 for encryption and 1 for decryption.
+
+.. cpp:function:: int botan_cipher_destroy(botan_cipher_t cipher)
+
+.. cpp:function:: int botan_cipher_clear(botan_cipher_t hash)
+
+.. cpp:function:: int botan_cipher_set_key(botan_cipher_t cipher, \
+ const uint8_t* key, size_t key_len)
+
+.. cpp:function:: int botan_cipher_is_authenticated(botan_cipher_t cipher)
+
+.. cpp:function:: size_t botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tag_len)
+
+ Write the tag length of the cipher to ``tag_len``. This will be zero for non-authenticated
+ ciphers.
+
+.. cpp:function:: int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
+
+ Returns 1 if the nonce length is valid, or 0 otherwise. Returns -1 on error (such as
+ the cipher object being invalid).
+
+.. cpp:function:: size_t botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl)
+
+ Return the default nonce length
+
+.. cpp:function:: int botan_cipher_set_associated_data(botan_cipher_t cipher, \
+ const uint8_t* ad, size_t ad_len)
+
+ Set associated data. Will fail unless the cipher is an AEAD.
+
+.. cpp:function:: int botan_cipher_start(botan_cipher_t cipher, \
+ const uint8_t* nonce, size_t nonce_len)
+
+ Start processing a message using the provided nonce.
+
+.. cpp:function:: int botan_cipher_update(botan_cipher_t cipher, \
+ uint32_t flags, \
+ uint8_t output[], \
+ size_t output_size, \
+ size_t* output_written, \
+ const uint8_t input_bytes[], \
+ size_t input_size, \
+ size_t* input_consumed)
+
+ Encrypt or decrypt data.
+
+PBKDF
+----------------------------------------
+
+.. cpp:function:: int botan_pbkdf(const char* pbkdf_algo, \
+ uint8_t out[], size_t out_len, \
+ const char* passphrase, \
+ const uint8_t salt[], size_t salt_len, \
+ size_t iterations)
+
+ Derive a key from a passphrase for a number of iterations
+ using the given PBKDF algorithm, e.g., "PBKDF2".
+
+.. cpp:function:: int botan_pbkdf_timed(const char* pbkdf_algo, \
+ uint8_t out[], size_t out_len, \
+ const char* passphrase, \
+ const uint8_t salt[], size_t salt_len, \
+ size_t milliseconds_to_run, \
+ size_t* out_iterations_used)
+
+ Derive a key from a passphrase using the given PBKDF algorithm,
+ e.g., "PBKDF2". If *out_iterations_used* is zero, instead the
+ PBKDF is run until *milliseconds_to_run* milliseconds have passed.
+ In this case, the number of iterations run will be written to
+ *out_iterations_used*.
+
+KDF
+----------------------------------------
+
+.. cpp:function:: int botan_kdf(const char* kdf_algo, \
+ uint8_t out[], size_t out_len, \
+ const uint8_t secret[], size_t secret_len, \
+ const uint8_t salt[], size_t salt_len, \
+ const uint8_t label[], size_t label_len)
+
+ Derive a key using the given KDF algorithm, e.g., "SP800-56C".
+ The derived key of length *out_len* bytes will be placed in *out*.
+
+Multiple Precision Integers
+----------------------------------------
+
+.. versionadded: 2.1.0
+
+.. cpp:type:: opaque* botan_mp_t
+
+ An opaque data type for a multiple precision integer. Don't mess with it.
+
+.. cpp:function:: int botan_mp_init(botan_mp_t* mp)
+
+ Initialize a ``botan_mp_t``. Initial value is zero, use `botan_mp_set_X` to load a value.
+
+.. cpp:function:: int botan_mp_destroy(botan_mp_t mp)
+
+ Free a ``botan_mp_t``
+
+.. cpp:function:: int botan_mp_to_hex(botan_mp_t mp, char* out)
+
+ Writes exactly ``botan_mp_num_bytes(mp)*2 + 1`` bytes to out
+
+.. cpp:function:: int botan_mp_to_str(botan_mp_t mp, uint8_t base, char* out, size_t* out_len)
+
+ Base can be either 10 or 16.
+
+.. cpp:function:: int botan_mp_set_from_int(botan_mp_t mp, int initial_value)
+
+ Set ``botan_mp_t`` from an integer value.
+
+.. cpp:function:: int botan_mp_set_from_mp(botan_mp_t dest, botan_mp_t source)
+
+ Set ``botan_mp_t`` from another MP.
+
+.. cpp:function:: int botan_mp_set_from_str(botan_mp_t dest, const char* str)
+
+ Set ``botan_mp_t`` from a string. Leading prefix of "0x" is accepted.
+
+.. cpp:function:: int botan_mp_num_bits(botan_mp_t n, size_t* bits)
+
+ Return the size of ``n`` in bits.
+
+.. cpp:function:: int botan_mp_num_bytes(botan_mp_t n, size_t* uint8_ts)
+
+ Return the size of ``n`` in bytes.
+
+.. cpp:function:: int botan_mp_to_bin(botan_mp_t mp, uint8_t vec[])
+
+ Writes exactly ``botan_mp_num_bytes(mp)`` to ``vec``.
+
+.. cpp:function:: int botan_mp_from_bin(botan_mp_t mp, const uint8_t vec[], size_t vec_len)
+
+ Loads ``botan_mp_t`` from a binary vector (as produced by ``botan_mp_to_bin``).
+
+.. cpp:function:: int botan_mp_is_negative(botan_mp_t mp)
+
+ Return 1 if ``mp`` is negative, otherwise 0.
+
+.. cpp:function:: int botan_mp_flip_sign(botan_mp_t mp)
+
+ Flip the sign of ``mp``.
+
+.. cpp:function:: int botan_mp_add(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+
+ Add two ``botan_mp_t`` and store the output in ``result``.
+
+.. cpp:function:: int botan_mp_sub(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+
+ Subtract two ``botan_mp_t`` and store the output in ``result``.
+
+.. cpp:function:: int botan_mp_mul(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+
+ Multiply two ``botan_mp_t`` and store the output in ``result``.
+
+.. cpp:function:: int botan_mp_div(botan_mp_t quotient, botan_mp_t remainder, \
+ botan_mp_t x, botan_mp_t y)
+
+ Divide ``x`` by ``y`` and store the output in ``quotient`` and ``remainder``.
+
+.. cpp:function:: int botan_mp_mod_mul(botan_mp_t result, botan_mp_t x, botan_mp_t y, botan_mp_t mod)
+
+ Set ``result`` to ``x`` times ``y`` modulo ``mod``.
+
+.. cpp:function:: int botan_mp_equal(botan_mp_t x, botan_mp_t y)
+
+ Return 1 if ``x`` is equal to ``y``, 0 if ``x`` is not equal to ``y``
+
+.. cpp:function:: int botan_mp_is_zero(const botan_mp_t x)
+
+ Return 1 if ``x`` is equal to zero, otherwise 0.
+
+.. cpp:function:: int botan_mp_is_odd(const botan_mp_t x)
+
+ Return 1 if ``x`` is odd, otherwise 0.
+
+.. cpp:function:: int botan_mp_is_even(const botan_mp_t x)
+
+ Return 1 if ``x`` is even, otherwise 0.
+
+.. cpp:function:: int botan_mp_is_positive(const botan_mp_t x)
+
+ Return 1 if ``x`` is greater than or equal to zero.
+
+.. cpp:function:: int botan_mp_is_negative(const botan_mp_t x)
+
+ Return 1 if ``x`` is less than zero.
+
+.. cpp:function:: int botan_mp_to_uint32(const botan_mp_t x, uint32_t* val)
+
+ If x fits in a 32-bit integer, set val to it and return 0. If x is out of
+ range an error is returned.
+
+.. cpp:function:: int botan_mp_cmp(int* result, botan_mp_t x, botan_mp_t y)
+
+ Three way comparison: set result to -1 if ``x`` is less than ``y``,
+ 0 if ``x`` is equal to ``y``, and 1 if ``x`` is greater than ``y``.
+
+.. cpp:function:: int botan_mp_swap(botan_mp_t x, botan_mp_t y)
+
+ Swap two ``botan_mp_t`` values.
+
+.. cpp:function:: int botan_mp_powmod(botan_mp_t out, botan_mp_t base, botan_mp_t exponent, botan_mp_t modulus)
+
+ Modular exponentiation.
+
+.. cpp:function:: int botan_mp_lshift(botan_mp_t out, botan_mp_t in, size_t shift)
+
+ Left shift by specified bit count, place result in ``out``.
+
+.. cpp:function:: int botan_mp_rshift(botan_mp_t out, botan_mp_t in, size_t shift)
+
+ Right shift by specified bit count, place result in ``out``.
+
+.. cpp:function:: int botan_mp_mod_inverse(botan_mp_t out, botan_mp_t in, botan_mp_t modulus)
+
+ Compute modular inverse. If no modular inverse exists (for instance because ``in`` and
+ ``modulus`` are not relatively prime), then sets ``out`` to -1.
+
+.. cpp:function:: int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits)
+
+ Create a random ``botan_mp_t`` of the specified bit size.
+
+.. cpp:function:: int botan_mp_rand_range(botan_mp_t rand_out, botan_rng_t rng, \
+ botan_mp_t lower_bound, botan_mp_t upper_bound)
+
+ Create a random ``botan_mp_t`` within the provided range.
+
+.. cpp:function:: int botan_mp_gcd(botan_mp_t out, botan_mp_t x, botan_mp_t y)
+
+ Compute the greatest common divisor of ``x`` and ``y``.
+
+.. cpp:function:: int botan_mp_is_prime(botan_mp_t n, botan_rng_t rng, size_t test_prob)
+
+ Test if ``n`` is prime. The algorithm used (Miller-Rabin) is probabilistic,
+ set ``test_prob`` to the desired assurance level. For example if
+ ``test_prob`` is 64, then sufficient Miller-Rabin iterations will run to
+ assure there is at most a ``1/2**64`` chance that ``n`` is composite.
+
+.. cpp:function:: int botan_mp_get_bit(botan_mp_t n, size_t bit)
+
+ Returns 0 if the specified bit of ``n`` is not set, 1 if it is set.
+
+.. cpp:function:: int botan_mp_set_bit(botan_mp_t n, size_t bit)
+
+ Set the specified bit of ``n``
+
+.. cpp:function:: int botan_mp_clear_bit(botan_mp_t n, size_t bit)
+
+ Clears the specified bit of ``n``
+
+
+Password Hashing
+----------------------------------------
+
+.. cpp:function:: int botan_bcrypt_generate(uint8_t* out, size_t* out_len, \
+ const char* password, \
+ botan_rng_t rng, \
+ size_t work_factor, \
+ uint32_t flags)
+
+ Create a password hash using Bcrypt.
+ The output buffer *out* should be of length 64 bytes.
+ The output is formatted bcrypt $2a$...
+
+.. cpp:function:: int botan_bcrypt_is_valid(const char* pass, const char* hash)
+
+ Check a previously created password hash. Returns
+ :cpp:enumerator:`BOTAN_SUCCESS` if if this password/hash
+ combination is valid, :cpp:enumerator:`BOTAN_FFI_INVALID_VERIFIER`
+ if the combination is not valid (but otherwise well formed),
+ negative on error.
+
+Public Key Creation, Import and Export
+----------------------------------------
+
+.. cpp:type:: opaque* botan_privkey_t
+
+ An opaque data type for a private key. Don't mess with it.
+
+.. cpp:function:: int botan_privkey_create(botan_privkey_t* key, \
+ const char* algo_name, \
+ const char* algo_params, \
+ botan_rng_t rng)
+
+.. cpp:function:: int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng, size_t n_bits)
+
+ Create an RSA key of the given size
+
+.. cpp:function:: int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng, const char* curve)
+
+ Create a ECDSA key of using a named curve
+
+.. cpp:function:: int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng, const char* curve)
+
+ Create a ECDH key of using a named curve
+
+.. cpp:function:: int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t)
+
+ Create a McEliece key using the specified parameters. See
+ :ref:`mceliece` for details on choosing parameters.
+
+.. cpp:function:: int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, const char* params)
+
+ Create a finite field Diffie-Hellman key using the specified named group, for example
+ "modp/ietf/3072".
+
+.. cpp:function:: int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng, \
+ const uint8_t bits[], size_t len, \
+ const char* password)
+
+ Load a private key. If the key is encrypted, ``password`` will be
+ used to attempt decryption.
+
+.. cpp:function:: int botan_privkey_destroy(botan_privkey_t key)
+
+ Destroy the object.
+
+.. cpp:function:: int botan_privkey_export(botan_privkey_t key, \
+ uint8_t out[], size_t* out_len, \
+ uint32_t flags)
+
+ Export a public key. If flags is 1 then PEM format is used.
+
+.. cpp:function:: int botan_privkey_export_encrypted(botan_privkey_t key, \
+ uint8_t out[], size_t* out_len, \
+ botan_rng_t rng, \
+ const char* passphrase, \
+ const char* encryption_algo, \
+ uint32_t flags)
+
+ Deprecated, use ``botan_privkey_export_encrypted_msec`` or ``botan_privkey_export_encrypted_iter``
+
+.. cpp::function:: int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key,
+ uint8_t out[], size_t* out_len, \
+ botan_rng_t rng, \
+ const char* passphrase, \
+ uint32_t pbkdf_msec_runtime, \
+ size_t* pbkdf_iterations_out, \
+ const char* cipher_algo, \
+ const char* pbkdf_algo, \
+ uint32_t flags);
+
+ Encrypt a key, running the key derivation function for ``pbkdf_msec_runtime`` milliseconds.
+ Returns the number of iterations used in ``pbkdf_iterations_out``.
+
+ ``cipher_algo`` must specify a CBC mode cipher (such as "AES-128/CBC") or as
+ a Botan-specific extension a GCM mode may be used.
+
+.. cpp::function:: int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key, \
+ uint8_t out[], size_t* out_len, \
+ botan_rng_t rng, \
+ const char* passphrase, \
+ size_t pbkdf_iterations, \
+ const char* cipher_algo, \
+ const char* pbkdf_algo, \
+ uint32_t flags);
+
+ Encrypt a private key. The PBKDF function runs for the specified number of iterations.
+ At least 100,000 is recommended.
+
+.. cpp:function:: int botan_privkey_export_pubkey(botan_pubkey_t* out, botan_privkey_t in)
+
+.. cpp:function:: int botan_privkey_get_field(botan_mp_t output, \
+ botan_privkey_t key, \
+ const char* field_name)
+
+ Read an algorithm specific field from the private key object, placing it into output.
+ For example "p" or "q" for RSA keys, or "x" for DSA keys or ECC keys.
+
+.. cpp:type:: opaque* botan_pubkey_t
+
+ An opaque data type for a public key. Don't mess with it.
+
+.. cpp:function:: int botan_pubkey_load(botan_pubkey_t* key, const uint8_t bits[], size_t len)
+
+.. cpp:function:: int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
+
+.. cpp:function:: int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
+
+.. cpp:function:: int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate)
+
+.. cpp:function:: int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash, \
+ uint8_t out[], size_t* out_len)
+
+.. cpp:function:: int botan_pubkey_destroy(botan_pubkey_t key)
+
+.. cpp:function:: int botan_pubkey_get_field(botan_mp_t output, \
+ botan_pubkey_t key, \
+ const char* field_name)
+
+ Read an algorithm specific field from the public key object, placing it into output.
+ For example "n" or "e" for RSA keys or "p", "q", "g", and "y" for DSA keys.
+
+RSA specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t rsa_key)
+
+ Set ``p`` to the first RSA prime.
+
+.. cpp:function:: int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t rsa_key)
+
+ Set ``q`` to the second RSA prime.
+
+.. cpp:function:: int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t rsa_key)
+
+ Set ``d`` to the RSA private exponent.
+
+.. cpp:function:: int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t rsa_key)
+
+ Set ``n`` to the RSA modulus.
+
+.. cpp:function:: int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t rsa_key)
+
+ Set ``e`` to the RSA public exponent.
+
+.. cpp:function:: int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t rsa_key)
+
+ Set ``e`` to the RSA public exponent.
+
+.. cpp:function:: int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t rsa_key)
+
+ Set ``n`` to the RSA modulus.
+
+.. cpp:function:: int botan_privkey_load_rsa(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t q, botan_mp_t e)
+
+ Initialize a private RSA key using parameters p, q, and e.
+
+.. cpp:function:: int botan_pubkey_load_rsa(botan_pubkey_t* key, \
+ botan_mp_t n, botan_mp_t e)
+
+ Initialize a public RSA key using parameters n and e.
+
+DSA specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_load_dsa(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t x)
+
+ Initialize a private DSA key using group parameters p, q, and g and private key x.
+
+.. cpp:function:: int botan_pubkey_load_dsa(botan_pubkey_t* key, \
+ botan_mp_t p, botan_mp_t q, botan_mp_t g, botan_mp_t y)
+
+ Initialize a private DSA key using group parameters p, q, and g and public key y.
+
+ElGamal specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_load_elgamal(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t x)
+
+ Initialize a private ElGamal key using group parameters p and g and private key x.
+
+.. cpp:function:: int botan_pubkey_load_elgamal(botan_pubkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t y)
+
+ Initialize a public ElGamal key using group parameters p and g and public key y.
+
+Diffie-Hellman specific functions
+----------------------------------------
+
+.. cpp:function:: int botan_privkey_load_dh(botan_privkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t x)
+
+ Initialize a private Diffie-Hellman key using group parameters p and g and private key x.
+
+.. cpp:function:: int botan_pubkey_load_dh(botan_pubkey_t* key, \
+ botan_mp_t p, botan_mp_t g, botan_mp_t y)
+
+ Initialize a public Diffie-Hellman key using group parameters p and g and public key y.
+
+Public Key Encryption/Decryption
+----------------------------------------
+
+.. cpp:type:: opaque* botan_pk_op_encrypt_t
+
+ An opaque data type for an encryption operation. Don't mess with it.
+
+.. cpp:function:: int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op, \
+ botan_pubkey_t key, \
+ const char* padding, \
+ uint32_t flags)
+
+ Create a new operation object which can be used to encrypt using the provided
+ key and the specified padding scheme (such as "OAEP(SHA-256)" for use with
+ RSA). Flags should be 0 in this version.
+
+.. cpp:function:: int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op)
+
+ Destroy the object.
+
+.. cpp:function:: int botan_pk_op_encrypt_output_length(botan_pk_op_encrypt_t op, \
+ size_t ptext_len, size_t* ctext_len)
+
+ Returns an upper bound on the output length if a plaintext of length ``ptext_len``
+ is encrypted with this key/parameter setting. This allows correctly sizing the
+ buffer that is passed to :cpp:func:`botan_pk_op_encrypt`.
+
+.. cpp:function:: int botan_pk_op_encrypt(botan_pk_op_encrypt_t op, \
+ botan_rng_t rng, \
+ uint8_t out[], size_t* out_len, \
+ const uint8_t plaintext[], size_t plaintext_len)
+
+ Encrypt the provided data using the key, placing the output in `out`. If
+ `out` is NULL, writes the length of what the ciphertext would have been to
+ `*out_len`. However this is computationally expensive (the encryption
+ actually occurs, then the result is discarded), so it is better to use
+ :cpp:func:`botan_pk_op_encrypt_output_length` to correctly size the buffer.
+
+.. cpp:type:: opaque* botan_pk_op_decrypt_t
+
+ An opaque data type for a decryption operation. Don't mess with it.
+
+.. cpp:function:: int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op, \
+ botan_privkey_t key, \
+ const char* padding, \
+ uint32_t flags)
+
+.. cpp:function:: int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op)
+
+.. cpp:function:: int botan_pk_op_decrypt_output_length(botan_pk_op_decrypt_t op, \
+ size_t ctext_len, size_t* ptext_len)
+
+ For a given ciphertext length, returns the upper bound on the size of the
+ plaintext that might be enclosed. This allows properly sizing the output
+ buffer passed to :cpp:func:`botan_pk_op_decrypt`.
+
+.. cpp:function:: int botan_pk_op_decrypt(botan_pk_op_decrypt_t op, \
+ uint8_t out[], size_t* out_len, \
+ uint8_t ciphertext[], size_t ciphertext_len)
+
+Signature Generation
+----------------------------------------
+
+.. cpp:type:: opaque* botan_pk_op_sign_t
+
+ An opaque data type for a signature generation operation. Don't mess with it.
+
+.. cpp:function:: int botan_pk_op_sign_create(botan_pk_op_sign_t* op, \
+ botan_privkey_t key, \
+ const char* hash_and_padding, \
+ uint32_t flags)
+
+ Create a signature operator for the provided key. The padding string
+ specifies what hash function and padding should be used, for example
+ "PKCS1v15(SHA-256)" or "EMSA1(SHA-384)".
+
+.. cpp:function:: int botan_pk_op_sign_destroy(botan_pk_op_sign_t op)
+
+ Destroy an object created by :cpp:func:`botan_pk_op_sign_create`.
+
+.. cpp:function:: int botan_pk_op_sign_output_length(botan_pk_op_sign_t op, size_t* sig_len)
+
+ Writes the length of the signatures that this signer will produce. This
+ allows properly sizing the buffer passed to
+ :cpp:func:`botan_pk_op_sign_finish`.
+
+.. cpp:function:: int botan_pk_op_sign_update(botan_pk_op_sign_t op, \
+ const uint8_t in[], size_t in_len)
+
+ Add bytes of the message to be signed.
+
+.. cpp:function:: int botan_pk_op_sign_finish(botan_pk_op_sign_t op, botan_rng_t rng, \
+ uint8_t sig[], size_t* sig_len)
+
+ Produce a signature over all of the bytes passed to :cpp:func:`botan_pk_op_sign_update`.
+ Afterwards, the sign operator is reset and may be used to sign a new message.
+
+Signature Verification
+----------------------------------------
+
+.. cpp:type:: opaque* botan_pk_op_verify_t
+
+ An opaque data type for a signature verification operation. Don't mess with it.
+
+.. cpp:function:: int botan_pk_op_verify_create(botan_pk_op_verify_t* op, \
+ botan_pubkey_t key, \
+ const char* hash_and_padding, \
+ uint32_t flags)
+
+.. cpp:function:: int botan_pk_op_verify_destroy(botan_pk_op_verify_t op)
+
+.. cpp:function:: int botan_pk_op_verify_update(botan_pk_op_verify_t op, \
+ const uint8_t in[], size_t in_len)
+
+ Add bytes of the message to be verified
+
+.. cpp:function:: int botan_pk_op_verify_finish(botan_pk_op_verify_t op, \
+ const uint8_t sig[], size_t sig_len)
+
+ Verify if the signature provided matches with the message provided as calls
+ to :cpp:func:`botan_pk_op_verify_update`.
+
+Key Agreement
+----------------------------------------
+
+.. cpp:type:: opaque* botan_pk_op_ka_t
+
+ An opaque data type for a key agreement operation. Don't mess with it.
+
+.. cpp:function:: int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op, \
+ botan_privkey_t key, \
+ const char* kdf, \
+ uint32_t flags)
+
+.. cpp:function:: int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op)
+
+.. cpp:function:: int botan_pk_op_key_agreement_export_public(botan_privkey_t key, \
+ uint8_t out[], size_t* out_len)
+
+.. cpp:function:: int botan_pk_op_key_agreement(botan_pk_op_ka_t op, \
+ uint8_t out[], size_t* out_len, \
+ const uint8_t other_key[], size_t other_key_len, \
+ const uint8_t salt[], size_t salt_len)
+
+.. cpp:function:: int botan_mceies_encrypt(botan_pubkey_t mce_key, \
+ botan_rng_t rng, \
+ const char* aead, \
+ const uint8_t pt[], size_t pt_len, \
+ const uint8_t ad[], size_t ad_len, \
+ uint8_t ct[], size_t* ct_len)
+
+.. cpp:function:: int botan_mceies_decrypt(botan_privkey_t mce_key, \
+ const char* aead, \
+ const uint8_t ct[], size_t ct_len, \
+ const uint8_t ad[], size_t ad_len, \
+ uint8_t pt[], size_t* pt_len)
+
+X.509 Certificates
+----------------------------------------
+
+.. cpp:type:: opaque* botan_x509_cert_t
+
+ An opaque data type for an X.509 certificate. Don't mess with it.
+
+.. cpp:function:: int botan_x509_cert_load(botan_x509_cert_t* cert_obj, \
+ const uint8_t cert[], size_t cert_len)
+
+ Load a certificate from the DER or PEM representation
+
+.. cpp:function:: int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* filename)
+
+ Load a certificate from a file.
+
+.. cpp:function:: int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert)
+
+ Create a new object that refers to the same certificate.
+
+.. cpp:function:: int botan_x509_cert_destroy(botan_x509_cert_t cert)
+
+ Destroy the certificate object
+
+.. cpp:function:: int botan_x509_cert_gen_selfsigned(botan_x509_cert_t* cert, \
+ botan_privkey_t key, \
+ botan_rng_t rng, \
+ const char* common_name, \
+ const char* org_name)
+
+.. cpp:function:: int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len)
+
+ Return the time the certificate becomes valid, as a string in form
+ "YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
+ relative to UTC. Prefer :cpp:func:`botan_x509_cert_not_before`.
+
+.. cpp:function:: int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len)
+
+ Return the time the certificate expires, as a string in form
+ "YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
+ relative to UTC. Prefer :cpp:func:`botan_x509_cert_not_after`.
+
+.. cpp:function:: int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch)
+
+ Return the time the certificate becomes valid, as seconds since epoch.
+
+.. cpp:function:: int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch)
+
+ Return the time the certificate expires, as seconds since epoch.
+
+.. cpp:function:: int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len)
+
+.. cpp:function:: int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+
+ Return the serial number of the certificate.
+
+.. cpp:function:: int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+
+ Return the authority key ID set in the certificate, which may be empty.
+
+.. cpp:function:: int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+
+ Return the subject key ID set in the certificate, which may be empty.
+
+.. cpp:function:: int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, \
+ uint8_t out[], size_t* out_len)
+
+ Get the serialized representation of the public key included in this certificate
+
+.. cpp:function:: int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key)
+
+ Get the public key included in this certificate as a newly allocated object
+
+.. cpp:function:: int botan_x509_cert_get_issuer_dn(botan_x509_cert_t cert, \
+ const char* key, size_t index, \
+ uint8_t out[], size_t* out_len)
+
+ Get a value from the issuer DN field.
+
+.. cpp:function:: int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert, \
+ const char* key, size_t index, \
+ uint8_t out[], size_t* out_len)
+
+ Get a value from the subject DN field.
+
+.. cpp:function:: int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len)
+
+ Format the certificate as a free-form string.
+
+.. cpp:enum:: botan_x509_cert_key_constraints
+
+ Certificate key usage constraints. Allowed values: `NO_CONSTRAINTS`,
+ `DIGITAL_SIGNATURE`, `NON_REPUDIATION`, `KEY_ENCIPHERMENT`,
+ `DATA_ENCIPHERMENT`, `KEY_AGREEMENT`, `KEY_CERT_SIGN`,
+ `CRL_SIGN`, `ENCIPHER_ONLY`, `DECIPHER_ONLY`.
+
+.. cpp:function:: int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage)
+
+
+.. cpp:function:: int botan_x509_cert_verify(int* validation_result, \
+ botan_x509_cert_t cert, \
+ const botan_x509_cert_t* intermediates, \
+ size_t intermediates_len, \
+ const botan_x509_cert_t* trusted, \
+ size_t trusted_len, \
+ const char* trusted_path, \
+ size_t required_strength, \
+ const char* hostname, \
+ uint64_t reference_time)
+
+ Verify a certificate. Returns 0 if validation was successful, 1 if
+ unsuccessful, or negative on error.
+
+ Sets ``validation_result`` to a code that provides more information.
+
+ If not needed, set ``intermediates`` to NULL and ``intermediates_len`` to
+ zero.
+
+ If not needed, set ``trusted`` to NULL and ``trusted_len`` to zero.
+
+ The ``trusted_path`` refers to a directory where one or more trusted CA
+ certificates are stored. It may be NULL if not needed.
+
+ Set ``required_strength`` to indicate the minimum key and hash strength
+ that is allowed. For instance setting to 80 allows 1024-bit RSA and SHA-1.
+ Setting to 110 requires 2048-bit RSA and SHA-256 or higher. Set to zero
+ to accept a default.
+
+ Set ``reference_time`` to be the time which the certificate chain is
+ validated against. Use zero to use the current system clock.
+
+.. cpp:function:: int botan_x509_cert_verify_with_crl(int* validation_result, \
+ botan_x509_cert_t cert, \
+ const botan_x509_cert_t* intermediates, \
+ size_t intermediates_len, \
+ const botan_x509_cert_t* trusted, \
+ size_t trusted_len, \
+ const botan_x509_crl_t* crls, \
+ size_t crls_len, \
+ const char* trusted_path, \
+ size_t required_strength, \
+ const char* hostname, \
+ uint64_t reference_time)
+
+ Certificate path validation supporting Certificate Revocation Lists.
+
+ Works the same as ``botan_x509_cert_cerify``.
+
+ ``crls`` is an array of ``botan_x509_crl_t`` objects, ``crls_len`` is its length.
+
+.. cpp:function:: const char* botan_x509_cert_validation_status(int code)
+
+ Return a (statically allocated) string associated with the verification
+ result.
+
+X.509 Certificate Revocation Lists
+----------------------------------------
+
+.. cpp:type:: opaque* botan_x509_crl_t
+
+ An opaque data type for an X.509 CRL.
+
+.. cpp:function:: int botan_x509_crl_load(botan_x509_crl_t* crl_obj, \
+ const uint8_t crl[], size_t crl_len)
+
+ Load a CRL from the DER or PEM representation.
+
+.. cpp:function:: int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* filename)
+
+ Load a CRL from a file.
+
+.. cpp:function:: int botan_x509_crl_destroy(botan_x509_crl_t crl)
+
+ Destroy the CRL object.
+
+.. cpp:function:: int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert)
+
+ Check whether a given ``crl`` contains a given ``cert``.
+ Return ``0`` when the certificate is revoked, ``-1`` otherwise.
diff --git a/comm/third_party/botan/doc/api_ref/filters.rst b/comm/third_party/botan/doc/api_ref/filters.rst
new file mode 100644
index 0000000000..04baebf5d0
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/filters.rst
@@ -0,0 +1,733 @@
+
+Pipe/Filter Message Processing
+========================================
+
+.. note::
+
+ The system described below provides a message processing system with a
+ straightforward API. However it makes many extra memory copies and
+ allocations than would otherwise be required, and also tends to make
+ applications using it somewhat opaque because it is not obvious what this or
+ that Pipe& object actually does (type of operation, number of messages
+ output (if any!), and so on), whereas using say a HashFunction or AEAD_Mode
+ provides a much better idea in the code of what operation is occurring.
+
+ This filter interface is no longer used within the library itself
+ (outside a few dusty corners) and will likely not see any further major
+ development. However it will remain included because the API is often
+ convenient and many applications use it.
+
+Many common uses of cryptography involve processing one or more
+streams of data. Botan provides services that make setting up data
+flows through various operations, such as compression, encryption, and
+base64 encoding. Each of these operations is implemented in what are
+called *filters* in Botan. A set of filters are created and placed into
+a *pipe*, and information "flows" through the pipe until it reaches
+the end, where the output is collected for retrieval. If you're
+familiar with the Unix shell environment, this design will sound quite
+familiar.
+
+Here is an example that uses a pipe to base64 encode some strings::
+
+ Pipe pipe(new Base64_Encoder); // pipe owns the pointer
+ pipe.start_msg();
+ pipe.write("message 1");
+ pipe.end_msg(); // flushes buffers, increments message number
+
+ // process_msg(x) is start_msg() && write(x) && end_msg()
+ pipe.process_msg("message2");
+
+ std::string m1 = pipe.read_all_as_string(0); // "message1"
+ std::string m2 = pipe.read_all_as_string(1); // "message2"
+
+Byte streams in the pipe are grouped into messages; blocks of data that
+are processed in an identical fashion (ie, with the same sequence of
+filter operations). Messages are delimited by calls to ``start_msg``
+and ``end_msg``. Each message in a pipe has its own identifier, which
+currently is an integer that increments up from zero.
+
+The ``Base64_Encoder`` was allocated using ``new``; but where was it
+deallocated? When a filter object is passed to a ``Pipe``, the pipe
+takes ownership of the object, and will deallocate it when it is no
+longer needed.
+
+There are two different ways to make use of messages. One is to send
+several messages through a ``Pipe`` without changing the ``Pipe``
+configuration, so you end up with a sequence of messages; one use of
+this would be to send a sequence of identically encrypted UDP packets,
+for example (note that the *data* need not be identical; it is just
+that each is encrypted, encoded, signed, etc in an identical
+fashion). Another is to change the filters that are used in the
+``Pipe`` between each message, by adding or removing filters;
+functions that let you do this are documented in the Pipe API section.
+
+Botan has about 40 filters that perform different operations on data.
+Here's code that uses one of them to encrypt a string with AES::
+
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 16); // a random 128-bit key
+ InitializationVector iv(rng, 16); // a random 128-bit IV
+
+ // The algorithm we want is specified by a string
+ Pipe pipe(get_cipher("AES-128/CBC", key, iv, ENCRYPTION));
+
+ pipe.process_msg("secrets");
+ pipe.process_msg("more secrets");
+
+ secure_vector<uint8_t> c1 = pipe.read_all(0);
+
+ uint8_t c2[4096] = { 0 };
+ size_t got_out = pipe.read(c2, sizeof(c2), 1);
+ // use c2[0...got_out]
+
+Note the use of ``AutoSeeded_RNG``, which is a random number
+generator. If you want to, you can explicitly set up the random number
+generators and entropy sources you want to, however for 99% of cases
+``AutoSeeded_RNG`` is preferable.
+
+``Pipe`` also has convenience methods for dealing with ``std::iostream``.
+Here is an example of this, using the bzip2 compression filter::
+
+ std::ifstream in("data.bin", std::ios::binary)
+ std::ofstream out("data.bin.bz2", std::ios::binary)
+
+ Pipe pipe(new Compression_Filter("bzip2", 9));
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ out << pipe;
+
+However there is a hitch to the code above; the complete contents of
+the compressed data will be held in memory until the entire message
+has been compressed, at which time the statement ``out << pipe`` is
+executed, and the data is freed as it is read from the pipe and
+written to the file. But if the file is very large, we might not have
+enough physical memory (or even enough virtual memory!) for that to be
+practical. So instead of storing the compressed data in the pipe for
+reading it out later, we divert it directly to the file::
+
+ std::ifstream in("data.bin", std::ios::binary)
+ std::ofstream out("data.bin.bz2", std::ios::binary)
+
+ Pipe pipe(new Compression_Filter("bzip2", 9), new DataSink_Stream(out));
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+This is the first code we've seen so far that uses more than one
+filter in a pipe. The output of the compressor is sent to the
+``DataSink_Stream``. Anything written to a ``DataSink_Stream`` is
+written to a file; the filter produces no output. As soon as the
+compression algorithm finishes up a block of data, it will send it
+along to the sink filter, which will immediately write it to the
+stream; if you were to call ``pipe.read_all()`` after
+``pipe.end_msg()``, you'd get an empty vector out. This is
+particularly useful for cases where you are processing a large amount
+of data, as it means you don't have to store everything in memory at
+once.
+
+Here's an example using two computational filters::
+
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 32);
+ InitializationVector iv(rng, 16);
+
+ Pipe encryptor(get_cipher("AES/CBC/PKCS7", key, iv, ENCRYPTION),
+ new Base64_Encoder);
+
+ encryptor.start_msg();
+ file >> encryptor;
+ encryptor.end_msg(); // flush buffers, complete computations
+ std::cout << encryptor;
+
+You can read from a pipe while you are still writing to it, which
+allows you to bound the amount of memory that is in use at any one
+time. A common idiom for this is::
+
+ pipe.start_msg();
+ std::vector<uint8_t> buffer(4096); // arbitrary size
+ while(infile.good())
+ {
+ infile.read((char*)&buffer[0], buffer.size());
+ const size_t got_from_infile = infile.gcount();
+ pipe.write(buffer, got_from_infile);
+
+ if(infile.eof())
+ pipe.end_msg();
+
+ while(pipe.remaining() > 0)
+ {
+ const size_t buffered = pipe.read(buffer, buffer.size());
+ outfile.write((const char*)&buffer[0], buffered);
+ }
+ }
+ if(infile.bad() || (infile.fail() && !infile.eof()))
+ throw Some_Exception();
+
+Fork
+---------------------------------
+
+It is common that you might receive some data and want to perform more
+than one operation on it (ie, encrypt it with Serpent and calculate
+the SHA-256 hash of the plaintext at the same time). That's where
+``Fork`` comes in. ``Fork`` is a filter that takes input and passes it
+on to *one or more* filters that are attached to it. ``Fork`` changes
+the nature of the pipe system completely: instead of being a linked
+list, it becomes a tree or acyclic graph.
+
+Each filter in the fork is given its own output buffer, and thus its
+own message. For example, if you had previously written two messages
+into a pipe, then you start a new one with a fork that has three
+paths of filter's inside it, you add three new messages to the
+pipe. The data you put into the pipe is duplicated and sent
+into each set of filter and the eventual output is placed into a
+dedicated message slot in the pipe.
+
+Messages in the pipe are allocated in a depth-first manner. This is only
+interesting if you are using more than one fork in a single pipe.
+As an example, consider the following::
+
+ Pipe pipe(new Fork(
+ new Fork(
+ new Base64_Encoder,
+ new Fork(
+ NULL,
+ new Base64_Encoder
+ )
+ ),
+ new Hex_Encoder
+ )
+ );
+
+In this case, message 0 will be the output of the first
+``Base64_Encoder``, message 1 will be a copy of the input (see below
+for how fork interprets NULL pointers), message 2 will be the output
+of the second ``Base64_Encoder``, and message 3 will be the output of
+the ``Hex_Encoder``. This results in message numbers being allocated
+in a top to bottom fashion, when looked at on the screen. However,
+note that there could be potential for bugs if this is not
+anticipated. For example, if your code is passed a filter, and you
+assume it is a "normal" one that only uses one message, your message
+offsets would be wrong, leading to some confusion during output.
+
+If Fork's first argument is a null pointer, but a later argument is
+not, then Fork will feed a copy of its input directly through. Here's
+a case where that is useful::
+
+ // have std::string ciphertext, auth_code, key, iv, mac_key;
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher("AES-128", key, iv, DECRYPTION),
+ new Fork(
+ 0, // this message gets plaintext
+ new MAC_Filter("HMAC(SHA-1)", mac_key)
+ )
+ );
+
+ pipe.process_msg(ciphertext);
+ std::string plaintext = pipe.read_all_as_string(0);
+ secure_vector<uint8_t> mac = pipe.read_all(1);
+
+ if(mac != auth_code)
+ error();
+
+Here we wanted to not only decrypt the message, but send the decrypted
+text through an additional computation, in order to compute the
+authentication code.
+
+Any filters that are attached to the pipe after the fork are
+implicitly attached onto the first branch created by the fork. For
+example, let's say you created this pipe::
+
+ Pipe pipe(new Fork(new Hash_Filter("SHA-256"),
+ new Hash_Filter("SHA-512")),
+ new Hex_Encoder);
+
+And then called ``start_msg``, inserted some data, then
+``end_msg``. Then ``pipe`` would contain two messages. The first one
+(message number 0) would contain the SHA-256 sum of the input in hex
+encoded form, and the other would contain the SHA-512 sum of the input
+in raw binary. In many situations you'll want to perform a sequence of
+operations on multiple branches of the fork; in which case, use
+the filter described in :ref:`chain`.
+
+There is also a ``Threaded_Fork`` which acts the same as ``Fork``,
+except it runs each of the filters in its own thread.
+
+.. _chain:
+
+Chain
+---------------------------------
+
+A ``Chain`` filter creates a chain of filters and encapsulates them
+inside a single filter (itself). This allows a sequence of filters to
+become a single filter, to be passed into or out of a function, or to
+a ``Fork`` constructor.
+
+You can call ``Chain``'s constructor with up to four ``Filter``
+pointers (they will be added in order), or with an array of filter
+pointers and a ``size_t`` that tells ``Chain`` how many filters are in
+the array (again, they will be attached in order). Here's the example
+from the last section, using chain instead of relying on the implicit
+pass through the other version used::
+
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("SHA-256"), new Hex_Encoder),
+ new Hash_Filter("SHA-512")
+ )
+ );
+
+Sources and Sinks
+----------------------------------------
+
+Data Sources
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A ``DataSource`` is a simple abstraction for a thing that stores
+bytes. This type is used heavily in the areas of the API related to
+ASN.1 encoding/decoding. The following types are ``DataSource``:
+``Pipe``, ``SecureQueue``, and a couple of special purpose ones:
+``DataSource_Memory`` and ``DataSource_Stream``.
+
+You can create a ``DataSource_Memory`` with an array of bytes and a
+length field. The object will make a copy of the data, so you don't
+have to worry about keeping that memory allocated. This is mostly for
+internal use, but if it comes in handy, feel free to use it.
+
+A ``DataSource_Stream`` is probably more useful than the memory based
+one. Its constructors take either a ``std::istream`` or a
+``std::string``. If it's a stream, the data source will use the
+``istream`` to satisfy read requests (this is particularly useful to
+use with ``std::cin``). If the string version is used, it will attempt
+to open up a file with that name and read from it.
+
+Data Sinks
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A ``DataSink`` (in ``data_snk.h``) is a ``Filter`` that takes
+arbitrary amounts of input, and produces no output. This means it's
+doing something with the data outside the realm of what
+``Filter``/``Pipe`` can handle, for example, writing it to a file
+(which is what the ``DataSink_Stream`` does). There is no need for
+``DataSink``s that write to a ``std::string`` or memory buffer,
+because ``Pipe`` can handle that by itself.
+
+Here's a quick example of using a ``DataSink``, which encrypts
+``in.txt`` and sends the output to ``out.txt``. There is
+no explicit output operation; the writing of ``out.txt`` is
+implicit::
+
+ DataSource_Stream in("in.txt");
+ Pipe pipe(get_cipher("AES-128/CTR-BE", key, iv),
+ new DataSink_Stream("out.txt"));
+ pipe.process_msg(in);
+
+A real advantage of this is that even if "in.txt" is large, only as
+much memory is needed for internal I/O buffers will be used.
+
+The Pipe API
+---------------------------------
+
+Initializing Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, ``Pipe`` will do nothing at all; any input placed into the
+``Pipe`` will be read back unchanged. Obviously, this has limited
+utility, and presumably you want to use one or more filters to somehow
+process the data. First, you can choose a set of filters to initialize
+the ``Pipe`` via the constructor. You can pass it either a set of up
+to four filter pointers, or a pre-defined array and a length::
+
+ Pipe pipe1(new Filter1(/*args*/), new Filter2(/*args*/),
+ new Filter3(/*args*/), new Filter4(/*args*/));
+ Pipe pipe2(new Filter1(/*args*/), new Filter2(/*args*/));
+
+ Filter* filters[5] = {
+ new Filter1(/*args*/), new Filter2(/*args*/), new Filter3(/*args*/),
+ new Filter4(/*args*/), new Filter5(/*args*/) /* more if desired... */
+ };
+ Pipe pipe3(filters, 5);
+
+This is by far the most common way to initialize a ``Pipe``. However,
+occasionally a more flexible initialization strategy is necessary;
+this is supported by 4 member functions. These functions may only be
+used while the pipe in question is not in use; that is, either before
+calling ``start_msg``, or after ``end_msg`` has been called (and no
+new calls to ``start_msg`` have been made yet).
+
+.. cpp:function:: void Pipe::prepend(Filter* filter)
+
+ Calling ``prepend`` will put the passed filter first in the list of
+ transformations. For example, if you prepend a filter implementing
+ encryption, and the pipe already had a filter that hex encoded the
+ input, then the next message processed would be first encrypted,
+ and *then* hex encoded.
+
+.. cpp:function:: void Pipe::append(Filter* filter)
+
+ Like ``prepend``, but places the filter at the end of the message
+ flow. This doesn't always do what you expect if there is a fork.
+
+.. cpp:function:: void Pipe::pop()
+
+ Removes the first filter in the flow.
+
+.. cpp:function:: void Pipe::reset()
+
+ Removes all the filters that the pipe currently holds - it is reset
+ to an empty/no-op state. Any data that is being retained by the
+ pipe is retained after a ``reset``, and ``reset`` does not affect
+ message numbers (discussed later).
+
+Giving Data to a Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Input to a ``Pipe`` is delimited into messages, which can be read from
+independently (ie, you can read 5 bytes from one message, and then all of
+another message, without either read affecting any other messages).
+
+.. cpp:function:: void Pipe::start_msg()
+
+ Starts a new message; if a message was already running, an exception is
+ thrown. After this function returns, you can call ``write``.
+
+.. cpp:function:: void Pipe::write(const uint8_t* input, size_t length)
+
+.. cpp:function:: void Pipe::write(const std::vector<uint8_t>& input)
+
+.. cpp:function:: void Pipe::write(const std::string& input)
+
+.. cpp:function:: void Pipe::write(DataSource& input)
+
+.. cpp:function:: void Pipe::write(uint8_t input)
+
+ All versions of ``write`` write the input into the filter sequence.
+ If a message is not currently active, an exception is thrown.
+
+.. cpp:function:: void Pipe::end_msg()
+
+ End the currently active message
+
+Sometimes, you may want to do only a single write per message. In this
+case, you can use the ``process_msg`` series of functions, which start
+a message, write their argument into the pipe, and then end the
+message. In this case you would not make any explicit calls to
+``start_msg``/``end_msg``.
+
+Pipes can also be used with the ``>>`` operator, and will accept a
+``std::istream``, or on Unix systems with the ``fd_unix`` module, a
+Unix file descriptor. In either case, the entire contents of the file
+will be read into the pipe.
+
+Getting Output from a Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Retrieving the processed data from a pipe is a bit more complicated,
+for various reasons. The pipe will separate each message into a
+separate buffer, and you have to retrieve data from each message
+independently. Each of the reader functions has a final parameter that
+specifies what message to read from. If this parameter is set to
+``Pipe::DEFAULT_MESSAGE``, it will read the current default message
+(``DEFAULT_MESSAGE`` is also the default value of this parameter).
+
+Functions in ``Pipe`` related to reading include:
+
+.. cpp:function:: size_t Pipe::read(uint8_t* out, size_t len)
+
+ Reads up to ``len`` bytes into ``out``, and returns the number of
+ bytes actually read.
+
+.. cpp:function:: size_t Pipe::peek(uint8_t* out, size_t len)
+
+ Acts exactly like `read`, except the data is not actually read; the
+ next read will return the same data.
+
+.. cpp:function:: secure_vector<uint8_t> Pipe::read_all()
+
+ Reads the entire message into a buffer and returns it
+
+.. cpp:function:: std::string Pipe::read_all_as_string()
+
+ Like ``read_all``, but it returns the data as a ``std::string``.
+ No encoding is done; if the message contains raw binary, so will
+ the string.
+
+.. cpp:function:: size_t Pipe::remaining()
+
+ Returns how many bytes are left in the message
+
+.. cpp:function:: Pipe::message_id Pipe::default_msg()
+
+ Returns the current default message number
+
+.. cpp:function:: Pipe::message_id Pipe::message_count()
+
+ Returns the total number of messages currently in the pipe
+
+.. cpp:function:: Pipe::set_default_msg(Pipe::message_id msgno)
+
+ Sets the default message number (which must be a valid message
+ number for that pipe). The ability to set the default message number
+ is particularly important in the case of using the file output
+ operations (``<<`` with a ``std::ostream`` or Unix file descriptor),
+ because there is no way to specify the message explicitly when using
+ the output operator.
+
+Pipe I/O for Unix File Descriptors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is a minor feature, but it comes in handy sometimes. In all
+installations of the library, Botan's ``Pipe`` object overloads the
+``<<`` and ``>>`` operators for C++ iostream objects,
+which is usually more than sufficient for doing I/O.
+
+However, there are cases where the iostream hierarchy does not map well to
+local 'file types', so there is also the ability to do I/O directly with Unix
+file descriptors. This is most useful when you want to read from or write to
+something like a TCP or Unix-domain socket, or a pipe, since for simple file
+access it's usually easier to just use C++'s file streams.
+
+If ``BOTAN_EXT_PIPE_UNIXFD_IO`` is defined, then you can use the
+overloaded I/O operators with Unix file descriptors. For an example of this,
+check out the ``hash_fd`` example, included in the Botan distribution.
+
+Filter Catalog
+---------------------------------
+
+This section documents most of the useful filters included in the
+library.
+
+Keyed Filters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A few sections ago, it was mentioned that ``Pipe`` can process
+multiple messages, treating each of them the same. Well, that was a
+bit of a lie. There are some algorithms (in particular, block ciphers
+not in ECB mode, and all stream ciphers) that change their state as
+data is put through them.
+
+Naturally, you might well want to reset the keys or (in the case of
+block cipher modes) IVs used by such filters, so multiple messages can
+be processed using completely different keys, or new IVs, or new keys
+and IVs, or whatever. And in fact, even for a MAC or an ECB block
+cipher, you might well want to change the key used from message to
+message.
+
+Enter ``Keyed_Filter``, which acts as an abstract interface for any
+filter that is uses keys: block cipher modes, stream ciphers, MACs,
+and so on. It has two functions, ``set_key`` and ``set_iv``. Calling
+``set_key`` will set (or reset) the key used by the algorithm. Setting
+the IV only makes sense in certain algorithms -- a call to ``set_iv``
+on an object that doesn't support IVs will cause an exception. You
+must call ``set_key`` *before* calling ``set_iv``.
+
+Here's a example::
+
+ Keyed_Filter *aes, *hmac;
+ Pipe pipe(new Base64_Decoder,
+ // Note the assignments to the cast and hmac variables
+ aes = get_cipher("AES-128/CBC", aes_key, iv),
+ new Fork(
+ 0, // Read the section 'Fork' to understand this
+ new Chain(
+ hmac = new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+ pipe.start_msg();
+ // use pipe for a while, decrypt some stuff, derive new keys and IVs
+ pipe.end_msg();
+
+ aes->set_key(aes_key2);
+ aes->set_iv(iv2);
+ hmac->set_key(mac_key2);
+
+ pipe.start_msg();
+ // use pipe for some other things
+ pipe.end_msg();
+
+There are some requirements to using ``Keyed_Filter`` that you must
+follow. If you call ``set_key`` or ``set_iv`` on a filter that is
+owned by a ``Pipe``, you must do so while the ``Pipe`` is
+"unlocked". This refers to the times when no messages are being
+processed by ``Pipe`` -- either before ``Pipe``'s ``start_msg`` is
+called, or after ``end_msg`` is called (and no new call to
+``start_msg`` has happened yet). Doing otherwise will result in
+undefined behavior, probably silently getting invalid output.
+
+And remember: if you're resetting both values, reset the key *first*.
+
+Cipher Filters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Getting a hold of a ``Filter`` implementing a cipher is very
+easy. Make sure you're including the header ``lookup.h``, and
+then call ``get_cipher``. You will pass the return value
+directly into a ``Pipe``. There are a couple different functions
+which do varying levels of initialization:
+
+.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
+ SymmetricKey key, InitializationVector iv, Cipher_Dir dir)
+
+.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
+ SymmetricKey key, Cipher_Dir dir)
+
+The version that doesn't take an IV is useful for things that don't
+use them, like block ciphers in ECB mode, or most stream ciphers. If
+you specify a cipher spec that does want a IV, and you use the version
+that doesn't take one, an exception will be thrown. The ``dir``
+argument can be either ``ENCRYPTION`` or ``DECRYPTION``.
+
+The cipher_spec is a string that specifies what cipher is to be
+used. The general syntax for "cipher_spec" is "STREAM_CIPHER",
+"BLOCK_CIPHER/MODE", or "BLOCK_CIPHER/MODE/PADDING". In the case of
+stream ciphers, no mode is necessary, so just the name is
+sufficient. A block cipher requires a mode of some sort, which can be
+"ECB", "CBC", "CFB(n)", "OFB", "CTR-BE", or "EAX(n)". The argument to
+CFB mode is how many bits of feedback should be used. If you just use
+"CFB" with no argument, it will default to using a feedback equal to
+the block size of the cipher. EAX mode also takes an optional bit
+argument, which tells EAX how large a tag size to use~--~generally
+this is the size of the block size of the cipher, which is the default
+if you don't specify any argument.
+
+In the case of the ECB and CBC modes, a padding method can also be
+specified. If it is not supplied, ECB defaults to not padding, and CBC
+defaults to using PKCS #5/#7 compatible padding. The padding methods
+currently available are "NoPadding", "PKCS7", "OneAndZeros", and
+"CTS". CTS padding is currently only available for CBC mode, but the
+others can also be used in ECB mode.
+
+Some example "cipher_spec arguments are: "AES-128/CBC",
+"Blowfish/CTR-BE", "Serpent/XTS", and "AES-256/EAX".
+
+"CTR-BE" refers to counter mode where the counter is incremented as if
+it were a big-endian encoded integer. This is compatible with most
+other implementations, but it is possible some will use the
+incompatible little endian convention. This version would be denoted
+as "CTR-LE" if it were supported.
+
+"EAX" is a new cipher mode designed by Wagner, Rogaway, and
+Bellare. It is an authenticated cipher mode (that is, no separate
+authentication is needed), has provable security, and is free from
+patent entanglements. It runs about half as fast as most of the other
+cipher modes (like CBC, OFB, or CTR), which is not bad considering you
+don't need to use an authentication code.
+
+Hashes and MACs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Hash functions and MACs don't need anything special when it comes to
+filters. Both just take their input and produce no output until
+``end_msg`` is called, at which time they complete the hash or MAC and
+send that as output.
+
+These filters take a string naming the type to be used. If for some
+reason you name something that doesn't exist, an exception will be thrown.
+
+.. cpp:function:: Hash_Filter::Hash_Filter(std::string hash, size_t outlen = 0)
+
+ This constructor creates a filter that hashes its input with
+ ``hash``. When ``end_msg`` is called on the owning pipe, the hash is
+ completed and the digest is sent on to the next filter in the
+ pipeline. The parameter ``outlen`` specifies how many bytes of the
+ hash output will be passed along to the next filter when ``end_msg``
+ is called. By default, it will pass the entire hash.
+
+ Examples of names for ``Hash_Filter`` are "SHA-1" and "Whirlpool".
+
+.. cpp:function:: MAC_Filter::MAC_Filter(std::string mac, SymmetricKey key, size_t outlen = 0)
+
+ This constructor takes a name for a mac, such as "HMAC(SHA-1)" or
+ "CMAC(AES-128)", along with a key to use. The optional ``outlen``
+ works the same as in ``Hash_Filter``.
+
+Encoders
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Often you want your data to be in some form of text (for sending over
+channels that aren't 8-bit clean, printing it, etc). The filters
+``Hex_Encoder`` and ``Base64_Encoder`` will convert arbitrary binary
+data into hex or base64 formats. Not surprisingly, you can use
+``Hex_Decoder`` and ``Base64_Decoder`` to convert it back into its
+original form.
+
+Both of the encoders can take a few options about how the data should
+be formatted (all of which have defaults). The first is a ``bool``
+which says if the encoder should insert line breaks. This defaults to
+false. Line breaks don't matter either way to the decoder, but it
+makes the output a bit more appealing to the human eye, and a few
+transport mechanisms (notably some email systems) limit the maximum
+line length.
+
+The second encoder option is an integer specifying how long such lines
+will be (obviously this will be ignored if line-breaking isn't being
+used). The default tends to be in the range of 60-80 characters, but
+is not specified. If you want a specific value, set it. Otherwise the
+default should be fine.
+
+Lastly, ``Hex_Encoder`` takes an argument of type ``Case``, which can
+be ``Uppercase`` or ``Lowercase`` (default is ``Uppercase``). This
+specifies what case the characters A-F should be output as. The base64
+encoder has no such option, because it uses both upper and lower case
+letters for its output.
+
+You can find the declarations for these types in ``hex_filt.h`` and
+``b64_filt.h``.
+
+Writing New Filters
+---------------------------------
+
+The system of filters and pipes was designed in an attempt to make it
+as simple as possible to write new filter types. There are four
+functions that need to be implemented by a class deriving from
+``Filter``:
+
+.. cpp:function:: std::string Filter::name() const
+
+ This should just return a useful decription of the filter object.
+
+.. cpp:function:: void Filter::write(const uint8_t* input, size_t length)
+
+ This function is what is called when a filter receives input for it
+ to process. The filter is not required to process the data right
+ away; many filters buffer their input before producing any output. A
+ filter will usually have ``write`` called many times during its
+ lifetime.
+
+.. cpp:function:: void Filter::send(uint8_t* output, size_t length)
+
+ Eventually, a filter will want to produce some output to send along
+ to the next filter in the pipeline. It does so by calling ``send``
+ with whatever it wants to send along to the next filter. There is
+ also a version of ``send`` taking a single byte argument, as a
+ convenience.
+
+ .. note::
+
+ Normally a filter does not need to override ``send``, though it
+ can for special handling. It does however need to call this
+ function whenever it wants to produce output.
+
+.. cpp:function:: void Filter::start_msg()
+
+ Implementing this function is optional. Implement it if your filter
+ would like to do some processing or setup at the start of each
+ message, such as allocating a data structure.
+
+.. cpp:function:: void Filter::end_msg()
+
+ Implementing this function is optional. It is called when it has
+ been requested that filters finish up their computations. The filter
+ should finish up with whatever computation it is working on (for
+ example, a compressing filter would flush the compressor and
+ ``send`` the final block), and empty any buffers in preparation for
+ processing a fresh new set of input.
+
+Additionally, if necessary, filters can define a constructor that
+takes any needed arguments, and a destructor to deal with deallocating
+memory, closing files, etc.
+
diff --git a/comm/third_party/botan/doc/api_ref/fpe.rst b/comm/third_party/botan/doc/api_ref/fpe.rst
new file mode 100644
index 0000000000..9d77a40864
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/fpe.rst
@@ -0,0 +1,98 @@
+Format Preserving Encryption
+========================================
+
+Format preserving encryption (FPE) refers to a set of techniques for
+encrypting data such that the ciphertext has the same format as the
+plaintext. For instance, you can use FPE to encrypt credit card
+numbers with valid checksums such that the ciphertext is also an
+credit card number with a valid checksum, or similarly for bank
+account numbers, US Social Security numbers, or even more general
+mappings like English words onto other English words.
+
+The scheme currently implemented in botan is called FE1, and described
+in the paper `Format Preserving Encryption
+<https://eprint.iacr.org/2009/251>`_ by Mihir Bellare, Thomas
+Ristenpart, Phillip Rogaway, and Till Stegers. FPE is an area of
+ongoing standardization and it is likely that other schemes will be
+included in the future.
+
+To encrypt an arbitrary value using FE1, you need to use a ranking
+method. Basically, the idea is to assign an integer to every value you
+might encrypt. For instance, a 16 digit credit card number consists of
+a 15 digit code plus a 1 digit checksum. So to encrypt a credit card
+number, you first remove the checksum, encrypt the 15 digit value
+modulo 10\ :sup:`15`, and then calculate what the checksum is for the
+new (ciphertext) number. Or, if you were encrypting words in a
+dictionary, you could rank the words by their lexicographical order,
+and choose the modulus to be the number of words in the dictionary.
+
+The interfaces for FE1 are defined in the header ``fpe_fe1.h``:
+
+.. versionadded:: 2.5.0
+
+.. cpp:class:: FPE_FE1
+
+ .. cpp:function:: FPE_FE1(const BigInt& n, size_t rounds = 5, \
+ bool compat_mode = false, \
+ std::string mac_algo = "HMAC(SHA-256)")
+
+ Initialize an FPE operation to encrypt/decrypt integers less
+ than *n*. It is expected that *n* is trivially factorable into
+ small integers. Common usage would be n to be a power of 10.
+
+ Note that the default parameters to this constructor are
+ **incompatible** with the ``fe1_encrypt`` and ``fe1_decrypt``
+ function originally added in 1.9.17. For compatibility, use
+ 3 rounds and set ``compat_mode`` to true.
+
+ .. cpp:function:: BigInt encrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const
+
+ Encrypts the value *x* modulo the value *n* using the *key* and *tweak*
+ specified. Returns an integer less than *n*. The *tweak* is a value that
+ does not need to be secret that parameterizes the encryption function. For
+ instance, if you were encrypting a database column with a single key, you
+ could use a per-row-unique integer index value as the tweak. The same
+ tweak value must be used during decryption.
+
+ .. cpp:function:: BigInt decrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const
+
+ Decrypts an FE1 ciphertext. The *tweak* must be the same as that provided
+ to the encryption function. Returns the plaintext integer.
+
+ Note that there is not any implicit authentication or checking of data in
+ FE1, so if you provide an incorrect key or tweak the result is simply a
+ random integer.
+
+ .. cpp:function:: BigInt encrypt(const BigInt& x, uint64_t tweak)
+
+ Convenience version of encrypt taking an integer tweak.
+
+ .. cpp:function:: BigInt decrypt(const BigInt& x, uint64_t tweak)
+
+ Convenience version of decrypt taking an integer tweak.
+
+There are two functions that handle the entire FE1 encrypt/decrypt operation.
+These are the original interface to FE1, first added in 1.9.17. However because
+they do the entire setup cost for each operation, they are significantly slower
+than the class-based API presented above.
+
+.. warning:: These functions are hardcoded to use 3 rounds, which may be
+ insufficient depending on the chosen modulus.
+
+.. cpp:function:: BigInt FPE::fe1_encrypt(const BigInt& n, const BigInt& X, \
+ const SymmetricKey& key, const std::vector<uint8_t>& tweak)
+
+ This creates an FPE_FE1 object, sets the key, and encrypts *X* using
+ the provided tweak.
+
+.. cpp:function:: BigInt FPE::fe1_decrypt(const BigInt& n, const BigInt& X, \
+ const SymmetricKey& key, const std::vector<uint8_t>& tweak)
+
+ This creates an FPE_FE1 object, sets the key, and decrypts *X* using
+ the provided tweak.
+
+This example encrypts a credit card number with a valid `Luhn checksum
+<https://en.wikipedia.org/wiki/Luhn_algorithm>`_ to another number with the same
+format, including a correct checksum.
+
+.. literalinclude:: ../../src/cli/cc_enc.cpp
diff --git a/comm/third_party/botan/doc/api_ref/hash.rst b/comm/third_party/botan/doc/api_ref/hash.rst
new file mode 100644
index 0000000000..6198535f3c
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/hash.rst
@@ -0,0 +1,351 @@
+Hash Functions and Checksums
+=============================
+
+Hash functions are one-way functions, which map data of arbitrary size to a
+fixed output length. Most of the hash functions in Botan are designed to be
+cryptographically secure, which means that it is computationally infeasible to
+create a collision (finding two inputs with the same hash) or preimages (given a
+hash output, generating an arbitrary input with the same hash). But note that
+not all such hash functions meet their goals, in particular MD4 and MD5 are
+trivially broken. However they are still included due to their wide adoption in
+various protocols.
+
+The class :cpp:class:`HashFunction` is defined in `botan/hash.h`.
+
+Using a hash function is typically split into three stages: initialization,
+update, and finalization (often referred to as a IUF interface). The
+initialization stage is implicit: after creating a hash function object, it is
+ready to process data. Then update is called one or more times. Calling update
+several times is equivalent to calling it once with all of the arguments
+concatenated. After completing a hash computation (eg using ``final``), the
+internal state is reset to begin hashing a new message.
+
+.. cpp:class:: HashFunction
+
+ .. cpp:function:: static std::unique_ptr<HashFunction> create(const std::string& name)
+
+ Return a newly allocated hash function object, or nullptr if the
+ name is not recognized.
+
+ .. cpp:function:: static std::unique_ptr<HashFunction> create_or_throw(const std::string& name)
+
+ Like ``create`` except that it will throw an exception instead of
+ returning nullptr.
+
+ .. cpp:function:: size_t output_length()
+
+ Return the size (in *bytes*) of the output of this function.
+
+ .. cpp:function:: void update(const uint8_t* input, size_t length)
+
+ Updates the computation with *input*.
+
+ .. cpp:function:: void update(uint8_t input)
+
+ Updates the computation with *input*.
+
+ .. cpp:function:: void update(const std::vector<uint8_t>& input)
+
+ Updates the computation with *input*.
+
+ .. cpp:function:: void update(const std::string& input)
+
+ Updates the computation with *input*.
+
+ .. cpp:function:: void final(uint8_t* out)
+
+ Finalize the calculation and place the result into ``out``.
+ For the argument taking an array, exactly ``output_length`` bytes will
+ be written. After you call ``final``, the algorithm is reset to
+ its initial state, so it may be reused immediately.
+
+ .. cpp:function:: secure_vector<uint8_t> final()
+
+ Similar to the other function of the same name, except it returns
+ the result in a newly allocated vector.
+
+ .. cpp:function:: secure_vector<uint8_t> process(const uint8_t in[], size_t length)
+
+ Equivalent to calling ``update`` followed by ``final``.
+
+ .. cpp:function:: secure_vector<uint8_t> process(const std::string& in)
+
+ Equivalent to calling ``update`` followed by ``final``.
+
+Code Example
+------------
+
+Assume we want to calculate the SHA-256, SHA-384, and SHA-3 hash digests of the STDIN stream using the Botan library.
+
+.. code-block:: cpp
+
+ #include <botan/hash.h>
+ #include <botan/hex.h>
+ #include <iostream>
+ int main ()
+ {
+ std::unique_ptr<Botan::HashFunction> hash1(Botan::HashFunction::create("SHA-256"));
+ std::unique_ptr<Botan::HashFunction> hash2(Botan::HashFunction::create("SHA-384"));
+ std::unique_ptr<Botan::HashFunction> hash3(Botan::HashFunction::create("SHA-3"));
+ std::vector<uint8_t> buf(2048);
+
+ while(std::cin.good())
+ {
+ //read STDIN to buffer
+ std::cin.read(reinterpret_cast<char*>(buf.data()), buf.size());
+ size_t readcount = std::cin.gcount();
+ //update hash computations with read data
+ hash1->update(buf.data(),readcount);
+ hash2->update(buf.data(),readcount);
+ hash3->update(buf.data(),readcount);
+ }
+ std::cout << "SHA-256: " << Botan::hex_encode(hash1->final()) << std::endl;
+ std::cout << "SHA-384: " << Botan::hex_encode(hash2->final()) << std::endl;
+ std::cout << "SHA-3: " << Botan::hex_encode(hash3->final()) << std::endl;
+ return 0;
+ }
+
+Available Hash Functions
+------------------------------
+
+The following cryptographic hash functions are implemented. If in doubt,
+any of SHA-384, SHA-3, or BLAKE2b are fine choices.
+
+BLAKE2b
+^^^^^^^^^
+
+Available if ``BOTAN_HAS_BLAKE2B`` is defined.
+
+A recently designed hash function. Very fast on 64-bit processors. Can output a
+hash of any length between 1 and 64 bytes, this is specified by passing a value
+to the constructor with the desired length.
+
+Named like "Blake2b" which selects default 512-bit output, or as
+"Blake2b(256)" to select 256 bits of output.
+
+GOST-34.11
+^^^^^^^^^^^^^^^
+
+.. deprecated:: 2.11
+
+Available if ``BOTAN_HAS_GOST_34_11`` is defined.
+
+Russian national standard hash. It is old, slow, and has some weaknesses. Avoid
+it unless you must.
+
+.. warning::
+ As this hash function is no longer approved by the latest Russian standards,
+ support for GOST 34.11 hash is deprecated and will be removed in a future
+ major release.
+
+Keccak-1600
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_KECCAK`` is defined.
+
+An older (and incompatible) variant of SHA-3, but sometimes used. Prefer SHA-3 in
+new code.
+
+MD4
+^^^^^^^^^
+
+Available if ``BOTAN_HAS_MD4`` is defined.
+
+An old hash function that is now known to be trivially breakable. It is very
+fast, and may still be suitable as a (non-cryptographic) checksum.
+
+.. warning::
+ Support for MD4 is deprecated and will be removed in a future major release.
+
+MD5
+^^^^^^^^^
+
+Available if ``BOTAN_HAS_MD5`` is defined.
+
+Widely used, now known to be broken.
+
+RIPEMD-160
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_RIPEMD160`` is defined.
+
+A 160 bit hash function, quite old but still thought to be secure (up to the
+limit of 2**80 computation required for a collision which is possible with any
+160 bit hash function). Somewhat deprecated these days.
+
+SHA-1
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SHA1`` is defined.
+
+Widely adopted NSA designed hash function. Starting to show significant signs of
+weakness, and collisions can now be generated. Avoid in new designs.
+
+SHA-256
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SHA2_32`` is defined.
+
+Relatively fast 256 bit hash function, thought to be secure.
+
+Also includes the variant SHA-224. There is no real reason to use SHA-224.
+
+SHA-512
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SHA2_64`` is defined.
+
+SHA-512 is faster than SHA-256 on 64-bit processors. Also includes the
+truncated variants SHA-384 and SHA-512/256, which have the advantage
+of avoiding message extension attacks.
+
+SHA-3
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SHA3`` is defined.
+
+The new NIST standard hash. Fairly slow.
+
+Supports 224, 256, 384 or 512 bit outputs. SHA-3 is faster with
+smaller outputs. Use as "SHA-3(256)" or "SHA-3(512)". Plain "SHA-3"
+selects default 512 bit output.
+
+SHAKE (SHAKE-128, SHAKE-256)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SHAKE`` is defined.
+
+These are actually XOFs (extensible output functions) based on SHA-3, which can
+output a value of any byte length. For example "SHAKE-128(1024)" will produce
+1024 bits of output. The specified length must be a multiple of 8. Not
+specifying an output length, "SHAKE-128" defaults to a 128-bit output and
+"SHAKE-256" defaults to a 256-bit output.
+
+.. warning::
+ In the case of SHAKE-128, the default output length in insufficient
+ to ensure security. The choice of default lengths was a bug which is
+ currently retained for compatability; they should have been 256 and
+ 512 bits resp to match SHAKE's security level. Using the default
+ lengths with SHAKE is deprecated and will be removed in a future major
+ release. Instead, always specify the desired output length.
+
+SM3
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SM3`` is defined.
+
+Chinese national hash function, 256 bit output. Widely used in industry there.
+Fast and seemingly secure, but no reason to prefer it over SHA-2 or SHA-3 unless
+required.
+
+Skein-512
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_SKEIN_512`` is defined.
+
+A contender for the NIST SHA-3 competition. Very fast on 64-bit systems. Can
+output a hash of any length between 1 and 64 bytes. It also accepts an optional
+"personalization string" which can create variants of the hash. This is useful
+for domain separation.
+
+To set a personalization string set the second param to any value,
+typically ASCII strings are used. Examples "Skein-512(256)" or
+"Skein-512(384,personalization_string)".
+
+Streebog (Streebog-256, Streebog-512)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_STREEBOG`` is defined.
+
+Newly designed Russian national hash function. Due to use of input-dependent
+table lookups, it is vulnerable to side channels. There is no reason to use it
+unless compatibility is needed.
+
+.. warning::
+ The Streebog Sbox has recently been revealed to have a hidden structure which
+ interacts with its linear layer in a way which may provide a backdoor when
+ used in certain ways. Avoid Streebog if at all possible.
+
+Tiger
+^^^^^^^^^^^^^^^
+
+.. deprecated:: 2.15
+
+Available if ``BOTAN_HAS_TIGER`` is defined.
+
+An older 192-bit hash function, optimized for 64-bit systems. Possibly
+vulnerable to side channels due to its use of table lookups.
+
+Tiger supports variable length output (16, 20 or 24 bytes) and
+variable rounds (which must be at least 3). Default is 24 byte output
+and 3 rounds. Specify with names like "Tiger" or "Tiger(20,5)".
+
+.. warning::
+ There are documented (albeit impractical) attacks on the full Tiger
+ hash leading to preimage attacks. This indicates possibility of a
+ serious weakness in the hash and for this reason it is deprecated
+ and will be removed in a future major release of the library.
+
+Whirlpool
+^^^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_WHIRLPOOL`` is defined.
+
+A 512-bit hash function standardized by ISO and NESSIE. Relatively slow, and due
+to the table based implementation it is potentially vulnerable to cache based
+side channels.
+
+Hash Function Combiners
+---------------------------
+
+These are functions which combine multiple hash functions to create a new hash
+function. They are typically only used in specialized applications.
+
+Parallel
+^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_PARALLEL_HASH`` is defined.
+
+Parallel simply concatenates multiple hash functions. For example
+"Parallel(SHA-256,SHA-512)" outputs a 256+512 bit hash created by hashing the
+input with both SHA-256 and SHA-512 and concatenating the outputs.
+
+Note that due to the "multicollision attack" it turns out that generating a
+collision for multiple parallel hash functions is no harder than generating a
+collision for the strongest hash function.
+
+Comp4P
+^^^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_COMB4P`` is defined.
+
+This combines two cryptographic hashes in such a way that preimage and collision
+attacks are provably at least as hard as a preimage or collision attack on the
+strongest hash.
+
+Checksums
+----------------
+
+.. note:: Checksums are not suitable for cryptographic use, but can be used for
+ error checking purposes.
+
+Adler32
+^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_ADLER32`` is defined.
+
+The Adler32 checksum is used in the zlib format. 32 bit output.
+
+CRC24
+^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_CRC24`` is defined.
+
+This is the CRC function used in OpenPGP. 24 bit output.
+
+CRC32
+^^^^^^^^^^^
+
+Available if ``BOTAN_HAS_CRC32`` is defined.
+
+This is the 32-bit CRC used in protocols such as Ethernet, gzip, PNG, etc.
diff --git a/comm/third_party/botan/doc/api_ref/kdf.rst b/comm/third_party/botan/doc/api_ref/kdf.rst
new file mode 100644
index 0000000000..f0975a8cc3
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/kdf.rst
@@ -0,0 +1,109 @@
+
+.. _key_derivation_function:
+
+Key Derivation Functions
+========================================
+
+Key derivation functions are used to turn some amount of shared secret
+material into uniform random keys suitable for use with symmetric
+algorithms. An example of an input which is useful for a KDF is a
+shared secret created using Diffie-Hellman key agreement.
+
+.. cpp:class:: KDF
+
+ .. cpp:function:: secure_vector<uint8_t> derive_key( \
+ size_t key_len, const std::vector<uint8_t>& secret, \
+ const std::string& salt = "") const
+
+ .. cpp:function:: secure_vector<uint8_t> derive_key( \
+ size_t key_len, const std::vector<uint8_t>& secret, \
+ const std::vector<uint8_t>& salt) const
+
+ .. cpp:function:: secure_vector<uint8_t> derive_key( \
+ size_t key_len, const std::vector<uint8_t>& secret, \
+ const uint8_t* salt, size_t salt_len) const
+
+ .. cpp:function:: secure_vector<uint8_t> derive_key( \
+ size_t key_len, const uint8_t* secret, size_t secret_len, \
+ const std::string& salt) const
+
+ All variations on the same theme. Deterministically creates a
+ uniform random value from *secret* and *salt*. Typically *salt* is
+ a label or identifier, such as a session id.
+
+You can create a :cpp:class:`KDF` using
+
+.. cpp:function:: KDF* get_kdf(const std::string& algo_spec)
+
+
+Available KDFs
+-------------------
+
+Botan includes many different KDFs simply because different protocols and
+standards have created subtly different approaches to this problem. For new
+code, use HKDF which is conservative, well studied, widely implemented and NIST
+approved.
+
+HKDF
+~~~~~
+
+Defined in RFC 5869, HKDF uses HMAC to process inputs. Also available
+are variants HKDF-Extract and HKDF-Expand. HKDF is the combined
+Extract+Expand operation. Use the combined HKDF unless you need
+compatibility with some other system.
+
+Available if ``BOTAN_HAS_HKDF`` is defined.
+
+KDF2
+~~~~~
+
+KDF2 comes from IEEE 1363. It uses a hash function.
+
+Available if ``BOTAN_HAS_KDF2`` is defined.
+
+KDF1-18033
+~~~~~~~~~~~~
+
+KDF1 from ISO 18033-2. Very similar to (but incompatible with) KDF2.
+
+Available if ``BOTAN_HAS_KDF1_18033`` is defined.
+
+KDF1
+~~~~~~
+
+KDF1 from IEEE 1363. It can only produce an output at most the length
+of the hash function used.
+
+Available if ``BOTAN_HAS_KDF1`` is defined.
+
+X9.42 PRF
+~~~~~~~~~~
+
+A KDF from ANSI X9.42. Sometimes used for Diffie-Hellman.
+
+Available if ``BOTAN_HAS_X942_PRF`` is defined.
+
+.. warning::
+ Support for X9.42 KDF is deprecated and will be removed in a future major release.
+
+SP800-108
+~~~~~~~~~~
+
+KDFs from NIST SP 800-108. Variants include "SP800-108-Counter",
+"SP800-108-Feedback" and "SP800-108-Pipeline".
+
+Available if ``BOTAN_HAS_SP800_108`` is defined.
+
+SP800-56A
+~~~~~~~~~~
+
+KDF from NIST SP 800-56A.
+
+Available if ``BOTAN_HAS_SP800_56A`` is defined.
+
+SP800-56C
+~~~~~~~~~~
+
+KDF from NIST SP 800-56C.
+
+Available if ``BOTAN_HAS_SP800_56C`` is defined.
diff --git a/comm/third_party/botan/doc/api_ref/keywrap.rst b/comm/third_party/botan/doc/api_ref/keywrap.rst
new file mode 100644
index 0000000000..5c3aac0a3e
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/keywrap.rst
@@ -0,0 +1,60 @@
+AES Key Wrapping
+=================================
+
+NIST specifies two mechanisms for wrapping (encrypting) symmetric keys using
+another key. The first (and older, more widely supported) method requires the
+input be a multiple of 8 bytes long. The other allows any length input, though
+only up to 2**32 bytes.
+
+These algorithms are described in NIST SP 800-38F, and RFCs 3394 and 5649.
+
+This API, defined in ``nist_keywrap.h``, first became available in version 2.4.0
+
+These functions take an arbitrary 128-bit block cipher object, which must
+already have been keyed with the key encryption key. NIST only allows these
+functions with AES, but any 128-bit cipher will do and some other implementations
+(such as in OpenSSL) do also allow other ciphers. Use AES for best interop.
+
+.. cpp:function:: std::vector<uint8_t> nist_key_wrap(const uint8_t input[], \
+ size_t input_len, const BlockCipher& bc)
+
+ This performs KW (key wrap) mode. The input must be a multiple of 8 bytes long.
+
+.. cpp:function:: secure_vector<uint8_t> nist_key_unwrap(const uint8_t input[], \
+ size_t input_len, const BlockCipher& bc)
+
+ This unwraps the result of nist_key_wrap, or throw Invalid_Authentication_Tag on error.
+
+.. cpp:function:: std::vector<uint8_t> nist_key_wrap_padded(const uint8_t input[], \
+ size_t input_len, const BlockCipher& bc)
+
+ This performs KWP (key wrap with padding) mode. The input can be any length.
+
+.. cpp:function:: secure_vector<uint8_t> nist_key_unwrap_padded(const uint8_t input[], \
+ size_t input_len, const BlockCipher& bc)
+
+ This unwraps the result of nist_key_wrap_padded, or throws Invalid_Authentication_Tag
+ on error.
+
+RFC 3394 Interface
+-----------------------------
+
+This is an older interface that was first available (with slight changes) in
+1.10, and available in its current form since 2.0 release. It uses a 128-bit,
+192-bit, or 256-bit key to encrypt an input key. AES is always used. The input
+must be a multiple of 8 bytes; if not an exception is thrown.
+
+This interface is defined in ``rfc3394.h``.
+
+.. cpp:function:: secure_vector<uint8_t> rfc3394_keywrap(const secure_vector<uint8_t>& key, \
+ const SymmetricKey& kek)
+
+ Wrap the input key using kek (the key encryption key), and return the result. It will
+ be 8 bytes longer than the input key.
+
+.. cpp:function:: secure_vector<uint8_t> rfc3394_keyunwrap(const secure_vector<uint8_t>& key, \
+ const SymmetricKey& kek)
+
+ Unwrap a key wrapped with rfc3394_keywrap.
+
+
diff --git a/comm/third_party/botan/doc/api_ref/message_auth_codes.rst b/comm/third_party/botan/doc/api_ref/message_auth_codes.rst
new file mode 100644
index 0000000000..a3391a3105
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/message_auth_codes.rst
@@ -0,0 +1,268 @@
+
+.. _mac:
+
+Message Authentication Codes (MAC)
+===================================
+
+A Message Authentication Code algorithm computes a tag over a message utilizing
+a shared secret key. Thus a valid tag confirms the authenticity and integrity of
+the message. Only entities in possession of the shared secret key are able to
+verify the tag.
+
+.. note::
+
+ When combining a MAC with unauthenticated encryption mode, prefer to first
+ encrypt the message and then MAC the ciphertext. The alternative is to MAC
+ the plaintext, which depending on exact usage can suffer serious security
+ issues. For a detailed discussion of this issue see the paper "The Order of
+ Encryption and Authentication for Protecting Communications" by Hugo
+ Krawczyk
+
+The Botan MAC computation is split into five stages.
+
+#. Instantiate the MAC algorithm.
+#. Set the secret key.
+#. Process IV.
+#. Process data.
+#. Finalize the MAC computation.
+
+.. cpp:class:: MessageAuthenticationCode
+
+ .. cpp:function:: std::string name() const
+
+ Returns a human-readable string of the name of this algorithm.
+
+ .. cpp:function:: void clear()
+
+ Clear the key.
+
+ .. cpp:function:: MessageAuthenticationCode* clone() const
+
+ Return a newly allocated object of the same type as this one.
+
+ .. cpp:function:: void set_key(const uint8_t* key, size_t length)
+
+ Set the shared MAC key for the calculation. This function has to be called before the data is processed.
+
+ .. cpp:function:: bool valid_keylength(size_t length) const
+
+ This function returns true if and only if *length* is a valid
+ keylength for the algorithm.
+
+ .. cpp:function:: size_t minimum_keylength() const
+
+ Return the smallest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len)
+
+ Set the IV for the MAC calculation. Note that not all MAC algorithms require an IV.
+ If an IV is required, the function has to be called before the data is processed.
+ For algorithms that don't require it, the call can be omitted, or else called
+ with ``nonce_len`` of zero.
+
+ .. cpp:function:: void update(const uint8_t* input, size_t length)
+
+ Process the passed data.
+
+ .. cpp:function:: void update(const secure_vector<uint8_t>& in)
+
+ Process the passed data.
+
+ .. cpp:function:: void update(uint8_t in)
+
+ Process a single byte.
+
+ .. cpp:function:: void final(uint8_t* out)
+
+ Complete the MAC computation and write the calculated tag to the passed byte array.
+
+ .. cpp:function:: secure_vector<uint8_t> final()
+
+ Complete the MAC computation and return the calculated tag.
+
+ .. cpp:function:: bool verify_mac(const uint8_t* mac, size_t length)
+
+ Finalize the current MAC computation and compare the result to the passed
+ ``mac``. Returns ``true``, if the verification is successful and false
+ otherwise.
+
+
+Code Examples
+------------------------
+
+The following example computes an HMAC with a random key then verifies the tag.
+
+ #include <botan/mac.h>
+ #include <botan/hex.h>
+ #include <botan/system_rng.h>
+ #include <assert.h>
+
+ std::string compute_mac(const std::string& msg, const Botan::secure_vector<uint8_t>& key)
+ {
+ auto hmac = Botan::MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)");
+
+ hmac->set_key(key);
+ hmac->update(msg);
+
+ return Botan::hex_encode(hmac->final());
+ }
+
+ int main()
+ {
+ Botan::System_RNG rng;
+
+ const auto key = rng.random_vec(32); // 256 bit random key
+
+ // "Message" != "Mussage" so tags will also not match
+ std::string tag1 = compute_mac("Message", key);
+ std::string tag2 = compute_mac("Mussage", key);
+ assert(tag1 != tag2);
+
+ // Recomputing with original input message results in identical tag
+ std::string tag3 = compute_mac("Message", key);
+ assert(tag1 == tag3);
+ }
+
+
+The following example code computes a AES-256 GMAC and subsequently verifies the
+tag. Unlike most other MACs, GMAC requires a nonce *which must not repeat or
+all security is lost*.
+
+.. code-block:: cpp
+
+ #include <botan/mac.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ const std::vector<uint8_t> key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337");
+ const std::vector<uint8_t> nonce = Botan::hex_decode("FFFFFFFFFFFFFFFFFFFFFFFF");
+ const std::vector<uint8_t> data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A");
+ std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create("GMAC(AES-256)"));
+ if(!mac)
+ return 1;
+ mac->set_key(key);
+ mac->start(nonce);
+ mac->update(data);
+ Botan::secure_vector<uint8_t> tag = mac->final();
+ std::cout << mac->name() << ": " << Botan::hex_encode(tag) << std::endl;
+
+ //Verify created MAC
+ mac->start(nonce);
+ mac->update(data);
+ std::cout << "Verification: " << (mac->verify_mac(tag) ? "success" : "failure");
+ return 0;
+ }
+
+The following example code computes a valid AES-128 CMAC tag and modifies the
+data to demonstrate a MAC verification failure.
+
+.. code-block:: cpp
+
+ #include <botan/mac.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C");
+ std::vector<uint8_t> data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A");
+ std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create("CMAC(AES-128)"));
+ if(!mac)
+ return 1;
+ mac->set_key(key);
+ mac->update(data);
+ Botan::secure_vector<uint8_t> tag = mac->final();
+ //Corrupting data
+ data.back()++;
+ //Verify with corrupted data
+ mac->update(data);
+ std::cout << "Verification with malformed data: " << (mac->verify_mac(tag) ? "success" : "failure");
+ return 0;
+ }
+
+Available MACs
+------------------------------------------
+
+Currently the following MAC algorithms are available in Botan. In new code,
+default to HMAC with a strong hash like SHA-256 or SHA-384.
+
+CBC-MAC
+~~~~~~~~~~~~
+
+An older authentication code based on a block cipher. Serious security problems,
+in particular **insecure** if messages of several different lengths are
+authenticated. Avoid unless required for compatibility.
+
+Available if ``BOTAN_HAS_CBC_MAC`` is defined.
+
+.. warning::
+ CBC-MAC support is deprecated and will be removed in a future major release.
+
+CMAC
+~~~~~~~~~~~~
+
+A modern CBC-MAC variant that avoids the security problems of plain CBC-MAC.
+Approved by NIST. Also sometimes called OMAC.
+
+Available if ``BOTAN_HAS_CMAC`` is defined.
+
+GMAC
+~~~~~~~~~~~~
+
+GMAC is related to the GCM authenticated cipher mode. It is quite slow unless
+hardware support for carryless multiplications is available. A new nonce
+must be used with **each** message authenticated, or otherwise all security is
+lost.
+
+Available if ``BOTAN_HAS_GMAC`` is defined.
+
+.. warning::
+ Due to the nonce requirement, GMAC is exceptionally fragile. Avoid it unless
+ absolutely required.
+
+HMAC
+~~~~~~~~~~~~
+
+A message authentication code based on a hash function. Very commonly used.
+
+Available if ``BOTAN_HAS_HMAC`` is defined.
+
+Poly1305
+~~~~~~~~~~~~
+
+A polynomial mac (similar to GMAC). Very fast, but tricky to use safely. Forms
+part of the ChaCha20Poly1305 AEAD mode. A new key must be used for **each**
+message, or all security is lost.
+
+Available if ``BOTAN_HAS_POLY1305`` is defined.
+
+.. warning::
+ Due to the nonce requirement, Poly1305 is exceptionally fragile. Avoid it unless
+ absolutely required.
+
+SipHash
+~~~~~~~~~~~~
+
+A modern and very fast PRF. Produces only a 64-bit output. Defaults to
+"SipHash(2,4)" which is the recommended configuration, using 2 rounds for each
+input block and 4 rounds for finalization.
+
+Available if ``BOTAN_HAS_SIPHASH`` is defined.
+
+X9.19-MAC
+~~~~~~~~~~~~
+
+A CBC-MAC variant sometimes used in finance. Always uses DES.
+Sometimes called the "DES retail MAC", also standardized in ISO 9797-1.
+
+It is slow and has known attacks. Avoid unless required.
+
+Available if ``BOTAN_HAS_X919_MAC`` is defined.
diff --git a/comm/third_party/botan/doc/api_ref/otp.rst b/comm/third_party/botan/doc/api_ref/otp.rst
new file mode 100644
index 0000000000..133201b4e6
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/otp.rst
@@ -0,0 +1,98 @@
+One Time Passwords
+========================
+
+.. versionadded:: 2.2.0
+
+One time password schemes are a user authentication method that relies on a
+fixed secret key which is used to derive a sequence of short passwords, each of
+which is accepted only once. Commonly this is used to implement two-factor
+authentication (2FA), where the user authenticates using both a conventional
+password (or a public key signature) and an OTP generated by a small device such
+as a mobile phone.
+
+Botan implements the HOTP and TOTP schemes from RFC 4226 and 6238.
+
+Since the range of possible OTPs is quite small, applications must rate limit
+OTP authentication attempts to some small number per second. Otherwise an attacker
+could quickly try all 1000000 6-digit OTPs in a brief amount of time.
+
+HOTP
+^^^^^^
+
+HOTP generates OTPs that are a short numeric sequence, between 6 and 8 digits
+(most applications use 6 digits), created using the HMAC of a 64-bit counter
+value. If the counter ever repeats the OTP will also repeat, thus both parties
+must assure the counter only increments and is never repeated or
+decremented. Thus both client and server must keep track of the next counter
+expected.
+
+Anyone with access to the client-specific secret key can authenticate as that
+client, so it should be treated with the same security consideration as would be
+given to any other symmetric key or plaintext password.
+
+.. cpp:class:: HOTP
+
+ Implement counter-based OTP
+
+ .. cpp:function:: HOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", size_t digits = 6)
+
+ Initialize an HOTP instance with a secret key (specific to each client),
+ a hash algorithm (must be SHA-1, SHA-256, or SHA-512), and the number of
+ digits with each OTP (must be 6, 7, or 8).
+
+ In RFC 4226, HOTP is only defined with SHA-1, but many HOTP
+ implementations support SHA-256 as an extension. The collision attacks
+ on SHA-1 do not have any known effect on HOTP's security.
+
+ .. cpp:function:: uint32_t generate_hotp(uint64_t counter)
+
+ Return the OTP associated with a specific counter value.
+
+ .. cpp:function:: std::pair<bool,uint64_t> verify_hotp(uint32_t otp, \
+ uint64_t starting_counter, size_t resync_range = 0)
+
+ Check if a provided OTP matches the one that should be generated for
+ the specified counter.
+
+ The *starting_counter* should be the counter of the last successful
+ authentication plus 1. If *resync_resync* is greater than 0, some number
+ of counter values above *starting_counter* will also be checked if
+ necessary. This is useful for instance when a client mistypes an OTP on
+ entry; the authentication will fail so the server will not update its
+ counter, but the client device will subsequently show the OTP for the
+ next counter. Depending on the environment a *resync_range* of 3 to 10
+ might be appropriate.
+
+ Returns a pair of (is_valid,next_counter_to_use). If the OTP is invalid
+ then always returns (false,starting_counter), since the last successful
+ authentication counter has not changed.
+
+
+TOTP
+^^^^^^^^^^
+
+TOTP is based on the same algorithm as HOTP, but instead of a counter a
+timestamp is used.
+
+.. cpp:class:: TOTP
+
+ .. cpp:function:: TOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", \
+ size_t digits = 6, size_t time_step = 30)
+
+ Setup to perform TOTP authentication using secret key *key*.
+
+ .. cpp:function:: uint32_t generate_totp(std::chrono::system_clock::time_point time_point)
+
+ .. cpp:function:: uint32_t generate_totp(uint64_t unix_time)
+
+ Generate and return a TOTP code based on a timestamp.
+
+ .. cpp:function:: bool verify_totp(uint32_t otp, std::chrono::system_clock::time_point time, \
+ size_t clock_drift_accepted = 0)
+
+ .. cpp:function:: bool verify_totp(uint32_t otp, uint64_t unix_time, \
+ size_t clock_drift_accepted = 0)
+
+ Return true if the provided OTP code is correct for the provided
+ timestamp. If required, use *clock_drift_accepted* to deal with
+ the client and server having slightly different clocks.
diff --git a/comm/third_party/botan/doc/api_ref/passhash.rst b/comm/third_party/botan/doc/api_ref/passhash.rst
new file mode 100644
index 0000000000..4ef26f7bea
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/passhash.rst
@@ -0,0 +1,219 @@
+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 authenticating party 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 effectiveness of offline dictionary generation, because for
+each potential password, an attacker would have to compute the one way
+function output for all possible salts. It also prevents the same
+password from producing the same output, as long as the salts do not
+collide. Choosing n-bit salts randomly, salt collisions become likely
+only after about 2\ :sup:\ `(n/2)` salts have been generated. Choosing a
+large salt (say 80 to 128 bits) ensures this is very unlikely. Note
+that in password hashing salt collisions are unfortunate, but not
+fatal - it simply allows the attacker to attack those two passwords in
+parallel easier than they would otherwise be able to.
+
+The other approach, 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).
+
+Memory usage while checking a password is also a consideration; if the
+computation requires using a certain minimum amount of memory, then an
+attacker can become memory-bound, which may in particular make
+customized cracking hardware more expensive. Some password hashing
+designs, such as scrypt, explicitly attempt to provide this. The
+bcrypt approach requires over 4 KiB of RAM (for the Blowfish key
+schedule) and may also make some hardware attacks more expensive.
+
+Botan provides three techniques for password hashing: Argon2, bcrypt, and
+passhash9 (based on PBKDF2).
+
+Argon2
+----------------------------------------
+
+.. versionadded:: 2.11.0
+
+Argon2 is the winner of the PHC (Password Hashing Competition) and provides
+a tunable memory hard password hash. It has a standard string encoding, which looks like::
+
+ "$argon2i$v=19$m=8192,t=10,p=3$YWFhYWFhYWE$itkWB9ODqTd85wUsoib7pfpVTNGMOu0ZJan1odl25V8"
+
+Argon2 has three tunable parameters: ``M``, ``p``, and ``t``. ``M`` gives the
+total memory consumption of the algorithm in kilobytes. Increasing ``p``
+increases the available parallelism of the computation. The ``t`` parameter
+gives the number of passes which are made over the data.
+
+.. note::
+ Currently Botan does not make use of ``p`` > 1, so it is best to set it to 1
+ to minimize any advantage to highly parallel cracking attempts.
+
+There are three variants of Argon2, namely Argon2d, Argon2i and Argon2id.
+Argon2d uses data dependent table lookups with may leak information about the
+password via side channel attacks, and is **not recommended** for password
+hashing. Argon2i uses data independent table lookups and is immune to these
+attacks, but at the cost of requiring higher ``t`` for security. Argon2id uses a
+hybrid approach which is thought to be highly secure. The algorithm designers
+recommend using Argon2id with ``t`` and ``p`` both equal to 1 and ``M`` set to
+the largest amount of memory usable in your environment.
+
+.. cpp:function:: std::string argon2_generate_pwhash(const char* password, size_t password_len, \
+ RandomNumberGenerator& rng, \
+ size_t p, size_t M, size_t t, \
+ size_t y = 2, size_t salt_len = 16, size_t output_len = 32)
+
+ Generate an Argon2 hash of the specified password. The ``y`` parameter specifies
+ the variant: 0 for Argon2d, 1 for Argon2i, and 2 for Argon2id.
+
+.. cpp:function:: bool argon2_check_pwhash(const char* password, size_t password_len, \
+ const std::string& hash)
+
+ Verify an Argon2 password hash against the provided password. Returns false if
+ the input hash seems malformed or if the computed hash does not match.
+
+Bcrypt
+----------------------------------------
+
+`Bcrypt <https://www.usenix.org/legacy/event/usenix99/provos/provos.pdf>`_ is a
+password hashing scheme originally designed for use in OpenBSD, but numerous
+other implementations exist. It is made available by including ``bcrypt.h``.
+
+It has the advantage that it requires a small amount (4K) of fast RAM
+to compute, which can make hardware password cracking somewhat more
+expensive.
+
+Bcrypt provides outputs that look like this::
+
+ "$2a$12$7KIYdyv8Bp32WAvc.7YvI.wvRlyVn0HP/EhPmmOyMQA4YKxINO0p2"
+
+.. note::
+
+ Due to the design of bcrypt, the password is effectively truncated at 72
+ characters; further characters are ignored and do not change the hash. To
+ support longer passwords, one common approach is to pre-hash the password
+ with SHA-256, then run bcrypt using the hex or base64 encoding of the hash as
+ the password. (Many bcrypt implementations truncate the password at the first
+ NULL character, so hashing the raw binary SHA-256 may cause problems. Botan's
+ bcrypt implementation will hash whatever values are given in the
+ ``std::string`` including any embedded NULLs so this is not an issue, but
+ might cause interop problems if another library needs to validate the
+ password hashes.)
+
+.. cpp:function:: std::string generate_bcrypt(const std::string& password, \
+ RandomNumberGenerator& rng, \
+ uint16_t work_factor = 12, \
+ char bcrypt_version = "a")
+
+ Takes the password to hash, a rng, and a work factor.
+ The resulting password hash is returned as a string.
+
+ Higher work factors increase the amount of time the algorithm runs,
+ increasing the cost of cracking attempts. The increase is exponential, so a
+ work factor of 12 takes roughly twice as long as work factor 11. The default
+ work factor was set to 10 up until the 2.8.0 release.
+
+ It is recommended to set the work factor as high as your system can tolerate
+ (from a performance and latency perspective) since higher work factors greatly
+ improve the security against GPU-based attacks. For example, for protecting
+ high value administrator passwords, consider using work factor 15 or 16; at
+ these work factors each bcrypt computation takes several seconds. Since admin
+ logins will be relatively uncommon, it might be acceptable for each login
+ attempt to take some time. As of 2018, a good password cracking rig (with 8
+ NVIDIA 1080 cards) can attempt about 1 billion bcrypt computations per month
+ for work factor 13. For work factor 12, it can do twice as many. For work
+ factor 15, it can do only one quarter as many attempts.
+
+ Due to bugs affecting various implementations of bcrypt, several different
+ variants of the algorithm are defined. As of 2.7.0 Botan supports generating
+ (or checking) the 2a, 2b, and 2y variants. Since Botan has never been
+ affected by any of the bugs which necessitated these version upgrades, all
+ three versions are identical beyond the version identifier. Which variant to
+ use is controlled by the ``bcrypt_version`` argument.
+
+ The bcrypt work factor must be at least 4 (though at this work factor bcrypt
+ is not very secure). The bcrypt format allows up to 31, but Botan currently
+ rejects all work factors greater than 18 since even that work factor requires
+ roughly 15 seconds of computation on a fast machine.
+
+.. cpp:function:: bool check_bcrypt(const std::string& password, \
+ const std::string& hash)
+
+ Takes a password and a bcrypt output and returns true if the
+ password is the same as the one that was used to generate the
+ bcrypt hash.
+
+.. _passhash9:
+
+Passhash9
+----------------------------------------
+
+Botan also provides a password hashing technique called passhash9, in
+``passhash9.h``, which is based on PBKDF2.
+
+Passhash9 hashes look like::
+
+ "$9$AAAKxwMGNPSdPkOKJS07Xutm3+1Cr3ytmbnkjO6LjHzCMcMQXvcT"
+
+This function should be secure with the proper parameters, and will remain in
+the library for the foreseeable future, but it is specific to Botan rather than
+being a widely used password hash. Prefer bcrypt or Argon2.
+
+.. warning::
+
+ This password format string ("$9$") conflicts with the format used
+ for scrypt password hashes on Cisco systems.
+
+.. cpp:function:: std::string generate_passhash9(const std::string& password, \
+ RandomNumberGenerator& rng, uint16_t work_factor = 15, uint8_t alg_id = 4)
+
+ Functions much like ``generate_bcrypt``. The last parameter,
+ ``alg_id``, specifies which PRF to use. Currently defined values are
+ 0: HMAC(SHA-1), 1: HMAC(SHA-256), 2: CMAC(Blowfish), 3: HMAC(SHA-384), 4: HMAC(SHA-512)
+
+ The work factor must be greater than zero and less than 512. This performs
+ 10000 * ``work_factor`` PBKDF2 iterations, using 96 bits of salt taken from
+ ``rng``. Using work factor of 10 or more is recommended.
+
+.. cpp:function:: bool check_passhash9(const std::string& password, \
+ const std::string& hash)
+
+ Functions much like ``check_bcrypt``
diff --git a/comm/third_party/botan/doc/api_ref/pbkdf.rst b/comm/third_party/botan/doc/api_ref/pbkdf.rst
new file mode 100644
index 0000000000..92f59f2780
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/pbkdf.rst
@@ -0,0 +1,190 @@
+
+.. _pbkdf:
+
+Password Based Key Derivation
+========================================
+
+Often one needs to convert a human readable password into a cryptographic
+key. It is useful to slow down the computation of these computations in order to
+reduce the speed of brute force search, thus they are parameterized in some
+way which allows their required computation to be tuned.
+
+PBKDF
+---------
+
+:cpp:class:`PBKDF` is the older API for this functionality, presented in header
+``pbkdf.h``. It does not support Scrypt, nor will it be able to support other
+future hashes (such as Argon2) that may be added in the future. In addition,
+this API requires the passphrase be entered as a ``std::string``, which means
+the secret will be stored in memory that will not be zeroed.
+
+.. cpp:class:: PBKDF
+
+ .. cpp:function:: void pbkdf_iterations(uint8_t out[], size_t out_len, \
+ const std::string& passphrase, \
+ const uint8_t salt[], size_t salt_len, \
+ size_t iterations) const
+
+ Run the PBKDF algorithm for the specified number of iterations,
+ with the given salt, and write output to the buffer.
+
+ .. cpp:function:: void pbkdf_timed(uint8_t out[], size_t out_len, \
+ const std::string& passphrase, \
+ const uint8_t salt[], size_t salt_len, \
+ std::chrono::milliseconds msec, \
+ size_t& iterations) const
+
+ Choose (via short run-time benchmark) how many iterations to perform
+ in order to run for roughly msec milliseconds. Writes the number
+ of iterations used to reference argument.
+
+ .. cpp:function:: OctetString derive_key( \
+ size_t output_len, const std::string& passphrase, \
+ const uint8_t* salt, size_t salt_len, \
+ size_t iterations) const
+
+ Computes a key from *passphrase* and the *salt* (of length
+ *salt_len* bytes) using an algorithm-specific interpretation of
+ *iterations*, producing a key of length *output_len*.
+
+ Use an iteration count of at least 10000. The salt should be
+ randomly chosen by a good random number generator (see
+ :ref:`random_number_generators` for how), or at the very least
+ unique to this usage of the passphrase.
+
+ If you call this function again with the same parameters, you will
+ get the same key.
+
+PasswordHash
+--------------
+
+.. versionadded:: 2.8.0
+
+This API has two classes, one representing the algorithm (such as
+"PBKDF2(SHA-256)", or "Scrypt") and the other representing a specific instance
+of the problem which is fully specified (say "Scrypt" with N=8192,r=64,p=8).
+
+.. cpp:class:: PasswordHash
+
+ .. cpp:function:: void derive_key(uint8_t out[], size_t out_len, \
+ const char* password, const size_t password_len, \
+ const uint8_t salt[], size_t salt_len) const
+
+ Derive a key, placing it into output
+
+ .. cpp:function:: std::string to_string() const
+
+ Return a descriptive string including the parameters (iteration count, etc)
+
+The ``PasswordHashFamily`` creates specific instances of ``PasswordHash``:
+
+.. cpp:class:: PasswordHashFamily
+
+ .. cpp:function:: static std::unique_ptr<PasswordHashFamily> create(const std::string& what)
+
+ For example "PBKDF2(SHA-256)", "Scrypt", "OpenPGP-S2K(SHA-384)". Returns
+ null if not available.
+
+ .. cpp:function:: std::unique_ptr<PasswordHash> default_params() const
+
+ Create a default instance of the password hashing algorithm. Be warned the
+ value returned here may change from release to release.
+
+ .. cpp:function:: std::unique_ptr<PasswordHash> tune(size_t output_len, std::chrono::milliseconds msec) const
+
+ Return a password hash instance tuned to run for approximately ``msec``
+ milliseconds when producing an output of length ``output_len``. (Accuracy
+ may vary, use the command line utility ``botan pbkdf_tune`` to check.)
+
+ .. cpp:function:: std::unique_ptr<PasswordHash> from_params( \
+ size_t i1, size_t i2 = 0, size_t i3 = 0) const
+
+ Create a password hash using some scheme specific format.
+ Eg PBKDF2 and PGP-S2K set iterations in i1
+ Scrypt uses N,r,p in i{1-3}
+ Bcrypt-PBKDF just has iterations
+ Argon2{i,d,id} would use iterations, memory, parallelism for i{1-3}, and Argon2 type is part of the family.
+
+ Values not needed should be set to 0.
+
+Available Schemes
+----------------------
+
+PBKDF2
+^^^^^^^^^^^^
+
+PBKDF2 is the "standard" password derivation scheme, widely implemented in many
+different libraries. It uses HMAC internally.
+
+Scrypt
+^^^^^^^^^^
+
+Scrypt is a relatively newer design which is "memory hard" - in
+addition to requiring large amounts of CPU power it uses a large block
+of memory to compute the hash. This makes brute force attacks using
+ASICs substantially more expensive.
+
+Scrypt is not supported through :cpp:class:`PBKDF`, only :cpp:class:`PasswordHash`,
+starting in 2.8.0. In addition, starting in version 2.7.0, scrypt is available
+with this function:
+
+.. cpp:function:: void scrypt(uint8_t output[], size_t output_len, \
+ const std::string& password, \
+ const uint8_t salt[], size_t salt_len, \
+ size_t N, size_t r, size_t p)
+
+ Computes the Scrypt using the password and salt, and produces an output
+ of arbitrary length.
+
+ The N, r, p parameters control how much work and memory Scrypt
+ uses. N is the primary control of the workfactor, and must be a
+ power of 2. For interactive logins use 32768, for protection of
+ secret keys or backups use 1048576.
+
+ The r parameter controls how 'wide' the internal hashing operation
+ is. It also increases the amount of memory that is used. Values
+ from 1 to 8 are reasonable.
+
+ Setting p parameter to greater than one splits up the work in a way
+ that up to p processors can work in parallel.
+
+ As a general recommendation, use N=32768, r=8, p=1
+
+Argon2
+^^^^^^^^^^
+
+.. versionadded:: 2.11.0
+
+Argon2 is the winner of the PHC (Password Hashing Competition) and
+provides a tunable memory hard PBKDF.
+
+OpenPGP S2K
+^^^^^^^^^^^^
+
+.. warning::
+
+ The OpenPGP algorithm is weak and strange, and should be avoided unless
+ implementing OpenPGP.
+
+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.
+
+PBKDF1
+^^^^^^^^^^^^
+
+PBKDF1 is an old scheme that can only produce an output length at most
+as long as the hash function. It is deprecated and will be removed in
+a future release. It is not supported through :cpp:class:`PasswordHash`.
diff --git a/comm/third_party/botan/doc/api_ref/pkcs11.rst b/comm/third_party/botan/doc/api_ref/pkcs11.rst
new file mode 100644
index 0000000000..9e0ddfa679
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/pkcs11.rst
@@ -0,0 +1,1419 @@
+.. _pkcs11:
+
+PKCS#11
+========================================
+
+.. versionadded:: 1.11.31
+
+|
+
+PKCS#11 is a platform-independent interface for accessing smart cards and
+hardware security modules (HSM). Vendors of PKCS#11 compatible devices usually
+provide a so called middleware or "PKCS#11 module" which implements the PKCS#11
+standard. This middleware translates calls from the platform-independent PKCS#11
+API to device specific calls. So application developers don't have to write smart card
+or HSM specific code for each device they want to support.
+
+ .. note::
+
+ The Botan PKCS#11 interface is implemented against version v2.40 of the standard.
+
+Botan wraps the C PKCS#11 API to provide a C++ PKCS#11 interface. This is done
+in two levels of abstraction: a low level API (see :ref:`pkcs11_low_level`) and
+a high level API (see :ref:`pkcs11_high_level`). The low level API provides
+access to all functions that are specified by the standard. The high level API
+represents an object oriented approach to use PKCS#11 compatible devices but
+only provides a subset of the functions described in the standard.
+
+To use the PKCS#11 implementation the ``pkcs11`` module has to be enabled.
+
+ .. note::
+
+ Both PKCS#11 APIs live in the namespace ``Botan::PKCS11``
+
+.. _pkcs11_low_level:
+
+Low Level API
+----------------------------------------
+
+The PKCS#11 standards committee provides header files (``pkcs11.h``, ``pkcs11f.h`` and
+``pkcs11t.h``) which define the PKCS#11 API in the C programming language. These
+header files could be used directly to access PKCS#11 compatible smart cards or
+HSMs. The external header files are shipped with Botan in version v2.4 of the standard. The PKCS#11 low
+level API wraps the original PKCS#11 API, but still allows to access all functions described in the
+standard and has the advantage that it is a C++ interface with features like RAII, exceptions
+and automatic memory management.
+
+The low level API is implemented by the :cpp:class:`LowLevel` class and can be accessed by
+including the header ``botan/p11.h``.
+
+Preface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+All constants that belong together in the PKCS#11 standard are grouped into C++
+enum classes. For example the different user types are grouped in the
+:cpp:enum:`UserType` enumeration:
+
+.. cpp:enum-class:: UserType : CK_USER_TYPE
+
+ .. cpp:enumerator:: UserType::SO = CKU_SO
+ .. cpp:enumerator:: UserType::User = CKU_USER
+ .. cpp:enumerator:: UserType::ContextSpecific = CKU_CONTEXT_SPECIFIC
+
+Additionally, all types that are used by the low or high level API are mapped by
+type aliases to more C++ like names. For instance:
+
+.. cpp:type:: FunctionListPtr = CK_FUNCTION_LIST_PTR
+
+.. rubric:: C-API Wrapping
+
+There is at least one method in the :cpp:class:`LowLevel` class that corresponds to a PKCS#11
+function. For example the :cpp:func:`C_GetSlotList` method in the :cpp:class:`LowLevel` class is defined as follows:
+
+.. cpp:class:: LowLevel
+
+ .. cpp:function:: bool C_GetSlotList(Bbool token_present, SlotId* slot_list_ptr, Ulong* count_ptr, ReturnValue* return_value = ThrowException) const
+
+The :cpp:class:`LowLevel` class calls the PKCS#11 function from the function list of the PKCS#11 module:
+
+ .. code-block:: c
+
+ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount )
+
+Where it makes sense there is also an overload of the :cpp:class:`LowLevel` method to make usage easier and safer:
+
+ .. cpp:function:: bool C_GetSlotList( bool token_present, std::vector<SlotId>& slot_ids, ReturnValue* return_value = ThrowException ) const
+
+With this overload the user of this API just has to pass a vector of :cpp:type:`SlotId` instead of pointers
+to preallocated memory for the slot list and the number of elements. Additionally, there is no need
+to call the method twice in order to determine the number of elements first.
+
+Another example is the :cpp:func:`C_InitPIN` overload:
+
+ .. cpp:function:: template<typename Talloc> bool C_InitPIN( SessionHandle session, const std::vector<uint8_t, TAlloc>& pin, ReturnValue* return_value = ThrowException ) const
+
+The templated ``pin`` parameter allows to pass the PIN as a ``std::vector<uint8_t>`` or a ``secure_vector<uint8_t>``.
+If used with a ``secure_vector`` it is assured that the memory is securely erased when the ``pin`` object is no longer needed.
+
+Error Handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All possible PKCS#11 return values are represented by the enum class:
+
+.. cpp:enum-class:: ReturnValue : CK_RV
+
+All methods of the :cpp:class:`LowLevel` class have a default parameter ``ReturnValue* return_value = ThrowException``.
+This parameter controls the error handling of all :cpp:class:`LowLevel` methods. The default
+behavior ``return_value = ThrowException`` is to throw an exception if the method does
+not complete successfully. If a non-``NULL`` pointer is passed, ``return_value`` receives the
+return value of the PKCS#11 function and no exception is thrown. In case ``nullptr`` is
+passed as ``return_value``, the exact return value is ignored and the method just returns
+``true`` if the function succeeds and ``false`` otherwise.
+
+Getting started
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An object of this class can be instantiated by providing a :cpp:type:`FunctionListPtr` to the :cpp:class:`LowLevel` constructor:
+
+ .. cpp:function:: explicit LowLevel(FunctionListPtr ptr)
+
+The :cpp:class:`LowLevel` class provides a static method to retrieve a :cpp:type:`FunctionListPtr`
+from a PKCS#11 module file:
+
+ .. cpp:function:: static bool C_GetFunctionList(Dynamically_Loaded_Library& pkcs11_module, FunctionListPtr* function_list_ptr_ptr, ReturnValue* return_value = ThrowException)
+
+----------
+
+Code Example: Object Instantiation
+
+ .. code-block:: cpp
+
+ Botan::Dynamically_Loaded_Library pkcs11_module( "C:\\pkcs11-middleware\\library.dll" );
+ Botan::PKCS11::FunctionListPtr func_list = nullptr;
+ Botan::PKCS11::LowLevel::C_GetFunctionList( pkcs11_module, &func_list );
+ Botan::PKCS11::LowLevel p11_low_level( func_list );
+
+----------
+
+Code Example: PKCS#11 Module Initialization
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::LowLevel p11_low_level(func_list);
+
+ Botan::PKCS11::C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr,
+ static_cast<CK_FLAGS>(Botan::PKCS11::Flag::OsLockingOk), nullptr };
+
+ p11_low_level.C_Initialize(&init_args);
+
+ // work with the token
+
+ p11_low_level.C_Finalize(nullptr);
+
+More code examples can be found in the test suite in the ``test_pkcs11_low_level.cpp`` file.
+
+.. _pkcs11_high_level:
+
+High Level API
+----------------------------------------
+
+The high level API provides access to the most commonly used PKCS#11 functionality in an
+object oriented manner. Functionality of the high level API includes:
+
+* Loading/unloading of PKCS#11 modules
+* Initialization of tokens
+* Change of PIN/SO-PIN
+* Session management
+* Random number generation
+* Enumeration of objects on the token (certificates, public keys, private keys)
+* Import/export/deletion of certificates
+* Generation/import/export/deletion of RSA and EC public and private keys
+* Encryption/decryption using RSA with support for OAEP and PKCS1-v1_5 (and raw)
+* Signature generation/verification using RSA with support for PSS and PKCS1-v1_5 (and raw)
+* Signature generation/verification using ECDSA
+* Key derivation using ECDH
+
+Module
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The :cpp:class:`Module` class represents a PKCS#11 shared library (module) and is defined in
+``botan/p11_module.h``.
+
+It is constructed from a a file path to a PKCS#11 module and optional :cpp:type:`C_InitializeArgs`:
+
+.. cpp:class:: Module
+
+ .. code-block:: cpp
+
+ Module(const std::string& file_path, C_InitializeArgs init_args =
+ { nullptr, nullptr, nullptr, nullptr, static_cast<CK_FLAGS>(Flag::OsLockingOk), nullptr })
+
+ It loads the shared library and calls :cpp:func:`C_Initialize` with the provided :cpp:type:`C_InitializeArgs`.
+ On destruction of the object :cpp:func:`C_Finalize` is called.
+
+There are two more methods in this class. One is for reloading the shared library
+and reinitializing the PKCS#11 module:
+
+ .. code-block:: cpp
+
+ void reload(C_InitializeArgs init_args =
+ { nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
+
+The other one is for getting general information about the PKCS#11 module:
+
+ .. cpp:function:: Info get_info() const
+
+ This function calls :cpp:func:`C_GetInfo` internally.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::Module module( "C:\\pkcs11-middleware\\library.dll" );
+
+ // Sometimes useful if a newly connected token is not detected by the PKCS#11 module
+ module.reload();
+
+ Botan::PKCS11::Info info = module.get_info();
+
+ // print library version
+ std::cout << std::to_string( info.libraryVersion.major ) << "."
+ << std::to_string( info.libraryVersion.minor ) << std::endl;
+
+Slot
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The :cpp:class:`Slot` class represents a PKCS#11 slot and is defined in
+``botan/p11_slot.h``.
+
+A PKCS#11 slot is usually a smart card reader that potentially contains a token.
+
+.. cpp:class:: Slot
+
+ .. cpp:function:: Slot(Module& module, SlotId slot_id)
+
+ To instantiate this class a reference to a :cpp:class:`Module` object and a ``slot_id`` have to be passed
+ to the constructor.
+
+ .. cpp:function:: static std::vector<SlotId> get_available_slots(Module& module, bool token_present)
+
+ Retrieve available slot ids by calling this static method.
+
+ The parameter ``token_present`` controls whether all slots or only slots with a
+ token attached are returned by this method. This method calls :cpp:func:`C_GetSlotList()`.
+
+ .. cpp:function:: SlotInfo get_slot_info() const
+
+ Returns information about the slot. Calls :cpp:func:`C_GetSlotInfo`.
+
+ .. cpp:function:: TokenInfo get_token_info() const
+
+ Obtains information about a particular token in the system. Calls :cpp:func:`C_GetTokenInfo`.
+
+ .. cpp:function:: std::vector<MechanismType> get_mechanism_list() const
+
+ Obtains a list of mechanism types supported by the slot. Calls :cpp:func:`C_GetMechanismList`.
+
+ .. cpp:function:: MechanismInfo get_mechanism_info(MechanismType mechanism_type) const
+
+ Obtains information about a particular mechanism possibly supported by a slot.
+ Calls :cpp:func:`C_GetMechanismInfo`.
+
+ .. cpp:function:: void initialize(const std::string& label, const secure_string& so_pin) const
+
+ Calls :cpp:func:`C_InitToken` to initialize the token. The ``label`` must not exceed 32 bytes.
+ The current PIN of the security officer must be passed in ``so_pin`` if the token
+ is reinitialized or if it's a factory new token, the ``so_pin`` that is passed will initially be set.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ // only slots with connected token
+ std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
+
+ // use first slot
+ Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
+
+ // print firmware version of the slot
+ Botan::PKCS11::SlotInfo slot_info = slot.get_slot_info();
+ std::cout << std::to_string( slot_info.firmwareVersion.major ) << "."
+ << std::to_string( slot_info.firmwareVersion.minor ) << std::endl;
+
+ // print firmware version of the token
+ Botan::PKCS11::TokenInfo token_info = slot.get_token_info();
+ std::cout << std::to_string( token_info.firmwareVersion.major ) << "."
+ << std::to_string( token_info.firmwareVersion.minor ) << std::endl;
+
+ // retrieve all mechanisms supported by the token
+ std::vector<Botan::PKCS11::MechanismType> mechanisms = slot.get_mechanism_list();
+
+ // retrieve information about a particular mechanism
+ Botan::PKCS11::MechanismInfo mech_info =
+ slot.get_mechanism_info( Botan::PKCS11::MechanismType::RsaPkcsOaep );
+
+ // maximum RSA key length supported:
+ std::cout << mech_info.ulMaxKeySize << std::endl;
+
+ // initialize the token
+ Botan::PKCS11::secure_string so_pin( 8, '0' );
+ slot.initialize( "Botan PKCS11 documentation test label", so_pin );
+
+Session
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The :cpp:class:`Session` class represents a PKCS#11 session and is defined in ``botan/p11_session.h``.
+
+A session is a logical connection between an application and a token.
+
+.. cpp:class:: Session
+
+ There are two constructors to create a new session and one constructor to
+ take ownership of an existing session. The destructor calls
+ :cpp:func:`C_Logout` if a user is logged in to this session and always
+ :cpp:func:`C_CloseSession`.
+
+ .. cpp:function:: Session(Slot& slot, bool read_only)
+
+ To initialize a session object a :cpp:class:`Slot` has to be specified on which the session
+ should operate. ``read_only`` specifies whether the session should be read only or read write.
+ Calls :cpp:func:`C_OpenSession`.
+
+ .. cpp:function:: Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback)
+
+ Creates a new session by passing a :cpp:class:`Slot`, session ``flags``, ``callback_data`` and a
+ ``notify_callback``. Calls :cpp:func:`C_OpenSession`.
+
+ .. cpp:function:: Session(Slot& slot, SessionHandle handle)
+
+ Takes ownership of an existing session by passing :cpp:class:`Slot` and a session ``handle``.
+
+ .. cpp:function:: SessionHandle release()
+
+ Returns the released :cpp:type:`SessionHandle`
+
+ .. cpp:function:: void login(UserType userType, const secure_string& pin)
+
+ Login to this session by passing :cpp:enum:`UserType` and ``pin``. Calls :cpp:func:`C_Login`.
+
+ .. cpp:function:: void logoff()
+
+ Logout from this session. Not mandatory because on destruction of the :cpp:class:`Session` object
+ this is done automatically.
+
+ .. cpp:function:: SessionInfo get_info() const
+
+ Returns information about this session. Calls :cpp:func:`C_GetSessionInfo`.
+
+ .. cpp:function:: void set_pin(const secure_string& old_pin, const secure_string& new_pin) const
+
+ Calls :cpp:func:`C_SetPIN` to change the PIN of the logged in user using the ``old_pin``.
+
+ .. cpp:function:: void init_pin(const secure_string& new_pin)
+
+ Calls :cpp:func:`C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session).
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ // open read only session
+ {
+ Botan::PKCS11::Session read_only_session( slot, true );
+ }
+
+ // open read write session
+ {
+ Botan::PKCS11::Session read_write_session( slot, false );
+ }
+
+ // open read write session by passing flags
+ {
+ Botan::PKCS11::Flags flags =
+ Botan::PKCS11::flags( Botan::PKCS11::Flag::SerialSession | Botan::PKCS11::Flag::RwSession );
+
+ Botan::PKCS11::Session read_write_session( slot, flags, nullptr, nullptr );
+ }
+
+ // move ownership of a session
+ {
+ Botan::PKCS11::Session session( slot, false );
+ Botan::PKCS11::SessionHandle handle = session.release();
+
+ Botan::PKCS11::Session session2( slot, handle );
+ }
+
+ Botan::PKCS11::Session session( slot, false );
+
+ // get session info
+ Botan::PKCS11::SessionInfo info = session.get_info();
+ std::cout << info.slotID << std::endl;
+
+ // login
+ Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
+ session.login( Botan::PKCS11::UserType::User, pin );
+
+ // set pin
+ Botan::PKCS11::secure_string new_pin = { '6', '5', '4', '3', '2', '1' };
+ session.set_pin( pin, new_pin );
+
+ // logoff
+ session.logoff();
+
+ // log in as security officer
+ Botan::PKCS11::secure_string so_pin = { '0', '0', '0', '0', '0', '0', '0', '0' };
+ session.login( Botan::PKCS11::UserType::SO, so_pin );
+
+ // change pin to old pin
+ session.init_pin( pin );
+
+Objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PKCS#11 objects consist of various attributes (:c:type:`CK_ATTRIBUTE`). For example :c:macro:`CKA_TOKEN`
+describes if a PKCS#11 object is a session object or a token object. The helper class :cpp:class:`AttributeContainer`
+helps with storing these attributes. The class is defined in ``botan/p11_object.h``.
+
+.. cpp:class:: AttributeContainer
+
+Attributes can be set in an :cpp:class:`AttributeContainer` by various ``add_`` methods:
+
+ .. cpp:function:: void add_class(ObjectClass object_class)
+
+ Add a class attribute (:c:macro:`CKA_CLASS` / :cpp:enumerator:`AttributeType::Class`)
+
+ .. cpp:function:: void add_string(AttributeType attribute, const std::string& value)
+
+ Add a string attribute (e.g. :c:macro:`CKA_LABEL` / :cpp:enumerator:`AttributeType::Label`).
+
+ .. cpp:function:: void AttributeContainer::add_binary(AttributeType attribute, const uint8_t* value, size_t length)
+
+ Add a binary attribute (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
+
+ .. cpp:function:: template<typename TAlloc> void AttributeContainer::add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary)
+
+ Add a binary attribute by passing a ``vector``/``secure_vector`` (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
+
+ .. cpp:function:: void AttributeContainer::add_bool(AttributeType attribute, bool value)
+
+ Add a bool attribute (e.g. :c:macro:`CKA_SENSITIVE` / :cpp:enumerator:`AttributeType::Sensitive`).
+
+ .. cpp:function:: template<typename T> void AttributeContainer::add_numeric(AttributeType attribute, T value)
+
+ Add a numeric attribute (e.g. :c:macro:`CKA_MODULUS_BITS` / :cpp:enumerator:`AttributeType::ModulusBits`).
+
+.. rubric:: Object Properties
+
+The PKCS#11 standard defines the mandatory and optional attributes for each object class.
+The mandatory and optional attribute requirements are mapped in so called property classes.
+Mandatory attributes are set in the constructor, optional attributes can be set via ``set_`` methods.
+
+In the top hierarchy is the :cpp:class:`ObjectProperties` class which inherits from the :cpp:class:`AttributeContainer`.
+This class represents the common attributes of all PKCS#11 objects.
+
+.. cpp:class:: ObjectProperties : public AttributeContainer
+
+The constructor is defined as follows:
+
+ .. cpp:function:: ObjectProperties(ObjectClass object_class)
+
+ Every PKCS#11 object needs an object class attribute.
+
+The next level defines the :cpp:class:`StorageObjectProperties` class which inherits from
+:cpp:class:`ObjectProperties`.
+
+.. cpp:class:: StorageObjectProperties : public ObjectProperties
+
+The only mandatory attribute is the object class, so the constructor is
+defined as follows:
+
+ .. cpp:function:: StorageObjectProperties(ObjectClass object_class)
+
+But in contrast to the :cpp:class:`ObjectProperties` class there are various setter methods. For example to
+set the :cpp:enumerator:`AttributeType::Label`:
+
+ .. cpp:function:: void set_label(const std::string& label)
+
+ Sets the label description of the object (RFC2279 string).
+
+The remaining hierarchy is defined as follows:
+
+* :cpp:class:`DataObjectProperties` inherits from :cpp:class:`StorageObjectProperties`
+* :cpp:class:`CertificateProperties` inherits from :cpp:class:`StorageObjectProperties`
+* :cpp:class:`DomainParameterProperties` inherits from :cpp:class:`StorageObjectProperties`
+* :cpp:class:`KeyProperties` inherits from :cpp:class:`StorageObjectProperties`
+* :cpp:class:`PublicKeyProperties` inherits from :cpp:class:`KeyProperties`
+* :cpp:class:`PrivateKeyProperties` inherits from :cpp:class:`KeyProperties`
+* :cpp:class:`SecretKeyProperties` inherits from :cpp:class:`KeyProperties`
+
+PKCS#11 objects themselves are represented by the :cpp:class:`Object` class.
+
+.. cpp:class:: Object
+
+Following constructors are defined:
+
+ .. cpp:function:: Object(Session& session, ObjectHandle handle)
+
+ Takes ownership over an existing object.
+
+ .. cpp:function:: Object(Session& session, const ObjectProperties& obj_props)
+
+ Creates a new object with the :cpp:class:`ObjectProperties` provided in ``obj_props``.
+
+The other methods are:
+
+ .. cpp:function:: secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const
+
+ Returns the value of the given attribute (using :cpp:func:`C_GetAttributeValue`)
+
+ .. cpp:function:: void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const
+
+ Sets the given value for the attribute (using :cpp:func:`C_SetAttributeValue`)
+
+ .. cpp:function:: void destroy() const
+
+ Destroys the object.
+
+ .. cpp:function:: ObjectHandle copy(const AttributeContainer& modified_attributes) const
+
+ Allows to copy the object with modified attributes.
+
+And static methods to search for objects:
+
+ .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template)
+
+ Searches for all objects of the given type that match ``search_template``.
+
+ .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label)
+
+ Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`).
+
+ .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<uint8_t>& id)
+
+ Searches for all objects of the given type using the id (:c:macro:`CKA_ID`).
+
+ .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label, const std::vector<uint8_t>& id)
+
+ Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`) and id (:c:macro:`CKA_ID`).
+
+ .. cpp:function:: template<typename T> static std::vector<T> search(Session& session)
+
+ Searches for all objects of the given type.
+
+.. rubric:: The ObjectFinder
+
+Another way for searching objects is to use the :cpp:class:`ObjectFinder` class. This class
+manages calls to the ``C_FindObjects*`` functions: :cpp:func:`C_FindObjectsInit`, :cpp:func:`C_FindObjects`
+and :cpp:func:`C_FindObjectsFinal`.
+
+.. cpp:class:: ObjectFinder
+
+The constructor has the following signature:
+
+ .. cpp:function:: ObjectFinder(Session& session, const std::vector<Attribute>& search_template)
+
+ A search can be prepared with an :cpp:class:`ObjectSearcher` by passing a :cpp:class:`Session` and a ``search_template``.
+
+The actual search operation is started by calling the :cpp:func:`find` method:
+
+ .. cpp:function:: std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const
+
+ Starts or continues a search for token and session objects that match a template. ``max_count``
+ specifies the maximum number of search results (object handles) that are returned.
+
+ .. cpp:function:: void finish()
+
+ Finishes the search operation manually to allow a new :cpp:class:`ObjectFinder` to exist.
+ Otherwise the search is finished by the destructor.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ // create an simple data object
+ Botan::secure_vector<uint8_t> value = { 0x00, 0x01 ,0x02, 0x03 };
+ std::size_t id = 1337;
+ std::string label = "test data object";
+
+ // set properties of the new object
+ Botan::PKCS11::DataObjectProperties data_obj_props;
+ data_obj_props.set_label( label );
+ data_obj_props.set_value( value );
+ data_obj_props.set_token( true );
+ data_obj_props.set_modifiable( true );
+ data_obj_props.set_object_id( Botan::DER_Encoder().encode( id ).get_contents_unlocked() );
+
+ // create the object
+ Botan::PKCS11::Object data_obj( session, data_obj_props );
+
+ // get label of this object
+ Botan::PKCS11::secure_string retrieved_label =
+ data_obj.get_attribute_value( Botan::PKCS11::AttributeType::Label );
+
+ // set a new label
+ Botan::PKCS11::secure_string new_label = { 'B', 'o', 't', 'a', 'n' };
+ data_obj.set_attribute_value( Botan::PKCS11::AttributeType::Label, new_label );
+
+ // copy the object
+ Botan::PKCS11::AttributeContainer copy_attributes;
+ copy_attributes.add_string( Botan::PKCS11::AttributeType::Label, "copied object" );
+ Botan::PKCS11::ObjectHandle copied_obj_handle = data_obj.copy( copy_attributes );
+
+ // search for an object
+ Botan::PKCS11::AttributeContainer search_template;
+ search_template.add_string( Botan::PKCS11::AttributeType::Label, "Botan" );
+ auto found_objs =
+ Botan::PKCS11::Object::search<Botan::PKCS11::Object>( session, search_template.attributes() );
+
+ // destroy the object
+ data_obj.destroy();
+
+RSA
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PKCS#11 RSA support is implemented in ``<botan/p11_rsa.h>``.
+
+.. rubric:: RSA Public Keys
+
+PKCS#11 RSA public keys are provided by the class :cpp:class:`PKCS11_RSA_PublicKey`. This class
+inherits from :cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. Furthermore there are two property classes defined
+to generate and import RSA public keys analogous to the other property classes described
+before: :cpp:class:`RSA_PublicKeyGenerationProperties` and :cpp:class:`RSA_PublicKeyImportProperties`.
+
+.. cpp:class:: PKCS11_RSA_PublicKey : public RSA_PublicKey, public Object
+
+ .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 RSA public keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props)
+
+ This constructor can be used to import an existing RSA public key with the :cpp:class:`RSA_PublicKeyImportProperties`
+ passed in ``pubkey_props`` to the token.
+
+.. rubric:: RSA Private Keys
+
+The support for PKCS#11 RSA private keys is implemented in a similar way. There are two property
+classes: :cpp:class:`RSA_PrivateKeyGenerationProperties` and :cpp:class:`RSA_PrivateKeyImportProperties`. The :cpp:class:`PKCS11_RSA_PrivateKey`
+class implements the actual support for PKCS#11 RSA private keys. This class inherits from :cpp:class:`Private_Key`,
+:cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. In contrast to the public key class there is a third constructor
+to generate private keys directly on the token or in the session and one method to export private keys.
+
+.. cpp:class:: PKCS11_RSA_PrivateKey : public Private_Key, public RSA_PublicKey, public Object
+
+ .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 RSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props)
+
+ This constructor can be used to import an existing RSA private key with the :cpp:class:`RSA_PrivateKeyImportProperties`
+ passed in ``priv_key_props`` to the token.
+
+ .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props)
+
+ Generates a new PKCS#11 RSA private key with bit length provided in ``bits`` and the :cpp:class:`RSA_PrivateKeyGenerationProperties`
+ passed in ``priv_key_props``.
+
+ .. cpp:function:: RSA_PrivateKey export_key() const
+
+ Returns the exported :cpp:class:`RSA_PrivateKey`.
+
+PKCS#11 RSA key pairs can be generated with the following free function:
+
+ .. cpp:function:: PKCS11_RSA_KeyPair PKCS11::generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props, const RSA_PrivateKeyGenerationProperties& priv_props)
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
+ session.login( Botan::PKCS11::UserType::User, pin );
+
+ /************ import RSA private key *************/
+
+ // create private key in software
+ Botan::AutoSeeded_RNG rng;
+ Botan::RSA_PrivateKey priv_key_sw( rng, 2048 );
+
+ // set the private key import properties
+ Botan::PKCS11::RSA_PrivateKeyImportProperties
+ priv_import_props( priv_key_sw.get_n(), priv_key_sw.get_d() );
+
+ priv_import_props.set_pub_exponent( priv_key_sw.get_e() );
+ priv_import_props.set_prime_1( priv_key_sw.get_p() );
+ priv_import_props.set_prime_2( priv_key_sw.get_q() );
+ priv_import_props.set_coefficient( priv_key_sw.get_c() );
+ priv_import_props.set_exponent_1( priv_key_sw.get_d1() );
+ priv_import_props.set_exponent_2( priv_key_sw.get_d2() );
+
+ priv_import_props.set_token( true );
+ priv_import_props.set_private( true );
+ priv_import_props.set_decrypt( true );
+ priv_import_props.set_sign( true );
+
+ // import
+ Botan::PKCS11::PKCS11_RSA_PrivateKey priv_key( session, priv_import_props );
+
+ /************ export PKCS#11 RSA private key *************/
+ Botan::RSA_PrivateKey exported = priv_key.export_key();
+
+ /************ import RSA public key *************/
+
+ // set the public key import properties
+ Botan::PKCS11::RSA_PublicKeyImportProperties pub_import_props( priv_key.get_n(), priv_key.get_e() );
+ pub_import_props.set_token( true );
+ pub_import_props.set_encrypt( true );
+ pub_import_props.set_private( false );
+
+ // import
+ Botan::PKCS11::PKCS11_RSA_PublicKey public_key( session, pub_import_props );
+
+ /************ generate RSA private key *************/
+
+ Botan::PKCS11::RSA_PrivateKeyGenerationProperties priv_generate_props;
+ priv_generate_props.set_token( true );
+ priv_generate_props.set_private( true );
+ priv_generate_props.set_sign( true );
+ priv_generate_props.set_decrypt( true );
+ priv_generate_props.set_label( "BOTAN_TEST_RSA_PRIV_KEY" );
+
+ Botan::PKCS11::PKCS11_RSA_PrivateKey private_key2( session, 2048, priv_generate_props );
+
+ /************ generate RSA key pair *************/
+
+ Botan::PKCS11::RSA_PublicKeyGenerationProperties pub_generate_props( 2048UL );
+ pub_generate_props.set_pub_exponent();
+ pub_generate_props.set_label( "BOTAN_TEST_RSA_PUB_KEY" );
+ pub_generate_props.set_token( true );
+ pub_generate_props.set_encrypt( true );
+ pub_generate_props.set_verify( true );
+ pub_generate_props.set_private( false );
+
+ Botan::PKCS11::PKCS11_RSA_KeyPair rsa_keypair =
+ Botan::PKCS11::generate_rsa_keypair( session, pub_generate_props, priv_generate_props );
+
+ /************ RSA encrypt *************/
+
+ Botan::secure_vector<uint8_t> plaintext = { 0x00, 0x01, 0x02, 0x03 };
+ Botan::PK_Encryptor_EME encryptor( rsa_keypair.first, rng, "Raw" );
+ auto ciphertext = encryptor.encrypt( plaintext, rng );
+
+ /************ RSA decrypt *************/
+
+ Botan::PK_Decryptor_EME decryptor( rsa_keypair.second, rng, "Raw" );
+ plaintext = decryptor.decrypt( ciphertext );
+
+ /************ RSA sign *************/
+
+ Botan::PK_Signer signer( rsa_keypair.second, rng, "EMSA4(SHA-256)", Botan::IEEE_1363 );
+ auto signature = signer.sign_message( plaintext, rng );
+
+ /************ RSA verify *************/
+
+ Botan::PK_Verifier verifier( rsa_keypair.first, "EMSA4(SHA-256)", Botan::IEEE_1363 );
+ auto ok = verifier.verify_message( plaintext, signature );
+
+ECDSA
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PKCS#11 ECDSA support is implemented in ``<botan/p11_ecdsa.h>``.
+
+.. rubric:: ECDSA Public Keys
+
+PKCS#11 ECDSA public keys are provided by the class :cpp:class:`PKCS11_ECDSA_PublicKey`. This class
+inherits from :cpp:class:`PKCS11_EC_PublicKey` and :cpp:class:`ECDSA_PublicKey`. The necessary property classes
+are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
+and :cpp:class:`EC_PublicKeyImportProperties`.
+
+.. cpp:class:: PKCS11_ECDSA_PublicKey : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey
+
+ .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
+
+ This constructor can be used to import an existing ECDSA public key with the :cpp:class:`EC_PublicKeyImportProperties`
+ passed in ``props`` to the token.
+
+ .. cpp:function:: ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const
+
+ Returns the exported :cpp:class:`ECDSA_PublicKey`.
+
+.. rubric:: ECDSA Private Keys
+
+The class :cpp:class:`PKCS11_ECDSA_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and implements support
+for PKCS#11 ECDSA private keys. There are two property classes for key generation
+and import: :cpp:class:`EC_PrivateKeyGenerationProperties` and :cpp:class:`EC_PrivateKeyImportProperties`.
+
+.. cpp:class:: PKCS11_ECDSA_PrivateKey : public PKCS11_EC_PrivateKey
+
+ .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
+
+ This constructor can be used to import an existing ECDSA private key with the :cpp:class:`EC_PrivateKeyImportProperties`
+ passed in ``props`` to the token.
+
+ .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
+
+ This constructor can be used to generate a new ECDSA private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
+ passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
+ ANSI X9.62 Parameters value.
+
+ .. cpp:function:: ECDSA_PrivateKey export_key() const
+
+ Returns the exported :cpp:class:`ECDSA_PrivateKey`.
+
+PKCS#11 ECDSA key pairs can be generated with the following free function:
+
+ .. cpp:function:: PKCS11_ECDSA_KeyPair PKCS11::generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
+ session.login( Botan::PKCS11::UserType::User, pin );
+
+ /************ import ECDSA private key *************/
+
+ // create private key in software
+ Botan::AutoSeeded_RNG rng;
+
+ Botan::ECDSA_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) );
+ priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID );
+
+ // set the private key import properties
+ Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props(
+ priv_key_sw.DER_domain(), priv_key_sw.private_value() );
+
+ priv_import_props.set_token( true );
+ priv_import_props.set_private( true );
+ priv_import_props.set_sign( true );
+ priv_import_props.set_extractable( true );
+
+ // label
+ std::string label = "test ECDSA key";
+ priv_import_props.set_label( label );
+
+ // import to card
+ Botan::PKCS11::PKCS11_ECDSA_PrivateKey priv_key( session, priv_import_props );
+
+ /************ export PKCS#11 ECDSA private key *************/
+ Botan::ECDSA_PrivateKey priv_exported = priv_key.export_key();
+
+ /************ import ECDSA public key *************/
+
+ // import to card
+ Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(),
+ Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ),
+ Botan::OCTET_STRING ).get_contents_unlocked() );
+
+ pub_import_props.set_token( true );
+ pub_import_props.set_verify( true );
+ pub_import_props.set_private( false );
+
+ // label
+ label = "test ECDSA pub key";
+ pub_import_props.set_label( label );
+
+ Botan::PKCS11::PKCS11_ECDSA_PublicKey public_key( session, pub_import_props );
+
+ /************ export PKCS#11 ECDSA public key *************/
+ Botan::ECDSA_PublicKey pub_exported = public_key.export_key();
+
+ /************ generate PKCS#11 ECDSA private key *************/
+ Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props;
+ priv_generate_props.set_token( true );
+ priv_generate_props.set_private( true );
+ priv_generate_props.set_sign( true );
+
+ Botan::PKCS11::PKCS11_ECDSA_PrivateKey pk( session,
+ Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ),
+ priv_generate_props );
+
+ /************ generate PKCS#11 ECDSA key pair *************/
+
+ Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
+ Botan::EC_Group( "secp256r1" ).DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
+
+ pub_generate_props.set_label( "BOTAN_TEST_ECDSA_PUB_KEY" );
+ pub_generate_props.set_token( true );
+ pub_generate_props.set_verify( true );
+ pub_generate_props.set_private( false );
+ pub_generate_props.set_modifiable( true );
+
+ Botan::PKCS11::PKCS11_ECDSA_KeyPair key_pair = Botan::PKCS11::generate_ecdsa_keypair( session,
+ pub_generate_props, priv_generate_props );
+
+ /************ PKCS#11 ECDSA sign and verify *************/
+
+ std::vector<uint8_t> plaintext( 20, 0x01 );
+
+ Botan::PK_Signer signer( key_pair.second, rng, "Raw", Botan::IEEE_1363, "pkcs11" );
+ auto signature = signer.sign_message( plaintext, rng );
+
+ Botan::PK_Verifier token_verifier( key_pair.first, "Raw", Botan::IEEE_1363, "pkcs11" );
+ bool ecdsa_ok = token_verifier.verify_message( plaintext, signature );
+
+ECDH
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PKCS#11 ECDH support is implemented in ``<botan/p11_ecdh.h>``.
+
+.. rubric:: ECDH Public Keys
+
+PKCS#11 ECDH public keys are provided by the class :cpp:class:`PKCS11_ECDH_PublicKey`. This class
+inherits from :cpp:class:`PKCS11_EC_PublicKey`. The necessary property classes
+are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
+and :cpp:class:`EC_PublicKeyImportProperties`.
+
+.. cpp:class:: PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey
+
+ .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
+
+ This constructor can be used to import an existing ECDH public key with the :cpp:class:`EC_PublicKeyImportProperties`
+ passed in ``props`` to the token.
+
+ .. cpp:function:: ECDH_PublicKey export_key() const
+
+ Returns the exported :cpp:class:`ECDH_PublicKey`.
+
+.. rubric:: ECDH Private Keys
+
+The class :cpp:class:`PKCS11_ECDH_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and :cpp:class:`PK_Key_Agreement_Key`
+and implements support for PKCS#11 ECDH private keys. There are two
+property classes. One for key generation and one for import: :cpp:class:`EC_PrivateKeyGenerationProperties` and
+:cpp:class:`EC_PrivateKeyImportProperties`.
+
+.. cpp:class:: PKCS11_ECDH_PrivateKey : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key
+
+ .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle)
+
+ Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
+ constructor.
+
+ .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
+
+ This constructor can be used to import an existing ECDH private key with the :cpp:class:`EC_PrivateKeyImportProperties`
+ passed in ``props`` to the token.
+
+ .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
+
+ This constructor can be used to generate a new ECDH private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
+ passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
+ ANSI X9.62 Parameters value.
+
+ .. cpp:function:: ECDH_PrivateKey export_key() const
+
+ Returns the exported :cpp:class:`ECDH_PrivateKey`.
+
+PKCS#11 ECDH key pairs can be generated with the following free function:
+
+.. cpp:function:: PKCS11_ECDH_KeyPair PKCS11::generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
+ session.login( Botan::PKCS11::UserType::User, pin );
+
+ /************ import ECDH private key *************/
+
+ Botan::AutoSeeded_RNG rng;
+
+ // create private key in software
+ Botan::ECDH_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) );
+ priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID );
+
+ // set import properties
+ Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props(
+ priv_key_sw.DER_domain(), priv_key_sw.private_value() );
+
+ priv_import_props.set_token( true );
+ priv_import_props.set_private( true );
+ priv_import_props.set_derive( true );
+ priv_import_props.set_extractable( true );
+
+ // label
+ std::string label = "test ECDH key";
+ priv_import_props.set_label( label );
+
+ // import to card
+ Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key( session, priv_import_props );
+
+ /************ export ECDH private key *************/
+ Botan::ECDH_PrivateKey exported = priv_key.export_key();
+
+ /************ import ECDH public key *************/
+
+ // set import properties
+ Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(),
+ Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ),
+ Botan::OCTET_STRING ).get_contents_unlocked() );
+
+ pub_import_props.set_token( true );
+ pub_import_props.set_private( false );
+ pub_import_props.set_derive( true );
+
+ // label
+ label = "test ECDH pub key";
+ pub_import_props.set_label( label );
+
+ // import
+ Botan::PKCS11::PKCS11_ECDH_PublicKey pub_key( session, pub_import_props );
+
+ /************ export ECDH private key *************/
+ Botan::ECDH_PublicKey exported_pub = pub_key.export_key();
+
+ /************ generate ECDH private key *************/
+
+ Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props;
+ priv_generate_props.set_token( true );
+ priv_generate_props.set_private( true );
+ priv_generate_props.set_derive( true );
+
+ Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key2( session,
+ Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ),
+ priv_generate_props );
+
+ /************ generate ECDH key pair *************/
+
+ Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
+ Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
+
+ pub_generate_props.set_label( label + "_PUB_KEY" );
+ pub_generate_props.set_token( true );
+ pub_generate_props.set_derive( true );
+ pub_generate_props.set_private( false );
+ pub_generate_props.set_modifiable( true );
+
+ Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair = Botan::PKCS11::generate_ecdh_keypair(
+ session, pub_generate_props, priv_generate_props );
+
+ /************ ECDH derive *************/
+
+ Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair_other = Botan::PKCS11::generate_ecdh_keypair(
+ session, pub_generate_props, priv_generate_props );
+
+ Botan::PK_Key_Agreement ka( key_pair.second, rng, "Raw", "pkcs11" );
+ Botan::PK_Key_Agreement kb( key_pair_other.second, rng, "Raw", "pkcs11" );
+
+ Botan::SymmetricKey alice_key = ka.derive_key( 32,
+ Botan::unlock( Botan::EC2OSP( key_pair_other.first.public_point(),
+ Botan::PointGFp::UNCOMPRESSED ) ) );
+
+ Botan::SymmetricKey bob_key = kb.derive_key( 32,
+ Botan::unlock( Botan::EC2OSP( key_pair.first.public_point(),
+ Botan::PointGFp::UNCOMPRESSED ) ) );
+
+ bool eq = alice_key == bob_key;
+
+RNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The PKCS#11 RNG is defined in ``<botan/p11_randomgenerator.h>``. The class :cpp:class:`PKCS11_RNG`
+implements the :cpp:class:`Hardware_RNG` interface.
+
+.. cpp:class:: PKCS11_RNG : public Hardware_RNG
+
+ .. cpp:function:: PKCS11_RNG(Session& session)
+
+ A PKCS#11 :cpp:class:`Session` must be passed to instantiate a ``PKCS11_RNG``.
+
+ .. cpp:function:: void randomize(uint8_t output[], std::size_t length) override
+
+ Calls :cpp:func:`C_GenerateRandom` to generate random data.
+
+ .. cpp:function:: void add_entropy(const uint8_t in[], std::size_t length) override
+
+ Calls :cpp:func:`C_SeedRandom` to add entropy to the random generation function of the token/middleware.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ Botan::PKCS11::PKCS11_RNG p11_rng( session );
+
+ /************ generate random data *************/
+ std::vector<uint8_t> random( 20 );
+ p11_rng.randomize( random.data(), random.size() );
+
+ /************ add entropy *************/
+ Botan::AutoSeeded_RNG auto_rng;
+ auto auto_rng_random = auto_rng.random_vec( 20 );
+ p11_rng.add_entropy( auto_rng_random.data(), auto_rng_random.size() );
+
+ /************ use PKCS#11 RNG to seed HMAC_DRBG *************/
+ Botan::HMAC_DRBG drbg( Botan::MessageAuthenticationCode::create( "HMAC(SHA-512)" ), p11_rng );
+ drbg.randomize( random.data(), random.size() );
+
+Token Management Functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The header file ``<botan/p11.h>`` also defines some free functions for token management:
+
+ .. cpp:function:: void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin, const secure_string& pin)
+
+ Initializes a token by passing a :cpp:class:`Slot`, a ``label`` and the ``so_pin`` of the security officer.
+
+ .. cpp:function:: void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin)
+
+ Change PIN with ``old_pin`` to ``new_pin``.
+
+ .. cpp:function:: void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin)
+
+ Change SO_PIN with ``old_so_pin`` to new ``new_so_pin``.
+
+ .. cpp:function:: void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin)
+
+ Sets user ``pin`` with ``so_pin``.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ /************ set pin *************/
+
+ Botan::PKCS11::Module module( Middleware_path );
+
+ // only slots with connected token
+ std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
+
+ // use first slot
+ Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
+
+ Botan::PKCS11::secure_string so_pin = { '1', '2', '3', '4', '5', '6', '7', '8' };
+ Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
+ Botan::PKCS11::secure_string test_pin = { '6', '5', '4', '3', '2', '1' };
+
+ // set pin
+ Botan::PKCS11::set_pin( slot, so_pin, test_pin );
+
+ // change back
+ Botan::PKCS11::set_pin( slot, so_pin, pin );
+
+ /************ initialize *************/
+ Botan::PKCS11::initialize_token( slot, "Botan handbook example", so_pin, pin );
+
+ /************ change pin *************/
+ Botan::PKCS11::change_pin( slot, pin, test_pin );
+
+ // change back
+ Botan::PKCS11::change_pin( slot, test_pin, pin );
+
+ /************ change security officer pin *************/
+ Botan::PKCS11::change_so_pin( slot, so_pin, test_pin );
+
+ // change back
+ Botan::PKCS11::change_so_pin( slot, test_pin, so_pin );
+
+X.509
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The header file ``<botan/p11_x509.h>`` defines the property class :cpp:class:`X509_CertificateProperties`
+and the class :cpp:class:`PKCS11_X509_Certificate`.
+
+.. cpp:class:: PKCS11_X509_Certificate : public Object, public X509_Certificate
+
+ .. cpp:function:: PKCS11_X509_Certificate(Session& session, ObjectHandle handle)
+
+ Allows to use existing certificates on the token by passing a valid :cpp:type:`ObjectHandle`.
+
+ .. cpp:function:: PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props)
+
+ Allows to import an existing X.509 certificate to the token with the :cpp:class:`X509_CertificateProperties`
+ passed in ``props``.
+
+----------
+
+Code example:
+
+ .. code-block:: cpp
+
+ // load existing certificate
+ Botan::X509_Certificate root( "test.crt" );
+
+ // set props
+ Botan::PKCS11::X509_CertificateProperties props(
+ Botan::DER_Encoder().encode( root.subject_dn() ).get_contents_unlocked(), root.BER_encode() );
+
+ props.set_label( "Botan PKCS#11 test certificate" );
+ props.set_private( false );
+ props.set_token( true );
+
+ // import
+ Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert( session, props );
+
+ // load by handle
+ Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert2( session, pkcs11_cert.handle() );
+
+Tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The PKCS#11 tests are not executed automatically because the depend on an external
+PKCS#11 module/middleware. The test tool has to be executed with ``--pkcs11-lib=``
+followed with the path of the PKCS#11 module and a second argument which controls the
+PKCS#11 tests that are executed. Passing ``pkcs11`` will execute all PKCS#11 tests but it's
+also possible to execute only a subset with the following arguments:
+
+- pkcs11-ecdh
+- pkcs11-ecdsa
+- pkcs11-lowlevel
+- pkcs11-manage
+- pkcs11-module
+- pkcs11-object
+- pkcs11-rng
+- pkcs11-rsa
+- pkcs11-session
+- pkcs11-slot
+- pkcs11-x509
+
+The following PIN and SO-PIN/PUK values are used in tests:
+
+- PIN 123456
+- SO-PIN/PUK 12345678
+
+ .. warning::
+
+ Unlike the CardOS (4.4, 5.0, 5.3), the aforementioned SO-PIN/PUK is
+ inappropriate for Gemalto (IDPrime MD 3840) cards, as it must be a byte array
+ of length 24. For this reason some of the tests for Gemalto card involving
+ SO-PIN will fail. You run into a risk of exceding login attempts and as a
+ result locking your card! Currently, specifying pin via command-line option
+ is not implemented, and therefore the desired PIN must be modified in the
+ header src/tests/test_pkcs11.h:
+
+ .. code-block:: cpp
+
+ // SO PIN is expected to be set to "12345678" prior to running the tests
+ const std::string SO_PIN = "12345678";
+ const auto SO_PIN_SECVEC = Botan::PKCS11::secure_string(SO_PIN.begin(), SO_PIN.end());
+
+
+Tested/Supported Smartcards
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You are very welcome to contribute your own test results for other testing environments or other cards.
+
+
+Test results
+
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| Smartcard | Status | OS | Midleware | Botan | Errors |
++=====================================+===========================================+===================================================+===================================================+===================================================+===================================================+
+| CardOS 4.4 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [50]_ |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| CardOS 5.0 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [51]_ |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [52]_ |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1903 | API Version 5.5.1 (Cryptoki v2.11) | 2.12.0 unreleased, Cryptoki v2.40 | [53]_ |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| Gemalto IDPrime MD 3840 | mostly works | Windows 10, 64-bit, version 1709 | IDGo 800, v1.2.4 (Cryptoki v2.20) | 2.4.0, Cryptoki v2.40 | [54]_ |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| SoftHSM 2.3.0 (OpenSSL 1.0.2g) | works | Windows 10, 64-bit, version 1709 | Cryptoki v2.40 | 2.4.0, Cryptoki v2.40 | |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+| SoftHSM 2.5.0 (OpenSSL 1.1.1) | works | Windows 10, 64-bit, version 1803 | Cryptoki v2.40 | 2.11.0, Cryptoki v2.40 | |
++-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
+
+.. [50] Failing operations for CardOS 4.4:
+
+ - object_copy [20]_
+
+ - rsa_privkey_export [21]_
+ - rsa_generate_private_key [22]_
+ - rsa_sign_verify [23]_
+
+ - ecdh_privkey_import [3]_
+ - ecdh_privkey_export [2]_
+ - ecdh_pubkey_import [4]_
+ - ecdh_pubkey_export [4]_
+ - ecdh_generate_private_key [3]_
+ - ecdh_generate_keypair [3]_
+ - ecdh_derive [3]_
+
+ - ecdsa_privkey_import [3]_
+ - ecdsa_privkey_export [2]_
+ - ecdsa_pubkey_import [4]_
+ - ecdsa_pubkey_export [4]_
+ - ecdsa_generate_private_key [3]_
+ - ecdsa_generate_keypair [3]_
+ - ecdsa_sign_verify [3]_
+
+ - rng_add_entropy [5]_
+
+
+.. [51] Failing operations for CardOS 5.0
+
+ - object_copy [20]_
+
+ - rsa_privkey_export [21]_
+ - rsa_generate_private_key [22]_
+ - rsa_sign_verify [23]_
+
+ - ecdh_privkey_export [2]_
+ - ecdh_pubkey_import [4]_
+ - ecdh_generate_private_key [32]_
+ - ecdh_generate_keypair [3]_
+ - ecdh_derive [33]_
+
+ - ecdsa_privkey_export [2]_
+ - ecdsa_generate_private_key [30]_
+ - ecdsa_generate_keypair [30]_
+ - ecdsa_sign_verify [30]_
+
+ - rng_add_entropy [5]_
+
+.. [52] Failing operations for CardOS 5.3
+
+ - object_copy [20]_
+
+ - rsa_privkey_export [21]_
+ - rsa_generate_private_key [22]_
+ - rsa_sign_verify [23]_
+
+ - ecdh_privkey_export [2]_
+ - ecdh_pubkey_import [6]_
+ - ecdh_pubkey_export [6]_
+ - ecdh_generate_private_key [30]_
+ - ecdh_generate_keypair [31]_
+ - ecdh_derive [30]_
+
+ - ecdsa_privkey_export [2]_
+ - ecdsa_pubkey_import [6]_
+ - ecdsa_pubkey_export [6]_
+ - ecdsa_generate_private_key [31]_
+ - ecdsa_generate_keypair [31]_
+ - ecdsa_sign_verify [34]_
+
+ - rng_add_entropy [5]_
+
+.. [53] Failing operations for CardOS 5.3 (middelware 5.5.1)
+
+ - ecdh_privkey_export [2]_
+ - ecdh_generate_private_key [35]_
+ - ecdsa_privkey_export [2]_
+ - ecdsa_generate_private_key [36]_
+ - c_copy_object [4]_
+
+ - object_copy [4]_
+
+ - rng_add_entropy [5]_
+
+ - rsa_sign_verify [3]_
+ - rsa_privkey_export [2]_
+ - rsa_generate_private_key [9]_
+
+.. [54] Failing operations for Gemalto IDPrime MD 3840
+
+ - session_login_logout [2]_
+ - session_info [2]_
+ - set_pin [2]_
+ - initialize [2]_
+ - change_so_pin [2]_
+
+ - object_copy [20]_
+
+ - rsa_generate_private_key [7]_
+ - rsa_encrypt_decrypt [8]_
+ - rsa_sign_verify [2]_
+
+ - rng_add_entropy [5]_
+
+Error descriptions
+
+.. [2] CKR_ARGUMENTS_BAD (0x7=7)
+.. [3] CKR_MECHANISM_INVALID (0x70=112)
+.. [4] CKR_FUNCTION_NOT_SUPPORTED (0x54=84)
+.. [5] CKR_RANDOM_SEED_NOT_SUPPORTED (0x120=288)
+.. [6] CKM_X9_42_DH_KEY_PAIR_GEN | CKR_DEVICE_ERROR (0x30=48)
+.. [7] CKR_TEMPLATE_INCONSISTENT (0xD1=209)
+.. [8] CKR_ENCRYPTED_DATA_INVALID | CKM_SHA256_RSA_PKCS (0x40=64)
+.. [9] CKR_TEMPLATE_INCOMPLETE (0xD0=208)
+
+.. [20] Test fails due to unsupported copy function (CKR_FUNCTION_NOT_SUPPORTED)
+.. [21] Generating private key for extraction with property extractable fails (CKR_ARGUMENTS_BAD)
+.. [22] Generate rsa private key operation fails (CKR_TEMPLATE_INCOMPLETE)
+.. [23] Raw RSA sign-verify fails (CKR_MECHANISM_INVALID)
+
+.. [30] Invalid argument Decoding error: BER: Value truncated
+.. [31] Invalid argument Decoding error: BER: Length field is to large
+.. [32] Invalid argument OS2ECP: Unknown format type 155
+.. [33] Invalid argument OS2ECP: Unknown format type 92
+.. [34] Invalid argument OS2ECP: Unknown format type 57
+.. [35] Invalid argument OS2ECP: Unknown format type 82
+.. [36] Invalid argument OS2ECP: Unknown format type 102
diff --git a/comm/third_party/botan/doc/api_ref/psk_db.rst b/comm/third_party/botan/doc/api_ref/psk_db.rst
new file mode 100644
index 0000000000..d9f8bf79be
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/psk_db.rst
@@ -0,0 +1,110 @@
+PSK Database
+======================
+
+.. versionadded:: 2.4.0
+
+Many applications need to store pre-shared keys (hereafter PSKs) for
+authentication purposes.
+
+An abstract interface to PSK stores, along with some implementations
+of same, are provided in ``psk_db.h``
+
+.. cpp:class:: PSK_Database
+
+ .. cpp:function:: bool is_encrypted() const
+
+ Returns true if (at least) the PSKs themselves are encrypted. Returns
+ false if PSKs are stored in plaintext.
+
+ .. cpp:function:: std::set<std::string> list_names() const
+
+ Return the set of valid names stored in the database, ie values for which
+ ``get`` will return a value.
+
+ .. cpp:function:: void set(const std::string& name, const uint8_t psk[], size_t psk_len)
+
+ Save a PSK. If ``name`` already exists, the current value will be
+ overwritten.
+
+ .. cpp:function:: secure_vector<uint8_t> get(const std::string& name) const
+
+ Return a value saved with ``set``. Throws an exception if ``name`` doesn't
+ exist.
+
+ .. cpp:function:: void remove(const std::string& name)
+
+ Remove ``name`` from the database. If ``name`` doesn't exist, ignores the request.
+
+ .. cpp::function:: std::string get_str(const std::string& name) const
+
+ Like ``get`` but casts the return value to a string.
+
+ .. cpp:function:: void set_str(const std::string& name, const std::string& psk)
+
+ Like ``set`` but accepts the psk as a string (eg for a password).
+
+ .. cpp:function:: template<typename Alloc> void set_vec(const std::string& name, \
+ const std::vector<uint8_t, Alloc>& psk)
+
+ Like ``set`` but accepting a vector.
+
+The same header also provides a specific instantiation of ``PSK_Database`` which
+encrypts both names and PSKs. It must be subclassed to provide the storage.
+
+.. cpp:class:: Encrypted_PSK_Database : public PSK_Database
+
+ .. cpp:function:: Encrypted_PSK_Database(const secure_vector<uint8_t>& master_key)
+
+ Initializes or opens a PSK database. The master key is used the secure the
+ contents. It may be of any length. If encrypting PSKs under a passphrase,
+ use a suitable key derivation scheme (such as PBKDF2) to derive the secret
+ key. If the master key is lost, all PSKs stored are unrecoverable.
+
+ Both names and values are encrypted using NIST key wrapping (see NIST
+ SP800-38F) with AES-256. First the master key is used with HMAC(SHA-256)
+ to derive two 256-bit keys, one for encrypting all names and the other to
+ key an instance of HMAC(SHA-256). Values are each encrypted under an
+ individual key created by hashing the encrypted name with HMAC. This
+ associates the encrypted key with the name, and prevents an attacker with
+ write access to the data store from taking an encrypted key associated
+ with one entity and copying it to another entity.
+
+ Names and PSKs are both padded to the next multiple of 8 bytes, providing
+ some obfuscation of the length.
+
+ One artifact of the names being encrypted is that is is possible to use
+ multiple different master keys with the same underlying storage. Each
+ master key will be responsible for a subset of the keys. An attacker who
+ knows one of the keys will be able to tell there are other values
+ encrypted under another key, but will not be able to tell how many other
+ master keys are in use.
+
+ .. cpp:function:: virtual void kv_set(const std::string& index, const std::string& value) = 0
+
+ Save an encrypted value. Both ``index`` and ``value`` will be non-empty
+ base64 encoded strings.
+
+ .. cpp:function:: virtual std::string kv_get(const std::string& index) const = 0
+
+ Return a value saved with ``kv_set``, or return the empty string.
+
+ .. cpp:function:: virtual void kv_del(const std::string& index) = 0
+
+ Remove a value saved with ``kv_set``.
+
+ .. cpp:function:: virtual std::set<std::string> kv_get_all() const = 0
+
+ Return all active names (ie values for which ``kv_get`` will return a
+ non-empty string).
+
+A subclass of ``Encrypted_PSK_Database`` which stores data in a SQL database
+is also available.
+
+.. cpp:class:: Encrypted_PSK_Database_SQL : public Encrypted_PSK_Database
+
+ .. cpp:function:: Encrypted_PSK_Database_SQL(const secure_vector<uint8_t>& master_key, \
+ std::shared_ptr<SQL_Database> db, \
+ const std::string& table_name)
+
+ Creates or uses the named table in ``db``. The SQL schema of the table is
+ ``(psk_name TEXT PRIMARY KEY, psk_value TEXT)``.
diff --git a/comm/third_party/botan/doc/api_ref/pubkey.rst b/comm/third_party/botan/doc/api_ref/pubkey.rst
new file mode 100644
index 0000000000..a8b93b4573
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/pubkey.rst
@@ -0,0 +1,954 @@
+Public Key Cryptography
+=================================
+
+Public key cryptography (also called asymmetric cryptography) is a collection
+of techniques allowing for encryption, signatures, and key agreement.
+
+Key Objects
+----------------------------------------
+
+Public and private keys are represented by classes ``Public_Key`` and it's
+subclass ``Private_Key``. The use of inheritance here means that a
+``Private_Key`` can be converted into a reference to a public key.
+
+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
+similarly for ``Private_Key``.
+
+Types of ``Public_Key`` include ``RSA_PublicKey``, ``DSA_PublicKey``,
+``ECDSA_PublicKey``, ``ECKCDSA_PublicKey``, ``ECGDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``,
+``Curve25519_PublicKey``, ``ElGamal_PublicKey``, ``McEliece_PublicKey``, ``XMSS_PublicKey``
+and ``GOST_3410_PublicKey``. There are corresponding ``Private_Key`` classes for each of these algorithms.
+
+.. _creating_new_private_keys:
+
+Creating New Private Keys
+----------------------------------------
+
+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
+
+.. 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*.
+
+ RSA key generation is relatively slow, and can take an unpredictable
+ amount of time. Generating a 2048 bit RSA key might take 5 to 10
+ seconds on a slow machine like a Raspberry Pi 2. Even on a fast
+ desktop it might take up to half a second. In a GUI blocking for
+ that long can be a problem. The usual approach is to perform key
+ generation in a new thread, with a animated modal UI element so the
+ user knows the application is still alive. If you wish to provide a
+ progress estimate things get a bit complicated but some library
+ users documented their approach in
+ `a blog post <https://medium.com/nexenio/indicating-progress-of-rsa-key-pair-generation-the-practical-approach-a049ba829dbe>`_.
+
+Algorithms based on the discrete-logarithm problem use 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_group`. A rough generalization is that the
+larger the group is, the more secure the algorithm is, but correspondingly the
+slower the operations will be.
+
+Given a ``DL_Group``, you can create new DSA, Diffie-Hellman and ElGamal 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:: ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+ The optional *x* parameter to each of these constructors 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_Group`` object, you can create a new ECDSA, ECKCDSA, ECGDSA,
+ECDH, or GOST 34.10-2001 private key with
+
+.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECKCDSA_PrivateKey::ECKCDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECGDSA_PrivateKey::ECGDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. _serializing_private_keys:
+
+Serializing Private Keys Using PKCS #8
+----------------------------------------
+
+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:: secure_vector<uint8_t> 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.
+
+ The currently supported PBE is PBES2 from PKCS5. Format is as follows:
+ ``PBE-PKCS5v20(CIPHER,PBKDF)``. Since 2.8.0, ``PBES2(CIPHER,PBKDF)`` also works.
+ Cipher can be any block cipher with /CBC or /GCM appended, for example
+ "AES-128/CBC" or "Camellia-256/GCM". For best interop with other systems, use
+ AES in CBC mode. The PBKDF can be either the name of a hash function (in which
+ case PBKDF2 is used with that hash) or "Scrypt", which causes the scrypt
+ memory hard password hashing function to be used. Scrypt is supported since
+ version 2.7.0.
+
+ Use `PBE-PKCS5v20(AES-256/CBC,SHA-256)` if you want to ensure the keys can
+ be imported by different software packages. Use
+ `PBE-PKCS5v20(AES-256/GCM,Scrypt)` for best security assuming you do not
+ care about interop.
+
+ For ciphers you can use anything which has an OID defined for CBC, GCM or SIV
+ modes. Currently this includes AES, Camellia, Serpent, Twofish, and SM4. Most
+ other libraries only support CBC mode for private key encryption. GCM has
+ been supported in PBES2 since 1.11.10. SIV has been supported since 2.8.
+
+.. 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 unencrypted 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:: secure_vector<uint8_t> 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 = "")
+
+These functions will return an object allocated key object based on the data
+from whatever source it is using (assuming, of course, the source is in fact
+storing a representation of a private key, and the decryption was
+successful). The encoding used (PEM or BER) need not be specified; the format
+will be detected automatically. The key is allocated with ``new``, and should
+be released with ``delete`` when you are done with it. The first takes a
+generic ``DataSource`` that you have to create - the other is a simple wrapper
+functions that take either a filename or a memory buffer and create the
+appropriate ``DataSource``.
+
+The versions taking a ``std::string`` attempt to decrypt using the password
+given (if the key is encrypted; if it is not, the passphase value will be
+ignored). If the passphrase does not decrypt the key, an exception will be
+thrown.
+
+The ones taking a ``User_Interface`` provide a simple callback interface which
+makes handling incorrect passphrases and such a bit simpler. 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.
+
+.. note::
+
+ In a future version, it is likely that ``User_Interface`` will be
+ replaced by a simple callback using ``std::function``.
+
+To use ``User_Interface``, derive a subclass and implement:
+
+.. cpp:function:: std::string User_Interface::get_passphrase(const std::string& what, \
+ const std::string& source, UI_Result& result) const
+
+ The ``what`` argument specifies what the passphrase is needed for (for
+ example, PKCS #8 key loading passes ``what`` as "PKCS #8 private key"). This
+ lets you provide the user with some indication of *why* your application is
+ asking for a passphrase; feel free to pass the string through ``gettext(3)``
+ or moral equivalent for i18n purposes. Similarly, ``source`` specifies where
+ the data in question came from, if available (for example, a file name). If
+ the source is not available for whatever reason, then ``source`` will be an
+ empty string; be sure to account for this possibility.
+
+ The function returns the passphrase as the return value, and a status code
+ in ``result`` (either ``OK`` or ``CANCEL_ACTION``). If ``CANCEL_ACTION`` is
+ returned in ``result``, then the return value will be ignored, and the
+ caller will take whatever action is necessary (typically, throwing an
+ exception stating that the passphrase couldn't be determined). In the
+ specific case of PKCS #8 key decryption, a ``Decoding_Error`` exception will
+ be thrown; your UI should assume this can happen, and provide appropriate
+ error handling (such as putting up a dialog box informing the user of the
+ situation, and canceling the operation in progress).
+
+.. _serializing_public_keys:
+
+Serializing Public Keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To import and export public keys, use:
+
+.. cpp:function:: std::vector<uint8_t> X509::BER_encode(const Public_Key& key)
+
+.. cpp:function:: std::string X509::PEM_encode(const Public_Key& key)
+
+.. cpp:function:: Public_Key* X509::load_key(DataSource& in)
+
+.. cpp:function:: Public_Key* X509::load_key(const secure_vector<uint8_t>& buffer)
+
+.. cpp:function:: Public_Key* X509::load_key(const std::string& filename)
+
+ These functions operate in the same way as the ones described in
+ :ref:`serializing_private_keys`, except that no encryption option is
+ available.
+
+.. _dl_group:
+
+DL_Group
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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 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 keys. They can also be used with
+ Diffie-Hellman and ElGamal, but this is less common. The currently available
+ groups are "dsa/jce/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)
+
+ 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 serialize a ``DL_Group`` using
+
+.. cpp:function:: secure_vector<uint8_t> DL_Group::DER_Encode(Format format)
+
+or
+
+.. cpp:function:: std::string DL_Group::PEM_encode(Format format)
+
+where *format* is any of
+
+* ``ANSI_X9_42`` (or ``DH_PARAMETERS``) for modp groups
+* ``ANSI_X9_57`` (or ``DSA_PARAMETERS``) for DSA-style groups
+* ``PKCS_3`` is an older format for modp groups; it should only
+ be used for backwards compatibility.
+
+You can reload a serialized group using
+
+.. cpp:function:: void DL_Group::BER_decode(DataSource& source, Format format)
+
+.. cpp:function:: void DL_Group::PEM_decode(DataSource& source)
+
+Code Example
+"""""""""""""""""
+The example below creates a new 2048 bit ``DL_Group``, prints the generated
+parameters and ANSI_X9_42 encodes the created group for further usage with DH.
+
+.. code-block:: cpp
+
+ #include <botan/dl_group.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+ #include <iostream>
+
+ int main()
+ {
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+ std::unique_ptr<Botan::DL_Group> group(new Botan::DL_Group(*rng.get(), Botan::DL_Group::Strong, 2048));
+ std::cout << std::endl << "p: " << group->get_p();
+ std::cout << std::endl << "q: " << group->get_q();
+ std::cout << std::endl << "g: " << group->get_q();
+ std::cout << std::endl << "ANSI_X9_42: " << std::endl << group->PEM_encode(Botan::DL_Group::ANSI_X9_42);
+
+ return 0;
+ }
+
+
+.. _ec_group:
+
+EC_Group
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An ``EC_Group`` is initialized by passing the name of the
+group to be used to the constructor. These groups have
+semi-standardized names like "secp256r1" and "brainpool512r1".
+
+Key Checking
+---------------------------------
+
+Most public key algorithms have limitations or restrictions on their
+parameters. For example RSA requires an odd exponent, and algorithms
+based on the discrete logarithm problem need a generator > 1.
+
+Each public key type has a function
+
+.. cpp:function:: bool Public_Key::check_key(RandomNumberGenerator& rng, bool strong)
+
+ This function performs a number of algorithm-specific tests that the key
+ seems to be mathematically valid and consistent, and returns true if all of
+ the tests pass.
+
+ It does not have anything to do with the validity of the key for any
+ particular use, nor does it have anything to do with certificates that link
+ a key (which, after all, is just some numbers) with a user or other
+ entity. If *strong* is ``true``, then it does "strong" checking, which
+ includes expensive operations like primality checking.
+
+As key checks are not automatically performed they must be called
+manually after loading keys from untrusted sources. If a key from an untrusted source
+is not checked, the implementation might be vulnerable to algorithm specific attacks.
+
+The following example loads the Subject Public Key from the x509 certificate ``cert.pem`` and checks the
+loaded key. If the key check fails a respective error is thrown.
+
+.. code-block:: cpp
+
+ #include <botan/x509cert.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+
+ int main()
+ {
+ Botan::X509_Certificate cert("cert.pem");
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+ std::unique_ptr<Botan::Public_Key> key(cert.subject_public_key());
+ if(!key->check_key(*rng.get(), false))
+ {
+ throw std::invalid_argument("Loaded key is invalid");
+ }
+ }
+
+Encryption
+---------------------------------
+
+Safe public key encryption requires the use of a padding scheme which hides
+the underlying mathematical properties of the algorithm. Additionally, they
+will add randomness, so encrypting the same plaintext twice produces two
+different ciphertexts.
+
+The primary interface for encryption is
+
+.. cpp:class:: PK_Encryptor
+
+ .. cpp:function:: secure_vector<uint8_t> encrypt( \
+ const uint8_t* in, size_t length, RandomNumberGenerator& rng) const
+
+ .. cpp:function:: secure_vector<uint8_t> encrypt( \
+ const std::vector<uint8_t>& in, RandomNumberGenerator& rng) const
+
+ These encrypt a message, returning the ciphertext.
+
+ .. cpp:function:: size_t maximum_input_size() const
+
+ Returns the maximum size of the message that can be processed, in
+ bytes. If you call :cpp:func:`PK_Encryptor::encrypt` with a value larger
+ than this the operation will fail with an exception.
+
+:cpp:class:`PK_Encryptor` is only an interface - to actually encrypt you have
+to create an implementation, of which there are currently three available in the
+library, :cpp:class:`PK_Encryptor_EME`, :cpp:class:`DLIES_Encryptor` and
+:cpp:class:`ECIES_Encryptor`. DLIES is a hybrid encryption scheme (from
+IEEE 1363) that uses the DH key agreement technique in combination with a KDF, a
+MAC and a symmetric encryption algorithm to perform message encryption. ECIES is
+similar to DLIES, but uses ECDH for the key agreement. Normally, public key
+encryption is done using algorithms which support it directly, such as RSA or
+ElGamal; these use the EME class:
+
+.. cpp:class:: PK_Encryptor_EME
+
+ .. cpp:function:: PK_Encryptor_EME(const Public_Key& key, std::string eme)
+
+ With *key* being the key you want to encrypt messages to. The padding
+ method to use is specified in *eme*.
+
+ The recommended values for *eme* is "EME1(SHA-1)" or "EME1(SHA-256)". If
+ you need compatibility with protocols using the PKCS #1 v1.5 standard,
+ you can also use "EME-PKCS1-v1_5".
+
+.. cpp:class:: DLIES_Encryptor
+
+ Available in the header ``dlies.h``
+
+ .. cpp:function:: DLIES_Encryptor(const DH_PrivateKey& own_priv_key, \
+ RandomNumberGenerator& rng, KDF* kdf, MessageAuthenticationCode* mac, \
+ size_t mac_key_len = 20)
+
+ Where *kdf* is a key derivation function (see
+ :ref:`key_derivation_function`) and *mac* is a
+ MessageAuthenticationCode. The encryption is performed by XORing the
+ message with a stream of bytes provided by the KDF.
+
+ .. cpp:function:: DLIES_Encryptor(const DH_PrivateKey& own_priv_key, \
+ RandomNumberGenerator& rng, KDF* kdf, Cipher_Mode* cipher, \
+ size_t cipher_key_len, MessageAuthenticationCode* mac, \
+ size_t mac_key_len = 20)
+
+ Instead of XORing the message a block cipher can be specified.
+
+.. cpp:class:: ECIES_Encryptor
+
+ Available in the header ``ecies.h``.
+
+ Parameters for encryption and decryption are set by the
+ :cpp:class:`ECIES_System_Params` class which stores the EC domain parameters,
+ the KDF (see :ref:`key_derivation_function`), the cipher (see
+ :ref:`cipher_modes`) and the MAC.
+
+ .. cpp:function:: ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, \
+ const ECIES_System_Params& ecies_params, \
+ RandomNumberGenerator& rng)
+
+ Where *private_key* is the key to use for the key agreement. The system
+ parameters are specified in *ecies_params* and the RNG to use is passed in
+ *rng*.
+
+ .. cpp:function:: ECIES_Encryptor(RandomNumberGenerator& rng, \
+ const ECIES_System_Params& ecies_params)
+
+ Creates an ephemeral private key which is used for the key agreement.
+
+The decryption classes are named :cpp:class:`PK_Decryptor`,
+:cpp:class:`PK_Decryptor_EME`, :cpp:class:`DLIES_Decryptor` and
+:cpp:class:`ECIES_Decryptor`. They are created in the exact same way, except
+they take the private key, and the processing function is named ``decrypt``.
+
+
+Botan implements the following encryption algorithms and padding schemes:
+
+1. RSA
+ - "PKCS1v15" || "EME-PKCS1-v1_5"
+ - "OAEP" || "EME-OAEP" || "EME1" || "EME1(SHA-1)" || "EME1(SHA-256)"
+#. DLIES
+#. ECIES
+#. SM2
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The following Code sample reads a PKCS #8 keypair from the passed location and
+subsequently encrypts a fixed plaintext with the included public key, using EME1
+with SHA-256. For the sake of completeness, the ciphertext is then decrypted using
+the private key.
+
+.. code-block:: cpp
+
+ #include <botan/pkcs8.h>
+ #include <botan/hex.h>
+ #include <botan/pk_keys.h>
+ #include <botan/pubkey.h>
+ #include <botan/auto_rng.h>
+ #include <botan/rng.h>
+ #include <iostream>
+ int main (int argc, char* argv[])
+ {
+ if(argc!=2)
+ return 1;
+ std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's.");
+ std::vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+
+ //load keypair
+ std::unique_ptr<Botan::Private_Key> kp(Botan::PKCS8::load_key(argv[1],*rng.get()));
+
+ //encrypt with pk
+ Botan::PK_Encryptor_EME enc(*kp,*rng.get(), "EME1(SHA-256)");
+ std::vector<uint8_t> ct = enc.encrypt(pt,*rng.get());
+
+ //decrypt with sk
+ Botan::PK_Decryptor_EME dec(*kp,*rng.get(), "EME1(SHA-256)");
+ std::cout << std::endl << "enc: " << Botan::hex_encode(ct) << std::endl << "dec: "<< Botan::hex_encode(dec.decrypt(ct));
+
+ return 0;
+ }
+
+
+Signatures
+---------------------------------
+
+Signature generation is performed using
+
+.. cpp:class:: PK_Signer
+
+ .. cpp:function:: PK_Signer(const Private_Key& key, \
+ const std::string& emsa, \
+ Signature_Format format = IEEE_1363)
+
+ Constructs a new signer object for the private key *key* using the
+ signature format *emsa*. The key must support signature operations. In
+ the current version of the library, this includes RSA, DSA, ECDSA, ECKCDSA,
+ ECGDSA, GOST 34.10-2001. Other signature schemes may be supported in the future.
+
+ .. note::
+
+ Botan both supports non-deterministic and deterministic (as per RFC
+ 6979) DSA and ECDSA signatures. Deterministic signatures are compatible
+ in the way that they can be verified with a non-deterministic implementation.
+ If the ``rfc6979`` module is enabled, deterministic DSA and ECDSA signatures
+ will be generated.
+
+ Currently available values for *emsa* include EMSA1, EMSA2, EMSA3, EMSA4,
+ and Raw. All of them, except Raw, take a parameter naming a message
+ digest function to hash the message with. The Raw encoding signs the
+ input directly; if the message is too big, the signing operation will
+ fail. Raw is not useful except in very specialized applications. Examples
+ are "EMSA1(SHA-1)" and "EMSA4(SHA-256)".
+
+ For RSA, use EMSA4 (also called PSS) unless you need compatibility with
+ software that uses the older PKCS #1 v1.5 standard, in which case use
+ EMSA3 (also called "EMSA-PKCS1-v1_5"). For DSA, ECDSA, ECKCDSA, ECGDSA and
+ GOST 34.10-2001 you should use EMSA1.
+
+ The *format* defaults to ``IEEE_1363`` which is the only available
+ format for RSA. For DSA, ECDSA, ECGDSA and ECKCDSA you can also use
+ ``DER_SEQUENCE``, which will format the signature as an ASN.1
+ SEQUENCE value.
+
+ .. cpp:function:: void update(const uint8_t* in, size_t length)
+ .. cpp:function:: void update(const std::vector<uint8_t>& in)
+ .. cpp:function:: void update(uint8_t in)
+
+ These add more data to be included in the signature
+ computation. Typically, the input will be provided directly to a
+ hash function.
+
+ .. cpp:function:: secure_vector<uint8_t> signature(RandomNumberGenerator& rng)
+
+ Creates the signature and returns it
+
+ .. cpp:function:: secure_vector<uint8_t> sign_message( \
+ const uint8_t* in, size_t length, RandomNumberGenerator& rng)
+
+ .. cpp:function:: secure_vector<uint8_t> sign_message( \
+ const std::vector<uint8_t>& in, RandomNumberGenerator& rng)
+
+ These functions are equivalent to calling
+ :cpp:func:`PK_Signer::update` and then
+ :cpp:func:`PK_Signer::signature`. Any data previously provided
+ using ``update`` will be included.
+
+Signatures are verified using
+
+.. cpp:class:: PK_Verifier
+
+ .. cpp:function:: PK_Verifier(const Public_Key& pub_key, \
+ const std::string& emsa, Signature_Format format = IEEE_1363)
+
+ Construct a new verifier for signatures associated with public
+ key *pub_key*. The *emsa* and *format* should be the same as
+ that used by the signer.
+
+ .. cpp:function:: void update(const uint8_t* in, size_t length)
+ .. cpp:function:: void update(const std::vector<uint8_t>& in)
+ .. cpp:function:: void update(uint8_t in)
+
+ Add further message data that is purportedly associated with the
+ signature that will be checked.
+
+ .. cpp:function:: bool check_signature(const uint8_t* sig, size_t length)
+ .. cpp:function:: bool check_signature(const std::vector<uint8_t>& sig)
+
+ Check to see if *sig* is a valid signature for the message data
+ that was written in. Return true if so. This function clears the
+ internal message state, so after this call you can call
+ :cpp:func:`PK_Verifier::update` to start verifying another
+ message.
+
+ .. cpp:function:: bool verify_message(const uint8_t* msg, size_t msg_length, \
+ const uint8_t* sig, size_t sig_length)
+
+ .. cpp:function:: bool verify_message(const std::vector<uint8_t>& msg, \
+ const std::vector<uint8_t>& sig)
+
+ These are equivalent to calling :cpp:func:`PK_Verifier::update`
+ on *msg* and then calling :cpp:func:`PK_Verifier::check_signature`
+ on *sig*.
+
+
+Botan implements the following signature algorithms:
+
+1. RSA
+#. DSA
+#. ECDSA
+#. ECGDSA
+#. ECKDSA
+#. GOST 34.10-2001
+#. Ed25519
+#. SM2
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following sample program below demonstrates the generation of a new ECDSA keypair over the curve secp512r1
+and a ECDSA signature using EMSA1 with SHA-256. Subsequently the computed signature is validated.
+
+.. code-block:: cpp
+
+ #include <botan/auto_rng.h>
+ #include <botan/ecdsa.h>
+ #include <botan/ec_group.h>
+ #include <botan/pubkey.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ Botan::AutoSeeded_RNG rng;
+ // Generate ECDSA keypair
+ Botan::ECDSA_PrivateKey key(rng, Botan::EC_Group("secp521r1"));
+
+ std::string text("This is a tasty burger!");
+ std::vector<uint8_t> data(text.data(),text.data()+text.length());
+ // sign data
+ Botan::PK_Signer signer(key, rng, "EMSA1(SHA-256)");
+ signer.update(data);
+ std::vector<uint8_t> signature = signer.signature(rng);
+ std::cout << "Signature:" << std::endl << Botan::hex_encode(signature);
+ // verify signature
+ Botan::PK_Verifier verifier(key, "EMSA1(SHA-256)");
+ verifier.update(data);
+ std::cout << std::endl << "is " << (verifier.check_signature(signature)? "valid" : "invalid");
+ return 0;
+ }
+
+
+Ed25519 Variants
+^^^^^^^^^^^^^^^^^^
+
+Most signature schemes in Botan follow a hash-then-sign paradigm. That is, the
+entire message is digested to a fixed length representative using a collision
+resistant hash function, and then the digest is signed. Ed25519 instead signs
+the message directly. This is beneficial, in that the Ed25519 design should
+remain secure even in the (extremely unlikely) event that a collision attack on
+SHA-512 is found. However it means the entire message must be buffered in
+memory, which can be a problem for many applications which might need to sign
+large inputs. To use this variety of Ed25519, use a padding name of "Pure".
+
+Ed25519ph (pre-hashed) instead hashes the message with SHA-512 and then signs
+the digest plus a special prefix specified in RFC 8032. To use it, specify
+padding name "Ed25519ph".
+
+Another variant of pre-hashing is used by GnuPG. There the message is digested
+with any hash function, then the digest is signed. To use it, specify any valid
+hash function. Even if SHA-512 is used, this variant is not compatible with
+Ed25519ph.
+
+For best interop with other systems, prefer "Ed25519ph".
+
+Key Agreement
+---------------------------------
+
+You can get a hold of a ``PK_Key_Agreement_Scheme`` object by calling
+``get_pk_kas`` with a key that is of a type that supports key
+agreement (such as a Diffie-Hellman key stored in a ``DH_PrivateKey``
+object), and the name of a key derivation function. This can be "Raw",
+meaning the output of the primitive itself is returned as the key, or
+"KDF1(hash)" or "KDF2(hash)" where "hash" is any string you happen to
+like (hopefully you like strings like "SHA-256" or "RIPEMD-160"), or
+"X9.42-PRF(keywrap)", which uses the PRF specified in ANSI X9.42. It
+takes the name or OID of the key wrap algorithm that will be used to
+encrypt a content encryption key.
+
+How key agreement works is that you trade public values with some
+other party, and then each of you runs a computation with the other's
+value and your key (this should return the same result to both
+parties). This computation can be called by using
+``derive_key`` with either a byte array/length pair, or a
+``secure_vector<uint8_t>`` than holds the public value of the other
+party. The last argument to either call is a number that specifies how
+long a key you want.
+
+Depending on the KDF you're using, you *might not* get back a key
+of the size you requested. In particular "Raw" will return a number
+about the size of the Diffie-Hellman modulus, and KDF1 can only return
+a key that is the same size as the output of the hash. KDF2, on the
+other hand, will always give you a key exactly as long as you request,
+regardless of the underlying hash used with it. The key returned is a
+``SymmetricKey``, ready to pass to a block cipher, MAC, or other
+symmetric algorithm.
+
+The public value that should be used can be obtained by calling
+``public_data``, which exists for any key that is associated with a
+key agreement algorithm. It returns a ``secure_vector<uint8_t>``.
+
+"KDF2(SHA-256)" is by far the preferred algorithm for key derivation
+in new applications. The X9.42 algorithm may be useful in some
+circumstances, but unless you need X9.42 compatibility, KDF2 is easier
+to use.
+
+
+Botan implements the following key agreement methods:
+
+1. ECDH over GF(p) Weierstrass curves
+#. ECDH over x25519
+#. DH over prime fields
+#. McEliece
+#. NewHope
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The code below performs an unauthenticated ECDH key agreement using the secp521r elliptic curve and
+applies the key derivation function KDF2(SHA-256) with 256 bit output length to the computed shared secret.
+
+.. code-block:: cpp
+
+ #include <botan/auto_rng.h>
+ #include <botan/ecdh.h>
+ #include <botan/ec_group.h>
+ #include <botan/pubkey.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ Botan::AutoSeeded_RNG rng;
+ // ec domain and
+ Botan::EC_Group domain("secp521r1");
+ std::string kdf = "KDF2(SHA-256)";
+ // generate ECDH keys
+ Botan::ECDH_PrivateKey keyA(rng, domain);
+ Botan::ECDH_PrivateKey keyB(rng, domain);
+ // Construct key agreements
+ Botan::PK_Key_Agreement ecdhA(keyA,rng,kdf);
+ Botan::PK_Key_Agreement ecdhB(keyB,rng,kdf);
+ // Agree on shared secret and derive symmetric key of 256 bit length
+ Botan::secure_vector<uint8_t> sA = ecdhA.derive_key(32,keyB.public_value()).bits_of();
+ Botan::secure_vector<uint8_t> sB = ecdhB.derive_key(32,keyA.public_value()).bits_of();
+
+ if(sA != sB)
+ return 1;
+
+ std::cout << "agreed key: " << std::endl << Botan::hex_encode(sA);
+ return 0;
+ }
+
+
+.. _mceliece:
+
+McEliece
+--------------------------
+
+McEliece is a cryptographic scheme based on error correcting codes which is
+thought to be resistant to quantum computers. First proposed in 1978, it is fast
+and patent-free. Variants have been proposed and broken, but with suitable
+parameters the original scheme remains secure. However the public keys are quite
+large, which has hindered deployment in the past.
+
+The implementation of McEliece in Botan was contributed by cryptosource GmbH. It
+is based on the implementation HyMES, with the kind permission of Nicolas
+Sendrier and INRIA to release a C++ adaption of their original C code under the
+Botan license. It was then modified by Falko Strenzke to add side channel and
+fault attack countermeasures. You can read more about the implementation at
+http://www.cryptosource.de/docs/mceliece_in_botan.pdf
+
+Encryption in the McEliece scheme consists of choosing a message block of size
+`n`, encoding it in the error correcting code which is the public key, then
+adding `t` bit errors. The code is created such that knowing only the public
+key, decoding `t` errors is intractable, but with the additional knowledge of
+the secret structure of the code a fast decoding technique exists.
+
+The McEliece implementation in HyMES, and also in Botan, uses an optimization to
+reduce the public key size, by converting the public key into a systemic code.
+This means a portion of the public key is a identity matrix, and can be excluded
+from the published public key. However it also means that in McEliece the
+plaintext is represented directly in the ciphertext, with only a small number of
+bit errors. Thus it is absolutely essential to only use McEliece with a CCA2
+secure scheme.
+
+One such scheme, KEM, is provided in Botan currently. It it a somewhat unusual
+scheme in that it outputs two values, a symmetric key for use with an AEAD, and
+an encrypted key. It does this by choosing a random plaintext (n - log2(n)*t
+bits) using ``McEliece_PublicKey::random_plaintext_element``. Then a random
+error mask is chosen and the message is coded and masked. The symmetric key is
+SHA-512(plaintext || error_mask). As long as the resulting key is used with a
+secure AEAD scheme (which can be used for transporting arbitrary amounts of
+data), CCA2 security is provided.
+
+In ``mcies.h`` there are functions for this combination:
+
+.. cpp:function:: secure_vector<uint8_t> mceies_encrypt(const McEliece_PublicKey& pubkey, \
+ const secure_vector<uint8_t>& pt, \
+ uint8_t ad[], size_t ad_len, \
+ RandomNumberGenerator& rng, \
+ const std::string& aead = "AES-256/OCB")
+
+.. cpp:function:: secure_vector<uint8_t> mceies_decrypt(const McEliece_PrivateKey& privkey, \
+ const secure_vector<uint8_t>& ct, \
+ uint8_t ad[], size_t ad_len, \
+ const std::string& aead = "AES-256/OCB")
+
+For a given security level (SL) a McEliece key would use
+parameters n and t, and have the corresponding key sizes listed:
+
++-----+------+-----+---------------+----------------+
+| SL | n | t | public key KB | private key KB |
++=====+======+=====+===============+================+
+| 80 | 1632 | 33 | 59 | 140 |
++-----+------+-----+---------------+----------------+
+| 107 | 2280 | 45 | 128 | 300 |
++-----+------+-----+---------------+----------------+
+| 128 | 2960 | 57 | 195 | 459 |
++-----+------+-----+---------------+----------------+
+| 147 | 3408 | 67 | 265 | 622 |
++-----+------+-----+---------------+----------------+
+| 191 | 4624 | 95 | 516 | 1234 |
++-----+------+-----+---------------+----------------+
+| 256 | 6624 | 115 | 942 | 2184 |
++-----+------+-----+---------------+----------------+
+
+You can check the speed of McEliece with the suggested parameters above
+using ``botan speed McEliece``
+
+
+eXtended Merkle Signature Scheme (XMSS)
+----------------------------------------
+
+Botan implements the single tree version of the eXtended Merkle Signature
+Scheme (XMSS) using Winternitz One Time Signatures+ (WOTS+). The implementation
+is based on `RFC 8391 "XMSS: eXtended Merkle Signature Scheme"
+<https://tools.ietf.org/html/rfc8391>`_.
+
+XMSS uses the Botan interfaces for public key cryptography.
+The following algorithms are implemented:
+
+1. XMSS-SHA2_10_256
+# XMSS-SHA2_16_256
+# XMSS-SHA2_20_256
+# XMSS-SHA2_10_512
+# XMSS-SHA2_16_512
+# XMSS-SHA2_20_512
+# XMSS-SHAKE_10_256
+# XMSS-SHAKE_16_256
+# XMSS-SHAKE_20_256
+# XMSS-SHAKE_10_512
+# XMSS-SHAKE_16_512
+# XMSS-SHAKE_20_512
+
+The algorithm name contains the hash function name, tree height and digest
+width defined by the corresponding parameter set. Choosing `XMSS-SHA2_10_256`
+for instance will use the SHA2-256 hash function to generate a tree of height
+ten.
+
+Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following code snippet shows a minimum example on how to create an XMSS
+public/private key pair and how to use these keys to create and verify a
+signature:
+
+.. code-block:: cpp
+
+ #include <iostream>
+ #include <botan/secmem.h>
+ #include <botan/auto_rng.h>
+ #include <botan/xmss.h>
+
+ int main()
+ {
+ // Create a random number generator used for key generation.
+ Botan::AutoSeeded_RNG rng;
+
+ // create a new public/private key pair using SHA2 256 as hash
+ // function and a tree height of 10.
+ Botan::XMSS_PrivateKey private_key(
+ Botan::XMSS_Parameters::xmss_algorithm_t::XMSS_SHA2_10_256,
+ rng);
+ Botan::XMSS_PublicKey public_key(private_key);
+
+ // create signature operation using the private key.
+ std::unique_ptr<Botan::PK_Ops::Signature> sig_op =
+ private_key.create_signature_op(rng, "", "");
+
+ // create and sign a message using the signature operation.
+ Botan::secure_vector<uint8_t> msg { 0x01, 0x02, 0x03, 0x04 };
+ sig_op->update(msg.data(), msg.size());
+ Botan::secure_vector<uint8_t> sig = sig_op->sign(rng);
+
+ // create verification operation using the public key
+ std::unique_ptr<Botan::PK_Ops::Verification> ver_op =
+ public_key.create_verification_op("", "");
+
+ // verify the signature for the previously generated message.
+ ver_op->update(msg.data(), msg.size());
+ if(ver_op->is_valid_signature(sig.data(), sig.size()))
+ {
+ std::cout << "Success." << std::endl;
+ }
+ else
+ {
+ std::cout << "Error." << std::endl;
+ }
+ }
diff --git a/comm/third_party/botan/doc/api_ref/python.rst b/comm/third_party/botan/doc/api_ref/python.rst
new file mode 100644
index 0000000000..e863b648b4
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/python.rst
@@ -0,0 +1,668 @@
+
+Python Binding
+========================================
+
+.. versionadded:: 1.11.14
+
+.. highlight:: python
+
+.. py:module:: botan
+
+The Python binding is based on the `ffi` module of botan and the
+`ctypes` module of the Python standard library.
+
+Starting in 2.8, the class names were renamed to match Python standard
+conventions. However aliases are defined which allow older code to
+continue to work; the older names are mentioned as "previously X".
+These aliases will be removed in a future major release.
+
+Versioning
+----------------------------------------
+.. py:function:: version_major()
+
+ Returns the major number of the library version.
+
+.. py:function:: version_minor()
+
+ Returns the minor number of the library version.
+
+.. py:function:: version_patch()
+
+ Returns the patch number of the library version.
+
+.. py:function:: version_string()
+
+ Returns a free form version string for the library
+
+Random Number Generators
+----------------------------------------
+
+.. py:class:: RandomNumberGenerator(rng_type = 'system')
+
+ Previously ``rng``
+
+ Type 'user' also allowed (userspace HMAC_DRBG seeded from system
+ rng). The system RNG is very cheap to create, as just a single file
+ handle or CSP handle is kept open, from first use until shutdown,
+ no matter how many 'system' rng instances are created. Thus it is
+ easy to use the RNG in a one-off way, with `botan.RandomNumberGenerator().get(32)`.
+
+ .. py:method:: get(length)
+
+ Return some bytes
+
+ .. py:method:: reseed(bits = 256)
+
+ Meaningless on system RNG, on userspace RNG causes a reseed/rekey
+
+ .. py:method:: reseed_from_rng(source_rng, bits = 256)
+
+ Take bits from the source RNG and use it to seed ``self``
+
+ .. py:method:: add_entropy(seed)
+
+ Add some unpredictable seed data to the RNG
+
+Hash Functions
+----------------------------------------
+
+.. py:class:: HashFunction(algo)
+
+ Previously ``hash_function``
+
+ The ``algo`` param is a string (eg 'SHA-1', 'SHA-384', 'BLAKE2b')
+
+ .. py:method:: algo_name()
+
+ Returns the name of this algorithm
+
+ .. py:method:: clear()
+
+ Clear state
+
+ .. py:method:: output_length()
+
+ Return output length in bytes
+
+ .. py:method:: update(x)
+
+ Add some input
+
+ .. py:method:: final()
+
+ Returns the hash of all input provided, resets
+ for another message.
+
+Message Authentication Codes
+----------------------------------------
+
+.. py:class:: MsgAuthCode(algo)
+
+ Previously ``message_authentication_code``
+
+ Algo is a string (eg 'HMAC(SHA-256)', 'Poly1305', 'CMAC(AES-256)')
+
+ .. py:method:: algo_name()
+
+ Returns the name of this algorithm
+
+ .. py:method:: clear()
+
+ Clear internal state including the key
+
+ .. py:method:: output_length()
+
+ Return the output length in bytes
+
+ .. py:method:: set_key(key)
+
+ Set the key
+
+ .. py:method:: update(x)
+
+ Add some input
+
+ .. py:method:: final()
+
+ Returns the MAC of all input provided, resets
+ for another message with the same key.
+
+Ciphers
+----------------------------------------
+
+.. py:class:: SymmetricCipher(object, algo, encrypt = True)
+
+ Previously ``cipher``
+
+ The algorithm is spcified as a string (eg 'AES-128/GCM',
+ 'Serpent/OCB(12)', 'Threefish-512/EAX').
+
+ Set the second param to False for decryption
+
+ .. py:method:: algo_name()
+
+ Returns the name of this algorithm
+
+ .. py:method:: tag_length()
+
+ Returns the tag length (0 for unauthenticated modes)
+
+ .. py:method:: default_nonce_length()
+
+ Returns default nonce length
+
+ .. py:method:: update_granularity()
+
+ Returns update block size. Call to update() must provide input
+ of exactly this many bytes
+
+ .. py:method:: is_authenticated()
+
+ Returns True if this is an AEAD mode
+
+ .. py:method:: valid_nonce_length(nonce_len)
+
+ Returns True if nonce_len is a valid nonce len for this mode
+
+ .. py:method:: clear()
+
+ Resets all state
+
+ .. py:method:: set_key(key)
+
+ Set the key
+
+ .. py:method:: set_assoc_data(ad)
+
+ Sets the associated data. Fails if this is not an AEAD mode
+
+ .. py:method:: start(nonce)
+
+ Start processing a message using nonce
+
+ .. py:method:: update(txt)
+
+ Consumes input text and returns output. Input text must be of
+ update_granularity() length. Alternately, always call finish
+ with the entire message, avoiding calls to update entirely
+
+ .. py:method:: finish(txt = None)
+
+ Finish processing (with an optional final input). May throw if
+ message authentication checks fail, in which case all plaintext
+ previously processed must be discarded. You may call finish()
+ with the entire message
+
+Bcrypt
+----------------------------------------
+
+.. py:function:: bcrypt(passwd, rng, work_factor = 10)
+
+ Provided the password and an RNG object, returns a bcrypt string
+
+.. py:function:: check_bcrypt(passwd, bcrypt)
+
+ Check a bcrypt hash against the provided password, returning True
+ iff the password matches.
+
+PBKDF
+----------------------------------------
+
+.. py:function:: pbkdf(algo, password, out_len, iterations = 100000, salt = None)
+
+ Runs a PBKDF2 algo specified as a string (eg 'PBKDF2(SHA-256)',
+ 'PBKDF2(CMAC(Blowfish))'). Runs with specified iterations, with
+ meaning depending on the algorithm. The salt can be provided or
+ otherwise is randomly chosen. In any case it is returned from the
+ call.
+
+ Returns out_len bytes of output (or potentially less depending on
+ the algorithm and the size of the request).
+
+ Returns tuple of salt, iterations, and psk
+
+.. py:function:: pbkdf_timed(algo, password, out_len, ms_to_run = 300, salt = rng().get(12))
+
+ Runs for as many iterations as needed to consumed ms_to_run
+ milliseconds on whatever we're running on. Returns tuple of salt,
+ iterations, and psk
+
+Scrypt
+---------------
+
+.. versionadded:: 2.8.0
+
+.. py:function:: scrypt(out_len, password, salt, N=1024, r=8, p=8)
+
+ Runs Scrypt key derivation function over the specified password
+ and salt using Scrypt parameters N, r, p.
+
+KDF
+----------------------------------------
+
+.. py:function:: kdf(algo, secret, out_len, salt)
+
+ Performs a key derviation function (such as "HKDF(SHA-384)") over
+ the provided secret and salt values. Returns a value of the
+ specified length.
+
+Public Key
+----------------------------------------
+
+.. py:class:: PublicKey(object)
+
+ Previously ``public_key``
+
+ .. py:classmethod:: load(val)
+
+ Load a public key. The value should be a PEM or DER blob.
+
+ .. py:classmethod:: load_rsa(n, e)
+
+ Load an RSA public key giving the modulus and public exponent
+ as integers.
+
+ .. py:classmethod:: load_dsa(p, q, g, y)
+
+ Load an DSA public key giving the parameters and public value
+ as integers.
+
+ .. py:classmethod:: load_dh(p, g, y)
+
+ Load an Diffie-Hellman public key giving the parameters and
+ public value as integers.
+
+ .. py:classmethod:: load_elgamal(p, q, g, y)
+
+ Load an ElGamal public key giving the parameters and
+ public value as integers.
+
+ .. py:classmethod:: load_ecdsa(curve, pub_x, pub_y)
+
+ Load an ECDSA public key giving the curve as a string
+ (like "secp256r1") and the public point as a pair of
+ integers giving the affine coordinates.
+
+ .. py:classmethod:: load_ecdh(curve, pub_x, pub_y)
+
+ Load an ECDH public key giving the curve as a string
+ (like "secp256r1") and the public point as a pair of
+ integers giving the affine coordinates.
+
+ .. py:classmethod:: load_sm2(curve, pub_x, pub_y)
+
+ Load a SM2 public key giving the curve as a string (like
+ "sm2p256v1") and the public point as a pair of integers giving
+ the affine coordinates.
+
+ .. py:method:: check_key(rng_obj, strong=True):
+
+ Test the key for consistency. If ``strong`` is ``True`` then
+ more expensive tests are performed.
+
+ .. py:method:: export(pem=False)
+
+ Exports the public key using the usual X.509 SPKI representation.
+ If ``pem`` is True, the result is a PEM encoded string. Otherwise
+ it is a binary DER value.
+
+ .. py:method:: to_der()
+
+ Like ``self.export(False)``
+
+ .. py:method:: to_pem()
+
+ Like ``self.export(True)``
+
+ .. py:method:: get_field(field_name)
+
+ Return an integer field related to the public key. The valid field names
+ vary depending on the algorithm. For example RSA public modulus can be
+ extracted with ``rsa_key.get_field("n")``.
+
+ .. py:method:: fingerprint(hash = 'SHA-256')
+
+ Returns a hash of the public key
+
+ .. py:method:: algo_name()
+
+ Returns the algorithm name
+
+ .. py:method:: estimated_strength()
+
+ Returns the estimated strength of this key against known attacks
+ (NFS, Pollard's rho, etc)
+
+Private Key
+----------------------------------------
+
+.. py:class:: PrivateKey
+
+ Previously ``private_key``
+
+ .. py:classmethod:: create(algo, param, rng)
+
+ Creates a new private key. The parameter type/value depends on
+ the algorithm. For "rsa" is is the size of the key in bits.
+ For "ecdsa" and "ecdh" it is a group name (for instance
+ "secp256r1"). For "ecdh" there is also a special case for group
+ "curve25519" (which is actually a completely distinct key type
+ with a non-standard encoding).
+
+ .. py:classmethod:: load(val, passphrase="")
+
+ Return a private key (DER or PEM formats accepted)
+
+ .. py:classmethod:: load_rsa(p, q, e)
+
+ Return a private RSA key
+
+ .. py:classmethod:: load_dsa(p, q, g, x)
+
+ Return a private DSA key
+
+ .. py:classmethod:: load_dh(p, g, x)
+
+ Return a private DH key
+
+ .. py:classmethod:: load_elgamal(p, q, g, x)
+
+ Return a private ElGamal key
+
+ .. py:classmethod:: load_ecdsa(curve, x)
+
+ Return a private ECDSA key
+
+ .. py:classmethod:: load_ecdh(curve, x)
+
+ Return a private ECDH key
+
+ .. py:classmethod:: load_sm2(curve, x)
+
+ Return a private SM2 key
+
+ .. py:method:: get_public_key()
+
+ Return a public_key object
+
+ .. py:method:: to_pem()
+
+ Return the PEM encoded private key (unencrypted). Like ``self.export(True)``
+
+ .. py:method:: to_der()
+
+ Return the PEM encoded private key (unencrypted). Like ``self.export(False)``
+
+ .. py:method:: check_key(rng_obj, strong=True):
+
+ Test the key for consistency. If ``strong`` is ``True`` then
+ more expensive tests are performed.
+
+ .. py:method:: algo_name()
+
+ Returns the algorithm name
+
+ .. py:method:: export(pem=False)
+
+ Exports the private key in PKCS8 format. If ``pem`` is True, the
+ result is a PEM encoded string. Otherwise it is a binary DER
+ value. The key will not be encrypted.
+
+ .. py:method:: export_encrypted(passphrase, rng, pem=False, msec=300, cipher=None, pbkdf=None)
+
+ Exports the private key in PKCS8 format, encrypted using the
+ provided passphrase. If ``pem`` is True, the result is a PEM
+ encoded string. Otherwise it is a binary DER value.
+
+ .. py:method:: get_field(field_name)
+
+ Return an integer field related to the public key. The valid field names
+ vary depending on the algorithm. For example first RSA secret prime can be
+ extracted with ``rsa_key.get_field("p")``. This function can also be
+ used to extract the public parameters.
+
+Public Key Operations
+----------------------------------------
+
+.. py:class:: PKEncrypt(pubkey, padding)
+
+ Previously ``pk_op_encrypt``
+
+ .. py:method:: encrypt(msg, rng)
+
+.. py:class:: PKDecrypt(privkey, padding)
+
+ Previously ``pk_op_decrypt``
+
+ .. py:method:: decrypt(msg)
+
+.. py:class:: PKSign(privkey, hash_w_padding)
+
+ Previously ``pk_op_sign``
+
+ .. py:method:: update(msg)
+ .. py:method:: finish(rng)
+
+.. py:class:: PKVerify(pubkey, hash_w_padding)
+
+ Previously ``pk_op_verify``
+
+ .. py:method:: update(msg)
+ .. py:method:: check_signature(signature)
+
+.. py:class:: PKKeyAgreement(privkey, kdf)
+
+ Previously ``pk_op_key_agreement``
+
+ .. py:method:: public_value()
+
+ Returns the public value to be passed to the other party
+
+ .. py:method:: agree(other, key_len, salt)
+
+ Returns a key derived by the KDF.
+
+Multiple Precision Integers (MPI)
+-------------------------------------
+.. versionadded:: 2.8.0
+
+.. py:class:: MPI(initial_value=None, radix=None)
+
+ Initialize an MPI object with specified value, left as zero otherwise. The
+ ``initial_value`` should be an ``int``, ``str``, or ``MPI``.
+ The ``radix`` value should be set to 16 when initializing from a base 16 `str` value.
+
+
+ Most of the usual arithmetic operators (``__add__``, ``__mul__``, etc) are
+ defined.
+
+ .. py:method:: inverse_mod(modulus)
+
+ Return the inverse of ``self`` modulo ``modulus``, or zero if no inverse exists
+
+ .. py:method:: is_prime(rng, prob=128)
+
+ Test if ``self`` is prime
+
+ .. py:method:: pow_mod(exponent, modulus):
+
+ Return ``self`` to the ``exponent`` power modulo ``modulus``
+
+ .. py:method:: mod_mul(other, modulus):
+
+ Return the multiplication product of ``self`` and ``other`` modulo ``modulus``
+
+ .. py:method:: gcd(other):
+
+ Return the greatest common divisor of ``self`` and ``other``
+
+
+Format Preserving Encryption (FE1 scheme)
+-----------------------------------------
+.. versionadded:: 2.8.0
+
+.. py:class:: FormatPreservingEncryptionFE1(modulus, key, rounds=5, compat_mode=False)
+
+ Initialize an instance for format preserving encryption
+
+ .. py:method:: encrypt(msg, tweak)
+
+ The msg should be a botan2.MPI or an object which can be converted to one
+
+ .. py:method:: decrypt(msg, tweak)
+
+ The msg should be a botan2.MPI or an object which can be converted to one
+
+HOTP
+-----------------------------------------
+.. versionadded:: 2.8.0
+
+.. py:class:: HOTP(key, hash="SHA-1", digits=6)
+
+ .. py:method:: generate(counter)
+
+ Generate an HOTP code for the provided counter
+
+ .. py:method:: check(code, counter, resync_range=0)
+
+ Check if provided ``code`` is the correct code for ``counter``.
+ If ``resync_range`` is greater than zero, HOTP also checks
+ up to ``resync_range`` following counter values.
+
+ Returns a tuple of (bool,int) where the boolean indicates if the
+ code was valid, and the int indicates the next counter value
+ that should be used. If the code did not verify, the next
+ counter value is always identical to the counter that was passed
+ in. If the code did verify and resync_range was zero, then the
+ next counter will always be counter+1.
+
+X509Cert
+-----------------------------------------
+
+.. py:class:: X509Cert(filename=None, buf=None)
+
+ .. py:method:: time_starts()
+
+ Return the time the certificate becomes valid, as a string in form
+ "YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
+ relative to UTC.
+
+ .. py:method:: time_expires()
+
+ Return the time the certificate expires, as a string in form
+ "YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
+ relative to UTC.
+
+ .. py:method:: to_string()
+
+ Format the certificate as a free-form string.
+
+ .. py:method:: fingerprint(hash_algo='SHA-256')
+
+ 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.
+
+ .. py:method:: serial_number()
+
+ Return the serial number of the certificate.
+
+ .. py:method:: authority_key_id()
+
+ Return the authority key ID set in the certificate, which may be empty.
+
+ .. py:method:: subject_key_id()
+
+ Return the subject key ID set in the certificate, which may be empty.
+
+ .. py:method:: subject_public_key_bits()
+
+ Get the serialized representation of the public key included in this certificate.
+
+ .. py:method:: subject_public_key()
+
+ Get the public key included in this certificate as an object of class ``PublicKey``.
+
+ .. py:method:: subject_dn(key, index)
+
+ Get a value from the subject DN field.
+
+ ``key`` specifies a value to get, for instance ``"Name"`` or `"Country"`.
+
+ .. py:method:: issuer_dn(key, index)
+
+ Get a value from the issuer DN field.
+
+ ``key`` specifies a value to get, for instance ``"Name"`` or `"Country"`.
+
+ .. py:method:: hostname_match(hostname)
+
+ Return True if the Common Name (CN) field of the certificate matches a given ``hostname``.
+
+ .. py:method:: not_before()
+
+ Return the time the certificate becomes valid, as seconds since epoch.
+
+ .. py:method:: not_after()
+
+ Return the time the certificate expires, as seconds since epoch.
+
+ .. py:method:: allowed_usage(usage_list)
+
+ Return True if the certificates Key Usage extension contains all constraints given in ``usage_list``.
+ Also return True if the certificate doesn't have this extension.
+ Example usage constraints are: ``"DIGITAL_SIGNATURE"``, ``"KEY_CERT_SIGN"``, ``"CRL_SIGN"``.
+
+ .. py:method:: verify(intermediates=None, \
+ trusted=None, \
+ trusted_path=None, \
+ required_strength=0, \
+ hostname=None, \
+ reference_time=0 \
+ crls=None)
+
+ Verify a certificate. Returns 0 if validation was successful, returns a positive error code
+ if the validation was unsuccesful.
+
+ ``intermediates`` is a list of untrusted subauthorities.
+
+ ``trusted`` is a list of trusted root CAs.
+
+ The `trusted_path` refers to a directory where one or more trusted CA
+ certificates are stored.
+
+ Set ``required_strength`` to indicate the minimum key and hash strength
+ that is allowed. For instance setting to 80 allows 1024-bit RSA and SHA-1.
+ Setting to 110 requires 2048-bit RSA and SHA-256 or higher. Set to zero
+ to accept a default.
+
+ If ``hostname`` is given, it will be checked against the certificates CN field.
+
+ Set ``reference_time`` to be the time which the certificate chain is
+ validated against. Use zero (default) to use the current system clock.
+
+ ``crls`` is a list of CRLs issued by either trusted or untrusted authorities.
+
+ .. py:classmethod:: validation_status(error_code)
+
+ Return an informative string associated with the verification return code.
+
+ .. py:method:: is_revoked(self, crl)
+
+ Check if the certificate (``self``) is revoked on the given ``crl``.
+
+X509CRL
+-----------------------------------------
+
+.. py:class:: X509CRL(filename=None, buf=None)
+
+ Class representing an X.509 Certificate Revocation List.
+
+ A CRL in PEM or DER format can be loaded from a file, with the ``filename`` argument,
+ or from a bytestring, with the ``buf`` argument.
+
+
+
+
+
+
diff --git a/comm/third_party/botan/doc/api_ref/rng.rst b/comm/third_party/botan/doc/api_ref/rng.rst
new file mode 100644
index 0000000000..01c27f73cf
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/rng.rst
@@ -0,0 +1,281 @@
+.. _random_number_generators:
+
+Random Number Generators
+========================================
+
+.. cpp:class:: RandomNumberGenerator
+
+ The base class for all RNG objects, is declared in ``rng.h``.
+
+ .. cpp:function:: void randomize(uint8_t* output_array, size_t length)
+
+ Places *length* random bytes into the provided buffer.
+
+ .. cpp:function:: void randomize_with_input(uint8_t* data, size_t length, \
+ const uint8_t* extra_input, size_t extra_input_len)
+
+ Like randomize, but first incorporates the additional input field into the
+ state of the RNG. The additional input could be anything which
+ parameterizes this request. Not all RNG types accept additional inputs,
+ the value will be silently ignored when not supported.
+
+ .. cpp:function:: void randomize_with_ts_input(uint8_t* data, size_t length)
+
+ Creates a buffer with some timestamp values and calls ``randomize_with_input``
+
+ .. note::
+
+ When RDRAND is enabled and available at runtime, instead of timestamps
+ the output of RDRAND is used as the additional data.
+
+ .. cpp:function:: uint8_t next_byte()
+
+ Generates a single random byte and returns it. Note that calling this
+ function several times is much slower than calling ``randomize`` once to
+ produce multiple bytes at a time.
+
+ .. cpp:function:: void add_entropy(const uint8_t* data, size_t length)
+
+ Incorporates provided data into the state of the PRNG, if at all possible.
+ This works for most RNG types, including the system and TPM RNGs. But if
+ the RNG doesn't support this operation, the data is dropped, no error is
+ indicated.
+
+ .. cpp:function:: bool accepts_input() const
+
+ This function returns ``false`` if it is known that this RNG object cannot
+ accept external inputs. In this case, any calls to
+ :cpp:func:`RandomNumberGenerator::add_entropy` will be ignored.
+
+ .. cpp:function:: void reseed_from_rng(RandomNumberGenerator& rng, \
+ size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS)
+
+ Reseed by calling ``rng`` to acquire ``poll_bits`` data.
+
+
+RNG Types
+----------------------------------------
+
+Several different RNG types are implemented. Some access hardware RNGs, which
+are only available on certain platforms. Others are mostly useful in specific
+situations.
+
+Generally prefer using the system RNG, or if not available use ``AutoSeeded_RNG``
+which is intended to provide best possible behavior in a userspace PRNG.
+
+System_RNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+On systems which support it, in ``system_rng.h`` you can access a shared
+reference to a process global instance of the system PRNG (using interfaces such
+as ``/dev/urandom``, ``getrandom``, ``arc4random``, or ``RtlGenRandom``):
+
+.. cpp:function:: RandomNumberGenerator& system_rng()
+
+ Returns a reference to the system RNG
+
+There is also a wrapper class ``System_RNG`` which simply invokes on
+the return value of ``system_rng()``. This is useful in situations where
+you may sometimes want to use the system RNG and a userspace RNG in others,
+for example::
+
+ std::unique_ptr<Botan::RandomNumberGenerator> rng;
+ #if defined(BOTAN_HAS_SYSTEM_RNG)
+ rng.reset(new System_RNG);
+ #else
+ rng.reset(new AutoSeeded_RNG);
+ #endif
+
+Unlike nearly any other object in Botan it is acceptable to share a single
+instance of ``System_RNG`` between threads, because the underlying RNG is itself
+thread safe due to being serialized by a mutex in the kernel itself.
+
+AutoSeeded_RNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+AutoSeeded_RNG is type naming a 'best available' userspace PRNG. The
+exact definition of this has changed over time and may change in the
+future, fortunately there is no compatibility concerns when changing
+any RNG since the only expectation is it produces bits
+indistinguishable from random.
+
+.. note:: Starting in 2.16.0, AutoSeeded_RNG uses an internal lock and so is
+ safe to share among threads. However if possible it is still better to
+ use a RNG per thread as otherwise the RNG object needlessly creates a
+ point of contention. In previous versions, the RNG does not have an
+ internal lock and all access to it must be serialized.
+
+The current version uses HMAC_DRBG with either SHA-384 or SHA-256. The
+initial seed is generated either by the system PRNG (if available) or
+a default set of entropy sources. These are also used for periodic
+reseeding of the RNG state.
+
+HMAC_DRBG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+HMAC DRBG is a random number generator designed by NIST and specified
+in SP 800-90A. It seems to be the most conservative generator of the
+NIST approved options.
+
+It can be instantiated with any HMAC but is typically used with
+SHA-256, SHA-384, or SHA-512, as these are the hash functions approved
+for this use by NIST.
+
+HMAC_DRBG's constructors are:
+
+.. cpp:class:: HMAC_DRBG
+
+ .. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
+ RandomNumberGenerator& underlying_rng, \
+ size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
+ size_t max_number_of_bytes_per_request = 64 * 1024)
+
+ Creates a DRBG which will automatically reseed as required by making
+ calls to ``underlying_rng`` either after being invoked
+ ``reseed_interval`` times, or if use of ``fork`` system call is
+ detected.
+
+ You can disable automatic reseeding by setting ``reseed_interval`` to
+ zero, in which case ``underlying_rng`` will only be invoked in the case
+ of ``fork``.
+
+ The specification of HMAC DRBG requires that each invocation produce no
+ more than 64 kibibytes of data. However, the RNG interface allows
+ producing arbitrary amounts of data in a single request. To accommodate
+ this, ``HMAC_DRBG`` treats requests for more data as if they were
+ multiple requests each of (at most) the maximum size. You can specify a
+ smaller maximum size with ``max_number_of_bytes_per_request``. There is
+ normally no reason to do this.
+
+ .. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
+ Entropy_Sources& entropy_sources, \
+ size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
+ size_t max_number_of_bytes_per_request = 64 * 1024)
+
+ Like above function, but instead of an RNG taking a set of entropy
+ sources to seed from as required.
+
+ .. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
+ RandomNumberGenerator& underlying_rng, \
+ Entropy_Sources& entropy_sources, \
+ size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
+ size_t max_number_of_bytes_per_request = 64 * 1024)
+
+ Like above function, but taking both an RNG and a set of entropy
+ sources to seed from as required.
+
+ .. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf)
+
+ Creates an unseeded DRBG. You must explicitly provide seed data later
+ on in order to use this RNG. This is primarily useful for deterministic
+ key generation.
+
+ Since no source of data is available to automatically reseed, automatic
+ reseeding is disabled when this constructor is used. If the RNG object
+ detects that ``fork`` system call was used without it being
+ subsequently reseeded, it will throw an exception.
+
+ .. cpp:function:: HMAC_DRBG(const std::string& hmac_hash)
+
+ Like the constructor just taking a PRF, except instead of a PRF object,
+ a string specifying what hash to use with HMAC is provided.
+
+ChaCha_RNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is a very fast userspace PRNG based on ChaCha20 and HMAC(SHA-256). The key
+for ChaCha is derived by hashing entropy inputs with HMAC. Then the ChaCha
+keystream generator is run, first to generate the new HMAC key (used for any
+future entropy additions), then the desired RNG outputs.
+
+This RNG composes two primitives thought to be secure (ChaCha and HMAC) in a
+simple and well studied way (the extract-then-expand paradigm), but is still an
+ad-hoc and non-standard construction. It is included because it is roughly 20x
+faster then HMAC_DRBG (basically running as fast as ChaCha can generate
+keystream bits), and certain applications need access to a very fast RNG.
+
+One thing applications using ``ChaCha_RNG`` need to be aware of is that for
+performance reasons, no backtracking resistance is implemented in the RNG
+design. An attacker who recovers the ``ChaCha_RNG`` state can recover the output
+backwards in time to the last rekey and forwards to the next rekey.
+
+An explicit reseeding (:cpp:func:`RandomNumberGenerator::add_entropy`) or
+providing any input to the RNG
+(:cpp:func:`RandomNumberGenerator::randomize_with_ts_input`,
+:cpp:func:`RandomNumberGenerator::randomize_with_input`) is sufficient to cause
+a reseeding. Or, if a RNG or entropy source was provided to the ``ChaCha_RNG``
+constructor, then reseeding will be performed automatically after a certain
+interval of requests.
+
+Processor_RNG
+^^^^^^^^^^^^^^^^^
+
+This RNG type directly invokes a CPU instruction capable of generating
+a cryptographically secure random number. On x86 it uses ``rdrand``,
+on POWER ``darn``. If the relevant instruction is not available, the
+constructor of the class will throw at runtime. You can test
+beforehand by checking the result of ``Processor_RNG::available()``.
+
+TPM_RNG
+^^^^^^^^^^^^^^^^^
+
+This RNG type allows using the RNG exported from a TPM chip.
+
+PKCS11_RNG
+^^^^^^^^^^^^^^^^^
+
+This RNG type allows using the RNG exported from a hardware token accessed via PKCS11.
+
+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.
+
+The following entropy sources are currently used:
+
+ * The system RNG (``arc4random``, ``/dev/urandom``, or ``RtlGenRandom``).
+ * RDRAND and RDSEED are used if available, but not counted as contributing entropy
+ * ``/dev/random`` and ``/dev/urandom``. This may be redundant with the system RNG
+ * ``getentropy``, only used on OpenBSD currently
+ * ``/proc`` walk: read files in ``/proc``. Last ditch protection against
+ flawed system RNG.
+ * Win32 stats: takes snapshot of current system processes. Last ditch
+ protection against flawed system RNG.
+
+Fork Safety
+---------------------------------
+
+On Unix platforms, the ``fork()`` and ``clone()`` system calls can
+be used to spawn a new child process. Fork safety ensures that the
+child process doesn't see the same output of random bytes as the
+parent process. Botan tries to ensure fork safety by feeding the
+process ID into the internal state of the random generator and by
+automatically reseeding the random generator if the process ID
+changed between two requests of random bytes. However, this does
+not protect against PID wrap around. The process ID is usually
+implemented as a 16 bit integer. In this scenario, a process will
+spawn a new child process, which exits the parent process and
+spawns a new child process himself. If the PID wrapped around, the
+second child process may get assigned the process ID of it's
+grandparent and the fork safety can not be ensured.
+
+Therefore, it is strongly recommended to explicitly reseed any
+userspace random generators after forking a new process. If this is
+not possible in your application, prefer using the system PRNG
+instead.
diff --git a/comm/third_party/botan/doc/api_ref/roughtime.rst b/comm/third_party/botan/doc/api_ref/roughtime.rst
new file mode 100644
index 0000000000..8e6cd7c20d
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/roughtime.rst
@@ -0,0 +1,6 @@
+Roughtime
+===========
+
+.. versionadded:: 2.13.0
+
+Botan includes a Roughtime client, available in ``botan/roughtime.h``
diff --git a/comm/third_party/botan/doc/api_ref/secmem.rst b/comm/third_party/botan/doc/api_ref/secmem.rst
new file mode 100644
index 0000000000..8dd479b7e8
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/secmem.rst
@@ -0,0 +1,31 @@
+
+Memory container
+========================================
+
+A major concern with mixing modern multi-user OSes and cryptographic
+code is that at any time the code (including secret keys) could be
+swapped to disk, where it can later be read by an attacker, or left
+floating around in memory for later retrieval.
+
+For this reason the library uses a ``std::vector`` with a custom
+allocator that will zero memory before deallocation, named via typedef
+as ``secure_vector``. Because it is simply a STL vector with a custom
+allocator, it has an identical API to the ``std::vector`` you know and
+love.
+
+Some operating systems offer the ability to lock memory into RAM,
+preventing swapping from occurring. Typically this operation is
+restricted to privileged users (root or admin), however some OSes
+including Linux and FreeBSD allow normal users to lock a small amount
+of memory. On these systems, allocations first attempt to allocate out
+of this small locked pool, and then if that fails will fall back to
+normal heap allocations.
+
+The ``secure_vector`` template is only meant for primitive data types
+(bytes or ints): if you want a container of higher level Botan
+objects, you can just use a ``std::vector``, since these objects know
+how to clear themselves when they are destroyed. You cannot, however,
+have a ``std::vector`` (or any other container) of ``Pipe`` objects or
+filters, because these types have pointers to other filters, and
+implementing copy constructors for these types would be both hard and
+quite expensive (vectors of pointers to such objects is fine, though).
diff --git a/comm/third_party/botan/doc/api_ref/srp.rst b/comm/third_party/botan/doc/api_ref/srp.rst
new file mode 100644
index 0000000000..cf0386b539
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/srp.rst
@@ -0,0 +1,77 @@
+Secure Remote Password
+========================================
+
+The library contains an implementation of the
+`SRP6-a <http://srp.stanford.edu/design.html>`_ password authenticated
+key exchange protocol in ``srp6.h``.
+
+A SRP client provides what is called a SRP *verifier* to the server.
+This verifier is based on a password, but the password cannot be
+easily derived from the verifier (however brute force attacks are
+possible). Later, the client and server can perform an SRP exchange,
+which results in a shared secret key. This key can be used for mutual
+authentication and/or encryption.
+
+SRP works in a discrete logarithm group. Special parameter sets for
+SRP6 are defined, denoted in the library as "modp/srp/<size>", for
+example "modp/srp/2048".
+
+.. warning::
+
+ While knowledge of the verifier does not easily allow an attacker
+ to get the raw password, they could still use the verifier to
+ impersonate the server to the client, so verifiers should be
+ protected as carefully as a plaintext password would be.
+
+.. cpp:function:: BigInt generate_srp6_verifier( \
+ const std::string& username, \
+ const std::string& password, \
+ const std::vector<uint8_t>& salt, \
+ const std::string& group_id, \
+ const std::string& hash_id)
+
+ Generates a new verifier using the specified password and salt.
+ This is stored by the server. The salt must also be stored. Later,
+ the given username and password are used to by the client during
+ the key agreement step.
+
+.. cpp:function:: std::string srp6_group_identifier( \
+ const BigInt& N, const BigInt& g)
+
+.. cpp:class:: SRP6_Server_Session
+
+ .. cpp:function:: BigInt step1(const BigInt& v, \
+ const std::string& group_id, \
+ const std::string& hash_id, \
+ RandomNumberGenerator& rng)
+
+ Takes a verifier (generated by generate_srp6_verifier) along
+ with the group_id, and output a value `B` which is provided to
+ the client.
+
+ .. cpp:function:: SymmetricKey step2(const BigInt& A)
+
+ Takes the parameter A generated by srp6_client_agree,
+ and return the shared secret key.
+
+ In the event of an impersonation attack (or wrong username/password, etc)
+ no error occurs, but the key returned will be different on the two sides.
+ The two sides must verify each other, for example by using the shared
+ secret to key an HMAC and then exchanging authenticated messages.
+
+.. cpp:function:: std::pair<BigInt,SymmetricKey> srp6_client_agree( \
+ const std::string& username, \
+ const std::string& password, \
+ const std::string& group_id, \
+ const std::string& hash_id, \
+ const std::vector<uint8_t>& salt, \
+ const BigInt& B, \
+ RandomNumberGenerator& rng)
+
+ The client receives these parameters from the server, except for
+ the username and password which are provided by the user. The
+ parameter B is the output of `step1`.
+
+ The client agreement step outputs a shared symmetric key along
+ with the parameter A which is returned to the server (and allows
+ it the compute the shared key).
diff --git a/comm/third_party/botan/doc/api_ref/stream_ciphers.rst b/comm/third_party/botan/doc/api_ref/stream_ciphers.rst
new file mode 100644
index 0000000000..dfee40970f
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/stream_ciphers.rst
@@ -0,0 +1,211 @@
+Stream Ciphers
+========================
+
+In contrast to block ciphers, stream ciphers operate on a plaintext stream
+instead of blocks. Thus encrypting data results in changing the internal state
+of the cipher and encryption of plaintext with arbitrary length is possible in
+one go (in byte amounts). All implemented stream ciphers derive from the base
+class :cpp:class:`StreamCipher` (`botan/stream_cipher.h`).
+
+.. warning::
+
+ Using a stream cipher without an authentication code is extremely insecure,
+ because an attacker can trivially modify messages. Prefer using an
+ authenticated cipher mode such as GCM or SIV.
+
+.. warning::
+
+ Encrypting more than one message with the same key requires careful management
+ of initialization vectors. Otherwise the keystream will be reused, which causes
+ the security of the cipher to completely fail.
+
+.. cpp:class:: StreamCipher
+
+ .. cpp:function:: std::string name() const
+
+ Returns a human-readable string of the name of this algorithm.
+
+ .. cpp:function:: void clear()
+
+ Clear the key.
+
+ .. cpp:function:: StreamCipher* clone() const
+
+ Return a newly allocated object of the same type as this one.
+
+ .. cpp:function:: void set_key(const uint8_t* key, size_t length)
+
+ Set the stream cipher key. If the length is not accepted, an
+ ``Invalid_Key_Length`` exception is thrown.
+
+ .. cpp:function:: bool valid_keylength(size_t length) const
+
+ This function returns true if and only if *length* is a valid
+ keylength for the algorithm.
+
+ .. cpp:function:: size_t minimum_keylength() const
+
+ Return the smallest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptable for the
+ algorithm.
+
+ .. cpp:function:: bool valid_iv_length(size_t iv_len) const
+
+ This function returns true if and only if *length* is a valid IV length for
+ the stream cipher. Some ciphers do not support IVs at all, and will return
+ false for any value except zero.
+
+ .. cpp:function:: size_t default_iv_length() const
+
+ Returns some default IV size, normally the largest IV supported by the cipher.
+ If this function returns zero, then IVs are not supported and any call to
+ ``set_iv`` with a non-empty value will fail.
+
+ .. cpp:function:: void set_iv(const uint8_t*, size_t len)
+
+ Load IV into the stream cipher state. This should happen after the key is
+ set and before any operation (encrypt/decrypt/seek) is called.
+
+ If the cipher does not support IVs, then a call with ``len`` equal to zero
+ will be accepted and any other length will cause a ``Invalid_IV_Length``
+ exception.
+
+ .. cpp:function:: void seek(uint64_t offset)
+
+ Sets the state of the stream cipher and keystream according to the passed
+ *offset*, exactly as if *offset* bytes had first been encrypted. The key
+ and (if required) the IV have to be set before this can be called. Not all
+ ciphers support seeking; such objects will throw ``Not_Implemented`` in
+ this case.
+
+ .. cpp:function:: void cipher(const uint8_t* in, uint8_t* out, size_t n)
+
+ Processes *n* bytes plain/ciphertext from *in* and writes the result to *out*.
+
+ .. cpp:function:: void cipher1(uint8_t* inout, size_t n)
+
+ Processes *n* bytes plain/ciphertext in place. Acts like :cpp:func:`cipher`\ (inout, inout, n).
+
+ .. cpp:function:: void encipher(std::vector<uint8_t> inout)
+ .. cpp:function:: void encrypt(std::vector<uint8_t> inout)
+ .. cpp:function:: void decrypt(std::vector<uint8_t> inout)
+
+ Processes plain/ciphertext *inout* in place. Acts like :cpp:func:`cipher`\ (inout.data(), inout.data(), inout.size()).
+
+Code Example
+-----------------
+
+The following code encrypts a provided plaintext using ChaCha20.
+
+.. code-block:: cpp
+
+ #include <botan/stream_cipher.h>
+ #include <botan/auto_rng.h>
+ #include <botan/hex.h>
+ #include <iostream>
+
+ int main()
+ {
+ std::string plaintext("This is a tasty burger!");
+ std::vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
+ const std::vector<uint8_t> key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
+ std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create("ChaCha(20)"));
+
+ //generate fresh nonce (IV)
+ std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
+ std::vector<uint8_t> iv(8);
+ rng->randomize(iv.data(),iv.size());
+
+ //set key and IV
+ cipher->set_key(key);
+ cipher->set_iv(iv.data(),iv.size());
+ cipher->encipher(pt);
+
+ std::cout << cipher->name() << " with iv " << Botan::hex_encode(iv) << ": "
+ << Botan::hex_encode(pt) << "\n";
+ return 0;
+ }
+
+Available Stream Ciphers
+----------------------------
+
+Botan provides the following stream ciphers. If in doubt use ChaCha20 or CTR(AES-256).
+
+CTR-BE
+~~~~~~~
+
+A cipher mode that converts a block cipher into a stream cipher. It offers
+parallel execution and can seek within the output stream, both useful
+properties.
+
+CTR mode requires an IV which can be any length up to the block size of the
+underlying cipher. If it is shorter than the block size, sufficient zero bytes
+are appended.
+
+It is possible to choose the width of the counter portion, which can improve
+performance somewhat, but limits the maximum number of bytes that can safely be
+encrypted. Different protocols have different conventions for the width of the
+counter portion. This is done by specifying with width (which must be at least 4
+bytes, allowing to encrypt 2\ :sup:`32` blocks of data) for example
+"CTR(AES-256,8)" to select a 64-bit counter.
+
+(The ``-BE`` suffix refers to big-endian convention for the counter.
+This is the most common case.)
+
+OFB
+~~~~~
+
+Another stream cipher based on a block cipher. Unlike CTR mode, it does not
+allow parallel execution or seeking within the output stream. Prefer CTR.
+
+Available if ``BOTAN_HAS_OFB`` is defined.
+
+ChaCha
+~~~~~~~~
+
+A very fast cipher, now widely deployed in TLS as part of the ChaCha20Poly1305
+AEAD. Can be used with 8 (fast but dangerous), 12 (balance), or 20 rounds
+(conservative). Even with 20 rounds, ChaCha is very fast. Use 20 rounds.
+
+ChaCha supports an optional IV (which defaults to all zeros). It can be of
+length 64, 96 or (since 2.8) 192 bits. Using ChaCha with a 192 bit nonce is also
+known as XChaCha.
+
+Available if ``BOTAN_HAS_CHACHA`` is defined.
+
+Salsa20
+~~~~~~~~~
+
+An earlier iteration of the ChaCha design, this cipher is popular due to its use
+in the libsodium library. Prefer ChaCha.
+
+Salsa supports an optional IV (which defaults to all zeros). It can be of length
+64 or 192 bits. Using Salsa with a 192 bit nonce is also known as XSalsa.
+
+Available if ``BOTAN_HAS_SALSA20`` is defined.
+
+SHAKE-128
+~~~~~~~~~~~~
+
+This is the SHAKE-128 XOF exposed as a stream cipher. It is slower than ChaCha
+and somewhat obscure. It does not support IVs or seeking within the cipher
+stream.
+
+Available if ``BOTAN_HAS_SHAKE_CIPHER`` is defined.
+
+RC4
+~~~~
+
+An old and very widely deployed stream cipher notable for its simplicity. It
+does not support IVs or seeking within the cipher stream.
+
+.. warning::
+
+ RC4 is now badly broken. **Avoid in new code** and use only if required for
+ compatibility with existing systems.
+
+Available if ``BOTAN_HAS_RC4`` is defined.
diff --git a/comm/third_party/botan/doc/api_ref/tls.rst b/comm/third_party/botan/doc/api_ref/tls.rst
new file mode 100644
index 0000000000..fdffeda26a
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/tls.rst
@@ -0,0 +1,1926 @@
+Transport Layer Security (TLS)
+========================================
+
+.. versionadded:: 1.11.0
+
+Botan has client and server implementations of various versions of the
+TLS protocol, including TLS v1.0, TLS v1.1, and TLS v1.2. As of
+version 1.11.13, support for the insecure SSLv3 protocol has been
+removed.
+
+There is also support for DTLS (v1.0 and v1.2), a variant of TLS
+adapted for operation on datagram transports such as UDP and
+SCTP. DTLS support should be considered as beta quality and further
+testing is invited.
+
+The TLS implementation does not know anything about sockets or the
+network layer. Instead, it calls a user provided callback (hereafter
+``output_fn``) whenever it has data that it would want to send to the
+other party (for instance, by writing it to a network socket), and
+whenever the application receives some data from the counterparty (for
+instance, by reading from a network socket) it passes that information
+to TLS using :cpp:func:`TLS::Channel::received_data`. If the data
+passed in results in some change in the state, such as a handshake
+completing, or some data or an alert being received from the other
+side, then the appropriate user provided callback will be invoked.
+
+If the reader is familiar with OpenSSL's BIO layer, it might be analogous
+to saying the only way of interacting with Botan's TLS is via a `BIO_mem` I/O
+abstraction. This makes the library completely agnostic to how you
+write your network layer, be it blocking sockets, libevent, asio, a
+message queue, lwIP on RTOS, some carrier pigeons, etc.
+
+Starting in 1.11.31, the application callbacks are encapsulated as the class
+``TLS::Callbacks`` with the following members. The first four (``tls_emit_data``,
+``tls_record_received``, ``tls_alert``, and ``tls_session_established``) are
+mandatory for using TLS, all others are optional and provide additional
+information about the connection.
+
+ .. cpp:function:: void tls_emit_data(const uint8_t data[], size_t data_len)
+
+ Mandatory. The TLS stack requests that all bytes of *data* be queued up to send to the
+ counterparty. After this function returns, the buffer containing *data* will
+ be overwritten, so a copy of the input must be made if the callback
+ cannot send the data immediately.
+
+ As an example you could ``send`` to perform a blocking write on a socket,
+ or append the data to a queue managed by your application, and initiate
+ an asynchronous write.
+
+ For TLS all writes must occur *in the order requested*.
+ For DTLS this ordering is not strictly required, but is still recommended.
+
+ .. cpp:function:: void tls_record_received(uint64_t rec_no, const uint8_t data[], size_t data_len)
+
+ Mandatory. Called once for each application_data record which is received, with the
+ matching (TLS level) record sequence number.
+
+ Currently empty records are ignored and do not instigate a callback,
+ but this may change in a future release.
+
+ As with ``tls_emit_data``, the array will be overwritten sometime after
+ the callback returns, so a copy should be made if needed.
+
+ For TLS the record number will always increase.
+
+ For DTLS, it is possible to receive records with the `rec_no` field out of
+ order, or with gaps, corresponding to reordered or lost datagrams.
+
+ .. cpp:function:: void tls_alert(Alert alert)
+
+ Mandatory. Called when an alert is received from the peer. Note that alerts
+ received before the handshake is complete are not authenticated and
+ could have been inserted by a MITM attacker.
+
+ .. cpp:function:: bool tls_session_established(const TLS::Session& session)
+
+ Mandatory. Called whenever a negotiation completes. This can happen more
+ than once on any connection, if renegotiation occurs. The *session* parameter
+ provides information about the session which was just established.
+
+ If this function returns false, the session will not be cached
+ for later resumption.
+
+ If this function wishes to cancel the handshake, it can throw an
+ exception which will send a close message to the counterparty and
+ reset the connection state.
+
+ .. cpp:function:: void tls_verify_cert_chain(const std::vector<X509_Certificate>& cert_chain, \
+ const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses, \
+ const std::vector<Certificate_Store*>& trusted_roots, \
+ Usage_Type usage, \
+ const std::string& hostname, \
+ const Policy& policy)
+
+ Optional - default implementation should work for many users.
+ It can be overridden for implementing extra validation routines
+ such as public key pinning.
+
+ Verifies the certificate chain in *cert_chain*, assuming the leaf
+ certificate is the first element. Throws an exception if any
+ error makes this certificate chain unacceptable.
+
+ If usage is `Usage_Type::TLS_SERVER_AUTH`, then *hostname* should
+ match the information in the server certificate. If usage is
+ `TLS_CLIENT_AUTH`, then *hostname* specifies the host the client
+ is authenticating against (from SNI); the callback can use this for
+ any special site specific auth logic.
+
+ The `ocsp_responses` is a possibly empty list of OCSP responses provided by
+ the server. In the current implementation of TLS OCSP stapling, only a
+ single OCSP response can be returned. A existing TLS extension allows the
+ server to send multiple OCSP responses, this extension may be supported in
+ the future in which case more than one OCSP response may be given during
+ this callback.
+
+ The `trusted_roots` parameter was returned by a call from the associated
+ `Credentials_Manager`.
+
+ The `policy` provided is the policy for the TLS session which is
+ being authenticated using this certificate chain. It can be consulted
+ for values such as allowable signature methods and key sizes.
+
+ .. cpp:function:: std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
+
+ Called by default `tls_verify_cert_chain` to set timeout for online OCSP requests
+ on the certificate chain. Return 0 to disable OCSP. Current default is 0.
+
+ .. cpp:function:: std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos)
+
+ Optional. Called by the server when a client includes a list of protocols in the ALPN extension.
+ The server then choose which protocol to use, or "" to disable sending any ALPN response.
+ The default implementation returns the empty string all of the time, effectively disabling
+ ALPN responses.
+
+ .. cpp:function:: void tls_session_activated()
+
+ Optional. By default does nothing. This is called when the session is
+ activated, that is once it is possible to send or receive data on the
+ channel. In particular it is possible for an implementation of this
+ function to perform an initial write on the channel.
+
+ .. cpp:function:: std::vector<uint8_t> tls_provide_cert_status(const std::vector<X509_Certificate>& chain, \
+ const Certificate_Status_Request& csr)
+
+ Optional. This can return a cached OCSP response. This is only
+ used on the server side, and only if the client requests OCSP
+ stapling.
+
+ .. cpp:function:: std::string tls_peer_network_identity()
+
+ Optional. Return a string that identifies the peer in some unique way
+ (for example, by formatting the remote IP and port into a string).
+ This is currently used to bind DTLS cookies to the network identity.
+
+ .. cpp:function:: void tls_inspect_handshake_msg(const Handshake_Message&)
+
+ This callback is optional, and can be used to inspect all handshake messages
+ while the session establishment occurs.
+
+ .. cpp:function:: void tls_modify_extensions(Extensions& extn, Connection_Side which_side)
+
+ This callback is optional, and can be used to modify extensions before they
+ are sent to the peer. For example this enables adding a custom extension,
+ or replacing or removing an extension set by the library.
+
+ .. cpp:function:: void tls_examine_extensions(const Extensions& extn, Connection_Side which_side)
+
+ This callback is optional, and can be used to examine extensions sent by
+ the peer.
+
+ .. cpp:function:: void tls_log_error(const char* msg)
+
+ Optional logging for an error message. (Not currently used)
+
+ .. cpp:function:: void tls_log_debug(const char* msg)
+
+ Optional logging for an debug message. (Not currently used)
+
+ .. cpp:function:: void tls_log_debug_bin(const char* descr, const uint8_t val[], size_t len)
+
+ Optional logging for an debug value. (Not currently used)
+
+ .. cpp:function:: std::string tls_decode_group_param(TLS::Group_Params group_param)
+
+ Optional. Called by the server when a client hello includes a list of supported groups in the
+ supported_groups extension and by the client when decoding the server key exchange including the selected curve identifier.
+ The function should return the name of the DH group or elliptic curve the passed
+ TLS group identifier should be mapped to. Therefore this callback enables the use of custom
+ elliptic curves or DH groups in TLS, if both client and server map the custom identifiers correctly.
+ Please note that it is required to allow the group TLS identifier in
+ in the used :cpp:class:`TLS::Policy`.
+
+Versions from 1.11.0 to 1.11.30 did not have ``TLS::Callbacks`` and instead
+used independent std::functions to pass the various callback functions.
+This interface is currently still included but is deprecated and will be removed
+in a future release. For the documentation for this interface, please check
+the docs for 1.11.30. This version of the manual only documents the new interface
+added in 1.11.31.
+
+TLS Channels
+----------------------------------------
+
+TLS servers and clients share an interface called `TLS::Channel`. A
+TLS channel (either client or server object) has these methods
+available:
+
+.. cpp:class:: TLS::Channel
+
+ .. cpp:function:: size_t received_data(const uint8_t buf[], size_t buf_size)
+ .. cpp:function:: size_t received_data(const std::vector<uint8_t>& buf)
+
+ This function is used to provide data sent by the counterparty
+ (eg data that you read off the socket layer). Depending on the
+ current protocol state and the amount of data provided this may
+ result in one or more callback functions that were provided to
+ the constructor being called.
+
+ The return value of ``received_data`` specifies how many more
+ bytes of input are needed to make any progress, unless the end of
+ the data fell exactly on a message boundary, in which case it
+ will return 0 instead.
+
+ .. cpp:function:: void send(const uint8_t buf[], size_t buf_size)
+ .. cpp:function:: void send(const std::string& str)
+ .. cpp:function:: void send(const std::vector<uint8_t>& vec)
+
+ Create one or more new TLS application records containing the
+ provided data and send them. This will eventually result in at
+ least one call to the ``output_fn`` callback before ``send``
+ returns.
+
+ If the current TLS connection state is unable to transmit new
+ application records (for example because a handshake has not
+ yet completed or the connection has already ended due to an
+ error) an exception will be thrown.
+
+ .. cpp:function:: void close()
+
+ A close notification is sent to the counterparty, and the
+ internal state is cleared.
+
+ .. cpp:function:: void send_alert(const Alert& alert)
+
+ Some other alert is sent to the counterparty. If the alert is
+ fatal, the internal state is cleared.
+
+ .. cpp:function:: bool is_active()
+
+ Returns true if and only if a handshake has been completed on
+ this connection and the connection has not been subsequently
+ closed.
+
+ .. cpp:function:: bool is_closed()
+
+ Returns true if and only if either a close notification or a
+ fatal alert message have been either sent or received.
+
+ .. cpp:function:: bool timeout_check()
+
+ This function does nothing unless the channel represents a DTLS
+ connection and a handshake is actively in progress. In this case
+ it will check the current timeout state and potentially initiate
+ retransmission of handshake packets. Returns true if a timeout
+ condition occurred.
+
+ .. cpp:function:: void renegotiate(bool force_full_renegotiation = false)
+
+ Initiates a renegotiation. The counterparty is allowed by the
+ protocol to ignore this request. If a successful renegotiation
+ occurs, the *handshake_cb* callback will be called again.
+
+ If *force_full_renegotiation* is false, then the client will
+ attempt to simply renew the current session - this will refresh
+ the symmetric keys but will not change the session master
+ secret. Otherwise it will initiate a completely new session.
+
+ For a server, if *force_full_renegotiation* is false, then a
+ session resumption will be allowed if the client attempts
+ it. Otherwise the server will prevent resumption and force the
+ creation of a new session.
+
+ .. cpp:function:: std::vector<X509_Certificate> peer_cert_chain()
+
+ Returns the certificate chain of the counterparty. When acting
+ as a client, this value will be non-empty unless the client's
+ policy allowed anonymous connections and the server then chose
+ an anonymous ciphersuite. Acting as a server, this value will
+ ordinarily be empty, unless the server requested a certificate
+ and the client responded with one.
+
+ .. cpp:function:: SymmetricKey key_material_export( \
+ const std::string& label, \
+ const std::string& context, \
+ size_t length)
+
+ Returns an exported key of *length* bytes derived from *label*,
+ *context*, and the session's master secret and client and server
+ random values. This key will be unique to this connection, and
+ as long as the session master secret remains secure an attacker
+ should not be able to guess the key.
+
+ Per :rfc:`5705`, *label* should begin with "EXPERIMENTAL" unless
+ the label has been standardized in an RFC.
+
+.. _tls_client:
+
+TLS Clients
+----------------------------------------
+
+.. cpp:class:: TLS::Client
+
+ .. cpp:function:: Client( \
+ Callbacks& callbacks, \
+ Session_Manager& session_manager, \
+ Credentials_Manager& creds, \
+ const Policy& policy, \
+ RandomNumberGenerator& rng, \
+ const Server_Information& server_info = Server_Information(), \
+ const Protocol_Version offer_version = Protocol_Version::latest_tls_version(), \
+ const std::vector<std::string>& next_protocols = std::vector<std::string>(), \
+ size_t reserved_io_buffer_size = 16*1024 \
+ )
+
+ Initialize a new TLS client. The constructor will immediately
+ initiate a new session.
+
+ The *callbacks* parameter specifies the various application callbacks
+ which pertain to this particular client connection.
+
+ The *session_manager* is an interface for storing TLS sessions,
+ which allows for session resumption upon reconnecting to a server.
+ In the absence of a need for persistent sessions, use
+ :cpp:class:`TLS::Session_Manager_In_Memory` which caches
+ connections for the lifetime of a single process. See
+ :ref:`tls_session_managers` for more about session managers.
+
+ The *credentials_manager* is an interface that will be called to
+ retrieve any certificates, secret keys, pre-shared keys, or SRP
+ information; see :doc:`credentials_manager` for more information.
+
+ Use the optional *server_info* to specify the DNS name of the
+ server you are attempting to connect to, if you know it. This helps
+ the server select what certificate to use and helps the client
+ validate the connection.
+
+ Note that the server name indicator name must be a FQDN. IP
+ addresses are not allowed by RFC 6066 and may lead to interoperability
+ problems.
+
+ Use the optional *offer_version* to control the version of TLS you
+ wish the client to offer. Normally, you'll want to offer the most
+ recent version of (D)TLS that is available, however some broken
+ servers are intolerant of certain versions being offered, and for
+ classes of applications that have to deal with such servers
+ (typically web browsers) it may be necessary to implement a version
+ backdown strategy if the initial attempt fails.
+
+ .. warning::
+
+ Implementing such a backdown strategy allows an attacker to
+ downgrade your connection to the weakest protocol that both you
+ and the server support.
+
+ Setting *offer_version* is also used to offer DTLS instead of TLS;
+ use :cpp:func:`TLS::Protocol_Version::latest_dtls_version`.
+
+ Optionally, the client will advertise *app_protocols* to the
+ server using the ALPN extension.
+
+ The optional *reserved_io_buffer_size* specifies how many bytes to
+ pre-allocate in the I/O buffers. Use this if you want to control
+ how much memory the channel uses initially (the buffers will be
+ resized as needed to process inputs). Otherwise some reasonable
+ default is used.
+
+Code Example
+^^^^^^^^^^^^
+A minimal example of a TLS client is provided below.
+The full code for a TLS client using BSD sockets is in `src/cli/tls_client.cpp`
+
+.. code-block:: cpp
+
+ #include <botan/tls_client.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls server, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls server, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls server was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls client.
+ *
+ * It returns a list of trusted CA certificates from a local directory.
+ * TLS client authentication is disabled. See src/lib/tls/credentials_manager.h.
+ */
+ class Client_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ Client_Credentials()
+ {
+ // Here we base trust on the system managed trusted CA list
+ m_stores.push_back(new Botan::System_Certificate_Store);
+ }
+
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return a list of certificates of CAs we trust for tls server certificates
+ // ownership of the pointers remains with Credentials_Manager
+ return m_stores;
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when using tls client authentication (optional), return
+ // a certificate chain being sent to the tls server,
+ // else an empty list
+ return std::vector<Botan::X509_Certificate>();
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when returning a chain in cert_chain(), return the private key
+ // associated with the leaf certificate here
+ return nullptr;
+ }
+
+ private:
+ std::vector<Botan::Certificate_Store*> m_stores;
+ };
+
+ int main()
+ {
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::AutoSeeded_RNG rng;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Client_Credentials creds;
+ Botan::TLS::Strict_Policy policy;
+
+ // open the tls connection
+ Botan::TLS::Client client(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng,
+ Botan::TLS::Server_Information("botan.randombit.net", 443),
+ Botan::TLS::Protocol_Version::TLS_V12);
+
+ while(!client.is_closed())
+ {
+ // read data received from the tls server, e.g., using BSD sockets or boost asio
+ // ...
+
+ // send data to the tls server using client.send_data()
+ }
+ }
+
+.. _tls_server:
+
+TLS Servers
+----------------------------------------
+
+.. cpp:class:: TLS::Server
+
+ .. cpp:function:: Server( \
+ Callbacks& callbacks, \
+ Session_Manager& session_manager, \
+ Credentials_Manager& creds, \
+ const Policy& policy, \
+ RandomNumberGenerator& rng, \
+ bool is_datagram = false, \
+ size_t reserved_io_buffer_size = 16*1024 \
+ )
+
+The first 5 arguments as well as the final argument
+*reserved_io_buffer_size*, are treated similarly to the :ref:`client
+<tls_client>`.
+
+If a client sends the ALPN extension, the ``callbacks`` function
+``tls_server_choose_app_protocol`` will be called and the result
+sent back to the client. If the empty string is returned, the server
+will not send an ALPN response. The function can also throw an exception
+to abort the handshake entirely, the ALPN specification says that if this
+occurs the alert should be of type `NO_APPLICATION_PROTOCOL`.
+
+The optional argument *is_datagram* specifies if this is a TLS or DTLS
+server; unlike clients, which know what type of protocol (TLS vs DTLS)
+they are negotiating from the start via the *offer_version*, servers
+would not until they actually received a client hello.
+
+Code Example
+^^^^^^^^^^^^
+A minimal example of a TLS server is provided below.
+The full code for a TLS server using asio is in `src/cli/tls_proxy.cpp`.
+
+.. code-block:: cpp
+
+ #include <botan/tls_client.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+ #include <botan/pk_keys.h>
+
+ #include <memory>
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls client, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls client, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls client was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls server.
+ *
+ * It returns a certificate and the associated private key to
+ * authenticate the tls server to the client.
+ * TLS client authentication is not requested.
+ * See src/lib/tls/credentials_manager.h.
+ */
+ class Server_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ Server_Credentials() : m_key(Botan::PKCS8::load_key("botan.randombit.net.key"))
+ {
+ }
+
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // if client authentication is required, this function
+ // shall return a list of certificates of CAs we trust
+ // for tls client certificates, otherwise return an empty list
+ return std::vector<Certificate_Store*>();
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the certificate chain being sent to the tls client
+ // e.g., the certificate file "botan.randombit.net.crt"
+ return { Botan::X509_Certificate("botan.randombit.net.crt") };
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the private key associated with the leaf certificate,
+ // in this case the one associated with "botan.randombit.net.crt"
+ return &m_key;
+ }
+
+ private:
+ std::unique_ptr<Botan::Private_Key> m_key;
+ };
+
+ int main()
+ {
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::AutoSeeded_RNG rng;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Server_Credentials creds;
+ Botan::TLS::Strict_Policy policy;
+
+ // accept tls connection from client
+ Botan::TLS::Server server(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng);
+
+ // read data received from the tls client, e.g., using BSD sockets or boost asio
+ // and pass it to server.received_data().
+ // ...
+
+ // send data to the tls client using server.send_data()
+ // ...
+ }
+
+.. _tls_sessions:
+
+TLS Sessions
+----------------------------------------
+
+TLS allows clients and servers to support *session resumption*, where
+the end point retains some information about an established session
+and then reuse that information to bootstrap a new session in way that
+is much cheaper computationally than a full handshake.
+
+Every time your handshake callback is called, a new session has been
+established, and a ``TLS::Session`` is included that provides
+information about that session:
+
+.. note::
+
+ The serialization format of Session is not considered stable and is allowed
+ to change even across minor releases. In the event of such a change, old
+ sessions will no longer be able to be resumed.
+
+.. cpp:class:: TLS::Session
+
+ .. cpp:function:: Protocol_Version version() const
+
+ Returns the :cpp:class:`protocol version <TLS::Protocol_Version>`
+ that was negotiated
+
+ .. cpp:function:: Ciphersuite ciphersite() const
+
+ Returns the :cpp:class:`ciphersuite <TLS::Ciphersuite>` that
+ was negotiated.
+
+ .. cpp:function:: Server_Information server_info() const
+
+ Returns information that identifies the server side of the
+ connection. This is useful for the client in that it
+ identifies what was originally passed to the constructor. For
+ the server, it includes the name the client specified in the
+ server name indicator extension.
+
+ .. cpp:function:: std::vector<X509_Certificate> peer_certs() const
+
+ Returns the certificate chain of the peer
+
+ .. cpp:function:: std::string srp_identifier() const
+
+ If an SRP ciphersuite was used, then this is the identifier
+ that was used for authentication.
+
+ .. cpp:function:: bool secure_renegotiation() const
+
+ Returns ``true`` if the connection was negotiated with the
+ correct extensions to prevent the renegotiation attack.
+
+ .. cpp:function:: std::vector<uint8_t> encrypt(const SymmetricKey& key, \
+ RandomNumberGenerator& rng)
+
+ Encrypts a session using a symmetric key *key* and returns a raw
+ binary value that can later be passed to ``decrypt``. The key
+ may be of any length. The format is described in
+ :ref:`tls_session_encryption`.
+
+ .. cpp:function:: static Session decrypt(const uint8_t ciphertext[], \
+ size_t length, \
+ const SymmetricKey& key)
+
+ Decrypts a session that was encrypted previously with ``encrypt`` and
+ ``key``, or throws an exception if decryption fails.
+
+ .. cpp:function:: secure_vector<uint8_t> DER_encode() const
+
+ Returns a serialized version of the session.
+
+ .. warning:: The return value of ``DER_encode`` contains the
+ master secret for the session, and an attacker who
+ recovers it could recover plaintext of previous
+ sessions or impersonate one side to the other.
+
+.. _tls_session_managers:
+
+TLS Session Managers
+----------------------------------------
+
+You may want sessions stored in a specific format or storage type. To
+do so, implement the ``TLS::Session_Manager`` interface and pass your
+implementation to the ``TLS::Client`` or ``TLS::Server`` constructor.
+
+.. cpp:class:: TLS::Session_Mananger
+
+ .. cpp:function:: void save(const Session& session)
+
+ Save a new *session*. It is possible that this sessions session
+ ID will replicate a session ID already stored, in which case the
+ new session information should overwrite the previous information.
+
+ .. cpp:function:: void remove_entry(const std::vector<uint8_t>& session_id)
+
+ Remove the session identified by *session_id*. Future attempts
+ at resumption should fail for this session.
+
+ .. cpp:function:: bool load_from_session_id(const std::vector<uint8_t>& session_id, \
+ Session& session)
+
+ Attempt to resume a session identified by *session_id*. If
+ located, *session* is set to the session data previously passed
+ to *save*, and ``true`` is returned. Otherwise *session* is not
+ modified and ``false`` is returned.
+
+ .. cpp:function:: bool load_from_server_info(const Server_Information& server, \
+ Session& session)
+
+ Attempt to resume a session with a known server.
+
+ .. cpp:function:: std::chrono::seconds session_lifetime() const
+
+ Returns the expected maximum lifetime of a session when using
+ this session manager. Will return 0 if the lifetime is unknown
+ or has no explicit expiration policy.
+
+.. _tls_session_manager_inmem:
+
+In Memory Session Manager
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``TLS::Session_Manager_In_Memory`` implementation saves sessions
+in memory, with an upper bound on the maximum number of sessions and
+the lifetime of a session.
+
+It is safe to share a single object across many threads as it uses a
+lock internally.
+
+.. cpp:class:: TLS::Session_Managers_In_Memory
+
+ .. cpp:function:: Session_Manager_In_Memory(RandomNumberGenerator& rng, \
+ size_t max_sessions = 1000, \
+ std::chrono::seconds session_lifetime = 7200)
+
+ Limits the maximum number of saved sessions to *max_sessions*, and
+ expires all sessions older than *session_lifetime*.
+
+Noop Session Mananger
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``TLS::Session_Manager_Noop`` implementation does not save
+sessions at all, and thus session resumption always fails. Its
+constructor has no arguments.
+
+SQLite3 Session Manager
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This session manager is only available if support for SQLite3 was
+enabled at build time. If the macro
+``BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER`` is defined, then
+``botan/tls_session_manager_sqlite.h`` contains
+``TLS::Session_Manager_SQLite`` which stores sessions persistently to
+a sqlite3 database. The session data is encrypted using a passphrase,
+and stored in two tables, named ``tls_sessions`` (which holds the
+actual session information) and ``tls_sessions_metadata`` (which holds
+the PBKDF information).
+
+.. warning:: The hostnames associated with the saved sessions are
+ stored in the database in plaintext. This may be a
+ serious privacy risk in some applications.
+
+.. cpp:class:: TLS::Session_Manager_SQLite
+
+ .. cpp:function:: Session_Manager_SQLite( \
+ const std::string& passphrase, \
+ RandomNumberGenerator& rng, \
+ const std::string& db_filename, \
+ size_t max_sessions = 1000, \
+ std::chrono::seconds session_lifetime = 7200)
+
+ Uses the sqlite3 database named by *db_filename*.
+
+TLS Policies
+----------------------------------------
+
+``TLS::Policy`` is how an application can control details of what will
+be negotiated during a handshake. The base class acts as the default
+policy. There is also a ``Strict_Policy`` (which forces only secure
+options, reducing compatibility) and ``Text_Policy`` which reads
+policy settings from a file.
+
+.. cpp:class:: TLS::Policy
+
+ .. cpp:function:: std::vector<std::string> allowed_ciphers() const
+
+ Returns the list of ciphers we are willing to negotiate, in order
+ of preference.
+
+ Clients send a list of ciphersuites in order of preference,
+ servers are free to choose any of them. Some servers will use the
+ clients preferences, others choose from the clients list
+ prioritizing based on its preferences.
+
+ No export key exchange mechanisms or ciphersuites are supported
+ by botan. The null encryption ciphersuites (which provide only
+ authentication, sending data in cleartext) are also not supported
+ by the implementation and cannot be negotiated.
+
+ Cipher names without an explicit mode refers to CBC+HMAC ciphersuites.
+
+ Default value: "ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM"
+
+ Also allowed: "AES-256", "AES-128",
+ "AES-256/CCM", "AES-128/CCM", "AES-256/CCM(8)", "AES-128/CCM(8)",
+ "Camellia-256/GCM", "Camellia-128/GCM", "ARIA-256/GCM", "ARIA-128/GCM",
+ "Camellia-256", "Camellia-128"
+
+ Also allowed (though currently experimental): "AES-128/OCB(12)",
+ "AES-256/OCB(12)"
+
+ In versions up to 2.8.0, the CBC and CCM ciphersuites "AES-256",
+ "AES-128", "AES-256/CCM" and "AES-128/CCM" were enabled by default.
+
+ Also allowed (although **not recommended**): "SEED", "3DES"
+
+ .. note::
+
+ Before 1.11.30 only the non-standard ChaCha20Poly1305 ciphersuite
+ was implemented. The RFC 7905 ciphersuites are supported in 1.11.30
+ onwards.
+
+ .. note::
+
+ Support for the broken RC4 cipher was removed in 1.11.17
+
+ .. note::
+
+ SEED and 3DES are deprecated and will be removed in a future release.
+
+ .. cpp:function:: std::vector<std::string> allowed_macs() const
+
+ Returns the list of algorithms we are willing to use for
+ message authentication, in order of preference.
+
+ Default: "AEAD", "SHA-256", "SHA-384", "SHA-1"
+
+ A plain hash function indicates HMAC
+
+ .. note::
+
+ SHA-256 is preferred over SHA-384 in CBC mode because the
+ protections against the Lucky13 attack are somewhat more
+ effective for SHA-256 than SHA-384.
+
+ .. cpp:function:: std::vector<std::string> allowed_key_exchange_methods() const
+
+ Returns the list of key exchange methods we are willing to use,
+ in order of preference.
+
+ Default: "CECPQ1", "ECDH", "DH"
+
+ .. note::
+
+ CECPQ1 key exchange provides post-quantum security to the key exchange
+ by combining NewHope with a standard x25519 ECDH exchange. This prevents
+ an attacker, even one with a quantum computer, from later decrypting the
+ contents of a recorded TLS transcript. The NewHope algorithm is very
+ fast, but adds roughly 4 KiB of additional data transfer to every TLS
+ handshake. And even if NewHope ends up completely broken, the 'extra'
+ x25519 exchange secures the handshake.
+
+ For applications where the additional data transfer size is unacceptable,
+ simply allow only ECDH key exchange in the application policy. DH
+ exchange also often involves transferring several additional Kb (without
+ the benefit of post quantum security) so if CECPQ1 is being disabled for
+ traffic overhead reasons, DH should also be avoided.
+
+ Also allowed: "RSA", "SRP_SHA", "ECDHE_PSK", "DHE_PSK", "PSK"
+
+ .. note::
+
+ Static RSA ciphersuites are disabled by default since 1.11.34.
+ In addition to not providing forward security, any server which is
+ willing to negotiate these ciphersuites exposes themselves to a variety
+ of chosen ciphertext oracle attacks which are all easily avoided by
+ signing (as in PFS) instead of decrypting.
+
+ .. note::
+
+ In order to enable RSA, SRP, or PSK ciphersuites one must also enable
+ authentication method "IMPLICIT", see :cpp:func:`allowed_signature_methods`.
+
+ .. cpp:function:: std::vector<std::string> allowed_signature_hashes() const
+
+ Returns the list of hash algorithms we are willing to use for
+ public key signatures, in order of preference.
+
+ Default: "SHA-512", "SHA-384", "SHA-256"
+
+ Also allowed (although **not recommended**): "SHA-1"
+
+ .. note::
+
+ This is only used with TLS v1.2. In earlier versions of the
+ protocol, signatures are fixed to using only SHA-1 (for
+ DSA/ECDSA) or a MD5/SHA-1 pair (for RSA).
+
+ .. cpp:function:: std::vector<std::string> allowed_signature_methods() const
+
+ Default: "ECDSA", "RSA"
+
+ Also allowed (disabled by default): "DSA", "IMPLICIT", "ANONYMOUS"
+
+ "IMPLICIT" enables ciphersuites which are authenticated not by a signature
+ but through a side-effect of the key exchange. In particular this setting
+ is required to enable PSK, SRP, and static RSA ciphersuites.
+
+ "ANONYMOUS" allows purely anonymous DH/ECDH key exchanges. **Enabling this
+ is not recommended**
+
+ .. note::
+
+ Both DSA authentication and anonymous DH ciphersuites are deprecated,
+ and will be removed in a future release.
+
+ .. cpp:function:: std::vector<Group_Params> key_exchange_groups() const
+
+ Return a list of ECC curve and DH group TLS identifiers we are willing to use, in order of preference.
+ The default ordering puts the best performing ECC first.
+
+ Default:
+ Group_Params::X25519,
+ Group_Params::SECP256R1, Group_Params::BRAINPOOL256R1,
+ Group_Params::SECP384R1, Group_Params::BRAINPOOL384R1,
+ Group_Params::SECP521R1, Group_Params::BRAINPOOL512R1,
+ Group_Params::FFDHE_2048, Group_Params::FFDHE_3072, Group_Params::FFDHE_4096,
+ Group_Params::FFDHE_6144, Group_Params::FFDHE_8192
+
+ No other values are currently defined.
+
+ .. cpp:function:: bool use_ecc_point_compression() const
+
+ Prefer ECC point compression.
+
+ Signals that we prefer ECC points to be compressed when transmitted to us.
+ The other party may not support ECC point compression and therefore may still
+ send points uncompressed.
+
+ Note that the certificate used during authentication must also follow the other
+ party's preference.
+
+ Default: false
+
+ .. note::
+
+ Support for EC point compression is deprecated and will be removed in a
+ future major release.
+
+ .. cpp:function:: bool acceptable_protocol_version(Protocol_Version version)
+
+ Return true if this version of the protocol is one that we are
+ willing to negotiate.
+
+ Default: Accepts TLS v1.2 and DTLS v1.2, and rejects all older versions.
+
+ .. cpp:function:: bool server_uses_own_ciphersuite_preferences() const
+
+ If this returns true, a server will pick the cipher it prefers the
+ most out of the client's list. Otherwise, it will negotiate the
+ first cipher in the client's ciphersuite list that it supports.
+
+ Default: true
+
+ .. cpp:function:: bool allow_client_initiated_renegotiation() const
+
+ If this function returns true, a server will accept a
+ client-initiated renegotiation attempt. Otherwise it will send
+ the client a non-fatal ``no_renegotiation`` alert.
+
+ Default: false
+
+ .. cpp:function:: bool allow_server_initiated_renegotiation() const
+
+ If this function returns true, a client will accept a
+ server-initiated renegotiation attempt. Otherwise it will send
+ the server a non-fatal ``no_renegotiation`` alert.
+
+ Default: false
+
+ .. cpp:function:: bool abort_connection_on_undesired_renegotiation() const
+
+ If a renegotiation attempt is being rejected due to the configuration of
+ :cpp:func:`TLS::Policy::allow_client_initiated_renegotiation` or
+ :cpp:func:`TLS::Policy::allow_server_initiated_renegotiation`, and
+ this function returns true then the connection is closed with a fatal
+ alert instead of the default warning alert.
+
+ Default: false
+
+ .. cpp:function:: bool allow_insecure_renegotiation() const
+
+ If this function returns true, we will allow renegotiation attempts
+ even if the counterparty does not support the RFC 5746 extensions.
+
+ .. warning:: Returning true here could expose you to attacks
+
+ Default: false
+
+ .. cpp:function:: size_t minimum_signature_strength() const
+
+ Return the minimum strength (as ``n``, representing ``2**n`` work)
+ we will accept for a signature algorithm on any certificate.
+
+ Use 80 to enable RSA-1024 (*not recommended*), or 128 to require
+ either ECC or large (~3000 bit) RSA keys.
+
+ Default: 110 (allowing 2048 bit RSA)
+
+ .. cpp:function:: bool require_cert_revocation_info() const
+
+ If this function returns true, and a ciphersuite using certificates was
+ negotiated, then we must have access to a valid CRL or OCSP response in
+ order to trust the certificate.
+
+ .. warning:: Returning false here could expose you to attacks
+
+ Default: true
+
+ .. cpp:function:: Group_Params default_dh_group() const
+
+ For ephemeral Diffie-Hellman key exchange, the server sends a
+ group parameter. Return the 2 Byte TLS group identifier specifying the group parameter a
+ server should use.
+
+ Default: 2048 bit IETF IPsec group ("modp/ietf/2048")
+
+ .. cpp:function:: size_t minimum_dh_group_size() const
+
+ Return the minimum size in bits for a Diffie-Hellman group that a
+ client will accept. Due to the design of the protocol the client
+ has only two options - accept the group, or reject it with a
+ fatal alert then attempt to reconnect after disabling ephemeral
+ Diffie-Hellman.
+
+ Default: 2048 bits
+
+ .. cpp:function:: bool allow_tls10() const
+
+ Return true from here to allow TLS v1.0. Since 2.8.0, returns
+ ``false`` by default.
+
+ .. cpp:function:: bool allow_tls11() const
+
+ Return true from here to allow TLS v1.1. Since 2.8.0, returns
+ ``false`` by default.
+
+ .. cpp:function:: bool allow_tls12() const
+
+ Return true from here to allow TLS v1.2. Returns ``true`` by default.
+
+ .. cpp:function:: size_t minimum_rsa_bits() const
+
+ Minimum accepted RSA key size. Default 2048 bits.
+
+ .. cpp:function:: size_t minimum_dsa_group_size() const
+
+ Minimum accepted DSA key size. Default 2048 bits.
+
+ .. cpp:function:: size_t minimum_ecdsa_group_size() const
+
+ Minimum size for ECDSA keys (256 bits).
+
+ .. cpp:function:: size_t minimum_ecdh_group_size() const
+
+ Minimum size for ECDH keys (255 bits).
+
+ .. cpp:function:: void check_peer_key_acceptable(const Public_Key& public_key) const
+
+ Allows the policy to examine peer public keys. Throw an exception
+ if the key should be rejected. Default implementation checks
+ against policy values `minimum_dh_group_size`, `minimum_rsa_bits`,
+ `minimum_ecdsa_group_size`, and `minimum_ecdh_group_size`.
+
+ .. cpp:function:: bool hide_unknown_users() const
+
+ The SRP and PSK suites work using an identifier along with a
+ shared secret. If this function returns true, when an identifier
+ that the server does not recognize is provided by a client, a
+ random shared secret will be generated in such a way that a
+ client should not be able to tell the difference between the
+ identifier not being known and the secret being wrong. This can
+ help protect against some username probing attacks. If it
+ returns false, the server will instead send an
+ ``unknown_psk_identity`` alert when an unknown identifier is
+ used.
+
+ Default: false
+
+ .. cpp:function:: u32bit session_ticket_lifetime() const
+
+ Return the lifetime of session tickets. Each session includes the
+ start time. Sessions resumptions using tickets older than
+ ``session_ticket_lifetime`` seconds will fail, forcing a full
+ renegotiation.
+
+ Default: 86400 seconds (1 day)
+
+TLS Ciphersuites
+----------------------------------------
+
+.. cpp:class:: TLS::Ciphersuite
+
+ .. cpp:function:: uint16_t ciphersuite_code() const
+
+ Return the numerical code for this ciphersuite
+
+ .. cpp:function:: std::string to_string() const
+
+ Return the full name of ciphersuite (for example
+ "RSA_WITH_RC4_128_SHA" or "ECDHE_RSA_WITH_AES_128_GCM_SHA256")
+
+ .. cpp:function:: std::string kex_algo() const
+
+ Return the key exchange algorithm of this ciphersuite
+
+ .. cpp:function:: std::string sig_algo() const
+
+ Return the signature algorithm of this ciphersuite
+
+ .. cpp:function:: std::string cipher_algo() const
+
+ Return the cipher algorithm of this ciphersuite
+
+ .. cpp:function:: std::string mac_algo() const
+
+ Return the authentication algorithm of this ciphersuite
+
+ .. cpp:function:: bool acceptable_ciphersuite(const Ciphersuite& suite) const
+
+ Return true if ciphersuite is accepted by the policy.
+
+ Allows an application to reject any ciphersuites, which are
+ undesirable for whatever reason without having to reimplement
+ :cpp:func:`TLS::Ciphersuite::ciphersuite_list`
+
+ .. cpp:function:: std::vector<uint16_t> ciphersuite_list(Protocol_Version version, bool have_srp) const
+
+ Return allowed ciphersuites in order of preference
+
+ Allows an application to have full control over ciphersuites
+ by returning desired ciphersuites in preference order.
+
+.. _tls_alerts:
+
+TLS Alerts
+----------------------------------------
+
+A ``TLS::Alert`` is passed to every invocation of a channel's *alert_cb*.
+
+.. cpp:class:: TLS::Alert
+
+ .. cpp:function:: is_valid() const
+
+ Return true if this alert is not a null alert
+
+ .. cpp:function:: is_fatal() const
+
+ Return true if this alert is fatal. A fatal alert causes the
+ connection to be immediately disconnected. Otherwise, the alert
+ is a warning and the connection remains valid.
+
+ .. cpp:function:: Type type() const
+
+ Returns the type of the alert as an enum
+
+ .. cpp:function:: std::string type_string()
+
+ Returns the type of the alert as a string
+
+TLS Protocol Version
+----------------------------------------
+
+TLS has several different versions with slightly different behaviors.
+The ``TLS::Protocol_Version`` class represents a specific version:
+
+.. cpp:class:: TLS::Protocol_Version
+
+ .. cpp:enum:: Version_Code
+
+ ``TLS_V10``, ``TLS_V11``, ``TLS_V12``, ``DTLS_V10``, ``DTLS_V12``
+
+ .. cpp:function:: Protocol_Version(Version_Code named_version)
+
+ Create a specific version
+
+ .. cpp:function:: uint8_t major_version() const
+
+ Returns major number of the protocol version
+
+ .. cpp:function:: uint8_t minor_version() const
+
+ Returns minor number of the protocol version
+
+ .. cpp:function:: std::string to_string() const
+
+ Returns string description of the version, for instance "TLS
+ v1.1" or "DTLS v1.0".
+
+ .. cpp:function:: static Protocol_Version latest_tls_version()
+
+ Returns the latest version of the TLS protocol known to the library
+ (currently TLS v1.2)
+
+ .. cpp:function:: static Protocol_Version latest_dtls_version()
+
+ Returns the latest version of the DTLS protocol known to the
+ library (currently DTLS v1.2)
+
+TLS Custom Curves
+----------------------------------------
+
+The supported_groups TLS extension is used in the client hello to advertise a list of supported elliptic curves
+and DH groups. The server subsequently selects one of the groups, which is supported by both endpoints.
+The groups are represented by their TLS identifier. This 2 Byte identifier is standardized for commonly used groups and curves.
+In addition, the standard reserves the identifiers 0xFE00 to 0xFEFF for custom groups or curves.
+
+Using non standardized custom curves is however not recommended and can be a serious risk if an
+insecure curve is used. Still, it might be desired in some scenarios to use custom curves or groups in the TLS handshake.
+
+To use custom curves with the Botan :cpp:class:`TLS::Client` or :cpp:class:`TLS::Server` the following additional adjustments have to be implemented
+as shown in the following code examples.
+
+1. Registration of the custom curve
+2. Implementation TLS callback ``tls_decode_group_param``
+3. Adjustment of the TLS policy by allowing the custom curve
+
+Client Code Example
+^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: cpp
+
+ #include <botan/tls_client.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+
+ #include <botan/ec_group.h>
+ #include <botan/oids.h>
+
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls server, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls server, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls server was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+ std::string tls_decode_group_param(Botan::TLS::Group_Params group_param) override
+ {
+ // handle TLS group identifier decoding and return name as string
+ // return empty string to indicate decoding failure
+
+ switch(static_cast<uint16_t>(group_param))
+ {
+ case 0xFE00:
+ return "testcurve1102";
+ default:
+ //decode non-custom groups
+ return Botan::TLS::Callbacks::tls_decode_group_param(group_param);
+ }
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls client.
+ *
+ * It returns a list of trusted CA certificates from a local directory.
+ * TLS client authentication is disabled. See src/lib/tls/credentials_manager.h.
+ */
+ class Client_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return a list of certificates of CAs we trust for tls server certificates,
+ // e.g., all the certificates in the local directory "cas"
+ return { new Botan::Certificate_Store_In_Memory("cas") };
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when using tls client authentication (optional), return
+ // a certificate chain being sent to the tls server,
+ // else an empty list
+ return std::vector<Botan::X509_Certificate>();
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // when returning a chain in cert_chain(), return the private key
+ // associated with the leaf certificate here
+ return nullptr;
+ }
+ };
+
+ class Client_Policy : public Botan::TLS::Strict_Policy
+ {
+ public:
+ std::vector<Botan::TLS::Group_Params> key_exchange_groups() const override
+ {
+ // modified strict policy to allow our custom curves
+ return
+ {
+ static_cast<Botan::TLS::Group_Params>(0xFE00)
+ };
+ }
+ };
+
+ int main()
+ {
+ // prepare rng
+ Botan::AutoSeeded_RNG rng;
+
+ // prepare custom curve
+
+ // prepare curve parameters
+ const Botan::BigInt p("0x92309a3e88b94312f36891a2055725bb35ab51af96b3a651d39321b7bbb8c51575a76768c9b6b323");
+ const Botan::BigInt a("0x4f30b8e311f6b2dce62078d70b35dacb96aa84b758ab5a8dff0c9f7a2a1ff466c19988aa0acdde69");
+ const Botan::BigInt b("0x9045A513CFFF9AE1F1CC84039D852D240344A1D5C9DB203C844089F855C387823EB6FCDDF49C909C");
+
+ const Botan::BigInt x("0x9120f3779a31296cefcb5a5a08831f1a6d438ad5a3f2ce60585ac19c74eebdc65cadb96bb92622c7");
+ const Botan::BigInt y("0x836db8251c152dfee071b72c6b06c5387d82f1b5c30c5a5b65ee9429aa2687e8426d5d61276a4ede");
+ const Botan::BigInt order("0x248c268fa22e50c4bcda24688155c96ecd6ad46be5c82d7a6be6e7068cb5d1ca72b2e07e8b90d853");
+
+ const Botan::BigInt cofactor(4);
+
+ const Botan::OID oid("1.2.3.1");
+
+ // create EC_Group object to register the curve
+ Botan::EC_Group testcurve1102(p, a, b, x, y, order, cofactor, oid);
+
+ if(!testcurve1102.verify_group(rng))
+ {
+ // Warning: if verify_group returns false the curve parameters are insecure
+ }
+
+ // register name to specified oid
+ Botan::OIDS::add_oid(oid, "testcurve1102");
+
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Client_Credentials creds;
+ Client_Policy policy;
+
+ // open the tls connection
+ Botan::TLS::Client client(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng,
+ Botan::TLS::Server_Information("botan.randombit.net", 443),
+ Botan::TLS::Protocol_Version::TLS_V12);
+
+
+ while(!client.is_closed())
+ {
+ // read data received from the tls server, e.g., using BSD sockets or boost asio
+ // ...
+
+ // send data to the tls server using client.send_data()
+
+ }
+ }
+
+Server Code Example
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: cpp
+
+ #include <botan/tls_server.h>
+ #include <botan/tls_callbacks.h>
+ #include <botan/tls_session_manager.h>
+ #include <botan/tls_policy.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor.h>
+ #include <botan/pk_keys.h>
+ #include <botan/pkcs8.h>
+
+ #include <botan/ec_group.h>
+ #include <botan/oids.h>
+
+ #include <memory>
+
+ /**
+ * @brief Callbacks invoked by TLS::Channel.
+ *
+ * Botan::TLS::Callbacks is an abstract class.
+ * For improved readability, only the functions that are mandatory
+ * to implement are listed here. See src/lib/tls/tls_callbacks.h.
+ */
+ class Callbacks : public Botan::TLS::Callbacks
+ {
+ public:
+ void tls_emit_data(const uint8_t data[], size_t size) override
+ {
+ // send data to tls client, e.g., using BSD sockets or boost asio
+ }
+
+ void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) override
+ {
+ // process full TLS record received by tls client, e.g.,
+ // by passing it to the application
+ }
+
+ void tls_alert(Botan::TLS::Alert alert) override
+ {
+ // handle a tls alert received from the tls server
+ }
+
+ bool tls_session_established(const Botan::TLS::Session& session) override
+ {
+ // the session with the tls client was established
+ // return false to prevent the session from being cached, true to
+ // cache the session in the configured session manager
+ return false;
+ }
+
+ std::string tls_decode_group_param(Botan::TLS::Group_Params group_param) override
+ {
+ // handle TLS group identifier decoding and return name as string
+ // return empty string to indicate decoding failure
+
+ switch(static_cast<uint16_t>(group_param))
+ {
+ case 0xFE00:
+ return "testcurve1102";
+ default:
+ //decode non-custom groups
+ return Botan::TLS::Callbacks::tls_decode_group_param(group_param);
+ }
+ }
+ };
+
+ /**
+ * @brief Credentials storage for the tls server.
+ *
+ * It returns a certificate and the associated private key to
+ * authenticate the tls server to the client.
+ * TLS client authentication is not requested.
+ * See src/lib/tls/credentials_manager.h.
+ */
+ class Server_Credentials : public Botan::Credentials_Manager
+ {
+ public:
+ Server_Credentials() : m_key(Botan::PKCS8::load_key("botan.randombit.net.key")
+ {
+ }
+
+ std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context) override
+ {
+ // if client authentication is required, this function
+ // shall return a list of certificates of CAs we trust
+ // for tls client certificates, otherwise return an empty list
+ return std::vector<Botan::Certificate_Store*>();
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the certificate chain being sent to the tls client
+ // e.g., the certificate file "botan.randombit.net.crt"
+ return { Botan::X509_Certificate("botan.randombit.net.crt") };
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context) override
+ {
+ // return the private key associated with the leaf certificate,
+ // in this case the one associated with "botan.randombit.net.crt"
+ return m_key.get();
+ }
+
+ private:
+ std::unique_ptr<Botan::Private_Key> m_key;
+ };
+
+ class Server_Policy : public Botan::TLS::Strict_Policy
+ {
+ public:
+ std::vector<Botan::TLS::Group_Params> key_exchange_groups() const override
+ {
+ // modified strict policy to allow our custom curves
+ return
+ {
+ static_cast<Botan::TLS::Group_Params>(0xFE00)
+ };
+ }
+ };
+
+ int main()
+ {
+
+ // prepare rng
+ Botan::AutoSeeded_RNG rng;
+
+ // prepare custom curve
+
+ // prepare curve parameters
+ const Botan::BigInt p("0x92309a3e88b94312f36891a2055725bb35ab51af96b3a651d39321b7bbb8c51575a76768c9b6b323");
+ const Botan::BigInt a("0x4f30b8e311f6b2dce62078d70b35dacb96aa84b758ab5a8dff0c9f7a2a1ff466c19988aa0acdde69");
+ const Botan::BigInt b("0x9045A513CFFF9AE1F1CC84039D852D240344A1D5C9DB203C844089F855C387823EB6FCDDF49C909C");
+
+ const Botan::BigInt x("0x9120f3779a31296cefcb5a5a08831f1a6d438ad5a3f2ce60585ac19c74eebdc65cadb96bb92622c7");
+ const Botan::BigInt y("0x836db8251c152dfee071b72c6b06c5387d82f1b5c30c5a5b65ee9429aa2687e8426d5d61276a4ede");
+ const Botan::BigInt order("0x248c268fa22e50c4bcda24688155c96ecd6ad46be5c82d7a6be6e7068cb5d1ca72b2e07e8b90d853");
+
+ const Botan::BigInt cofactor(4);
+
+ const Botan::OID oid("1.2.3.1");
+
+ // create EC_Group object to register the curve
+ Botan::EC_Group testcurve1102(p, a, b, x, y, order, cofactor, oid);
+
+ if(!testcurve1102.verify_group(rng))
+ {
+ // Warning: if verify_group returns false the curve parameters are insecure
+ }
+
+ // register name to specified oid
+ Botan::OIDS::add_oid(oid, "testcurve1102");
+
+ // prepare all the parameters
+ Callbacks callbacks;
+ Botan::TLS::Session_Manager_In_Memory session_mgr(rng);
+ Server_Credentials creds;
+ Server_Policy policy;
+
+ // accept tls connection from client
+ Botan::TLS::Server server(callbacks,
+ session_mgr,
+ creds,
+ policy,
+ rng);
+
+ // read data received from the tls client, e.g., using BSD sockets or boost asio
+ // and pass it to server.received_data().
+ // ...
+
+ // send data to the tls client using server.send_data()
+ // ...
+ }
+
+TLS Stream
+----------------------------------------
+
+:cpp:class:`TLS::Stream` offers a Boost.Asio compatible wrapper around :cpp:class:`TLS::Client` and :cpp:class:`TLS::Server`.
+It can be used as an alternative to Boost.Asio's `ssl::stream <https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ssl__stream.html>`_ with minor adjustments to the using code.
+It offers the following interface:
+
+.. cpp:class:: template <class StreamLayer, class ChannelT> TLS::Stream
+
+ *StreamLayer* specifies the type of the stream's *next layer*, for example a `Boost.Asio TCP socket <https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ip__tcp/socket.html>`_.
+ *ChannelT* is the type of the stream's *native handle*; it defaults to :cpp:class:`TLS::Channel` and should not be specified manually.
+
+ .. cpp:function:: template <typename... Args> \
+ explicit Stream(Context& context, Args&& ... args)
+
+ Construct a new TLS stream.
+ The *context* parameter will be used to initialize the underlying *native handle*, i.e. the :ref:`TLS::Client <tls_client>` or :ref:`TLS::Server <tls_server>`, when :cpp:func:`handshake` is called.
+ Using code must ensure the context is kept alive for the lifetime of the stream.
+ The further *args* will be forwarded to the *next layer*'s constructor.
+
+ .. cpp:function:: template <typename... Args> \
+ explicit Stream(Arg&& arg, Context& context)
+
+ Convenience constructor for :cpp:class:`boost::asio::ssl::stream` compatibility.
+ The parameters have the same meaning as for the first constructor, but their order is changed and only one argument can be passed to the *next layer* constructor.
+
+
+ .. cpp:function:: void handshake(Connection_Side side, boost::system::error_code& ec)
+
+ Set up the *native handle* and perform the TLS handshake.
+
+ .. cpp:function:: void handshake(Connection_Side side)
+
+ Overload of :cpp:func:`handshake` that throws an exception if an error occurs.
+
+ .. cpp:function:: template <typename HandshakeHandler> \
+ DEDUCED async_handshake(Connection_Side side, HandshakeHandler&& handler)
+
+ Asynchronous variant of :cpp:func:`handshake`.
+ The function returns immediately and calls the *handler* callback function after performing asynchronous I/O to complete the TLS handshake.
+ The return type is an automatically deduced specialization of :cpp:class:`boost::asio::async_result`, depending on the *HandshakeHandler* type.
+
+
+ .. cpp:function:: void shutdown(boost::system::error_code& ec)
+
+ Calls :cpp:func:`TLS::Channel::close` on the native handle and writes the TLS alert to the *next layer*.
+
+ .. cpp:function:: void shutdown()
+
+ Overload of :cpp:func:`shutdown` that throws an exception if an error occurs.
+
+ .. cpp:function:: template <typename ShutdownHandler> \
+ void async_shutdown(ShutdownHandler&& handler)
+
+ Asynchronous variant of :cpp:func:`shutdown`.
+ The function returns immediately and calls the *handler* callback function after performing asynchronous I/O to complete the TLS shutdown.
+
+
+ .. cpp:function:: template <typename MutableBufferSequence> \
+ std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec)
+
+ Reads encrypted data from the *next layer*, decrypts it, and writes it into the provided *buffers*.
+ If an error occurs, *error_code* is set.
+ Returns the number of bytes read.
+
+ .. cpp:function:: template <typename MutableBufferSequence> \
+ std::size_t read_some(const MutableBufferSequence& buffers)
+
+ Overload of :cpp:func:`read_some` that throws an exception if an error occurs.
+
+ .. cpp:function:: template <typename MutableBufferSequence, typename ReadHandler> \
+ DEDUCED async_read_some(const MutableBufferSequence& buffers, ReadHandler&& handler)
+
+ Asynchronous variant of :cpp:func:`read_some`.
+ The function returns immediately and calls the *handler* callback function after writing the decrypted data into the provided *buffers*.
+ The return type is an automatically deduced specialization of :cpp:class:`boost::asio::async_result`, depending on the *ReadHandler* type.
+ *ReadHandler* should suffice the `requirements to a Boost.Asio read handler <https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ReadHandler.html>`_.
+
+
+ .. cpp:function:: template <typename ConstBufferSequence> \
+ std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec)
+
+ Encrypts data from the provided *buffers* and writes it to the *next layer*.
+ If an error occurs, *error_code* is set.
+ Returns the number of bytes written.
+
+ .. cpp:function:: template <typename ConstBufferSequence> \
+ std::size_t write_some(const ConstBufferSequence& buffers)
+
+ Overload of :cpp:func:`write_some` that throws an exception rather than setting an error code.
+
+ .. cpp:function:: template <typename ConstBufferSequence, typename WriteHandler> \
+ DEDUCED async_write_some(const ConstBufferSequence& buffers, WriteHandler&& handler)
+
+ Asynchronous variant of :cpp:func:`write_some`.
+ The function returns immediately and calls the *handler* callback function after writing the encrypted data to the *next layer*.
+ The return type is an automatically deduced specialization of :cpp:class:`boost::asio::async_result`, depending on the *WriteHandler* type.
+ *WriteHandler* should suffice the `requirements to a Boost.Asio write handler <https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/WriteHandler.html>`_.
+
+.. cpp:class:: TLS::Context
+
+ A helper class to initialize and configure the Stream's underlying *native handle* (see :cpp:class:`TLS::Client` and :cpp:class:`TLS::Server`).
+
+ .. cpp:function:: Context(Credentials_Manager& credentialsManager, \
+ RandomNumberGenerator& randomNumberGenerator, \
+ Session_Manager& sessionManager, \
+ Policy& policy, \
+ Server_Information serverInfo = Server_Information())
+
+ Constructor for TLS::Context.
+
+ .. cpp:function:: void set_verify_callback(Verify_Callback_T callback)
+
+ Set a user-defined callback function for certificate chain verification. This
+ will cause the stream to override the default implementation of the
+ :cpp:func:`tls_verify_cert_chain` callback.
+
+TLS Stream Client Code Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The code below illustrates how to build a simple HTTPS client based on the TLS Stream and Boost.Beast. When run, it fetches the content of `https://botan.randombit.net/news.html` and prints it to stdout.
+
+.. code-block:: cpp
+
+ #include <iostream>
+
+ #include <botan/asio_stream.h>
+ #include <botan/auto_rng.h>
+ #include <botan/certstor_system.h>
+
+ #include <boost/asio.hpp>
+ #include <boost/beast.hpp>
+ #include <boost/bind.hpp>
+
+ namespace http = boost::beast::http;
+ namespace _ = boost::asio::placeholders;
+
+ // very basic credentials manager
+ class Credentials_Manager : public Botan::Credentials_Manager
+ {
+ public:
+ Credentials_Manager() {}
+
+ std::vector<Botan::Certificate_Store*>
+ trusted_certificate_authorities(const std::string&, const std::string&) override
+ {
+ return {&cert_store_};
+ }
+
+ private:
+ Botan::System_Certificate_Store cert_store_;
+ };
+
+ // a simple https client based on TLS::Stream
+ class client
+ {
+ public:
+ client(boost::asio::io_context& io_context,
+ boost::asio::ip::tcp::resolver::iterator endpoint_iterator,
+ http::request<http::string_body> req)
+ : request_(req)
+ , ctx_(credentials_mgr_,
+ rng_,
+ session_mgr_,
+ policy_,
+ Botan::TLS::Server_Information())
+ , stream_(io_context, ctx_)
+ {
+ boost::asio::async_connect(stream_.lowest_layer(), endpoint_iterator,
+ boost::bind(&client::handle_connect, this, _::error));
+ }
+
+ void handle_connect(const boost::system::error_code& error)
+ {
+ if(error)
+ {
+ std::cout << "Connect failed: " << error.message() << "\n";
+ return;
+ }
+ stream_.async_handshake(Botan::TLS::Connection_Side::CLIENT,
+ boost::bind(&client::handle_handshake, this, _::error));
+ }
+
+ void handle_handshake(const boost::system::error_code& error)
+ {
+ if(error)
+ {
+ std::cout << "Handshake failed: " << error.message() << "\n";
+ return;
+ }
+ http::async_write(stream_, request_,
+ boost::bind(&client::handle_write, this, _::error, _::bytes_transferred));
+ }
+
+ void handle_write(const boost::system::error_code& error, size_t)
+ {
+ if(error)
+ {
+ std::cout << "Write failed: " << error.message() << "\n";
+ return;
+ }
+ http::async_read(stream_, reply_, response_,
+ boost::bind(&client::handle_read, this, _::error, _::bytes_transferred));
+ }
+
+ void handle_read(const boost::system::error_code& error, size_t)
+ {
+ if(!error)
+ {
+ std::cout << "Reply: ";
+ std::cout << response_.body() << "\n";
+ }
+ else
+ {
+ std::cout << "Read failed: " << error.message() << "\n";
+ }
+ }
+
+ private:
+ http::request<http::dynamic_body> request_;
+ http::response<http::string_body> response_;
+ boost::beast::flat_buffer reply_;
+
+ Botan::TLS::Session_Manager_Noop session_mgr_;
+ Botan::AutoSeeded_RNG rng_;
+ Credentials_Manager credentials_mgr_;
+ Botan::TLS::Policy policy_;
+
+ Botan::TLS::Context ctx_;
+ Botan::TLS::Stream<boost::asio::ip::tcp::socket> stream_;
+ };
+
+ int main()
+ {
+ boost::asio::io_context io_context;
+
+ boost::asio::ip::tcp::resolver resolver(io_context);
+ boost::asio::ip::tcp::resolver::query query("botan.randombit.net", "443");
+ boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
+
+ http::request<http::string_body> req;
+ req.version(11);
+ req.method(http::verb::get);
+ req.target("/news.html");
+ req.set(http::field::host, "botan.randombit.net");
+
+ client c(io_context, iterator, req);
+
+ io_context.run();
+ }
+
+.. _tls_session_encryption:
+
+TLS Session Encryption
+-------------------------
+
+A unified format is used for encrypting TLS sessions either for durable storage
+(on client or server) or when creating TLS session tickets. This format is *not
+stable* even across the same major version.
+
+The current session encryption scheme was introduced in 2.13.0, replacing the
+format previously used since 1.11.13.
+
+Session encryption accepts a key of any length, though for best security a key
+of 256 bits should be used. This master key is used to key an instance of HMAC
+using the SHA-512/256 hash.
+
+First a "key name" or identifier is created, by HMAC'ing the fixed string "BOTAN
+TLS SESSION KEY NAME" and truncating to 4 bytes. This is the initial prefix of
+the encrypted session, and will remain fixed as long as the same ticket key is
+used. This allows quickly rejecting sessions which are encrypted using an
+unknown or incorrect key.
+
+Then a key used for AES-256 in GCM mode is created by first choosing a 128 bit
+random seed, and HMAC'ing it to produce a 256-bit value. This means for any one
+master key as many as 2\ :sup:`128` GCM keys can be created. This is done
+because NIST recommends that when using random nonces no one GCM key be used to
+encrypt more than 2\ :sup:`32` messages (to avoid the possiblity of nonce
+reuse).
+
+A random 96-bit nonce is created and included in the header.
+
+AES in GCM is used to encrypt and authenticate the serialized session. The
+key name, key seed, and AEAD nonce are all included as additional data.
diff --git a/comm/third_party/botan/doc/api_ref/tpm.rst b/comm/third_party/botan/doc/api_ref/tpm.rst
new file mode 100644
index 0000000000..7598c4bd81
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/tpm.rst
@@ -0,0 +1,113 @@
+Trusted Platform Module (TPM)
+==========================================
+
+.. versionadded:: 1.11.26
+
+Some computers come with a TPM, which is a small side processor which can
+perform certain operations which include RSA key generation and signing, a
+random number generator, accessing a small amount of NVRAM, and a set of PCRs
+which can be used to measure software state (this is TPMs most famous use, for
+authenticating a boot sequence).
+
+The TPM NVRAM and PCR APIs are not supported by Botan at this time, patches welcome.
+
+Currently only v1.2 TPMs are supported, and the only TPM library supported is
+TrouSerS (http://trousers.sourceforge.net/). Hopefully both of these limitations
+will be removed in a future release, in order to support newer TPM v2.0 systems.
+The current code has been tested with an ST TPM running in a Lenovo laptop.
+
+Test for TPM support with the macro ``BOTAN_HAS_TPM``, include ``<botan/tpm.h>``.
+
+First, create a connection to the TPM with a ``TPM_Context``. The context is
+passed to all other TPM operations, and should remain alive as long as any other
+TPM object which the context was passed to is still alive, otherwise errors or
+even an application crash are possible. In the future, the API may change to
+using ``shared_ptr`` to remove this problem.
+
+.. cpp:class:: TPM_Context
+
+ .. cpp:function:: TPM_Context(pin_cb cb, const char* srk_password)
+
+ The (somewhat improperly named) pin_cb callback type takes a std::string as
+ an argument, which is an informative message for the user. It should return
+ a string containing the password entered by the user.
+
+ Normally the SRK password is null. Use nullptr to signal this.
+
+The TPM contains a RNG of unknown design or quality. If that doesn't scare you
+off, you can use it with ``TPM_RNG`` which implements the standard
+``RandomNumberGenerator`` interface.
+
+.. cpp:class:: TPM_RNG
+
+ .. cpp:function:: TPM_RNG(TPM_Context& ctx)
+
+ Initialize a TPM RNG object. After initialization, reading from
+ this RNG reads from the hardware? RNG on the TPM.
+
+The v1.2 TPM uses only RSA, but because this key is implemented completely in
+hardware it uses a different private key type, with a somewhat different API to
+match the TPM's behavior.
+
+.. cpp:class:: TPM_PrivateKey
+
+ .. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, size_t bits, const char* key_password)
+
+ Create a new RSA key stored on the TPM. The bits should be either 1024
+ or 2048; the TPM interface hypothetically allows larger keys but in
+ practice no v1.2 TPM hardware supports them.
+
+ The TPM processor is not fast, be prepared for this to take a while.
+
+ The key_password is the password to the TPM key ?
+
+ .. cpp:function:: std::string register_key(TPM_Storage_Type storage_type)
+
+ Registers a key with the TPM. The storage_type can be either
+ `TPM_Storage_Type::User` or `TPM_Storage_Type::System`. If System, the
+ key is stored on the TPM itself. If User, it is stored on the local hard
+ drive in a database maintained by an intermediate piece of system
+ software (which actual interacts with the physical TPM on behalf of any
+ number of applications calling the TPM API).
+
+ The TPM has only some limited space to store private keys and may reject
+ requests to store the key.
+
+ In either case the key is encrypted with an RSA key which was generated
+ on the TPM and which it will not allow to be exported. Thus (so goes the
+ theory) without physically attacking the TPM
+
+ Returns a UUID which can be passed back to constructor below.
+
+ .. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, const std::string& uuid, \
+ TPM_Storage_Type storage_type)
+
+ Load a registered key. The UUID was returned by the ``register_key`` function.
+
+ .. cpp:function:: std::vector<uint8_t> export_blob() const
+
+ Export the key as an encrypted blob. This blob can later be presented
+ back to the same TPM to load the key.
+
+ .. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, const std::vector<uint8_t>& blob)
+
+ Load a TPM key previously exported as a blob with ``export_blob``.
+
+ .. cpp:function:: std::unique_ptr<Public_Key> public_key() const
+
+ Return the public key associated with this TPM private key.
+
+ TPM does not store public keys, nor does it support signature verification.
+
+ .. cpp:function:: TSS_HKEY handle() const
+
+ Returns the bare TSS key handle. Use if you need to call the raw TSS API.
+
+A ``TPM_PrivateKey`` can be passed to a ``PK_Signer`` constructor and used to
+sign messages just like any other key. Only PKCS #1 v1.5 signatures are supported
+by the v1.2 TPM.
+
+.. cpp:function:: std::vector<std::string> TPM_PrivateKey::registered_keys(TPM_Context& ctx)
+
+ This static function returns the list of all keys (in URL format)
+ registered with the system
diff --git a/comm/third_party/botan/doc/api_ref/tss.rst b/comm/third_party/botan/doc/api_ref/tss.rst
new file mode 100644
index 0000000000..947b835d0a
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/tss.rst
@@ -0,0 +1,45 @@
+Threshold Secret Sharing
+========================================
+
+.. versionadded:: 1.9.1
+
+Threshold secret sharing allows splitting a secret into ``N`` shares such that
+``M`` (for specified ``M`` <= ``N``) is sufficient to recover the secret, but an
+attacker with ``M - 1`` shares cannot derive any information about the secret.
+
+The implementation in Botan follows an expired Internet draft
+"draft-mcgrew-tss-03". Several other implementations of this TSS format exist.
+
+.. cpp:class:: RTSS_Share
+
+ .. cpp:function:: static std::vector<RTSS_Share> split(uint8_t M, uint8_t N, \
+ const uint8_t secret[], uint16_t secret_len, \
+ const std::vector<uint8_t>& identifier, \
+ const std::string& hash_fn, \
+ RandomNumberGenerator& rng)
+
+ Split a secret. The identifier is an optional key identifier which may be
+ up to 16 bytes long. Shorter identifiers are padded with zeros.
+
+ The hash function must be either "SHA-1", "SHA-256", or "None" to disable
+ the checksum.
+
+ This will return a vector of length ``N``, any ``M`` of these shares is
+ sufficient to reconstruct the data.
+
+ .. cpp:function:: static secure_vector<uint8_t> reconstruct(const std::vector<RTSS_Share>& shares)
+
+ Given a sufficient number of shares, reconstruct a secret.
+
+ .. cpp:function:: RTSS_Share(const uint8_t data[], size_t len)
+
+ Read a TSS share as a sequence of bytes.
+
+ .. cpp:function:: const secure_vector<uint8>& data() const
+
+ Return the data of this share.
+
+ .. cpp:function:: uint8_t share_id() const
+
+ Return the share ID which will be in the range 1...255
+
diff --git a/comm/third_party/botan/doc/api_ref/versions.rst b/comm/third_party/botan/doc/api_ref/versions.rst
new file mode 100644
index 0000000000..511141b75f
--- /dev/null
+++ b/comm/third_party/botan/doc/api_ref/versions.rst
@@ -0,0 +1,100 @@
+
+Versioning
+========================================
+
+All versions are of the tuple (major,minor,patch).
+
+As of Botan 2.0.0, Botan uses semantic versioning. The minor number increases if
+any feature addition is made. The patch version is used to indicate a release
+where only bug fixes were applied. If an incompatible API change is required,
+the major version will be increased.
+
+The library has functions for checking compile-time and runtime versions.
+
+The build-time version information is defined in `botan/build.h`
+
+.. c:macro:: BOTAN_VERSION_MAJOR
+
+ The major version of the release.
+
+.. c:macro:: BOTAN_VERSION_MINOR
+
+ The minor version of the release.
+
+.. c:macro:: BOTAN_VERSION_PATCH
+
+ The patch version of the release.
+
+.. c:macro:: BOTAN_VERSION_DATESTAMP
+
+ Expands to an integer of the form YYYYMMDD if this is an official
+ release, or 0 otherwise. For instance, 1.10.1, which was released
+ on July 11, 2011, has a `BOTAN_VERSION_DATESTAMP` of 20110711.
+
+.. c:macro:: BOTAN_DISTRIBUTION_INFO
+
+ .. versionadded:: 1.9.3
+
+ A macro expanding to a string that is set at build time using the
+ ``--distribution-info`` option. It allows a packager of the library
+ to specify any distribution-specific patches. If no value is given
+ at build time, the value is the string "unspecified".
+
+.. c:macro:: BOTAN_VERSION_VC_REVISION
+
+ .. versionadded:: 1.10.1
+
+ A macro expanding to a string that is set to a revision identifier
+ corresponding to the source, or "unknown" if this could not be
+ determined. It is set for all official releases, and for builds that
+ originated from within a git checkout.
+
+The runtime version information, and some helpers for compile time
+version checks, are included in `botan/version.h`
+
+.. cpp:function:: std::string version_string()
+
+ Returns a single-line string containing relevant information about
+ this build and version of the library in an unspecified format.
+
+.. cpp:function:: uint32_t version_major()
+
+ Returns the major part of the version.
+
+.. cpp:function:: uint32_t version_minor()
+
+ Returns the minor part of the version.
+
+.. cpp:function:: uint32_t version_patch()
+
+ Returns the patch part of the version.
+
+.. cpp:function:: uint32_t version_datestamp()
+
+ Return the datestamp of the release (or 0 if the current version is
+ not an official release).
+
+.. cpp:function:: std::string runtime_version_check(uint32_t major, uint32_t minor, uint32_t patch)
+
+ Call this function with the compile-time version being built against, eg::
+
+ Botan::runtime_version_check(BOTAN_VERSION_MAJOR, BOTAN_VERSION_MINOR, BOTAN_VERSION_PATCH)
+
+ It will return an empty string if the versions match, or otherwise
+ an error message indicating the discrepancy. This only is useful in
+ dynamic libraries, where it is possible to compile and run against
+ different versions.
+
+.. c:macro:: BOTAN_VERSION_CODE_FOR(maj,min,patch)
+
+ Return a value that can be used to compare versions. The current
+ (compile-time) version is available as the macro
+ `BOTAN_VERSION_CODE`. For instance, to choose one code path for
+ version 2.1.0 and later, and another code path for older releases::
+
+ #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,1,0)
+ // 2.1+ code path
+ #else
+ // code path for older versions
+ #endif
+
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``.