Advanced Encryption Standard

#cryptxdevquotes: AE-effing-S. On a goddamn calculator. - Adam Beckingham

Module Functionality
Provides a fast, secure algorithm for two parties to exchange information privately using a single key for encryption and decryption. Advanced Encryption Standard is currently the gold standard for encryption and is one of the most widely-used encryption algorithms.

Cipher Modes

enum cryptx_aes_cipher_modes

Values:

enumerator CRYPTX_AES_CBC

selects Cyclic Block Chain (CBC) mode

enumerator CRYPTX_AES_CTR

selects Counter (CTR) mode

enumerator CRYPTX_AES_GCM

selects Galois Counter (GCM) mode

Cipher Flags

enum cryptx_aes_padding_schemes

Values:

enumerator PAD_PKCS7

PKCS#7 padding | DEFAULT.

enumerator PAD_DEFAULT = PAD_PKCS7

selects the scheme marked DEFAULT.

Using this is recommended in case a change to the standards would set a stronger padding scheme as default

enumerator PAD_ISO2

ISO-9797 M2 padding.

enum cryptx_aes_default_flags

Defines defaults for various cipher modes.

Values:

enumerator CRYPTX_AES_CBC_DEFAULTS = (PAD_DEFAULT | 0)
enumerator CRYPTX_AES_CTR_DEFAULTS = (((0x0f & (8)) << 6) | ((0x0f & (8)) << 2) | 0)
enumerator CRYPTX_AES_GCM_DEFAULTS = (0)
cryptx_aes_cbc_flagset(padding_mode)

Defines a macro to set flags for AES CBC mode.

cryptx_aes_ctr_flagset(nonce_len, counter_len)

Defines a macro to set flags for AES CTR mode.

cryptx_aes_gcm_flagset

GCM has no flags, pass 0 .

Macros

CRYPTX_KEYLEN_AES128
CRYPTX_KEYLEN_AES192
CRYPTX_KEYLEN_AES256
CRYPTX_BLOCKSIZE_AES
cryptx_aes_get_ciphertext_len(len)

Defines a macro to return the byte length of an AES ciphertext given a plaintext length.

Response Codes

enum aes_error_t

Defines response codes returned by the AES API.

Values:

enumerator AES_OK

AES operation completed successfully.

enumerator AES_INVALID_ARG

AES operation failed, bad argument.

enumerator AES_INVALID_MSG

AES operation failed, message invalid.

enumerator AES_INVALID_CIPHERMODE

AES operation failed, cipher mode undefined.

enumerator AES_INVALID_PADDINGMODE

AES operation failed, padding mode undefined.

enumerator AES_INVALID_CIPHERTEXT

AES operation failed, ciphertext error.

enumerator AES_INVALID_OPERATION

AES operation failed, used encrypt context for decrypt or vice versa.

Functions

aes_error_t cryptx_aes_init(struct cryptx_aes_ctx *context, const void *key, size_t keylen, const void *iv, size_t ivlen, uint8_t cipher_mode, uint24_t flags)

Initializes a stateful AES cipher context to be used for encryption or decryption.

Parameters
  • context – Pointer to an AES cipher context to initialize.

  • key – Pointer to an 128, 192, or 256 bit key to load into the AES context.

  • keylen – The size, in bytes, of the key to load.

  • iv – Pointer to Initialization vector, a buffer equal to the block size filled with random bytes.

  • ivlen – Length of the initalization vector. Capped at 16 bytes. Certain cipher modes have different recommendations.

  • cipher_mode – Operational mode of the cipher to initialize.

  • flags – A series of flags to configure the AES context with. Use the provided defaults enumeration or the flagset macros above.

Returns

An aes_error_t indicating the status of the AES operation.

aes_error_t cryptx_aes_encrypt(const struct cryptx_aes_ctx *context, const void *plaintext, size_t len, void *ciphertext)

