aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-12-03 12:33:42 -0500
committerJack Lloyd <[email protected]>2017-12-04 04:01:06 -0500
commit57128566bd57649f7d3a128944e3bde66d415309 (patch)
tree4c93a2807a729f977da7f86f76baf536a581c8be /doc
parentcfd137da35488edb573cb670bedc314671d206f0 (diff)
Split up symmetric crypto page into MAC, stream, block and mode pages
Diffstat (limited to 'doc')
-rw-r--r--doc/deprecated.txt13
-rw-r--r--doc/manual/block_cipher.rst340
-rw-r--r--doc/manual/cipher_modes.rst305
-rw-r--r--doc/manual/contents.rst8
-rw-r--r--doc/manual/hash.rst85
-rw-r--r--doc/manual/lowlevel.rst72
-rw-r--r--doc/manual/message_auth_codes.rst217
-rw-r--r--doc/manual/pubkey.rst2
-rw-r--r--doc/manual/rng.rst9
-rw-r--r--doc/manual/stream_ciphers.rst171
-rw-r--r--doc/manual/symmetric_crypto.rst574
-rw-r--r--doc/manual/tpm.rst2
-rw-r--r--doc/todo.rst2
13 files changed, 1091 insertions, 709 deletions
diff --git a/doc/deprecated.txt b/doc/deprecated.txt
index 0d750ec65..cbb48c797 100644
--- a/doc/deprecated.txt
+++ b/doc/deprecated.txt
@@ -13,10 +13,15 @@ in the source.
- The TLS constructors taking `std::function` for callbacks. Instead
use the TLS::Callbacks interface.
-- The Buffered_Computation class. In a future release the class will be removed,
- and all of member functions instead declared directly on MessageAuthenticationCode
- and HashFunction. So this only affects you if you are directly referencing
- `Botan::Buffered_Computation` in some way.
+- The Buffered_Computation base class. In a future release the class will be
+ removed, and all of member functions instead declared directly on
+ MessageAuthenticationCode and HashFunction. So this only affects you if you
+ are directly referencing `Botan::Buffered_Computation` in some way.
+
+- The SymmetricAlgorithm base class. Similarly to Buffered_Computation, in a
+ future release the class will be removed and its member functions copied to
+ classes which currently subclass it. This only affects your code if you
+ are referencing `Botan::SymmetricAlgorithm` directly.
- Platform support for BeOS and IRIX operating systems
diff --git a/doc/manual/block_cipher.rst b/doc/manual/block_cipher.rst
new file mode 100644
index 000000000..316884682
--- /dev/null
+++ b/doc/manual/block_cipher.rst
@@ -0,0 +1,340 @@
+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.
+
+.. note::
+
+ In general a bare block cipher is not what you should be using. You probably
+ want a cipher mode instead (see :ref:`cipher_modes`)
+
+.. 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 acceptible for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptible 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 parallism
+ 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. The ciphers that
+seem best for new code are AES, Serpent, and Threefish-512.
+
+Avoid any 64-bit cipher in new code. 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.
+
+If you are developing new code and have no particular opinion, pick AES.
+
+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 contestent in the NIST AES competition.
+Rarely used, and now deprecated in Botan. Use AES or Serpent instead.
+
+Available if ``BOTAN_HAS_CAST256`` is defined.
+
+Camellia
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Comes in three variants, Camellia-128, Camellia-192, and Camellia-256.
+
+A Japanese design standardized by ISO, NESSIE and CRYPTREC. Somewhat common.
+Prefer AES or Serpent in new designs.
+
+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. Very slow, but still common in
+some industries such as finance. Avoid in new code.
+
+Available if ``BOTAN_HAS_DES`` is defined.
+
+GOST-28147-89
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A old 64-bit Russian cipher. Possible security issues. Avoid unless
+compatability is needed.
+
+Available if ``BOTAN_HAS_GOST_28147_89`` is defined.
+
+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.
+
+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. The
+implementation in Botan is deprecated, and it is likely to be removed in a
+future release.
+
+Available if ``BOTAN_HAS_MISTY1`` is defined.
+
+Noekeon
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A fast 128-bit cipher by the designers of AES. Easily secured against side
+channels.
+
+Available if ``BOTAN_HAS_NOEKEON`` is defined.
+
+SEED
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A older South Korean cipher, widely used in industry there.
+
+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 and seemingly very secure, but obscure. Standardized by NESSIE.
+
+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,
+especially if no SIMD instruction set is 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
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+An AES contender. 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/doc/manual/cipher_modes.rst b/doc/manual/cipher_modes.rst
new file mode 100644
index 000000000..ffd36a218
--- /dev/null
+++ b/doc/manual/cipher_modes.rst
@@ -0,0 +1,305 @@
+.. _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 acceptible for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptible for the
+ algorithm.
+
+ .. cpp:function:: void start_msg(const uint8_t* nonce, size_t nonce_len)
+
+ Set the IV (unique per-message nonce) of the mode of operation and prepare for message processing.
+
+ .. 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 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
+
+.. 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::get_cipher_mode("AES-128/CBC/PKCS7", Botan::ENCRYPTION));
+ enc->set_key(key);
+
+ Botan::secure_vector<uint8_t> pt(plaintext.data(), plaintext.data()+plaintext.length());
+
+ //generate fresh nonce (IV)
+ enc->start(rng.random_vec(enc->default_nonce_length()));
+ 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.
+
+CFB
+~~~~~~~~~~~~
+
+Available if ``BOTAN_HAS_MODE_CFB`` is defined.
+
+CFB uses a block cipher to create a self-syncronizing stream cipher. It is used
+for example in the OpenPGP protocol. There is no reason to prefer it.
+
+XTS
+~~~~~~~~~
+
+Available if ``BOTAN_HAS_MODE_XTS`` is defined.
+
+XTS is a mode specialized for encrypting disk storage. XTS requires all inputs
+be at least 1 byte longer than the native block size of the cipher.
+
+.. _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`.
+
+The AEAD interface can be used directly, or as part of the filter system by
+using :cpp:class:`AEAD_Filter` (a subclass of :cpp:class:`Keyed_Filter` which
+will be returned by :cpp:func:`get_cipher` if the named cipher is an AEAD 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.
+
+ .. warning::
+ With most AEADs, if the same nonce is ever used to encrypt two
+ different messages under the same key, all security is lost.
+
+ .. 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, finish will throw an instance of Integrity_Failure
+ if the MAC does not validate. 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.
+
+ One simply way to assure this could never happen is to never
+ call update, and instead always marshall 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
+-------------------------
+
+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.
+
+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 resistent";
+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 duplicated message (this is because for identical plaintexts SIV
+will output the same ciphertext each time, in the case the nonce is repeated.)
+
+CCM
+~~~~~
+
+Available if ``BOTAN_HAS_AEAD_CCM`` is defined.
+
+Requires a 128-bit block cipher. This is a NIST standard mode but that is about
+all to recommenmd it. Prefer EAX.
diff --git a/doc/manual/contents.rst b/doc/manual/contents.rst
index 48e6edbfe..d4e06f82d 100644
--- a/doc/manual/contents.rst
+++ b/doc/manual/contents.rst
@@ -11,16 +11,17 @@ Contents
versions
secmem
rng
- filters
hash
- symmetric_crypto
+ block_cipher
+ stream_ciphers
+ message_auth_codes
+ cipher_modes
pubkey
mceliece
x509
tls
credentials_manager
bigint
- lowlevel
kdf
pbkdf
keywrap
@@ -28,6 +29,7 @@ Contents
cryptobox
srp
psk_db
+ filters
fpe
compression
pkcs11
diff --git a/doc/manual/hash.rst b/doc/manual/hash.rst
index abf9d7a70..7b317f498 100644
--- a/doc/manual/hash.rst
+++ b/doc/manual/hash.rst
@@ -62,7 +62,40 @@ internal state is reset to begin hashing a new message.
Equivalent to calling ``update`` followed by ``final``.
-Cryptographic Hash Functions
+Code Example
+------------
+
+Assume we want to calculate the SHA-1, Whirlpool 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-1"));
+ std::unique_ptr<Botan::HashFunction> hash2(Botan::HashFunction::create("Whirlpool"));
+ 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-1: " << Botan::hex_encode(hash1->final()) << std::endl;
+ std::cout << "Whirlpool: " << 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.
@@ -148,7 +181,7 @@ Available if ``BOTAN_HAS_SHA3`` is defined.
The new NIST standard hash. Fairly slow.
SHAKE (SHAKE-128, SHAKE-256)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHAKE`` is defined.
@@ -249,50 +282,4 @@ CRC32
Available if ``BOTAN_HAS_CRC32`` is defined.
-This is some kind of 32 bit CRC (which one?).
-
-
-Code Example
-------------
-
-Assume we want to calculate the SHA-1, Whirlpool 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-1"));
- std::unique_ptr<Botan::HashFunction> hash2(Botan::HashFunction::create("Whirlpool"));
- 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-1: " << Botan::hex_encode(hash1->final()) << std::endl;
- std::cout << "Whirlpool: " << Botan::hex_encode(hash2->final()) << std::endl;
- std::cout << "SHA-3: " << Botan::hex_encode(hash3->final()) << std::endl;
- return 0;
- }
-
-
-A Note on Checksums
---------------------
-
-Checksums are very similar to hash functions, and in fact share the
-same interface. But there are some significant differences, the major
-ones being that the output size is very small (usually in the range of
-2 to 4 bytes), and is not cryptographically secure. But for their
-intended purpose (error checking), they perform very well. Some
-examples of checksums included in Botan are the Adler32 and CRC32
-checksums.
+This is the 32-bit CRC used in protocols such as Ethernet, gzip, PNG, etc.
diff --git a/doc/manual/lowlevel.rst b/doc/manual/lowlevel.rst
deleted file mode 100644
index bcffcd632..000000000
--- a/doc/manual/lowlevel.rst
+++ /dev/null
@@ -1,72 +0,0 @@
-
-The Low-Level Interface
-=================================
-
-Botan has two different interfaces. The one documented in this section
-is meant more for implementing higher-level types (see the section on
-filters, earlier in this manual) than for use by applications. Using
-it safely requires a solid knowledge of encryption techniques and best
-practices, so unless you know, for example, what CBC mode and nonces
-are, and why PKCS #1 padding is important, you should avoid this
-interface in favor of something working at a higher level.
-
-Basic Algorithm Abilities
----------------------------------
-
-There are a small handful of functions implemented by most of Botan's
-algorithm objects. Among these are:
-
-.. cpp:function:: std::string name()
-
-Returns a human-readable string of the name of this
-algorithm. Examples of names returned are "AES-128" and
-"HMAC(SHA-512)". You can turn names back into algorithm objects using
-the functions in ``lookup.h``.
-
-.. cpp:function:: void clear()
-
-Clear out the algorithm's internal state. A block cipher object will
-"forget" its key, a hash function will "forget" any data put into it,
-etc. The object will look and behave as it did when you initially
-allocated it.
-
-.. cpp:function:: T* clone()
-
-The ``clone`` has many different return types, such as
-``BlockCipher``\* and ``HashFunction``\*, depending on what kind of
-object it is called on. Note that unlike Java's clone, this returns a
-new object in a "pristine" state; that is, operations done on the
-initial object before calling ``clone`` do not affect the initial
-state of the new clone.
-
-Cloned objects can (and should) be deallocated with the C++ ``delete``
-operator.
-
-Keys and IVs
----------------------------------
-
-Both symmetric keys and initialization values can be considered byte
-(or octet) strings. These are represented by
-
-.. cpp:class:: OctetString
-
- Also known as ``SymmetricKey`` and ``InitializationVector``, when
- you want to express intent.
-
- .. cpp:function:: OctetString(RandomNumberGenerator& rng, size_t length)
-
- This constructor creates a new random key *length* bytes long
- using the random number generator.
-
- .. cpp:function:: OctetString(std::string str)
-
- The argument *str* is assumed to be a hex string; it is
- converted to binary and stored. Whitespace is ignored.
-
- .. cpp:function:: OctetString(const uint8_t* input, size_t length)
-
- This constructor copies its input.
-
- .. cpp:function:: as_string() const
-
- Returns the hex representation of the key or IV
diff --git a/doc/manual/message_auth_codes.rst b/doc/manual/message_auth_codes.rst
new file mode 100644
index 000000000..31ab5f348
--- /dev/null
+++ b/doc/manual/message_auth_codes.rst
@@ -0,0 +1,217 @@
+
+.. _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 acceptible for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptible 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 Example
+------------------------
+
+The following example code computes a AES-256 GMAC and subsequently verifies the tag.
+
+.. 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> iv = 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(iv);
+ 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(iv);
+ 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 or CMAC.
+
+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 compatability.
+
+Available if ``BOTAN_HAS_CBC_MAC`` is defined.
+
+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.
+
+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.
+
+SipHash
+~~~~~~~~~~~~
+
+A modern and very fast PRF. Produces only a 64-bit output.
+
+Available if ``BOTAN_HAS_SIPHASH`` is defined.
+
+X9.19-MAC
+~~~~~~~~~~~~
+
+A CBC-MAC variant sometimes used in finance. Always uses DES. Avoid unless
+required.
+
+Available if ``BOTAN_HAS_X919_MAC`` is defined.
+
diff --git a/doc/manual/pubkey.rst b/doc/manual/pubkey.rst
index c72793d89..8a7991e53 100644
--- a/doc/manual/pubkey.rst
+++ b/doc/manual/pubkey.rst
@@ -436,7 +436,7 @@ ElGamal; these use the EME class:
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:`symmetric_crypto`) and the MAC.
+ :ref:`cipher_modes`) and the MAC.
.. cpp:function:: ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, \
const ECIES_System_Params& ecies_params, \
diff --git a/doc/manual/rng.rst b/doc/manual/rng.rst
index 11094d832..99cc83914 100644
--- a/doc/manual/rng.rst
+++ b/doc/manual/rng.rst
@@ -67,7 +67,8 @@ 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 compatability concerns when changing
-such an RNG.
+any RNG since the only expectation is it produces bits
+indistinguishable from random.
Note well: like most other classes in Botan, it is not safe to share
an instance of ``AutoSeeded_RNG`` among multiple threads without
@@ -139,5 +140,7 @@ 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 the
-random generator after forking a new process.
+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/doc/manual/stream_ciphers.rst b/doc/manual/stream_ciphers.rst
new file mode 100644
index 000000000..80dfa7729
--- /dev/null
+++ b/doc/manual/stream_ciphers.rst
@@ -0,0 +1,171 @@
+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`).
+
+Note that some of the implemented stream ciphers require a fresh initialisation
+vector.
+
+.. 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 acceptible for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptible 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:: 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.
+
+ .. cpp:function:: void seek(uint64_t offset)
+
+ Sets the state of the stream cipher and keystream according to the passed
+ *offset*. Therefore the key and the IV (if required) have to be set
+ beforehand.
+
+ .. 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 CTR or ChaCha.
+
+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.
+
+(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.
+
+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.
+
+.. note::
+
+ The 'XSalsa20' variant of Salsa20 is also supported by the same class; this
+ is selected by using a 192-bit nonce instead of Salsa20's 64-bit nonce.
+
+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.
+
+Available if ``BOTAN_HAS_SHAKE_CIPHER`` is defined.
+
+RC4
+~~~~
+
+An old and very widely deployed stream cipher notable for its
+simplicity. Now broken. **Avoid in new code**
+
+Available if ``BOTAN_HAS_RC4`` is defined.
+
diff --git a/doc/manual/symmetric_crypto.rst b/doc/manual/symmetric_crypto.rst
deleted file mode 100644
index 605d329fb..000000000
--- a/doc/manual/symmetric_crypto.rst
+++ /dev/null
@@ -1,574 +0,0 @@
-.. _symmetric_crypto:
-
-Symmetric Key Cryptography
-===========================================
-Block ciphers, stream ciphers and MACs are all keyed operations.
-They require a particular key, which is a chosen, sampled or computed
-string of bits of a specified length. The length required by any particular algorithm
-may vary, depending on both the algorithm specification and the implementation.
-You can query any Botan object to find out what key length(s) it supports.
-
-To make this similarity in terms of keying explicit, all algorithms of
-those types are derived from the :cpp:class:`SymmetricAlgorithm` base.
-This type provides functions for setting the key, and querying
-restrictions on the size of the key.
-
-.. cpp:class:: SymmetricAlgorithm
-
- .. cpp:function:: void set_key(const uint8_t* key, size_t length)
-
- .. cpp:function:: void set_key(const SymmetricKey& key)
-
- 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, the results are undefined.
-
- .. 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 acceptible for the
- algorithm.
-
- .. cpp:function:: size_t maximum_keylength() const
-
- Return the largest key length (in bytes) that is acceptible for the
- algorithm.
-
-Block Ciphers
----------------------------------
-A block cipher is a deterministic symmetric encryption algorithm, which
-encrypts data of a fixed length, called block size. All block ciphers classes
-in Botan are subclasses of :cpp:class:`BlockCipher` defined in `botan/block_cipher.h`.
-As a symmetrically keyed algorithm, it subclasses the :cpp:class:`SymmetricAlgorithm` interface.
-Note that a block cipher by itself is only secure for plaintext with the length of a single block.
-When processing data larger than a single block, a block cipher mode should be used for data processing.
-
-.. cpp:class:: BlockCipher
-
- .. cpp:function:: size_t block_size() const
-
- Returns the block size of the cipher in bytes.
-
- .. cpp:function:: void encrypt_n(const uint8_t* in, \
- uint8_t* out, size_t n) const
-
- Encrypt *n* 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 encrypt(const uint8_t* in, uint8_t* out) const
-
- Encrypt a single block, taking the input from *in* and placing
- it in *out*. Acts like :cpp:func:`encrypt_n`\ (in, out, 1).
-
- .. cpp:function:: void encrypt(const std::vector<uint8_t> in, std::vector<uint8_t> out) const
-
- Encrypt a single or multiple full blocks, taking the input from *in* and placing it in *out*.
- Acts like :cpp:func:`encrypt_n`\ (in.data(), out.data(), in.size()/ block_size()).
-
- .. cpp:function:: void encrypt(std::vector<uint8_t> inout) const
-
- Encrypt a single or multiple full blocks in place.
- Acts like :cpp:func:`encrypt_n`\ (inout.data(), inout.data(), inout.size()/ block_size()).
-
- .. cpp:function:: void encrypt(uint8_t* block) const
-
- Identical to :cpp:func:`encrypt`\ (block, block)
-
- .. cpp:function:: void decrypt_n(const uint8_t* in, uint8_t out, size_t n) const
-
- Decrypt *n* blocks of data, taking the input from *in* and
- placing the plaintext in *out*. The two pointers may be
- identical, but should not overlap ranges.
-
- .. cpp:function:: void decrypt(const uint8_t* in, uint8_t* out) const
-
- Decrypt a single block, taking the input from *in* and placing it
- in *out*. Acts like :cpp:func:`decrypt_n`\ (in, out, 1).
-
- .. cpp:function:: void decrypt(const std::vector<uint8_t> in, std::vector<uint8_t> out) const
-
- Decrypt a single or multiple full blocks, taking the input from *in* and placing it in *out*.
- Acts like :cpp:func:`decrypt_n`\ (in.data(), out.data(), in.size()/ block_size()).
-
- .. cpp:function:: void decrypt(std::vector<uint8_t> inout) const
-
- Decrypt a single or multiple full blocks in place.
- Acts like :cpp:func:`decrypt_n`\ (inout.data(), inout.data(), inout.size()/ block_size()).
-
- .. cpp:function:: void decrypt(uint8_t* block) const
-
- Identical to :cpp:func:`decrypt`\ (block, block)
-
- .. cpp:function:: size_t parallelism() const
-
- Returns the native parallelism of this implementation, ie how
- many blocks can be processed in parallel if sufficient data is
- passed to :cpp:func:`encrypt_n` or :cpp:func:`decrypt_n`.
-
-The following block ciphers are implemented in Botan:
-
-#. AES (AES-128, AES-192, AES-256)
-#. ARIA
-#. Blowfish
-#. CAST (CAST-128, CAST-256)
-#. Camellia (Camellia-128, Camellia-192, Camellia-256)
-#. Cascade
-#. DES/3DES
-#. DESX
-#. GOST-28147-89
-#. IDEA
-#. Kasumi
-#. Lion
-#. MISTY1
-#. Noekeon
-#. SEED
-#. SHACAL2
-#. SM4
-#. Serpent
-#. Threefish-512
-#. Twofish
-#. XTEA
-
-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;
- }
-
-Modes of Operation
----------------------------
-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 on a padded plaintext.
-Botan implements the following block cipher padding schemes
-
-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.
-ISO/IEC 7816-4
- The first padding byte is set to 0x80, the remaining padding bytes are set to 0x00.
-
-and offers the following unauthenticated modes of operation:
-
-#. ECB (Electronic Codebook Mode)
-#. CBC (Cipher Block Chaining Mode)
-#. CFB (Cipher Feedback Mode)
-#. XTS (XEX-based tweaked-codebook mode with ciphertext stealing)
-#. OFB (Output Feedback Mode)
-#. CTR (Counter Mode)
-
-The classes :cpp:class:`ECB_Mode`, :cpp:class:`CBC_Mode`, :cpp:class:`CFB_Mode` and :cpp:class:`XTS_Mode` are
-are derived from the base class :cpp:class:`Cipher_Mode`, which is declared in ``botan/cipher_mode.h``.
-
-.. cpp:class:: Cipher_Mode
-
- .. cpp:function:: void set_key(const SymmetricKey& key)
- .. cpp:function:: void set_key(const uint8_t* key, size_t length)
-
- Set the symmetric key to be used.
-
- .. cpp:function:: void start_msg(const uint8_t* nonce, size_t nonce_len)
-
- Set the IV (unique per-message nonce) of the mode of operation and prepare for message processing.
-
- .. 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 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.
-
-Note that :cpp:class:`CTR_BE` and :cpp:class:`OFB` are derived from the base class :cpp:class:`StreamCipher` and thus act like a stream cipher.
-The class :cpp:class:`StreamCipher` is described in the respective section.
-
-
-Code Example
-"""""""""""""""""""""
-The following code encrypts the specified plaintext using AES-128/CBC with PKCS#7 padding.
-
-.. 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()
- {
- 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.");
- Botan::secure_vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
- const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C");
- std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode("AES-128/CBC/PKCS7", Botan::ENCRYPTION));
- enc->set_key(key);
-
- //generate fresh nonce (IV)
- std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
- std::vector<uint8_t> iv(enc->default_nonce_length());
- rng->randomize(iv.data(),iv.size());
- enc->start(iv);
- enc->finish(pt);
- std::cout << std::endl << enc->name() << " with iv " << Botan::hex_encode(iv) << std::endl << Botan::hex_encode(pt);
- return 0;
- }
-
-
-AEAD Modes of Operation
----------------------------
-
-.. versionadded:: 1.11.3
-
-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:`Symmetric_Algorithm`.
-
-The AEAD interface can be used directly, or as part of the filter system by
-using :cpp:class:`AEAD_Filter` (a subclass of :cpp:class:`Keyed_Filter` which
-will be returned by :cpp:func:`get_cipher` if the named cipher is an AEAD mode).
-
-AEAD modes currently available include GCM, OCB, EAX, SIV and CCM. All
-support a 128-bit block cipher such as AES. EAX and OCB also support
-256 and 512 bit block ciphers.
-
-.. 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.
-
- .. 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, finish will throw an instance of Integrity_Failure
- if the MAC does not validate. 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.
-
- One simply way to assure this could never happen is to never
- call update, and instead always marshall 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.
-
-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`), which
-implements the :cpp:class:`SymmetricAlgorithm` interface. Note that some of the implemented
-stream ciphers require a fresh initialisation vector.
-
-.. cpp:class:: StreamCipher
-
- .. 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.
-
- .. 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.
-
- .. cpp:function:: void seek(uint64_t offset)
-
- Sets the state of the stream cipher and keystream according to the passed *offset*.
- Therefore the key and the IV (if required) have to be set beforehand.
-
- .. 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()).
-
-Botan provides the following stream ciphers:
-
-#. ChaCha
-#. Salsa20
-#. SHAKE-128
-#. RC4
-
-Code Example
-""""""""""""""
-The following code encrypts a provided plaintext using ChaCha20.
-
-.. code-block:: cpp
-
- #include <botan/stream_cipher.h>
- #include <botan/rng.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"));
-
- //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());
- std::cout << std::endl << cipher->name() << " with iv " << Botan::hex_encode(iv) << std::endl;
- cipher->encipher(pt);
- std::cout << Botan::hex_encode(pt);
-
- return 0;
- }
-
-
-
-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 associated data.
-Only entities in possesion of the shared secret key are able to verify the tag.
-The base class ``MessageAuthenticationCode`` (in ``botan/mac.h``) implements the interfaces
-:cpp:class:`SymmetricAlgorithm` and :cpp:class:`BufferedComputation` (see Hash).
-
-.. note::
- Avoid MAC-then-encrypt if possible and use encrypt-then-MAC.
-
-Currently the following MAC algorithms are available in Botan:
-
-- CBC-MAC (with AES-128/DES)
-- CMAC / OMAC (with AES-128/AES-192/AES-256/Blowfish/Threefish-512)
-- GMAC (with AES-128/AES-192/AES-256)
-- HMAC (with MD5, RIPEMD-160, SHA-1, SHA-256)
-- Poly1305
-- SipHash
-- x9.19-MAC
-
-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:: 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:: 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.
-
- .. cpp:function:: void update(const uint8_t* input, size_t length)
- .. 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 successfull and false otherwise.
-
-
-Code Example
-""""""""""""""""""""""
-The following example code computes a AES-256 GMAC and subsequently verifies the tag.
-
-.. 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> iv = 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(iv);
- 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(iv);
- 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;
- }
diff --git a/doc/manual/tpm.rst b/doc/manual/tpm.rst
index de9e170f8..ddf615d03 100644
--- a/doc/manual/tpm.rst
+++ b/doc/manual/tpm.rst
@@ -1,4 +1,4 @@
-Trusted Platform Module (TPM) Support
+Trusted Platform Module (TPM)
==========================================
.. versionadded:: 1.11.26
diff --git a/doc/todo.rst b/doc/todo.rst
index e0958dcb7..84e78d6aa 100644
--- a/doc/todo.rst
+++ b/doc/todo.rst
@@ -193,8 +193,6 @@ Documentation
* X.509 certs, path validation
* Specific docs covering one major topic (RSA, ECDSA, AES/GCM, ...)
* Some howto style docs (setting up CA, ...)
-* List each cipher, hash, etc, describe its usage, and give the
- header file and BOTAN_HAS_X macro associated with it.
Packaging
------------