.. _library_block_ciphers:

``block_ciphers``
=================

The ``block_ciphers`` library provides portable block cipher
implementations. It defines a ``block_cipher_protocol`` protocol with
the predicates:

- ``encrypt_block/3``
- ``decrypt_block/3``
- ``block_size/1``
- ``key_size/1``

The library also defines ``block_cipher_prepared_key_protocol``, which
extends the basic protocol with predicates for preparing a key once and
reusing its opaque representation for repeated block operations. Keys,
plaintext, ciphertext, initialization vectors, and counters are
represented by lists of bytes.

API documentation
-----------------

Open the
`../../apis/library_index.html#block-ciphers <../../apis/library_index.html#block-ciphers>`__
link in a web browser.

Loading
-------

To load all entities in this library, load the ``loader.lgt`` file:

::

   | ?- logtalk_load(block_ciphers(loader)).

Testing
-------

To test this library predicates, load the ``tester.lgt`` file:

::

   | ?- logtalk_load(block_ciphers(tester)).

Supported block ciphers
-----------------------

The library implements AES as specified in FIPS 197 using three objects:

- ``aes128``, accepting a 16-byte key
- ``aes192``, accepting a 24-byte key
- ``aes256``, accepting a 32-byte key

All three objects use 16-byte blocks. They extend ground instances of
the shared parametric object ``aes_common(KeySize, Nk, Nr)``, which
contains the key expansion and encryption and decryption round
implementations.

Block cipher modes
------------------

The library provides generic ``ecb``, ``cbc``, and ``ctr`` mode objects.
Their first argument is any cipher object implementing
``block_cipher_prepared_key_protocol``. The key is prepared once per
mode operation.

The ``ecb`` object provides:

- ``encrypt/4`` and ``decrypt/4`` for block-aligned input without
  padding
- ``encrypt_padded/4`` and ``decrypt_padded/4`` using PKCS#7 padding

The ``cbc`` object provides:

- ``encrypt/5`` and ``decrypt/5`` for block-aligned input without
  padding
- ``encrypt_padded/5`` and ``decrypt_padded/5`` using PKCS#7 padding

The third argument of the CBC predicates is an explicit initialization
vector whose length is exactly one cipher block. The IV is neither
generated by the library nor prefixed to the ciphertext.

The ``ctr`` object provides ``crypt/5`` and ``crypt/6`` for both
encryption and decryption. Their third argument is an explicit initial
counter whose length is exactly one cipher block. The counter is
interpreted as a whole-block unsigned big-endian integer and incremented
modulo the block width while processing the input. The ``crypt/6``
predicate additionally returns the next unused counter, which equals the
initial counter for empty input and is otherwise incremented once per
processed input block. The object is stateless; clients must manage
counters across calls and ensure that counter sequences do not overlap
when using the same key. CTR accepts arbitrary input lengths, including
a final partial block.

Raw ECB and CBC operations accept empty input but otherwise require a
byte length divisible by the cipher block size. PKCS#7 encryption
accepts any input length and always appends padding. Thus, empty or
already block-aligned input receives a complete padding block. Padded
decryption requires non-empty, block-aligned ciphertext and rejects
malformed padding.

Security considerations
-----------------------

The block primitive and all three modes are unauthenticated. Prefer an
authenticated-encryption construction for general-purpose encryption.

ECB reveals equality and patterns between plaintext blocks and is
unsuitable for encrypting confidential structured data.

CBC requires an unpredictable fresh IV for each encryption under a key.
It provides confidentiality but not integrity or authenticity and must
be paired with a secure authentication construction. Applications must
also avoid exposing distinguishable padding failures to attackers, which
can create a padding oracle.

CTR requires that a key and counter sequence is never reused. Reuse
reveals relationships between plaintexts. CTR ciphertext is malleable
and must be authenticated separately.

The portable table-based implementation is not guaranteed to execute in
constant time and makes no side-channel resistance claims.

CMAC compatibility
------------------

The protocols are designed to support a future generic CMAC library.
CMAC uses the block-encryption primitive and does not depend on CBC
mode, despite using a related chaining operation. It can query
``block_size/1`` and ``key_size/1`` and use either ``encrypt_block/3``
or the prepared-key predicates without depending on AES-specific
constants or implementation details.

Example
-------

Encrypt the standard FIPS 197 AES-128 example block:

::

   | ?- aes128::encrypt_block(
            [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f],
            [0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff],
            Ciphertext
        ).
   Ciphertext = [105,196,224,216,106,123,4,48,216,205,183,128,112,180,197,90]
   yes

Encrypt and decrypt an arbitrary-length message using CBC with PKCS#7
padding and an explicit IV:

::

   | ?- Key = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        IV = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
        cbc::encrypt_padded(aes128, Key, IV, [1,2,3,4,5], Ciphertext),
        cbc::decrypt_padded(aes128, Key, IV, Ciphertext, Plaintext).
   Plaintext = [1,2,3,4,5]
   yes
