Unauthenticated encryption

These APIs provide support for unauthenticated encryption and decryption, including bare stream ciphers and other length-preserving algorithms such as block ciphers in XTS mode. The legitimate use cases for these algorithms are:

  • Support for legacy protocols that really should have chosen an authenticated mode (or even another primitive entirely) but didn’t.

  • Internal components of authenticated modes. For example, AES-CTR is used by AES-GCM and AES-CCM internally.

  • Storage encryption that cannot accommodate ciphertext expansion. Usually AES-XTS is used for this.

  • Stream ciphers for key derivation and random number generation.

Besides the above, these shouldn’t be used.

AES-CBC and AES-CBC-CTS

This API provides support for AES in the CBC and CBC-CTS modes of operation.

void aes_cbc_encrypt(u8 *dst, const u8 *src, size_t len, u8 iv[static AES_BLOCK_SIZE], aes_encrypt_arg key)

Encrypt data using AES-CBC

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to encrypt. Must be a multiple of AES_BLOCK_SIZE.

u8 iv[static AES_BLOCK_SIZE]

The initialization vector. It is updated with the next value, i.e. the last ciphertext block (or left unchanged if len == 0).

aes_encrypt_arg key

The key, already prepared using aes_preparekey() or aes_prepareenckey()

Description

This supports incremental encryption. The length of each chunk must be a multiple of AES_BLOCK_SIZE, and the updated iv must be passed in each time.

Context

Any context.

void aes_cbc_decrypt(u8 *dst, const u8 *src, size_t len, u8 iv[static AES_BLOCK_SIZE], const struct aes_key *key)

Decrypt data using AES-CBC

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to decrypt. Must be a multiple of AES_BLOCK_SIZE.

u8 iv[static AES_BLOCK_SIZE]

The initialization vector. It is updated with the next value, i.e. the last ciphertext block (or left unchanged if len == 0).

const struct aes_key *key

The key, already prepared using aes_preparekey()

Description

This supports incremental decryption. The length of each chunk must be a multiple of AES_BLOCK_SIZE, and the updated iv must be passed in each time.

Context

Any context.

void aes_cbc_cts_encrypt(u8 *dst, const u8 *src, size_t len, u8 iv[static AES_BLOCK_SIZE], aes_encrypt_arg key)

Encrypt data using AES-CBC-CTS (CS3 variant)

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to encrypt, at least AES_BLOCK_SIZE

u8 iv[static AES_BLOCK_SIZE]

The initialization vector, clobbered by this function

aes_encrypt_arg key

The key, already prepared using aes_preparekey() or aes_prepareenckey()

Context

Any context.

void aes_cbc_cts_decrypt(u8 *dst, const u8 *src, size_t len, u8 iv[static AES_BLOCK_SIZE], const struct aes_key *key)

Decrypt data using AES-CBC-CTS (CS3 variant)

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to decrypt, at least AES_BLOCK_SIZE

u8 iv[static AES_BLOCK_SIZE]

The initialization vector, clobbered by this function

const struct aes_key *key

The key, already prepared using aes_preparekey()

Context

Any context.

AES-CTR and AES-XCTR

This API provides support for AES in the CTR and XCTR modes of operation.

void aes_ctr(u8 *dst, const u8 *src, size_t len, u8 ctr[static AES_BLOCK_SIZE], aes_encrypt_arg key)

AES-CTR en/decryption

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to en/decrypt

u8 ctr[static AES_BLOCK_SIZE]

The counter. It will be incremented by ceil(len / AES_BLOCK_SIZE).

aes_encrypt_arg key

The key, already prepared using aes_preparekey() or aes_prepareenckey()

Description

This implements AES in counter mode with a 128-bit big endian counter.

This exists only for use by the implementation of modes built on top of CTR (e.g., GCM and CCM) and some legacy protocols that use CTR mode directly. Callers are expected to know how to use CTR mode appropriately, including choosing (key, counter) pairs appropriately to avoid keystream reuse.

This supports incremental en/decryption. The length of each non-final chunk must be a multiple of AES_BLOCK_SIZE, and the updated ctr must be passed in each time.

Context

Any context.

void aes_xctr(u8 *dst, const u8 *src, size_t len, u64 *ctr, const u8 iv[static AES_BLOCK_SIZE], aes_encrypt_arg key)

AES-XCTR en/decryption

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to en/decrypt

u64 *ctr

The block counter (in host endianness). For the first call, set it to 1. It will be incremented by ceil(len / AES_BLOCK_SIZE).

const u8 iv[static AES_BLOCK_SIZE]

The initialization vector

aes_encrypt_arg key

The key, already prepared using aes_preparekey() or aes_prepareenckey()

Description

