CRYPTO_LOCK_INIT(3MONOCYPHER) | 3MONOCYPHER | CRYPTO_LOCK_INIT(3MONOCYPHER)

# NAME

crypto_lock_init, crypto_lock_aead_auth, crypto_lock_update, crypto_lock_final, crypto_unlock_init, crypto_unlock_aead_auth, crypto_unlock_update, crypto_unlock_final, crypto_lock_auth, crypto_lock_encrypt — incremental authenticated encryption with additional data

# SYNOPSIS

#include <monocypher.h>
void
crypto_lock_init(crypto_lock_ctx *ctx, const uint8_t key[32], const uint8_t nonce[24]);
void
crypto_lock_aead_auth(crypto_lock_ctx *ctx, const uint8_t *ad, size_t ad_size);
void
crypto_lock_update(crypto_lock_ctx *ctx, uint8_t *cipher_text, const uint8_t *plain_text, size_t text_size);
void
crypto_lock_final(crypto_lock_ctx *ctx, uint8_t mac[16]);
void
crypto_unlock_init(crypto_unlock_ctx *ctx, const uint8_t key[32], const uint8_t nonce[24]);
void
crypto_unlock_aead_auth(crypto_unlock_ctx *ctx, const uint8_t *ad, size_t ad_size);
void
crypto_unlock_update(crypto_unlock_ctx *ctx, uint8_t *plain_text, const uint8_t *cipher_text, size_t text_size);
int
crypto_unlock_final(crypto_unlock_ctx *ctx, const uint8_t mac[16]);
void
crypto_lock_auth(crypto_lock_ctx *ctx, const uint8_t *ad, size_t ad_size);
void
crypto_lock_encrypt(crypto_lock_ctx *ctx, uint8_t *cipher_text, const uint8_t *plain_text, size_t text_size);

# DESCRIPTION

These functions are variants of crypto_lock(3monocypher), crypto_unlock(3monocypher), crypto_aead_lock(3monocypher) and crypto_aead_unlock(3monocypher). Prefer those simpler functions if possible.
This incremental interface can be used to encrypt and decrypt messages too large to fit in a single buffer. The arguments are the same as described for the direct interface described in crypto_lock(3monocypher).
Encryption requires four steps:

- Initialise a context with crypto_lock_init().
- Authenticate additional data, if any, with crypto_lock_aead_auth().
- Encrypt and authenticate some data with crypto_lock_update().
- Generate the MAC with crypto_lock_final().

Decryption also requires four steps:

- Initialise a context with crypto_unlock_init().
- Verify additional data, if any, with crypto_unlock_aead_auth().
- Decrypt and verify some data with crypto_unlock_update().
- Verify the MAC with crypto_unlock_final().

crypto_lock_encrypt() encrypts or decrypts data without authenticating it. It is meant as a building block. Used with crypto_lock_auth(), it enables various AEAD constructions. Most users do not need either of them. Prefer crypto_lock_update() and crypto_unlock_update() instead.

# RETURN VALUES

crypto_lock_init(), crypto_unlock_init(), crypto_lock_auth(), crypto_lock_encrypt(), crypto_lock_aead_auth(), crypto_unlock_aead_auth(), crypto_lock_update(), crypto_unlock_update(), and crypto_lock_final() return nothing. They cannot fail.
crypto_unlock_final() returns 0 on success or -1 if the message was corrupted. Corruption can be caused by transmission errors, programmer error, or an attacker's interference. Always check the return value.

# EXAMPLES

