/* * cifra - embedded cryptography library * Written in 2014 by Joseph Birr-Pixton * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to the * public domain worldwide. This software is distributed without any * warranty. * * You should have received a copy of the CC0 Public Domain Dedication * along with this software. If not, see * . */ /** * The AES block cipher * ==================== * * This is a small, simple implementation of AES. Key expansion is done * first, filling in a :c:type:`cf_aes_context`. Then encryption and * decryption can be performed as desired. * * Usually you don't want to use AES directly; you should use it via * a :doc:`block cipher mode `. */ #ifndef AES_H #define AES_H #include #include #include "prp.h" /* .. c:macro:: AES_BLOCKSZ * AES has a 128-bit block size. This quantity is in bytes. */ #define AES_BLOCKSZ 16 /* --- Size configuration --- */ /* .. c:macro:: AES128_ROUNDS * .. c:macro:: AES192_ROUNDS * .. c:macro:: AES256_ROUNDS * * Round counts for different key sizes. */ #define AES128_ROUNDS 10 #define AES192_ROUNDS 12 #define AES256_ROUNDS 14 /* .. c:macro:: CF_AES_MAXROUNDS * * You can reduce the maximum number of rounds this implementation * supports. This reduces the storage needed by :c:type:`cf_aes_context`. * * The default is :c:macro:`AES256_ROUNDS` and is good for all key * sizes. */ #ifndef CF_AES_MAXROUNDS # define CF_AES_MAXROUNDS AES256_ROUNDS #endif /* .. c:macro:: CF_AES_ENCRYPT_ONLY * * Define this to 1 if you don't need to decrypt anything. * This saves space. :c:func:`cf_aes_decrypt` calls `abort(3)`. */ #ifndef CF_AES_ENCRYPT_ONLY # define CF_AES_ENCRYPT_ONLY 0 #endif /* .. c:type:: cf_aes_context * This type represents an expanded AES key. Create one * using :c:func:`cf_aes_init`, make use of one using * :c:func:`cf_aes_encrypt` or :c:func:`cf_aes_decrypt`. * * The contents of this structure are equivalent to the * original key material. You should clean the * contents of this structure with :c:func:`cf_aes_finish` * when you're done. * * .. c:member:: cf_aes_context.rounds * * Number of rounds to use, set by :c:func:`cf_aes_init`. * * This depends on the original key size, and will be * :c:macro:`AES128_ROUNDS`, :c:macro:`AES192_ROUNDS` or * :c:macro:`AES256_ROUNDS`. * * .. c:member:: cf_aes_context.ks * * Expanded key material. Filled in by :c:func:`cf_aes_init`. */ typedef struct { uint32_t rounds; uint32_t ks[AES_BLOCKSZ / 4 * (CF_AES_MAXROUNDS + 1)]; } cf_aes_context; /* .. c:function:: $DECL * This function does AES key expansion. It destroys * existing contents of :c:data:`ctx`. * * :param ctx: expanded key context, filled in by this function. * :param key: pointer to key material, of :c:data:`nkey` bytes. * :param nkey: length of key material. Must be `16`, `24` or `32`. */ extern void cf_aes_init(cf_aes_context *ctx, const uint8_t *key, size_t nkey); /* .. c:function:: $DECL * Encrypts the given block, from :c:data:`in` to :c:data:`out`. * These may alias. * * Fails at runtime if :c:data:`ctx` is invalid. * * :param ctx: expanded key context * :param in: input block (read) * :param out: output block (written) */ extern void cf_aes_encrypt(const cf_aes_context *ctx, const uint8_t in[AES_BLOCKSZ], uint8_t out[AES_BLOCKSZ]); /* .. c:function:: $DECL * Decrypts the given block, from :c:data:`in` to :c:data:`out`. * These may alias. * * Fails at runtime if :c:data:`ctx` is invalid. * * :param ctx: expanded key context * :param in: input block (read) * :param out: output block (written) */ extern void cf_aes_decrypt(const cf_aes_context *ctx, const uint8_t in[AES_BLOCKSZ], uint8_t out[AES_BLOCKSZ]); /* .. c:function:: $DECL * Erase scheduled key material. * * Call this when you're done to erase the round keys. */ extern void cf_aes_finish(cf_aes_context *ctx); /* .. c:var:: const cf_prp cf_aes * Abstract interface to AES. See :c:type:`cf_prp` for * more information. */ extern const cf_prp cf_aes; #endif