This implements AES in XOR Counter mode, as specified in the paper “Length-preserving encryption with HCTR2” (https://eprint.iacr.org/2021/1441.pdf).

This exists only for use by the implementation of modes built on top of XCTR. Callers are expected to know how to use XCTR mode appropriately, including choosing (key, IV) pairs appropriately to avoid keystream reuse.

This supports incremental en/decryption. The length of each non-final chunk must be a multiple of AES_BLOCK_SIZE, and the updated ctr must be passed in each time.

Context

Any context.

AES-ECB

This API provides support for AES in the ECB mode of operation.

void aes_ecb_encrypt(u8 *dst, const u8 *src, size_t len, aes_encrypt_arg key)

Encrypt data using AES-ECB

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to encrypt. Must be a multiple of AES_BLOCK_SIZE.

aes_encrypt_arg key

The key, already prepared using aes_preparekey() or aes_prepareenckey()

Description

ECB mode is insecure by itself. This function exists only for compatibility with legacy protocols and for internal use by other modes.

This supports incremental encryption, but the length of each chunk must be a multiple of AES_BLOCK_SIZE.

Context

Any context.

void aes_ecb_decrypt(u8 *dst, const u8 *src, size_t len, const struct aes_key *key)

Decrypt data using AES-ECB

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to decrypt. Must be a multiple of AES_BLOCK_SIZE.

const struct aes_key *key

The key, already prepared using aes_preparekey()

Description

ECB mode is insecure by itself. This function exists only for compatibility with legacy protocols and for internal use by other modes.

This supports incremental decryption, but the length of each chunk must be a multiple of AES_BLOCK_SIZE.

Context

Any context.

AES-XTS

This API provides support for AES in the XTS mode of operation.

struct aes_xts_key

A key prepared for AES-XTS encryption and decryption

Definition:

struct aes_xts_key {
};

Members

Description

Note that (depending on the architecture) this typically is around 768 bytes, which makes it a bit too large to allocate on the stack in most cases.

int aes_xts_preparekey(struct aes_xts_key *key, const u8 *in_key, size_t key_len, int flags)

Prepare a key for AES-XTS encryption and decryption

Parameters

struct aes_xts_key *key

(output) The key structure to initialize

const u8 *in_key

The raw AES-XTS key

size_t key_len

Length of the raw key in bytes

int flags

Optional flag XTS_FORBID_WEAK_KEYS to forbid keys whose two halves are the same.

Description

Users should use memzero_explicit() to zeroize the key struct at the end of its lifetime. (But if this function fails, zeroization is unnecessary.)

Context

Any context.

Return

  • 0 on success

  • -EINVAL if the key is rejected because its length isn’t 32, 64, or (when FIPS mode isn’t enabled) 48; or because its two halves are the same and either XTS_FORBID_WEAK_KEYS is given or FIPS mode is enabled.

void aes_xts_encrypt(u8 *dst, const u8 *src, size_t len, u8 tweak[static AES_BLOCK_SIZE], const struct aes_xts_key *key, bool cont)

Encrypt data using AES-XTS

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to encrypt. On non-final calls it must be a nonzero multiple of AES_BLOCK_SIZE. On the final call it can be any value >= AES_BLOCK_SIZE, i.e. ciphertext stealing is supported.

u8 tweak[static AES_BLOCK_SIZE]

The tweak. It is updated with the next value, unless len isn’t a multiple of AES_BLOCK_SIZE in which case the value is unspecified.

const struct aes_xts_key *key

The key, already prepared using aes_xts_preparekey()

bool cont

false to begin encrypting a new message (do the tweak encryption); true to continue encrypting a message (skip tweak encryption)

Description

This supports both one-shot and incremental encryption. On the first call, pass cont = false. On any later calls, pass cont = true and the updated tweak; all earlier len must have been multiples of AES_BLOCK_SIZE.

Context

Any context.

void aes_xts_decrypt(u8 *dst, const u8 *src, size_t len, u8 tweak[static AES_BLOCK_SIZE], const struct aes_xts_key *key, bool cont)

Decrypt data using AES-XTS

Parameters

u8 *dst

The destination buffer. Can be in-place or out-of-place. For other overlaps the behavior is unspecified.

const u8 *src

The source data

size_t len

Number of bytes to decrypt. On non-final calls it must be a nonzero multiple of AES_BLOCK_SIZE. On the final call it can be any value >= AES_BLOCK_SIZE, i.e. ciphertext stealing is supported.

u8 tweak[static AES_BLOCK_SIZE]

The tweak. It is updated with the next value, unless len isn’t a multiple of AES_BLOCK_SIZE in which case the value is unspecified.

const struct aes_xts_key *key

The key, already prepared using aes_xts_preparekey()

bool cont

false to begin decrypting a new message (do the tweak encryption); true to continue decrypting a message (skip tweak encryption)

Description

This supports both one-shot and incremental decryption. On the first call, pass cont = false. On any later calls, pass cont = true and the updated tweak; all earlier len must have been multiples of AES_BLOCK_SIZE.

Context

Any context.