Encryption:

    const uint8_t key        [ 32]; /* Session key                 */
    const uint8_t nonce      [ 32]; /* Unique per session key      */
    const uint8_t ad         [500]; /* Optional additional data    */
    const uint8_t plain_text [500]; /* Secret message              */
    uint8_t       cipher_text[500]; /* Encrypted message           */
    uint8_t       mac        [ 16]; /* Message authentication code */

    /* Set up initial context */
    crypto_lock_ctx ctx;
    crypto_lock_init(&ctx, key, nonce);
    /* Wipe the key if it is no longer needed */
    crypto_wipe(key, 32);

    /* Authenticate additional data */
    for (size_t i = 0; i < 500; i += 100) {
        crypto_lock_aead_auth(&ctx, ad + i, 100);
    }

    /* Encrypt message */
    for (size_t i = 0; i < 500; i += 100) {
        crypto_lock_update(&ctx, cipher_text + i, plain_text + i, 100);
        /* Wipe the secret message if it is no longer needed */
        crypto_wipe(plain_text + i, 100);
    }

    /* Produce the MAC */
    crypto_lock_final(&ctx, mac);

To decrypt the above:

    const uint8_t key        [ 32]; /* Session key              */
    const uint8_t nonce      [ 32]; /* Unique per session key   */
    const uint8_t mac        [ 16]; /* Transmitted MAC          */
    const uint8_t ad         [500]; /* Optional additional data */
    const uint8_t cipher_text[500]; /* Encrypted message        */
    uint8_t       plain_text [500]; /* Secret message           */

    /* Set up initial context */
    crypto_unlock_ctx ctx;
    crypto_unlock_init(&ctx, key, nonce);
    /* Wipe the key if it is no longer needed */
    crypto_wipe(key, 32);

    /* Verify additional data */
    for (size_t i = 0; i < 500; i += 100) {
        crypto_unlock_aead_auth(&ctx, ad + i, 100);
    }

    /* Decrypt message */
    for (size_t i = 0; i < 500; i += 100) {
        crypto_unlock_update(&ctx, plain_text + i, cipher_text + i, 100);
    }

    /* Check the MAC */
    if (crypto_unlock_final(&ctx, mac)) {
        /* Corrupted message, abort processing */
    } else {
        /* Genuine message */
    }

    /* Wipe the secret message if it is no longer needed */
    crypto_wipe(plain_text, 500);

In-place encryption without additional data:

    const uint8_t key   [ 32]; /* Session key                 */
    const uint8_t nonce [ 32]; /* Unique per session key      */
    uint8_t       text  [500]; /* Message                     */
    uint8_t       mac   [ 16]; /* Message authentication code */

    /* Set up initial context */
    crypto_lock_ctx ctx;
    crypto_lock_init(&ctx, key, nonce);
    /* Wipe the key if it is no longer needed */
    crypto_wipe(key, 32);

    /* Encrypt message */
    for (size_t i = 0; i < 500; i += 100) {
        crypto_lock_update(&ctx, text + i, text + i, 100);
    }

    /* Produce the MAC */
    crypto_lock_final(&ctx, mac);

# SEE ALSO

crypto_aead_lock(3monocypher), crypto_aead_unlock(3monocypher), crypto_key_exchange(3monocypher), crypto_lock(3monocypher), crypto_unlock(3monocypher), crypto_wipe(3monocypher), intro(3monocypher)

# STANDARDS

These functions implement the XChacha20 (encryption) and Poly1305 (MAC) primitives. Chacha20 and Poly1305 are described in RFC 7539. XChacha20 derives from Chacha20 the same way XSalsa20 derives from Salsa20, and benefits from the same security reduction (proven secure as long as Chacha20 itself is secure).

# SECURITY CONSIDERATIONS

Messages are not verified until the call to crypto_unlock_final(). Make sure to call it and check the return value before processing the message. Messages may be stored before they are verified, but they cannot be trusted. Processing untrusted messages increases the attack surface of the system. Doing so securely is hard. Do not process messages before calling crypto_unlock_final().

# IMPLEMENTATION DETAILS

- crypto_unlock_ctx is an alias to crypto_lock_ctx.
- crypto_unlock_init() is an alias to crypto_lock_init().
- crypto_lock_aead_auth() and crypto_unlock_aead_auth() are aliases to crypto_lock_auth().

The incremental interface is roughly three times slower than the direct interface at identifying corrupted messages. This is because the incremental interface works in a single pass and has to interleave decryption and verification. Users who expect a high corruption rate may want to avoid it.

December 28, 2017 | Linux 4.4.0-116-generic