VoodooPad Encrypt-then-MAC AEAD Encryption


Introduction

VoodooPad's ETM-AEAD provides an AEAD cipher (Authenticated Encryption with Authenticated Data) based on the composition of an unauthenticated block cipher and HMAC.

VoodooPad's implementation of ETM-AEAD is based on the composition of well-understood standards and recommendations:



To prevent padding oracle attacks, as well as to decrease the potential attack surface of the application, ETM-AEAD uses encrypt-then-MAC for all authenticated encrypted data.


This choice of standards for ETM-AEAD was based on their industry prevalence, implementation availability, and NIST recommendation's for our use cases. While an authenticating encryption mode such as CCM may be preferable from an implementation perspective, platform support is lacking: neither Mac OS X nor iOS ship with support for an authenticated encryption mode in the standard system libraries.


The ETM-AEAD Algorithm

This specification defines the implementation of authenticated encryption with associated data based on the composition of AES-CBC with PKCS#7 padding, with HMAC providing encrypt-then-MAC authentication.


This specification does not define the mechanism by which the encryption and authentication keys are acquired, nor the use of a specific AES key size or HMAC cryptographic hash function.


Inputs

The specification of encryption and decryption assumes the following definitions:


Encryption

To perform encryption:


1. PRIVATE_DATA is PKCS#7 padded and AES-CBC encrypted using ENC_KEY and ENC_IV:


ENC_PRIVATE_DATA = aes-cbc-encrypt(ENC_KEY, ENC_IV, pkcs7_pad(PRIVATE_DATA))


2. The HMAC is computed -- using MAC_KEY -- over ENC_IV || ENC_PRIVATE_DATA || ASSOC_DATA || ASSOC_DATA_LEN


HMAC_INPUT = ENC_IV || ENC_PRIVATE_DATA || ASSOC_DATA || ASSOC_DATA_LEN HMAC = hmac(MAC_KEY, HMAC_INPUT)


3. The ciphertext result C is emitted as the concatenation of ENC_PRIVATE_DATA || ASSOC_DATA || HMAC.


Decryption

The decryption process operates on inputs ENC_KEY, ENC_IV, MAC_KEY, ASSOC_DATA_LEN, and ciphertext value C (as emitted by the encryption process)


To perform decryption of ciphertext C:


1. The HMAC of ciphertext C's authenticated data is computed:


HMAC_INPUT = ENC_IV || C.ENC_PRIVATE_DATA || C.ASSOC_DATA || ASSOC_DATA_LEN HMAC = hmac(MAC_KEY, HMAC_INPUT)


2. The computed HMAC is compared -- using a constant time comparison function -- against C.HMAC. If the values are not equal, input C is discarded as invalid and decryption terminates with an error:


if (!constant_time_compare(HMAC, C.HMAC)) return E_INVALID_HMAC;


3. To ensure the initial bytes of ASSOC_DATA are not interpreted as the final bytes of ENC_PRIVATE_DATA, the original length of ENC_PRIVATE_DATA mustbe computed from ASSOC_DATA_LEN.

4. Using the input length computed in step #3, the plaintext representation of ENC_PRIVATE_DATA is decrypted:

PADDED_PRIVATE_DATA = aes-cbc-decrypt(ENC_KEY, ENC_IV, ENC_PRIVATE_DATA).


5. PKCS7 padding is removed from PRIVATE_DATA:


PRIVATE_DATA = pkcs7_unpad(PADDED_PRIVATE_DATA)


Standard ETM-AEAD Serialization

This section defines a non-mandatory byte-level serialization format for use with ETM-AEAD.


This serialization format is defined using ABNF notation, as specified in RFC 5234. All terminal rules are binary encoded, without padding unless otherwise specified. All multi-byte integers MUST be stored in little-endian format.


aead_data = aes_iv

            assoc_data_len

            enc_private_data

            assoc_data

            hmac


aes_iv = *OCTET                 ; AES-CBC IV used to encrypt enc_private_data

enc_private_data = *OCTET       ; AES-CBC-PKCS7 encrypted ENC_PRIVATE_DATA


assoc_data = *OCTET             ; HMAC-authenticated, unencrypted ASSOC_DATA


assoc_data_len = UINT64         ; The size of assoc_data, in bytes.


hmac = *OCTET                   ; HMAC computed as per the ETM-AEAD specification.