初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

290
external/cifra_AES128-EAX/bitops.h vendored Normal file
View File

@@ -0,0 +1,290 @@
/*
* 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 BITOPS_H
#define BITOPS_H
#include <stdint.h>
#include <stddef.h>
/* Assorted bitwise and common operations used in ciphers. */
/** Circularly rotate right x by n bits.
* 0 > n > 32. */
static inline uint32_t rotr32(uint32_t x, unsigned n)
{
return (x >> n) | (x << (32 - n));
}
/** Circularly rotate left x by n bits.
* 0 > n > 32. */
static inline uint32_t rotl32(uint32_t x, unsigned n)
{
return (x << n) | (x >> (32 - n));
}
/** Circularly rotate right x by n bits.
* 0 > n > 64. */
static inline uint64_t rotr64(uint64_t x, unsigned n)
{
return (x >> n) | (x << (64 - n));
}
/** Circularly rotate left x by n bits.
* 0 > n > 64. */
static inline uint64_t rotl64(uint64_t x, unsigned n)
{
return (x << n) | (x >> (64 - n));
}
/** Read 4 bytes from buf, as a 32-bit big endian quantity. */
static inline uint32_t read32_be(const uint8_t buf[4])
{
return (buf[0] << 24) |
(buf[1] << 16) |
(buf[2] << 8) |
(buf[3]);
}
/** Read 4 bytes from buf, as a 32-bit little endian quantity. */
static inline uint32_t read32_le(const uint8_t buf[4])
{
return (buf[3] << 24) |
(buf[2] << 16) |
(buf[1] << 8) |
(buf[0]);
}
/** Read 8 bytes from buf, as a 64-bit big endian quantity. */
static inline uint64_t read64_be(const uint8_t buf[8])
{
uint32_t hi = read32_be(buf),
lo = read32_be(buf + 4);
return ((uint64_t)hi) << 32 |
lo;
}
/** Read 8 bytes from buf, as a 64-bit little endian quantity. */
static inline uint64_t read64_le(const uint8_t buf[8])
{
uint32_t hi = read32_le(buf + 4),
lo = read32_le(buf);
return ((uint64_t)hi) << 32 |
lo;
}
/** Encode v as a 32-bit big endian quantity into buf. */
static inline void write32_be(uint32_t v, uint8_t buf[4])
{
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf = v & 0xff;
}
/** Encode v as a 32-bit little endian quantity into buf. */
static inline void write32_le(uint32_t v, uint8_t buf[4])
{
*buf++ = v & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf = (v >> 24) & 0xff;
}
/** Encode v as a 64-bit big endian quantity into buf. */
static inline void write64_be(uint64_t v, uint8_t buf[8])
{
*buf++ = (v >> 56) & 0xff;
*buf++ = (v >> 48) & 0xff;
*buf++ = (v >> 40) & 0xff;
*buf++ = (v >> 32) & 0xff;
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf = v & 0xff;
}
/** Encode v as a 64-bit little endian quantity into buf. */
static inline void write64_le(uint64_t v, uint8_t buf[8])
{
*buf++ = v & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 32) & 0xff;
*buf++ = (v >> 40) & 0xff;
*buf++ = (v >> 48) & 0xff;
*buf = (v >> 56) & 0xff;
}
/** out = in ^ b8.
* out and in may alias. */
static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = in[i] ^ b8;
}
/** out = x ^ y.
* out, x and y may alias. */
static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = x[i] ^ y[i];
}
/* out ^= x
* out and x may alias. */
static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords)
{
for (size_t i = 0; i < nwords; i++)
out[i] ^= x[i];
}
/** Produce 0xffffffff if x == y, zero otherwise, without branching. */
static inline uint32_t mask_u32(uint32_t x, uint32_t y)
{
uint32_t diff = x ^ y;
uint32_t diff_is_zero = ~diff & (diff - 1);
return - (diff_is_zero >> 31);
}
/** Product 0xff if x == y, zero otherwise, without branching. */
static inline uint8_t mask_u8(uint32_t x, uint32_t y)
{
uint32_t diff = x ^ y;
uint8_t diff_is_zero = ~diff & (diff - 1);
return - (diff_is_zero >> 7);
}
/** Select the ith entry from the given table of n values, in a side channel-silent
* way. */
static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n)
{
uint32_t r = 0;
for (uint32_t ii = 0; ii < n; ii++)
{
uint32_t mask = mask_u32(i, ii);
r = (r & ~mask) | (tab[ii] & mask);
}
return r;
}
/** Select the ith entry from the given table of n values, in a side channel-silent
* way. */
static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n)
{
uint8_t r = 0;
for (uint32_t ii = 0; ii < n; ii++)
{
uint8_t mask = mask_u8(i, ii);
r = (r & ~mask) | (tab[ii] & mask);
}
return r;
}
/** Select the ath, bth, cth and dth entries from the given table of n values,
* placing the results into a, b, c and d. */
static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
volatile const uint8_t *tab, uint32_t n)
{
uint8_t ra = 0,
rb = 0,
rc = 0,
rd = 0;
uint8_t mask;
for (uint32_t i = 0; i < n; i++)
{
uint8_t item = tab[i];
mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask);
mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask);
mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask);
mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask);
}
*a = ra;
*b = rb;
*c = rc;
*d = rd;
}
/** out ^= if0 or if1, depending on the value of bit. */
static inline void select_xor128(uint32_t out[4],
const uint32_t if0[4],
const uint32_t if1[4],
uint8_t bit)
{
uint32_t mask1 = mask_u32(bit, 1);
uint32_t mask0 = ~mask1;
out[0] ^= (if0[0] & mask0) | (if1[0] & mask1);
out[1] ^= (if0[1] & mask0) | (if1[1] & mask1);
out[2] ^= (if0[2] & mask0) | (if1[2] & mask1);
out[3] ^= (if0[3] & mask0) | (if1[3] & mask1);
}
/** Increments the integer stored at v (of non-zero length len)
* with the least significant byte first. */
static inline void incr_le(uint8_t *v, size_t len)
{
size_t i = 0;
while (1)
{
if (++v[i] != 0)
return;
i++;
if (i == len)
return;
}
}
/** Increments the integer stored at v (of non-zero length len)
* with the most significant byte last. */
static inline void incr_be(uint8_t *v, size_t len)
{
len--;
while (1)
{
if (++v[len] != 0)
return;
if (len == 0)
return;
len--;
}
}
/** Copies len bytes from in to out, with in shifted left by offset bits
* to the right. */
static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset)
{
uint8_t byte_off = offset / 8;
uint8_t bit_off = offset & 7;
uint8_t rmask = (1 << bit_off) - 1;
uint8_t lmask = ~rmask;
for (size_t i = 0; i < len; i++)
{
out[i] = (in[i + byte_off] << bit_off) & lmask;
out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask;
}
}
#endif

