diff options
Diffstat (limited to 'comm/third_party/botan/doc/api_ref/cipher_modes.rst')
-rw-r--r-- | comm/third_party/botan/doc/api_ref/cipher_modes.rst | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/comm/third_party/botan/doc/api_ref/cipher_modes.rst b/comm/third_party/botan/doc/api_ref/cipher_modes.rst new file mode 100644 index 0000000000..413db70b57 --- /dev/null +++ b/comm/third_party/botan/doc/api_ref/cipher_modes.rst @@ -0,0 +1,384 @@ +.. _cipher_modes: + +Cipher Modes +===================== + +A block cipher by itself, is only able to securely encrypt a single data block. +To be able to securely encrypt data of arbitrary length, a mode of operation +applies the block cipher's single block operation repeatedly to encrypt +an entire message. + +All cipher mode implementations are are derived from the base class +:cpp:class:`Cipher_Mode`, which is declared in ``botan/cipher_mode.h``. + +.. warning:: + Using an unauthenticted cipher mode without combining it with a + :ref:`mac` is insecure. Prefer using an :ref:`aead`. + +.. cpp:class:: Cipher_Mode + + .. cpp:function:: void set_key(const uint8_t* key, size_t length) + + Set the symmetric key to be used. + + .. cpp:function:: bool valid_keylength(size_t length) const + + This function returns true if and only if *length* is a valid + keylength for the algorithm. + + .. cpp:function:: size_t minimum_keylength() const + + Return the smallest key length (in bytes) that is acceptable for the + algorithm. + + .. cpp:function:: size_t maximum_keylength() const + + Return the largest key length (in bytes) that is acceptable for the + algorithm. + + .. cpp:function:: size_t default_nonce_length() const + + Return the default (preferable) nonce size for this cipher mode. + + .. cpp:function:: bool valid_nonce_length(size_t nonce_len) const + + Return true if *nonce_len* is a valid length for a nonce with this + algorithm. + + .. cpp:function:: bool authenticated() const + + Return true if this cipher mode is authenticated + + .. cpp:function:: size_t tag_size() const + + Return the length in bytes of the authentication tag this algorithm + generates. If the mode is not authenticated, this will return 0. If the mode + is authenticated, it will return some positive value (typically somewhere + between 8 and 16). + + .. cpp:function:: void clear() + + Clear all internal state. The object will act exactly like one which was + just allocated. + + .. cpp:function:: void reset() + + Reset all message state. For example if you called :cpp:func:`start_msg`, + then :cpp:func:`process` to process some ciphertext, but then encounter an + IO error and must abandon the current message, you can call `reset`. The + object will retain the key (unlike calling :cpp:func:`clear` which also + resets the key) but the nonce and current message state will be erased. + + .. cpp:function:: void start_msg(const uint8_t* nonce, size_t nonce_len) + + Set up for processing a new message. This function must be called with a new + random value for each message. For almost all modes (excepting SIV), if the + same nonce is ever used twice with the same key, the encryption scheme loses + its confidentiality and/or authenticity properties. + + .. cpp:function:: void start(const std::vector<uint8_t> nonce) + + Acts like :cpp:func:`start_msg`\ (nonce.data(), nonce.size()). + + .. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len) + + Acts like :cpp:func:`start_msg`\ (nonce, nonce_len). + + .. cpp:function:: virtual size_t update_granularity() const + + The :cpp:class:`Cipher_Mode` interface requires message processing in multiples of the block size. + Returns size of required blocks to update and 1, if the mode can process messages of any length. + + .. cpp:function:: virtual size_t process(uint8_t* msg, size_t msg_len) + + Process msg in place and returns the number of bytes written. *msg* must + be a multiple of :cpp:func:`update_granularity`. + + .. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0) + + Continue processing a message in the buffer in place. The passed buffer's + size must be a multiple of :cpp:func:`update_granularity`. The first + *offset* bytes of the buffer will be ignored. + + .. cpp:function:: size_t minimum_final_size() const + + Returns the minimum size needed for :cpp:func:`finish`. + + .. cpp:function:: void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) + + Finalize the message processing with a final block of at least :cpp:func:`minimum_final_size` size. + The first *offset* bytes of the passed final block will be ignored. + +Code Example +--------------------- + +The following code encrypts the specified plaintext using AES-128/CBC +with PKCS#7 padding. + +.. warning:: + This example ignores the requirement to authenticate the ciphertext + +.. note:: + Simply replacing the string "AES-128/CBC/PKCS7" string in the example below + with "AES-128/GCM" suffices to use authenticated encryption. + +.. code-block:: cpp + + #include <botan/rng.h> + #include <botan/auto_rng.h> + #include <botan/cipher_mode.h> + #include <botan/hex.h> + #include <iostream> + + int main() + { + Botan::AutoSeeded_RNG rng; + + const std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's."); + const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); + + std::unique_ptr<Botan::Cipher_Mode> enc = Botan::Cipher_Mode::create("AES-128/CBC/PKCS7", Botan::ENCRYPTION); + enc->set_key(key); + + //generate fresh nonce (IV) + Botan::secure_vector<uint8_t> iv = rng.random_vec(enc->default_nonce_length()); + + // Copy input data to a buffer that will be encrypted + Botan::secure_vector<uint8_t> pt(plaintext.data(), plaintext.data()+plaintext.length()); + + enc->start(iv); + enc->finish(pt); + + std::cout << enc->name() << " with iv " << Botan::hex_encode(iv) << " " << Botan::hex_encode(pt) << "\n"; + return 0; + } + + +Available Unauthenticated Cipher Modes +----------------------------------------- + +.. note:: + CTR and OFB modes are also implemented, but these are treated as + :cpp:class:`Stream_Cipher`\s instead. + +CBC +~~~~~~~~~~~~ + +Available if ``BOTAN_HAS_MODE_CBC`` is defined. + +CBC requires the plaintext be padded using a reversible rule. The following +padding schemes are implemented + +PKCS#7 (RFC5652) + The last byte in the padded block defines the padding length p, the remaining padding bytes are set to p as well. +ANSI X9.23 + The last byte in the padded block defines the padding length, the remaining padding is filled with 0x00. +OneAndZeros (ISO/IEC 7816-4) + The first padding byte is set to 0x80, the remaining padding bytes are set to 0x00. + +Ciphertext stealing (CTS) is also implemented. This scheme allows the +ciphertext to have the same length as the plaintext, however using CTS +requires the input be at least one full block plus one byte. It is +also less commonly implemented. + +CFB +~~~~~~~~~~~~ + +Available if ``BOTAN_HAS_MODE_CFB`` is defined. + +CFB uses a block cipher to create a self-synchronizing stream cipher. It is used +for example in the OpenPGP protocol. There is no reason to prefer it, as it has +worse performance characteristics than modes such as CTR or CBC. + +XTS +~~~~~~~~~ + +Available if ``BOTAN_HAS_MODE_XTS`` is defined. + +XTS is a mode specialized for encrypting disk or database storage +where ciphertext expansion is not possible. XTS requires all inputs be +at least one full block (16 bytes for AES), however for any acceptable +input length, there is no ciphertext expansion. + +.. _aead: + +AEAD Mode +--------------------------- + +AEAD (Authenticated Encryption with Associated Data) modes provide message +encryption, message authentication, and the ability to authenticate additional +data that is not included in the ciphertext (such as a sequence number or +header). It is a subclass of :cpp:class:`Cipher_Mode`. + +.. cpp:class:: AEAD_Mode + + .. cpp:function:: void set_key(const SymmetricKey& key) + + Set the key + + .. cpp:function:: Key_Length_Specification key_spec() const + + Return the key length specification + + .. cpp:function:: void set_associated_data(const uint8_t ad[], size_t ad_len) + + Set any associated data for this message. For maximum portability between + different modes, this must be called after :cpp:func:`set_key` and before + :cpp:func:`start`. + + If the associated data does not change, it is not necessary to call this + function more than once, even across multiple calls to :cpp:func:`start` + and :cpp:func:`finish`. + + .. cpp:function:: void start(const uint8_t nonce[], size_t nonce_len) + + Start processing a message, using *nonce* as the unique per-message + value. It does not need to be random, simply unique (per key). + + .. warning:: + With almost all AEADs, if the same nonce is ever used to encrypt two + different messages under the same key, all security is lost. If + reliably generating unique nonces is difficult in your environment, + use SIV mode which retains security even if nonces are repeated. + + .. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0) + + Continue processing a message. The *buffer* is an in/out parameter and + may be resized. In particular, some modes require that all input be + consumed before any output is produced; with these modes, *buffer* will + be returned empty. + + On input, the buffer must be sized in blocks of size + :cpp:func:`update_granularity`. For instance if the update granularity + was 64, then *buffer* could be 64, 128, 192, ... bytes. + + The first *offset* bytes of *buffer* will be ignored (this allows in + place processing of a buffer that contains an initial plaintext header) + + .. cpp:function:: void finish(secure_vector<uint8_t>& buffer, size_t offset = 0) + + Complete processing a message with a final input of *buffer*, which is + treated the same as with :cpp:func:`update`. It must contain at least + :cpp:func:`final_minimum_size` bytes. + + Note that if you have the entire message in hand, calling finish without + ever calling update is both efficient and convenient. + + .. note:: + + During decryption, if the supplied authentication tag does not + validate, finish will throw an instance of Invalid_Authentication_Tag + (aka Integrity_Failure, which was the name for this exception in + versions before 2.10, a typedef is included for compatability). + + If this occurs, all plaintext previously output via calls to update + must be destroyed and not used in any way that an attacker could + observe the effects of. This could be anything from echoing the + plaintext back (perhaps in an error message), or by making an external + RPC whose destination or contents depend on the plaintext. The only + thing you can do is buffer it, and in the event of an invalid tag, + erase the previously decrypted content from memory. + + One simply way to assure this could never happen is to never + call update, and instead always marshal the entire message + into a single buffer and call finish on it when decrypting. + + .. cpp:function:: size_t update_granularity() const + + The AEAD interface requires :cpp:func:`update` be called with blocks of + this size. This will be 1, if the mode can process any length inputs. + + .. cpp:function:: size_t final_minimum_size() const + + The AEAD interface requires :cpp:func:`finish` be called with at least + this many bytes (which may be zero, or greater than + :cpp:func:`update_granularity`) + + .. cpp:function:: bool valid_nonce_length(size_t nonce_len) const + + Returns true if *nonce_len* is a valid nonce length for this scheme. For + EAX and GCM, any length nonces are allowed. OCB allows any value between + 8 and 15 bytes. + + .. cpp:function:: size_t default_nonce_length() const + + Returns a reasonable length for the nonce, typically either 96 + bits, or the only supported length for modes which don't + support 96 bit nonces. + + +Available AEAD Modes +------------------------- + +If in doubt about what to use, pick ChaCha20Poly1305, AES-256/GCM, or AES-256/SIV. +Both ChaCha20Poly1305 and AES with GCM are widely implemented. SIV is somewhat +more obscure (and is slower than either GCM or ChaCha20Poly1305), but has +excellent security properties. + +ChaCha20Poly1305 +~~~~~~~~~~~~~~~~~~ + +Available if ``BOTAN_HAS_AEAD_CHACHA20_POLY1305`` is defined. + +Unlike the other AEADs which are based on block ciphers, this mode is based on +the ChaCha stream cipher and the Poly1305 authentication code. It is very fast +on all modern platforms. + +ChaCha20Poly1305 supports 64-bit, 96-bit, and (since 2.8) 192-bit nonces. 64-bit nonces +are the "classic" ChaCha20Poly1305 design. 96-bit nonces are used by the IETF standard +version of ChaCha20Poly1305. And 192-bit nonces is the XChaCha20Poly1305 construction, +which is somewhat less common. + +For best interop use the IETF version with 96-bit nonces. However 96 bits is small enough +that it can be dangerous to generate nonces randomly if more than ~ 2^32 messages are +encrypted under a single key, since if a nonce is ever reused ChaCha20Poly1305 becomes +insecure. It is better to use a counter for the nonce in this case. + +If you are encrypting many messages under a single key and cannot maintain a counter for +the nonce, prefer XChaCha20Poly1305 since a 192 bit nonce is large enough that randomly +chosen nonces are extremely unlikely to repeat. + +GCM +~~~~~ + +Available if ``BOTAN_HAS_AEAD_GCM`` is defined. + +NIST standard, commonly used. Requires a 128-bit block cipher. Fairly slow, +unless hardware support for carryless multiplies is available. + +OCB +~~~~~ + +Available if ``BOTAN_HAS_AEAD_OCB`` is defined. + +A block cipher based AEAD. Supports 128-bit, 256-bit and 512-bit block ciphers. +This mode is very fast and easily secured against side channels. Adoption has +been poor because it is patented in the United States, though a license is +available allowing it to be freely used by open source software. + +EAX +~~~~~ + +Available if ``BOTAN_HAS_AEAD_EAX`` is defined. + +A secure composition of CTR mode and CMAC. Supports 128-bit, 256-bit and 512-bit +block ciphers. + +SIV +~~~~~~ + +Available if ``BOTAN_HAS_AEAD_SIV`` is defined. + +Requires a 128-bit block cipher. Unlike other AEADs, SIV is "misuse resistant"; +if a nonce is repeated, SIV retains security, with the exception that if the +same nonce is used to encrypt the same message multiple times, an attacker can +detect the fact that the message was duplicated (this is simply because if both +the nonce and the message are reused, SIV will output identical ciphertexts). + +CCM +~~~~~ + +Available if ``BOTAN_HAS_AEAD_CCM`` is defined. + +A composition of CTR mode and CBC-MAC. Requires a 128-bit block cipher. This is +a NIST standard mode, but that is about all to recommend it. Prefer EAX. |