Performs a stateful AES encryption of an arbitrary length of data.

Parameters
  • context – Pointer to an AES cipher context.

  • plaintext – Pointer to data to encrypt.

  • len – Length of data at plaintext to encrypt.

  • ciphertext – Pointer to buffer to write encrypted data to.

Returns

An aes_error_t indicating the status of the AES operation.

aes_error_t cryptx_aes_decrypt(const struct cryptx_aes_ctx *context, const void *ciphertext, size_t len, void *plaintext)

Performs a stateful AES decryption of an arbitrary length of data.

Parameters
  • context – Pointer to AES cipher context.

  • ciphertext – Pointer to data to decrypt.

  • len – Length of data at ciphertext to decrypt.

  • plaintext – Pointer to buffer to write decryped data to.

Returns

An aes_error_t indicating the status of the AES operation.

cryptx_aes_ctx aes;
char* msg = "The fox jumped over the dog!";
uint8_t aes_key[CRYPTX_KEYLEN_AES256],
        aes_iv[CRYPTX_BLOCKSIZE_AES];

// generate random key
if(!cryptx_csrand_fill(aes_key, sizeof(aes_key))) return;
// generate random iv
if(!cryptx_csrand_fill(aes_iv, sizeof(aes_iv))) return;

if(cryptx_aes_init(&aes, aes_key, sizeof(aes_key),
                aes_iv, sizeof(aes_iv),
                CRYPTX_AES_GCM, CRYPTX_AES_GCM_DEFAULTS) != AES_OK)
  return;

size_t encr_len = strlen(msg)+1
cryptx_aes_encrypt(&aes, msg, encr_len, msg);

network_send(aes_iv, CRYPTX_BLOCKSIZE_AES);
network_send(msg, encr_len);

The following functions are only valid for Galois Counter Mode (GCM). Attempting to use them for any other cipher mode will return AES_INVALID_CIPHERMODE.

aes_error_t cryptx_aes_update_aad(struct cryptx_aes_ctx *context, const void *aad, size_t aad_len)

Updates the cipher context for given AAD (Additional Authenticated Data).

AAD is data that is only authenticated, not encrypted.

Parameters
  • context – Pointer to an AES context.

  • aad – Pointer to additional authenticated data segment.

  • aad_len – Length of additional data segment.

Returns

An aes_error_t indicating the status of the AES operation.

aes_error_t cryptx_aes_digest(struct cryptx_aes_ctx *context, uint8_t *digest)

Returns the current authentication tag for data parsed so far.

Parameters
  • context – Pointer to an AES context

  • digest – Pointer to a buffer to output digest to. Must be at least 16 bytes large.

Returns

An aes_error_t indicating the status of the AES operation.

bool cryptx_aes_verify(const struct cryptx_aes_ctx *context, const void *aad, size_t aad_len, const void *ciphertext, size_t ciphertext_len, uint8_t *tag)

Parses the specified AAD and ciphertext and then compares the output auth tag to an expected auth tag.

Parameters
  • context – Pointer to an AES context.

  • aad – Pointer to associated data to authenticate.

  • aad_len – Length of associated data to authenticate.

  • ciphertext – Pointer to ciphertext to authenticate.

  • ciphertext_len – Length of ciphertext to authenticate.

  • tag – Pointer to expected auth tag to validate against.

Returns

TRUE if authentication tag matches expected, FALSE otherwise.

cryptx_aes_ctx aes;
char* msg = "The fox jumped over the dog!";
char* header = "A header string.";
uint8_t aes_key[CRYPTX_KEYLEN_AES256],
        aes_iv[CRYPTX_BLOCKSIZE_AES],
        auth_tag[CRYPTX_BLOCKSIZE_AES];

// generate random key
if(!cryptx_csrand_fill(aes_key, sizeof(aes_key))) return;
// generate random iv
if(!cryptx_csrand_fill(aes_iv, sizeof(aes_iv))) return;