197
external/cifra_AES128-EAX/blockwise.c vendored Normal file
View File

@@ -0,0 +1,197 @@
/*
* 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/>.
*/
#include "blockwise.h"
#include "bitops.h"
#include "tassert.h"
#include <string.h>
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
cf_blockwise_accumulate_final(partial, npartial, nblock,
inp, nbytes,
process, process, ctx);
}
void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, size_t nbytes,
cf_blockwise_in_fn process,
cf_blockwise_in_fn process_final,
void *ctx)
{
const uint8_t *bufin = inp;
assert(partial && *npartial < nblock);
assert(inp || !nbytes);
assert(process && ctx);
/* If we have partial data, copy in to buffer. */
if (*npartial && nbytes)
{
size_t space = nblock - *npartial;
size_t taken = MIN(space, nbytes);
memcpy(partial + *npartial, bufin, taken);
bufin += taken;
nbytes -= taken;
*npartial += taken;
/* If that gives us a full block, process it. */
if (*npartial == nblock)
{
if (nbytes == 0)
process_final(ctx, partial);
else
process(ctx, partial);
*npartial = 0;
}
}
/* now nbytes < nblock or *npartial == 0. */
/* If we have a full block of data, process it directly. */
while (nbytes >= nblock)
{
/* Partial buffer must be empty, or we're ignoring extant data */
assert(*npartial == 0);
if (nbytes == nblock)
process_final(ctx, bufin);
else
process(ctx, bufin);
bufin += nblock;
nbytes -= nblock;
}
/* Finally, if we have remaining data, buffer it. */
while (nbytes)
{
size_t space = nblock - *npartial;
size_t taken = MIN(space, nbytes);
memcpy(partial + *npartial, bufin, taken);
bufin += taken;
nbytes -= taken;
*npartial += taken;
/* If we started with *npartial, we must have copied it
* in first. */
assert(*npartial < nblock);
}
}
void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, void *outp, size_t nbytes,
cf_blockwise_out_fn process, void *ctx)
{
const uint8_t *inb = inp;
uint8_t *outb = outp;
assert(partial && *npartial < nblock);
assert(inp || !nbytes);
assert(process && ctx);
while (nbytes)
{
/* If we're out of material, and need more, produce a block. */
if (*npartial == 0)
{
process(ctx, partial);
*npartial = nblock;
}
size_t offset = nblock - *npartial;
size_t taken = MIN(*npartial, nbytes);
xor_bb(outb, inb, partial + offset, taken);
*npartial -= taken;
nbytes -= taken;
outb += taken;
inb += taken;
}
}
void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t byte, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
/* only memset the whole of the block once */
int filled = 0;
while (nbytes)
{
size_t start = *npartial;
size_t count = MIN(nbytes, nblock - start);
if (!filled)
memset(partial + start, byte, count);
if (start == 0 && count == nblock)
filled = 1;
if (start + count == nblock)
{
process(ctx, partial);
*npartial = 0;
} else {
*npartial += count;
}
nbytes -= count;
}
}
void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
switch (nbytes)
{
case 0: break;
case 1: fbyte ^= lbyte;
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
break;
case 2:
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
break;
default:
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
/* If the middle and last bytes differ, then process the last byte separately.
* Otherwise, just extend the middle block size. */
if (lbyte != mbyte)
{
cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 2, process, ctx);
cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
} else {
cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 1, process, ctx);
}
break;
}
}

