153 lines
4.3 KiB
C
153 lines
4.3 KiB
C
|
/*
|
||
|
* cifra - embedded cryptography library
|
||
|
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
|
||
|
*
|
||
|
* 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
|
||
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* 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 <modes>`.
|
||
|
*/
|
||
|
|
||
|
#ifndef AES_H
|
||
|
#define AES_H
|
||
|
|
||
|
#include <stddef.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#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
|