if(cryptx_aes_init(&aes, aes_key, sizeof(aes_key),
                aes_iv, sizeof(aes_iv),
                CRYPTX_AES_GCM, CRYPTX_AES_GCM_DEFAULTS) != AES_OK)
  return;

size_t encr_len = strlen(msg)+1
cryptx_aes_update_aad(&aes, header, strlen(header));
cryptx_aes_encrypt(&aes, msg, encr_len, msg);
cryptx_aes_digest(&aes, auth_tag);

network_send(aes_iv, CRYPTX_BLOCKSIZE_AES);
network_send(msg, encr_len);
network_send(auth_tag, CRYPTX_BLOCKSIZE_AES);

There are also some enforced constraints on when these functions can be called, intended to prevent undefined behavior as well as to close a particularly nasty tag-forgery vulnerability 1 in GCM.

GCM FUNCTION VALIDITY CONTROL FLOW

After Function Call

cryptx_aes_update_aad

cryptx_aes_encrypt

cryptx_aes_digest

cryptx_aes_init

VALID

VALID

VALID

cryptx_aes_update_aad

VALID

VALID

VALID

cryptx_aes_encrypt

INVALID

VALID

VALID

cryptx_aes_digest

INVALID

INVALID

INVALID

Initialization Vector Requirements

  • CBC Mode

    Requirement: Initialization vector must be securely-random.
    Non-Compliance Effect: Vulnerability to chosen plaintext attack 2.
    Assurance: Generate a random IV with cryptx_csrand_fill for use with this mode.
  • CTR & GCM Modes

    Requirement: Initialization vector must be unique (not re-used) over the same key.
    Non-Compliance Effect: Vulnerability to many-time pad 3.
    Additional Options: A fixed nonce may preceed the counter portion of the IV. This should be securely random. Default configuration for CTR mode is an 8 byte nonce followed by an 8 byte counter, though this can be configured during cipher initialization.
    Assurance: For counter block of length N bits, after processing 2 ^ N blocks of plaintext data: (1) generate new nonce/counter blocks and prepend to ciphertext, or (2) generate and negotiate new key.

Notes

  1. The initialization vector used for the cipher state (or message for GCM mode) may be communicated to the other party as the first block of the ciphertext.

  2. The AES cipher begins to leak information after a certain number of blocks have been encrypted under a single key. This number differs by cipher mode but can range anywhere from 2 ^ 48 to 2^64 blocks of data. This is a stupidly large amount of data that you will never realistically reach.

  3. CBC and CTR modes by themselves ensure confidentiality but do not provide any assurances of message integrity or authenticity. If you need a truly secure construction, use GCM mode or append a keyed hash (HMAC) to the encrypted message.


1

GCM Nonce-Misuse/Forbidden Attack Vulnerability. It involves the leaking of bits of the hash subkey used to generate the authentication tag if the same initialization vector is used to authenticate multiple messages. This allows an attacker to embed a valid signature for an altered message. To resolve this vulnerability within this GCM implementation call cryptx_aes_init again with a new initialization vector after you return a digest for a data stream. For more details on this vulnerability click here.

2

Chosen Plaintext Attack. An attack against a cryptosystem involving requesting multiple encryptions while controlling bits of the input plaintext. This allows an attacker to reveal bits of the encryption secret. To resolve this vulnerability the output of an encryption algorithm needs to be securely random. See Initialization Vector Requirements.

3

Many-Time Pad. This vulnerability derived from the One-Time Pad algorithm which was one of the first encryption algorithms developed. It involved XOR’ing a message with a key of equal length and had perfect secrecy. Issues arose with this algorithm if the key began to repeat, which would reveal the plaintext given only a few ciphertexts. AES CTR and GCM modes use the counter block within the IV to generate a one-time pad and therefore are subject to this vulnerability. To resolve this vulnerability ensure that you do not allow your counter/nonce block combination to repeat under the same key.