147
external/cifra_AES128-EAX/blockwise.h vendored Normal file
View File

@@ -0,0 +1,147 @@
/*
* 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 BLOCKWISE_H
#define BLOCKWISE_H
#include <stdint.h>
#include <stddef.h>
/* Processing function for cf_blockwise_accumulate. */
typedef void (*cf_blockwise_in_fn)(void *ctx, const uint8_t *data);
/* Processing function for cf_blockwise_xor. */
typedef void (*cf_blockwise_out_fn)(void *ctx, uint8_t *data);
/* This function manages the common abstraction of accumulating input in
* a buffer, and processing it when a full block is available.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
*/
void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
/* This function manages the common abstraction of accumulating input in
* a buffer, and processing it when a full block is available.
* This version supports calling a different processing function for
* the last block.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
* process_final is called last (but may not be called at all if
* all input is buffered).
*/
void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, size_t nbytes,
cf_blockwise_in_fn process,
cf_blockwise_in_fn process_final,
void *ctx);
/* This function manages XORing an input stream with a keystream
* to produce an output stream. The keystream is produced in blocks
* (ala a block cipher in counter mode).
*
* partial is the keystream buffer (maintained by the caller)
* on entry, *npartial is the currently valid count of bytes in partial:
* unused bytes are at the *end*. So *npartial = 4 means the last four
* bytes of partial are usable as keystream.
* on exit, npartial is updated to reflect the new state of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* output is where to write input xored with the keystream -- also length
* nbytes.
* process is the processing function, passed ctx and partial which it
* should fill with fresh key stream.
*/
void cf_blockwise_xor(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, void *output, size_t nbytes,
cf_blockwise_out_fn newblock,
void *ctx);
/* This function processes a single byte a number of times. It's useful
* for padding, and more efficient than calling cf_blockwise_accumulate
* a bunch of times.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
* byte is the byte to process, nbytes times.
*/
void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t byte, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
/* This function attempts to process patterns of bytes common in
* block cipher padding.
*
* This takes three bytes:
* - a first byte, fbyte,
* - a middle byte, mbyte,
* - a last byte, lbyte.
*
* If nbytes is zero, nothing happens.
* If nbytes is one, the byte fbyte ^ lbyte is processed.
* If nbytes is two, the fbyte then lbyte are processed.
* If nbytes is three or more, fbyte, then one or more mbytes, then fbyte
* is processed.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
*/
void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
#endif

59
external/cifra_AES128-EAX/cf_config.h vendored Normal file
View File

@@ -0,0 +1,59 @@
/*
* 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 CF_CONFIG_H
#define CF_CONFIG_H
/**
* Library configuration
* =====================
*/
/* .. c:macro:: CF_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need all available side channel protections.
* **This option may alter the ABI**.
*
* This has a non-trivial performance penalty. Where a
* side-channel free option is cheap or free (like checking
* a MAC) this is always done in a side-channel free way.
*
* The default is **on** for all available protections.
*/
#ifndef CF_SIDE_CHANNEL_PROTECTION
# define CF_SIDE_CHANNEL_PROTECTION 1
#endif
/* .. c:macro:: CF_TIME_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need timing/branch prediction side channel
* protection.
*
* You probably want this. The default is on. */
#ifndef CF_TIME_SIDE_CHANNEL_PROTECTION
# define CF_TIME_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
#endif
/* .. c:macro:: CF_CACHE_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need cache side channel protection.
*
* If you have a microcontroller with no cache, you can turn this off
* without negative effects.
*
* The default is on. This will have some performance impact,
* especially on AES.
*/
#ifndef CF_CACHE_SIDE_CHANNEL_PROTECTION
# define CF_CACHE_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
#endif
#endif

150
external/cifra_AES128-EAX/cifra_cmac.c vendored Normal file
View File

