From 57128566bd57649f7d3a128944e3bde66d415309 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 3 Dec 2017 12:33:42 -0500 Subject: Split up symmetric crypto page into MAC, stream, block and mode pages --- doc/deprecated.txt | 13 +- doc/manual/block_cipher.rst | 340 ++++++++++++++++++++++ doc/manual/cipher_modes.rst | 305 ++++++++++++++++++++ doc/manual/contents.rst | 8 +- doc/manual/hash.rst | 85 +++--- doc/manual/lowlevel.rst | 72 ----- doc/manual/message_auth_codes.rst | 217 ++++++++++++++ doc/manual/pubkey.rst | 2 +- doc/manual/rng.rst | 9 +- doc/manual/stream_ciphers.rst | 171 ++++++++++++ doc/manual/symmetric_crypto.rst | 574 -------------------------------------- doc/manual/tpm.rst | 2 +- doc/todo.rst | 2 - 13 files changed, 1091 insertions(+), 709 deletions(-) create mode 100644 doc/manual/block_cipher.rst create mode 100644 doc/manual/cipher_modes.rst delete mode 100644 doc/manual/lowlevel.rst create mode 100644 doc/manual/message_auth_codes.rst create mode 100644 doc/manual/stream_ciphers.rst delete mode 100644 doc/manual/symmetric_crypto.rst (limited to 'doc') 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 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 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 void encrypt(std::vector& block) const + + Assumes ``block`` is of a multiple of the block size. + + .. cpp:function:: template void decrypt(std::vector& 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 + #include + #include + int main () + { + std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + std::vector block = Botan::hex_decode("00112233445566778899AABBCCDDEEFF"); + std::unique_ptr cipher(Botan::BlockCipher::create("AES-256")); + cipher->set_key(key); + cipher->encrypt(block); + std::cout << std::endl <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 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& 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& 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 + #include + #include + #include + #include + + 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 key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); + + std::unique_ptr enc(Botan::get_cipher_mode("AES-128/CBC/PKCS7", Botan::ENCRYPTION)); + enc->set_key(key); + + Botan::secure_vector 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& 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& 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 + #include + #include + int main () + { + std::unique_ptr hash1(Botan::HashFunction::create("SHA-1")); + std::unique_ptr hash2(Botan::HashFunction::create("Whirlpool")); + std::unique_ptr hash3(Botan::HashFunction::create("SHA-3")); + std::vector buf(2048); + + while(std::cin.good()) + { + //read STDIN to buffer + std::cin.read(reinterpret_cast(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 - #include - #include - int main () - { - std::unique_ptr hash1(Botan::HashFunction::create("SHA-1")); - std::unique_ptr hash2(Botan::HashFunction::create("Whirlpool")); - std::unique_ptr hash3(Botan::HashFunction::create("SHA-3")); - std::vector buf(2048); - - while(std::cin.good()) - { - //read STDIN to buffer - std::cin.read(reinterpret_cast(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& 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 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 + #include + #include + + int main() + { + const std::vector key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337"); + const std::vector iv = Botan::hex_decode("FFFFFFFFFFFFFFFFFFFFFFFF"); + const std::vector data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); + std::unique_ptr mac(Botan::MessageAuthenticationCode::create("GMAC(AES-256)")); + if(!mac) + return 1; + mac->set_key(key); + mac->start(iv); + mac->update(data); + Botan::secure_vector 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 + #include + #include + + int main() + { + const std::vector key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); + std::vector data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); + std::unique_ptr mac(Botan::MessageAuthenticationCode::create("CMAC(AES-128)")); + if(!mac) + return 1; + mac->set_key(key); + mac->update(data); + Botan::secure_vector 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 inout) + .. cpp:function:: void encrypt(std::vector inout) + .. cpp:function:: void decrypt(std::vector 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 + #include + #include + #include + + int main() + { + std::string plaintext("This is a tasty burger!"); + std::vector pt(plaintext.data(),plaintext.data()+plaintext.length()); + const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + std::unique_ptr cipher(Botan::StreamCipher::create("ChaCha(20)")); + + //generate fresh nonce (IV) + std::unique_ptr rng(new Botan::AutoSeeded_RNG); + std::vector 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 in, std::vector 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 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 in, std::vector 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 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 - #include - #include - int main () - { - std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); - std::vector block = Botan::hex_decode("00112233445566778899AABBCCDDEEFF"); - std::unique_ptr cipher(Botan::BlockCipher::create("AES-256")); - cipher->set_key(key); - cipher->encrypt(block); - std::cout << std::endl <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 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& 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& 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 - #include - #include - #include - #include - - 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 pt(plaintext.data(),plaintext.data()+plaintext.length()); - const std::vector key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); - std::unique_ptr enc(Botan::get_cipher_mode("AES-128/CBC/PKCS7", Botan::ENCRYPTION)); - enc->set_key(key); - - //generate fresh nonce (IV) - std::unique_ptr rng(new Botan::AutoSeeded_RNG); - std::vector 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& 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& 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 inout) - .. cpp:function:: void encrypt(std::vector inout) - .. cpp:function:: void decrypt(std::vector 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 - #include - #include - #include - #include - - - int main() - { - std::string plaintext("This is a tasty burger!"); - std::vector pt(plaintext.data(),plaintext.data()+plaintext.length()); - const std::vector key = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); - std::unique_ptr cipher(Botan::StreamCipher::create("ChaCha")); - - //generate fresh nonce (IV) - std::unique_ptr rng(new Botan::AutoSeeded_RNG); - std::vector 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& 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 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 - #include - #include - - int main() - { - const std::vector key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337"); - const std::vector iv = Botan::hex_decode("FFFFFFFFFFFFFFFFFFFFFFFF"); - const std::vector data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); - std::unique_ptr mac(Botan::MessageAuthenticationCode::create("GMAC(AES-256)")); - if(!mac) - return 1; - mac->set_key(key); - mac->start(iv); - mac->update(data); - Botan::secure_vector 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 - #include - #include - - int main() - { - const std::vector key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); - std::vector data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); - std::unique_ptr mac(Botan::MessageAuthenticationCode::create("CMAC(AES-128)")); - if(!mac) - return 1; - mac->set_key(key); - mac->update(data); - Botan::secure_vector 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 ------------ -- cgit v1.2.3