123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- /*
- * 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/>.
- */
- #ifndef MODES_H
- #define MODES_H
- #include <stddef.h>
- #include <stdint.h>
- #include "prp.h"
- /**
- * Block cipher modes
- * ==================
- */
- /**
- * CBC mode
- * --------
- * This implementation allows encryption or decryption of whole
- * blocks in CBC mode. It does not offer a byte-wise incremental
- * interface, or do any padding.
- *
- * This mode provides no useful integrity and should not be used
- * directly.
- */
- /* .. c:type:: cf_cbc
- * This structure binds together the things needed to encrypt/decrypt whole
- * blocks in CBC mode.
- *
- * .. c:member:: cf_cbc.prp
- * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
- *
- * .. c:member:: cf_cbc.prpctx
- * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
- * pointer to a :c:type:`cf_aes_context` instance.
- *
- * .. c:member:: cf_cbc.block
- * The IV or last ciphertext block.
- */
- typedef struct
- {
- const cf_prp *prp;
- void *prpctx;
- uint8_t block[CF_MAXBLOCK];
- } cf_cbc;
- /* .. c:function:: $DECL
- * Initialise CBC encryption/decryption context using selected prp, prp context and IV. */
- void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]);
- /* .. c:function:: $DECL
- * Encrypt blocks in CBC mode. input and output
- * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
- void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
- /* .. c:function:: $DECL
- * Decrypt blocks in CBC mode. input and output
- * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
- void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
- /**
- * Counter mode
- * ------------
- * This implementation allows incremental encryption/decryption of
- * messages. Encryption and decryption are the same operation.
- *
- * The counter is always big-endian, but has configurable location
- * and size within the nonce block. The counter wraps, so you
- * should make sure the length of a message with a given nonce
- * doesn't cause nonce reuse.
- *
- * This mode provides no integrity and should not be used directly.
- */
- /* .. c:type:: cf_ctr
- *
- * .. c:member:: cf_ctr.prp
- * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
- *
- * .. c:member:: cf_ctr.prpctx
- * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
- * pointer to a :c:type:`cf_aes_context` instance.
- *
- * .. c:member:: cf_ctr.nonce
- * The next block to encrypt to get another block of key stream.
- *
- * .. c:member:: cf_ctr.keymat
- * The current block of key stream.
- *
- * .. c:member:: cf_ctr.nkeymat
- * The number of bytes at the end of :c:member:`keymat` that are so-far unused.
- * If this is zero, all the bytes are used up and/or of undefined value.
- *
- * .. c:member:: cf_ctr.counter_offset
- * The offset (in bytes) of the counter block within the nonce.
- *
- * .. c:member:: cf_ctr.counter_width
- * The width (in bytes) of the counter block in the nonce.
- */
- typedef struct
- {
- const cf_prp *prp;
- void *prpctx;
- uint8_t nonce[CF_MAXBLOCK];
- uint8_t keymat[CF_MAXBLOCK];
- size_t nkeymat;
- size_t counter_offset;
- size_t counter_width;
- } cf_ctr;
- /* .. c:function:: $DECL
- * Initialise CTR encryption/decryption context using selected prp and nonce.
- * (nb, this only increments the whole nonce as a big endian block) */
- void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]);
- /* .. c:function:: $DECL
- * Set the location and width of the nonce counter.
- *
- * eg. offset = 12, width = 4 means the counter is mod 2^32 and placed
- * at the end of the nonce. */
- void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width);
- /* .. c:function:: $DECL
- * Encrypt or decrypt bytes in CTR mode.
- * input and output may alias and must point to specified number of bytes. */
- void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes);
- /* .. c:function:: $DECL
- * Discards the rest of this block of key stream. */
- void cf_ctr_discard_block(cf_ctr *ctx);
- /**
- * CBC-MAC
- * -------
- * This is a incremental interface to computing a CBC-MAC tag over a message.
- *
- * It optionally pads the message with PKCS#5/PKCS#7 padding -- if you don't
- * do this, messages must be an exact number of blocks long.
- *
- * You shouldn't use this directly because it isn't secure for variable-length
- * messages. Use CMAC instead.
- */
- /* .. c:type:: cf_cbcmac_stream
- * Stream interface to CBC-MAC signing.
- *
- * .. c:member:: cf_cbcmac.prp
- * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
- *
- * .. c:member:: cf_cbcmac.prpctx
- * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
- * pointer to a :c:type:`cf_aes_context` instance.
- *
- * .. c:member:: cf_cbcmac.cbc
- * CBC data.
- *
- * .. c:member:: cf_cbcmac.buffer
- * Buffer for data which can't be processed until we have a full block.
- *
- * .. c:member:: cf_cbcmac.used
- * How many bytes at the front of :c:member:`buffer` are valid.
- */
- typedef struct
- {
- const cf_prp *prp;
- void *prpctx;
- cf_cbc cbc;
- uint8_t buffer[CF_MAXBLOCK];
- size_t used;
- } cf_cbcmac_stream;
- /* .. c:function:: $DECL
- * Initialise CBC-MAC signing context using selected prp. */
- void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx);
- /* .. c:function:: $DECL
- * Reset the streaming signing context, to sign a new message. */
- void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx);
- /* .. c:function:: $DECL
- * Process ndata bytes at data. */
- void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t ndata);
- /* .. c:function:: $DECL
- * Finish the current block of data by adding zeroes. Does nothing if there
- * are no bytes awaiting processing. */
- void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx);
- /* .. c:function:: $DECL
- * Output the MAC to ctx->prp->blocksz bytes at out.
- * ctx->used must be zero: the inputed message must be an exact number of
- * blocks. */
- void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
- /* .. c:function:: $DECL
- * Output the MAC to ctx->prp->blocksz bytes at out.
- *
- * The message is padded with PKCS#5 padding. */
- void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
- /**
- * CMAC
- * ----
- * This is both a one-shot and incremental interface to
- * computing a CMAC tag over a message.
- *
- * The one-shot interface separates out the per-key computation,
- * so if you need to compute lots of MACs with one key you don't
- * pay that cost more than once.
- *
- * CMAC is a good choice for a symmetric MAC.
- */
- /* .. c:type:: cf_cmac
- * One-shot interface to CMAC signing.
- *
- * .. c:member:: cf_cmac.prp
- * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
- *
- * .. c:member:: cf_cmac.prpctx
- * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
- * pointer to a :c:type:`cf_aes_context` instance.
- *
- * .. c:member:: cf_cmac.B
- * The XOR offset for the last message block if it is a complete block
- * (also known as K\ :sub:`1`).
- *
- * .. c:member:: cf_cmac.P
- * The XOR offset for the last message block if it is a partial block
- * (also known as K\ :sub:`2`).
- */
- typedef struct
- {
- const cf_prp *prp;
- void *prpctx;
- uint8_t B[CF_MAXBLOCK];
- uint8_t P[CF_MAXBLOCK];
- } cf_cmac;
- /* .. c:function:: $DECL
- * Initialise CMAC signing context using selected prp. */
- void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx);
- /* .. c:function:: $DECL
- * CMAC sign the given data. The MAC is written to ctx->prp->blocksz
- * bytes at out. This is a one-shot function. */
- void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t bytes,
- uint8_t out[CF_MAXBLOCK]);
- /* .. c:type:: cf_cmac_stream
- * Stream interface to CMAC signing.
- *
- * Input data in arbitrary chunks using :c:func:`cf_cmac_stream_update`.
- * The last bit of data must be signalled with the `isfinal` flag to
- * that function, and the data cannot be zero length unless the whole
- * message is empty.
- *
- * .. c:member:: cf_cmac_stream.cmac
- * CMAC one-shot data.
- *
- * .. c:member:: cf_cmac_stream.cbc
- * CBC block encryption data.
- *
- * .. c:member:: cf_cmac_stream.buffer
- * Buffer for data which can't be processed until we have a full block.
- *
- * .. c:member:: cf_cmac_stream.used
- * How many bytes at the front of :c:member:`buffer` are valid.
- *
- * .. c:member:: cf_cmac_stream.processed
- * How many bytes in total we've processed. This is used to correctly
- * process empty messages.
- *
- * .. c:member:: cf_cmac_stream.finalised
- * A flag set when the final chunk of the message has been processed.
- * Only when this flag is set can you get the MAC out.
- */
- typedef struct
- {
- cf_cmac cmac;
- cf_cbc cbc;
- uint8_t buffer[CF_MAXBLOCK];
- size_t used;
- size_t processed;
- int finalised;
- } cf_cmac_stream;
- /* .. c:function:: $DECL
- * Initialise CMAC streaming signing context using selected prp. */
- void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx);
- /* .. c:function:: $DECL
- * Reset the streaming signing context, to sign a new message. */
- void cf_cmac_stream_reset(cf_cmac_stream *ctx);
- /* .. c:function:: $DECL
- * Process ndata bytes at data. isfinal is non-zero if this is the last piece
- * of data. */
- void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t ndata,
- int isfinal);
- /* .. c:function:: $DECL
- * Output the MAC to ctx->cmac->prp->blocksz bytes at out.
- * cf_cmac_stream_update with isfinal non-zero must have been called
- * since the last _init/_reset. */
- void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
- /**
- * EAX
- * ---
- *
- * The EAX authenticated encryption mode. This is a one-shot
- * interface.
- *
- * EAX is a pretty respectable and fast AEAD mode.
- */
- /* .. c:function:: $DECL
- * EAX authenticated encryption.
- *
- * This function does not fail.
- *
- * :param prp/prpctx: describe the block cipher to use.
- * :param plain: message plaintext.
- * :param nplain: length of message. May be zero.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD. May be zero.
- * :param nonce: nonce. This must not repeat for a given key.
- * :param nnonce: length of nonce. The nonce can be any length.
- * :param cipher: ciphertext output. `nplain` bytes are written here.
- * :param tag: authentication tag. `ntag` bytes are written here.
- * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
- */
- void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *plain, size_t nplain,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- uint8_t *cipher,
- uint8_t *tag, size_t ntag);
- /* .. c:function:: $DECL
- * EAX authenticated decryption.
- *
- * :return: 0 on success, non-zero on error. Nothing is written to plain on error.
- *
- * :param prp/prpctx: describe the block cipher to use.
- * :param cipher: message ciphertext.
- * :param ncipher: message length.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD.
- * :param nonce: nonce.
- * :param nnonce: length of nonce.
- * :param tag: authentication tag. `ntag` bytes are read from here.
- * :param ntag: authentication tag length.
- * :param plain: plaintext output. `ncipher` bytes are written here.
- */
- int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *cipher, size_t ncipher,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- const uint8_t *tag, size_t ntag,
- uint8_t *plain);
- /**
- * GCM
- * ---
- * The GCM ('Galois counter mode') authenticated encryption mode.
- * This is a one-shot interface.
- *
- * GCM is a reasonably respectable AEAD mode. It's somewhat more
- * complex than EAX, and side channel-free implementations can
- * be quite slow.
- */
- /* .. c:function:: $DECL
- * GCM authenticated encryption.
- *
- * This function does not fail.
- *
- * :param prp/prpctx: describe the block cipher to use.
- * :param plain: message plaintext.
- * :param nplain: length of message. May be zero.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD. May be zero.
- * :param nonce: nonce. This must not repeat for a given key.
- * :param nnonce: length of nonce. The nonce can be any length, but 12 bytes is strongly recommended.
- * :param cipher: ciphertext output. `nplain` bytes are written here.
- * :param tag: authentication tag. `ntag` bytes are written here.
- * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
- *
- * This function does not fail.
- */
- void cf_gcm_encrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *plain, size_t nplain,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- uint8_t *cipher,
- uint8_t *tag, size_t ntag);
- /* .. c:function:: $DECL
- * GCM authenticated decryption.
- *
- * :return: 0 on success, non-zero on error. Nothing is written to plain on error.
- *
- * :param prp: describe the block cipher to use.
- * :param prpctx: describe the block cipher to use.
- * :param cipher: message ciphertext.
- * :param ncipher: message length.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD.
- * :param nonce: nonce.
- * :param nnonce: length of nonce.
- * :param tag: authentication tag. `ntag` bytes are read from here.
- * :param ntag: authentication tag length.
- * :param plain: plaintext output. `ncipher` bytes are written here.
- */
- int cf_gcm_decrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *cipher, size_t ncipher,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- const uint8_t *tag, size_t ntag,
- uint8_t *plain);
- /**
- * CCM
- * ---
- *
- * The CCM ('Counter with CBC-MAC') authenticated encryption mode.
- * CCM is a widely used AEAD mode (in IPSec, WPA2, Bluetooth, etc.)
- *
- * It works (at a high level) by just gluing together CTR and CBC-MAC
- * modes (in MAC-then-encrypt mode) and then fixing the problems inherent
- * with CBC-MAC in over-complicated ways.
- *
- * This is a one-shot interface, which is good because the underlying
- * mechanism isn't actually online: you need to know the message length
- * before you start, or do everything in two passes.
- */
- /* .. c:function:: $DECL
- * CCM authenticated encryption.
- *
- * This function does not fail.
- *
- * :param prp/prpctx: describe the block cipher to use.
- * :param plain: message plaintext.
- * :param nplain: length of message. May be zero. Must meet the constraints placed on it by `L`.
- * :param L: length of the message length encoding. This must be in the interval `[2,8]` and gives a maximum message size of 2\ :sup:`8L` bytes.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD. May be zero.
- * :param nonce: nonce. This must not repeat for a given key.
- * :param nnonce: length of nonce. Must be exactly `15 - L` bytes for a 128-bit block cipher.
- * :param cipher: ciphertext output. `nplain` bytes are written here.
- * :param tag: authentication tag. `ntag` bytes are written here.
- * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
- */
- void cf_ccm_encrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *plain, size_t nplain, size_t L,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- uint8_t *cipher,
- uint8_t *tag, size_t ntag);
- /* .. c:function:: $DECL
- * CCM authenticated decryption.
- *
- * :return: 0 on success, non-zero on error. Plain is cleared on error.
- *
- * :param prp: describe the block cipher to use.
- * :param prpctx: describe the block cipher to use.
- * :param cipher: message ciphertext.
- * :param ncipher: length of message.
- * :param L: length of the message length encoding. See :c:func:`cf_ccm_encrypt`.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD.
- * :param nonce: nonce.
- * :param nnonce: length of nonce.
- * :param tag: authentication tag. `ntag` bytes are read from here.
- * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
- * :param plain: plaintext output. `ncipher` bytes are written here.
- */
- int cf_ccm_decrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *cipher, size_t ncipher, size_t L,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- const uint8_t *tag, size_t ntag,
- uint8_t *plain);
- /**
- * OCB
- * ---
- *
- * OCB is an authenticated encryption mode by Phil Rogaway.
- *
- * This is version 3, as standardised in RFC7253. It's defined
- * only for block ciphers with a 128-bit block size.
- *
- * This is a one-shot interface.
- */
- /* .. c:function:: $DECL
- * OCB authenticated encryption.
- *
- * This function does not fail.
- *
- * :param prp/prpctx: describe the block cipher to use.
- * :param plain: message plaintext.
- * :param nplain: length of message. May be zero.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD. May be zero.
- * :param nonce: nonce. This must not repeat for a given key.
- * :param nnonce: length of nonce. Must be 15 or fewer bytes.
- * :param cipher: ciphertext output. `nplain` bytes are written here.
- * :param tag: authentication tag. `ntag` bytes are written here.
- * :param ntag: authentication tag length. Must be 16 or fewer bytes.
- */
- void cf_ocb_encrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *plain, size_t nplain,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- uint8_t *cipher,
- uint8_t *tag, size_t ntag);
- /* .. c:function:: $DECL
- * OCB authenticated decryption.
- *
- * :return: 0 on success, non-zero on error. `plain` is cleared on error.
- *
- * :param prp: describe the block cipher to use.
- * :param prpctx: describe the block cipher to use.
- * :param cipher: message ciphertext.
- * :param ncipher: length of message.
- * :param header: additionally authenticated data (AAD).
- * :param nheader: length of AAD.
- * :param nonce: nonce.
- * :param nnonce: length of nonce.
- * :param tag: authentication tag. `ntag` bytes are read from here.
- * :param ntag: authentication tag length.
- * :param plain: plaintext output. `ncipher` bytes are written here.
- */
- int cf_ocb_decrypt(const cf_prp *prp, void *prpctx,
- const uint8_t *cipher, size_t ncipher,
- const uint8_t *header, size_t nheader,
- const uint8_t *nonce, size_t nnonce,
- const uint8_t *tag, size_t ntag,
- uint8_t *plain);
- #endif
|