@@ -0,0 +1,150 @@
/*
* 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/>.
*/
#include "handy.h"
#include "prp.h"
#include "modes.h"
#include "bitops.h"
#include "blockwise.h"
#include "gf128.h"
#include "tassert.h"
#include <string.h>
void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx)
{
uint8_t L[CF_MAXBLOCK];
assert(prp->blocksz == 16);
mem_clean(ctx, sizeof *ctx);
/* L = E_K(0^n) */
mem_clean(L, prp->blocksz);
prp->encrypt(prpctx, L, L);
/* B = 2L */
cf_gf128 gf;
cf_gf128_frombytes_be(L, gf);
cf_gf128_double(gf, gf);
cf_gf128_tobytes_be(gf, ctx->B);
/* P = 4L */
cf_gf128_double(gf, gf);
cf_gf128_tobytes_be(gf, ctx->P);
ctx->prp = prp;
ctx->prpctx = prpctx;
}
void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK])
{
cf_cmac_stream stream;
stream.cmac = *ctx;
cf_cmac_stream_reset(&stream);
cf_cmac_stream_update(&stream, data, len, 1);
cf_cmac_stream_final(&stream, out);
}
void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx)
{
cf_cmac_init(&ctx->cmac, prp, prpctx);
cf_cmac_stream_reset(ctx);
}
void cf_cmac_stream_reset(cf_cmac_stream *ctx)
{
uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero);
mem_clean(ctx->buffer, sizeof ctx->buffer);
ctx->used = 0;
ctx->processed = 0;
ctx->finalised = 0;
}
static void cmac_process(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
uint8_t output[CF_MAXBLOCK];
cf_cbc_encrypt(&ctx->cbc, block, output, 1);
ctx->processed += ctx->cmac.prp->blocksz;
}
static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block,
const uint8_t *xor)
{
uint8_t input[CF_MAXBLOCK];
uint8_t output[CF_MAXBLOCK];
xor_bb(input, block, xor, ctx->cmac.prp->blocksz);
cf_cbc_encrypt(&ctx->cbc, input, output, 1);
ctx->processed += ctx->cmac.prp->blocksz;
/* signature is in ctx->cbc.block. */
}
static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.B);
ctx->finalised = 1;
}
static void cmac_process_final_pad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.P);
ctx->finalised = 1;
}
void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
{
size_t blocksz = ctx->cmac.prp->blocksz;
cf_blockwise_in_fn final_fn = cmac_process;
int needpad = 0;
if (isfinal)
{
int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;
assert(!ctx->finalised); /* finalised before? */
assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */
/* If we have a whole number of blocks, and at least 1 block, we XOR in B.
* Otherwise, we need to pad and XOR in P. */
if (whole_number_of_blocks && !empty_message)
final_fn = cmac_process_final_nopad;
else
needpad = 1;
}
/* Input data */
cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz,
data, len,
cmac_process,
final_fn, ctx);
/* Input padding */
if (needpad)
{
cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz,
0x80, 0x00, 0x00, blocksz - ctx->used,
cmac_process_final_pad, ctx);
}
}
void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
{
assert(ctx->finalised);
memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz);
}

View File

@@ -0,0 +1,416 @@
/*
* 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/>.
*/
#include <string.h>
#include <stdlib.h>
#include "handy.h"
#include "cf_config.h"
#include "cifra_eax_aes.h"
#include "bitops.h"
#include "tassert.h"
static const uint8_t S[256] =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4,
0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7,
0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3,
0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,
0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3,
0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe,
0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92,
0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2,
0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5,
0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25,
0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42,
0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
static const uint8_t Rcon[11] =
{
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
};
#ifdef INLINE_FUNCS
static inline uint32_t word4(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
{
return b0 << 24 | b1 << 16 | b2 << 8 | b3;
}
static inline uint8_t byte(uint32_t w, unsigned x)
{
/* nb. bytes are numbered 0 (leftmost, top)
* to 3 (rightmost). */
x = 3 - x;
return (w >> (x * 8)) & 0xff;
}
static uint32_t round_constant(uint32_t i)
{
return Rcon[i] << 24;
}
static uint32_t rot_word(uint32_t w)
{
/* Takes
* word [a0,a1,a2,a3]
* returns
* word [a1,a2,a3,a0]
*
*/
return rotl32(w, 8);
}
#endif
#define word4(a, b, c, d) (((uint32_t)(a) << 24) | ((uint32_t)(b) << 16) | ((uint32_t)(c) << 8) | (d))
#define byte(w, x) ((w >> ((3 - (x)) << 3)) & 0xff)
#define round_constant(i) ((uint32_t)(Rcon[i]) << 24)
#define rot_word(w) rotl32((w), 8)
static uint32_t sub_word(uint32_t w, const uint8_t *sbox)
{
uint8_t a = byte(w, 0),
b = byte(w, 1),
c = byte(w, 2),
d = byte(w, 3);
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
select_u8x4(&a, &b, &c, &d, sbox, 256);
#else
a = sbox[a];
b = sbox[b];
c = sbox[c];
d = sbox[d];
#endif
return word4(a, b, c, d);
}
static void aes_schedule(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
{
size_t i,
nb = AES_BLOCKSZ / 4,
nk = nkey / 4,
n = nb * (ctx->rounds + 1);
uint32_t *w = ctx->ks;
/* First words are just the key. */
for (i = 0; i < nk; i++)
{
w[i] = read32_be(key + i * 4);
}
uint32_t i_div_nk = 1;
uint32_t i_mod_nk = 0;
for (; i < n; i++, i_mod_nk++)
{
uint32_t temp = w[i - 1];
if (i_mod_nk == nk)
{
i_div_nk++;
i_mod_nk = 0;
}
if (i_mod_nk == 0)
temp = sub_word(rot_word(temp), S) ^ round_constant(i_div_nk);
else if (nk > 6 && i_mod_nk == 4)
temp = sub_word(temp, S);
w[i] = w[i - nk] ^ temp;
}
}
void cf_aes_init(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
{
memset(ctx, 0, sizeof *ctx);
switch (nkey)
{
#if CF_AES_MAXROUNDS >= AES128_ROUNDS
case 16:
ctx->rounds = AES128_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
#if CF_AES_MAXROUNDS >= AES192_ROUNDS
case 24:
ctx->rounds = AES192_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
#if CF_AES_MAXROUNDS >= AES256_ROUNDS
case 32:
ctx->rounds = AES256_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
default:
abort();
}
}
static void add_round_key(uint32_t state[4], const uint32_t rk[4])
{
state[0] ^= rk[0];
state[1] ^= rk[1];
state[2] ^= rk[2];
state[3] ^= rk[3];
}
static void sub_block(uint32_t state[4])
{
state[0] = sub_word(state[0], S);
state[1] = sub_word(state[1], S);
state[2] = sub_word(state[2], S);
state[3] = sub_word(state[3], S);
}
static void shift_rows(uint32_t state[4])
{
uint32_t u, v, x, y;
u = word4(byte(state[0], 0),
byte(state[1], 1),
byte(state[2], 2),
byte(state[3], 3));
v = word4(byte(state[1], 0),
byte(state[2], 1),
byte(state[3], 2),
byte(state[0], 3));
x = word4(byte(state[2], 0),
byte(state[3], 1),
byte(state[0], 2),
byte(state[1], 3));
y = word4(byte(state[3], 0),
byte(state[0], 1),
byte(state[1], 2),
byte(state[2], 3));
state[0] = u;
state[1] = v;
state[2] = x;
state[3] = y;
}
static uint32_t gf_poly_mul2(uint32_t x)
{
return
((x & 0x7f7f7f7f) << 1) ^
(((x & 0x80808080) >> 7) * 0x1b);
}
static uint32_t mix_column(uint32_t x)
{
uint32_t x2 = gf_poly_mul2(x);
return x2 ^ rotr32(x ^ x2, 24) ^ rotr32(x, 16) ^ rotr32(x, 8);
}
static void mix_columns(uint32_t state[4])
{
state[0] = mix_column(state[0]);
state[1] = mix_column(state[1]);
state[2] = mix_column(state[2]);
state[3] = mix_column(state[3]);
}
void cf_aes_encrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
assert(ctx->rounds == AES128_ROUNDS ||
ctx->rounds == AES192_ROUNDS ||
ctx->rounds == AES256_ROUNDS);
uint32_t state[4] = {
read32_be(in + 0),
read32_be(in + 4),
read32_be(in + 8),
read32_be(in + 12)
};
const uint32_t *round_keys = ctx->ks;
add_round_key(state, round_keys);
round_keys += 4;
for (uint32_t round = 1; round < ctx->rounds; round++)
{
sub_block(state);
shift_rows(state);
mix_columns(state);
add_round_key(state, round_keys);
round_keys += 4;
}
sub_block(state);
shift_rows(state);
add_round_key(state, round_keys);
write32_be(state[0], out + 0);
write32_be(state[1], out + 4);
write32_be(state[2], out + 8);
write32_be(state[3], out + 12);
}
#if CF_AES_ENCRYPT_ONLY == 0
static const uint8_t S_inv[256] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e,
0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,
0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,
0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,
0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,
0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,
0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,
0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,
0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,
0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,
0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
static void inv_sub_block(uint32_t state[4])
{
state[0] = sub_word(state[0], S_inv);
state[1] = sub_word(state[1], S_inv);
state[2] = sub_word(state[2], S_inv);
state[3] = sub_word(state[3], S_inv);
}
static void inv_shift_rows(uint32_t state[4])
{
uint32_t u, v, x, y;
u = word4(byte(state[0], 0),
byte(state[3], 1),
byte(state[2], 2),
byte(state[1], 3));
v = word4(byte(state[1], 0),
byte(state[0], 1),
byte(state[3], 2),
byte(state[2], 3));
x = word4(byte(state[2], 0),
byte(state[1], 1),
byte(state[0], 2),
byte(state[3], 3));
y = word4(byte(state[3], 0),
byte(state[2], 1),
byte(state[1], 2),
byte(state[0], 3));
state[0] = u;
state[1] = v;
state[2] = x;
state[3] = y;
}
static uint32_t inv_mix_column(uint32_t x)
{
uint32_t x2 = gf_poly_mul2(x),
x4 = gf_poly_mul2(x2),
x9 = x ^ gf_poly_mul2(x4),
x11 = x2 ^ x9,
x13 = x4 ^ x9;
return x ^ x2 ^ x13 ^ rotr32(x11, 24) ^ rotr32(x13, 16) ^ rotr32(x9, 8);
}
static void inv_mix_columns(uint32_t state[4])
{
state[0] = inv_mix_column(state[0]);
state[1] = inv_mix_column(state[1]);
state[2] = inv_mix_column(state[2]);
state[3] = inv_mix_column(state[3]);
}
void cf_aes_decrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
assert(ctx->rounds == AES128_ROUNDS ||
ctx->rounds == AES192_ROUNDS ||
ctx->rounds == AES256_ROUNDS);
uint32_t state[4] = {
read32_be(in + 0),
read32_be(in + 4),
read32_be(in + 8),
read32_be(in + 12)
};
const uint32_t *round_keys = &ctx->ks[ctx->rounds << 2];
add_round_key(state, round_keys);
round_keys -= 4;
for (uint32_t round = ctx->rounds - 1; round != 0; round--)
{
inv_shift_rows(state);
inv_sub_block(state);
add_round_key(state, round_keys);
inv_mix_columns(state);
round_keys -= 4;
}
inv_shift_rows(state);
inv_sub_block(state);
add_round_key(state, round_keys);
write32_be(state[0], out + 0);
write32_be(state[1], out + 4);
write32_be(state[2], out + 8);
write32_be(state[3], out + 12);
}
#else
void cf_aes_decrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
abort();
}
#endif
void cf_aes_finish(cf_aes_context *ctx)
{
mem_clean(ctx, sizeof *ctx);
}
const cf_prp cf_aes = {
.blocksz = AES_BLOCKSZ,
.encrypt = (cf_prp_block) cf_aes_encrypt,
.decrypt = (cf_prp_block) cf_aes_decrypt
};

View File

@@ -0,0 +1,152 @@
/*
* 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

115
external/cifra_AES128-EAX/eax.c vendored Normal file
View File

@@ -0,0 +1,115 @@
/*
* 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/>.
*/
#include "prp.h"
#include "modes.h"
#include "tassert.h"
#include "handy.h"
#include <string.h>
static void cmac_compute_n(cf_cmac_stream *ctx,
uint8_t t,
const uint8_t *input, size_t ninput,
uint8_t out[CF_MAXBLOCK])
{
size_t blocksz = ctx->cmac.prp->blocksz;
assert(blocksz > 0);
uint8_t firstblock[CF_MAXBLOCK];
memset(firstblock, 0, blocksz);
firstblock[blocksz - 1] = t;
cf_cmac_stream_reset(ctx);
if (ninput)
{
cf_cmac_stream_update(ctx, firstblock, blocksz, 0);
cf_cmac_stream_update(ctx, input, ninput, 1);
} else {
cf_cmac_stream_update(ctx, firstblock, blocksz, 1);
}
cf_cmac_stream_final(ctx, out);
}
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, /* the same size as nplain */
uint8_t *tag, size_t ntag)
{
uint8_t NN[CF_MAXBLOCK],
HH[CF_MAXBLOCK],
CC[CF_MAXBLOCK];
cf_cmac_stream cmac;
cf_cmac_stream_init(&cmac, prp, prpctx);
/* NN = OMAC_K^0(N) */
cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
/* HH = OMAC_K^1(H) */
cmac_compute_n(&cmac, 1, header, nheader, HH);
/* C = CTR_K^NN(M) */
cf_ctr ctr;
cf_ctr_init(&ctr, prp, prpctx, NN);
cf_ctr_cipher(&ctr, plain, cipher, nplain);
/* CC = OMAC_K^2(C) */
cmac_compute_n(&cmac, 2, cipher, nplain, CC);
/* Tag = NN ^ CC ^ HH
* T = Tag [ first tau bits ] */
assert(ntag <= prp->blocksz);
for (size_t i = 0; i < ntag; i++)
tag[i] = NN[i] ^ CC[i] ^ HH[i];
}
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) /* the same size as ncipher */
{
uint8_t NN[CF_MAXBLOCK],
HH[CF_MAXBLOCK],
CC[CF_MAXBLOCK];
cf_cmac_stream cmac;
cf_cmac_stream_init(&cmac, prp, prpctx);
/* NN = OMAC_K^0(N) */
cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
/* HH = OMAC_K^1(H) */
cmac_compute_n(&cmac, 1, header, nheader, HH);
/* CC = OMAC_K^2(C) */
cmac_compute_n(&cmac, 2, cipher, ncipher, CC);
uint8_t tt[CF_MAXBLOCK];
assert(ntag && ntag <= prp->blocksz);
for (size_t i = 0; i < ntag; i++)
tt[i] = NN[i] ^ CC[i] ^ HH[i];
if (!mem_eq(tt, tag, ntag))
return 1;
cf_ctr ctr;
cf_ctr_init(&ctr, prp, prpctx, NN);
cf_ctr_cipher(&ctr, cipher, plain, ncipher);
return 0;
}

113
external/cifra_AES128-EAX/gf128.c vendored Normal file
View File

@@ -0,0 +1,113 @@
/*
* 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/>.
*/
#include "cf_config.h"
#include "gf128.h"
#include "bitops.h"
#include <string.h>
void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16])
{
write32_be(in[0], out + 0);
write32_be(in[1], out + 4);
write32_be(in[2], out + 8);
write32_be(in[3], out + 12);
}
void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out)
{
out[0] = read32_be(in + 0);
out[1] = read32_be(in + 4);
out[2] = read32_be(in + 8);
out[3] = read32_be(in + 12);
}
/* out = 2 * in. Arguments may alias. */
void cf_gf128_double(const cf_gf128 in, cf_gf128 out)
{
uint8_t table[2] = { 0x00, 0x87 };
uint32_t borrow = 0;
uint32_t inword;
inword = in[3]; out[3] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[2]; out[2] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[1]; out[1] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[0]; out[0] = (inword << 1) | borrow; borrow = inword >> 31;
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
out[3] ^= select_u8(borrow, table, 2);
#else
out[3] ^= table[borrow];
#endif
}
/* out = 2 * in. Arguments may alias. */
void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out)
{
uint8_t table[2] = { 0x00, 0xe1 };
uint32_t borrow = 0;
uint32_t inword;
inword = in[0]; out[0] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[1]; out[1] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[2]; out[2] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[3]; out[3] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
out[0] ^= select_u8(borrow, table, 2) << 24;
#else
out[0] ^= table[borrow] << 24;
#endif
}
/* out = x + y. Arguments may alias. */
void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
{
out[0] = x[0] ^ y[0];
out[1] = x[1] ^ y[1];
out[2] = x[2] ^ y[2];
out[3] = x[3] ^ y[3];
}
/* out = xy. Arguments may alias. */
void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
{
#if CF_TIME_SIDE_CHANNEL_PROTECTION
cf_gf128 zero = { 0 };
#endif
/* Z_0 = 0^128
* V_0 = Y */
cf_gf128 Z, V;
memset(Z, 0, sizeof Z);
memcpy(V, y, sizeof V);
for (int i = 0; i < 128; i++)
{
uint32_t word = x[i >> 5];
uint8_t bit = (word >> (31 - (i & 31))) & 1;
#if CF_TIME_SIDE_CHANNEL_PROTECTION
select_xor128(Z, zero, V, bit);
#else
if (bit)
xor_words(Z, V, 4);
#endif
cf_gf128_double_le(V, V);
}
memcpy(out, Z, sizeof Z);
}

55
external/cifra_AES128-EAX/gf128.h vendored Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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 GF128_H
#define GF128_H
#include <stddef.h>
#include <stdint.h>
/**
* @brief Operations in GF(2^128).
*
* These implementations are constant time, but relatively slow.
*/
typedef uint32_t cf_gf128[4];
/* Unpack from big-endian bytes into out. */
void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out);
/* Pack in big-endian order into out. */
void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]);
/* out = 2 * in. Arguments may not alias. */
void cf_gf128_double(const cf_gf128 in, cf_gf128 out);
/* out = 2 * in. Arguments may not alias.
* This differs from cf_gf128_double because it interprets the
* block in little endian: the lsb is the msb of the
* first element, the msb is the lsb of the last element.
*
* GCM uses this convention. */
void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out);
/* out = x + y. Arguments may alias. */
void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
/* out = xy. Arguments may alias.
*
* This uses cf_gf128_double_le internally, and is suitable for
* GCM. */
void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
#endif

88
external/cifra_AES128-EAX/handy.h vendored Normal file
View File

@@ -0,0 +1,88 @@
#ifndef HANDY_H
#define HANDY_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/*
* Handy CPP defines and C inline functions.
*/
/* Evaluates to the number of items in array-type variable arr. */
#define ARRAYCOUNT(arr) (sizeof arr / sizeof arr[0])
/* Normal MIN/MAX macros. Evaluate argument expressions only once. */
#ifndef MIN
#define MIN(x, y) \
({ typeof (x) __x = (x); \
typeof (y) __y = (y); \
__x < __y ? __x : __y; })
#endif
#ifndef MAX
#define MAX(x, y) \
({ typeof (x) __x = (x); \
typeof (y) __y = (y); \
__x > __y ? __x : __y; })
#endif
/* Swap two values. Uses GCC type inference magic. */
#ifndef SWAP
#define SWAP(x, y) \
do { \
typeof (x) __tmp = (x); \
(x) = (y); \
(y) = __tmp; \
} while (0)
#endif
/** Stringify its argument. */
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
/* Error handling macros.
*
* These expect a zero = success, non-zero = error convention.
*/
/** Error: return.
*
* If the expression fails, return the error from this function. */
#define ER(expr) do { typeof (expr) err_ = (expr); if (err_) return err_; } while (0)
/** Error: goto.
*
* If the expression fails, goto x_err. Assumes defn of label
* x_err and 'error_type err'. */
#define EG(expr) do { err = (expr); if (err) goto x_err; } while (0)
/** Like memset(ptr, 0, len), but not allowed to be removed by
* compilers. */
static inline void mem_clean(volatile void *v, size_t len)
{
if (len)
{
memset((void *) v, 0, len);
(void) *((volatile uint8_t *) v);
}
}
/** Returns 1 if len bytes at va equal len bytes at vb, 0 if they do not.
* Does not leak length of common prefix through timing. */
static inline unsigned mem_eq(const void *va, const void *vb, size_t len)
{
const volatile uint8_t *a = va;
const volatile uint8_t *b = vb;
uint8_t tmp;
uint8_t diff = 0;
while (len--)
{
tmp = *b++;
diff |= *a++ ^ tmp;
}
return !diff;
}
#endif

121
external/cifra_AES128-EAX/license.txt vendored Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

99
external/cifra_AES128-EAX/modes.c vendored Normal file
View File

@@ -0,0 +1,99 @@
/*
* 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/>.
*/
#include "prp.h"
#include "modes.h"
#include "bitops.h"
#include "blockwise.h"
#include <string.h>
#include "tassert.h"
/* CBC */
void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK])
{
ctx->prp = prp;
ctx->prpctx = prpctx;
memcpy(ctx->block, iv, prp->blocksz);
}
void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
{
uint8_t buf[CF_MAXBLOCK];
size_t nblk = ctx->prp->blocksz;
while (blocks--)
{
xor_bb(buf, input, ctx->block, nblk);
ctx->prp->encrypt(ctx->prpctx, buf, ctx->block);
memcpy(output, ctx->block, nblk);
input += nblk;
output += nblk;
}
}
void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
{
uint8_t buf[CF_MAXBLOCK];
size_t nblk = ctx->prp->blocksz;
while (blocks--)
{
ctx->prp->decrypt(ctx->prpctx, input, buf);
xor_bb(output, buf, ctx->block, nblk);
memcpy(ctx->block, input, nblk);
input += nblk;
output += nblk;
}
}
/* CTR */
void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK])
{
memset(ctx, 0, sizeof *ctx);
ctx->counter_offset = 0;
ctx->counter_width = prp->blocksz;
ctx->prp = prp;
ctx->prpctx = prpctx;
ctx->nkeymat = 0;
memcpy(ctx->nonce, nonce, prp->blocksz);
}
void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width)
{
assert(ctx->prp->blocksz <= offset + width);
ctx->counter_offset = offset;
ctx->counter_width = width;
}
static void ctr_next_block(void *vctx, uint8_t *out)
{
cf_ctr *ctx = vctx;
ctx->prp->encrypt(ctx->prpctx, ctx->nonce, out);
incr_be(ctx->nonce + ctx->counter_offset, ctx->counter_width);
}
void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
{
cf_blockwise_xor(ctx->keymat, &ctx->nkeymat,
ctx->prp->blocksz,
input, output, bytes,
ctr_next_block,
ctx);
}
void cf_ctr_discard_block(cf_ctr *ctx)
{
ctx->nkeymat = 0;
}

560
external/cifra_AES128-EAX/modes.h vendored Normal file
View File

@@ -0,0 +1,560 @@
/*
* 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

64
external/cifra_AES128-EAX/prp.h vendored Normal file
View File

@@ -0,0 +1,64 @@
/*
* 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 PRP_H
#define PRP_H
#include <stddef.h>
#include <stdint.h>
/**
* General block cipher description
* ================================
* This allows us to implement block cipher modes which can work
* with different block ciphers.
*/
/* .. c:type:: cf_prp_block
* Block processing function type.
*
* The `in` and `out` blocks may alias.
*
* :rtype: void
* :param ctx: block cipher-specific context object.
* :param in: input block.
* :param out: output block.
*/
typedef void (*cf_prp_block)(void *ctx, const uint8_t *in, uint8_t *out);
/* .. c:type:: cf_prp
* Describes an PRP in a general way.
*
* .. c:member:: cf_prp.blocksz
* Block size in bytes. Must be no more than :c:macro:`CF_MAXBLOCK`.
*
* .. c:member:: cf_prp.encrypt
* Block encryption function.
*
* .. c:member:: cf_prp.decrypt
* Block decryption function.
*/
typedef struct
{
size_t blocksz;
cf_prp_block encrypt;
cf_prp_block decrypt;
} cf_prp;
/* .. c:macro:: CF_MAXBLOCK
* The maximum block cipher blocksize we support, in bytes.
*/
#define CF_MAXBLOCK 16
#endif

32
external/cifra_AES128-EAX/tassert.h vendored Normal file
View File

@@ -0,0 +1,32 @@
/*
* 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 TASSERT_H
#define TASSERT_H
/* Tiny assert
* -----------
*
* This is an assert(3) definition which doesn't include any
* strings, but just branches to abort(3) on failure.
*/
#ifndef FULL_FAT_ASSERT
# include <stdlib.h>
# define assert(expr) do { if (!(expr)) abort(); } while (0)
#else
# include <assert.h>
#endif
#endif