Commit fbbf4ca1 authored by Davide Galassi's avatar Davide Galassi

Merge branch 'feature/incremental_cmac' into 'master'

Incremental CMAC

Closes #11

See merge request !13
parents 977b0a55 55189ac5
Pipeline #52083742 passed with stages
in 1 minute and 19 seconds
......@@ -15,12 +15,14 @@
extern "C"{
#endif
#define CRY_CMAC_BLOCK_SIZE 16
struct cry_cmac_ctx {
void *ciph_ctx; /**< Block cipher context */
const struct cry_ciph_itf *ciph_itf; /**< Block cipher interface */
unsigned char k1[16];
unsigned char k2[16];
unsigned char mac[16];
size_t blklen; /**< Pending block size */
unsigned char blk[CRY_CMAC_BLOCK_SIZE]; /**< Pending block */
unsigned char mac[CRY_CMAC_BLOCK_SIZE]; /**< Current MAC */
};
typedef struct cry_cmac_ctx cry_cmac_ctx;
......
#include <cry/cmac.h>
#include <string.h>
#include "misc.h"
static void xor_128(unsigned char *o, const unsigned char *a,
const unsigned char *b)
{
size_t i;
for (i = 0; i < 16; i++)
for (i = 0; i < CRY_CMAC_BLOCK_SIZE; i++)
o[i] = a[i] ^ b[i];
}
static void cbc_compute_subkeys(cry_cmac_ctx *ctx)
static void cbc_compute_subkeys(cry_cmac_ctx *ctx,
unsigned char *k1, unsigned char *k2)
{
unsigned char blank[16] = {0};
unsigned char blank[CRY_CMAC_BLOCK_SIZE] = {0};
unsigned char msb;
size_t i;
unsigned char *k1 = ctx->k1;
unsigned char *k2 = ctx->k2;
ctx->ciph_itf->encrypt(ctx->ciph_ctx, k1, blank, 16);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, k1, blank, CRY_CMAC_BLOCK_SIZE);
msb = (k1[0] & 0x80);
for (i = 0; i < 16; i++) {
for (i = 0; i < CRY_CMAC_BLOCK_SIZE; i++) {
k1[i] <<= 1;
if (i < 15 && ((k1[i + 1] & 0x80) != 0))
if (i < CRY_CMAC_BLOCK_SIZE-1 && ((k1[i + 1] & 0x80) != 0))
k1[i] |= 1;
}
if (msb != 0)
k1[15] ^= 0x87;
k1[CRY_CMAC_BLOCK_SIZE-1] ^= 0x87;
msb = (k1[0] & 0x80);
for (i = 0; i < 16; i++) {
for (i = 0; i < CRY_CMAC_BLOCK_SIZE; i++) {
k2[i] = k1[i] << 1;
if (i < 15 && ((k1[i + 1] & 0x80) != 0))
if (i < CRY_CMAC_BLOCK_SIZE-1 && ((k1[i + 1] & 0x80) != 0))
k2[i] |= 1;
}
if (msb != 0)
k2[15] ^= 0x87;
k2[CRY_CMAC_BLOCK_SIZE-1] ^= 0x87;
}
static void pad(unsigned char *pad, const unsigned char *last, size_t size)
{
size_t i;
for (i = 0; i < 16; i++) {
if (i < size)
pad[i] = last[i];
else if (i == size)
pad[i] = 0x80;
else
pad[i] = 0x00;
}
}
void cry_cmac_init(cry_cmac_ctx *ctx, void *ciph_ctx,
const cry_ciph_itf *ciph_itf,
unsigned char *key, size_t keylen)
......@@ -62,45 +48,68 @@ void cry_cmac_init(cry_cmac_ctx *ctx, void *ciph_ctx,
ctx->ciph_ctx = ciph_ctx;
ctx->ciph_itf = ciph_itf;
ciph_itf->key_set(ciph_ctx, key, keylen);
cbc_compute_subkeys(ctx);
}
void cry_cmac_update(cry_cmac_ctx *ctx, const unsigned char *data, size_t len)
{
unsigned char block[16], last[16], padded[16];
unsigned char block[CRY_CMAC_BLOCK_SIZE];
size_t n, i;
int flag;
n = (len + 15) / 16; /* n is number of rounds */
if (n == 0) {
n = 1;
flag = 0;
} else {
if ((len % 16) == 0)
flag = 1; /* last block is a complete block */
else
flag = 0; /* last block is not complete block */
/* There was an incomplete block */
if (ctx->blklen > 0) {
n = CRY_MIN(len, CRY_CMAC_BLOCK_SIZE - ctx->blklen);
memcpy(ctx->blk + ctx->blklen, data, n);
len -= n;
data += n;
ctx->blklen += n;
if (ctx->blklen < CRY_CMAC_BLOCK_SIZE || len == 0)
return; /* may be the last block */
xor_128(block, ctx->mac, ctx->blk);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, ctx->mac, block, CRY_CMAC_BLOCK_SIZE);
}
if (flag) {
/* last block is complete block */
xor_128(last, &data[16*(n-1)], ctx->k1);
} else {
pad(padded, &data[16*(n-1)], len % 16);
xor_128(last, padded, ctx->k2);
}
/* Compute number of rounds */
n = (len + CRY_CMAC_BLOCK_SIZE-1) / CRY_CMAC_BLOCK_SIZE;
if (n == 0)
return;
n--;
memset(ctx->mac, 0, 16);
for (i = 0; i < (n - 1); i++) {
xor_128(block, ctx->mac, &data[16*i]);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, ctx->mac, block, 16);
/* last block shall be processed in the digest */
for (i = 0; i < n; i++) {
xor_128(block, ctx->mac, &data[CRY_CMAC_BLOCK_SIZE*i]);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, ctx->mac, block, CRY_CMAC_BLOCK_SIZE);
}
xor_128(block, ctx->mac, last);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, ctx->mac, block, 16);
/* last block is not complete block */
ctx->blklen = len % CRY_CMAC_BLOCK_SIZE;
if (ctx->blklen == 0)
ctx->blklen = CRY_CMAC_BLOCK_SIZE;
memcpy(ctx->blk, &data[CRY_CMAC_BLOCK_SIZE*n], ctx->blklen);
}
static void pad(unsigned char *blk, size_t size)
{
size_t i;
blk[size] = 0x80;
for (i = size + 1; i < CRY_CMAC_BLOCK_SIZE; i++)
blk[i] = 0x00;
}
void cry_cmac_digest(cry_cmac_ctx *ctx, unsigned char *mac)
{
unsigned char k1[CRY_CMAC_BLOCK_SIZE], k2[CRY_CMAC_BLOCK_SIZE], last[CRY_CMAC_BLOCK_SIZE];
cbc_compute_subkeys(ctx, k1, k2);
if (ctx->blklen == CRY_CMAC_BLOCK_SIZE) {
xor_128(last, ctx->blk, k1);
} else {
pad(ctx->blk, ctx->blklen);
xor_128(last, ctx->blk, k2);
}
xor_128(ctx->blk, ctx->mac, last);
ctx->ciph_itf->encrypt(ctx->ciph_ctx, ctx->mac, ctx->blk, CRY_CMAC_BLOCK_SIZE);
memcpy(mac, ctx->mac, sizeof(ctx->mac));
}
......@@ -13,16 +13,16 @@ objs := \
memxor_test.o \
base64_test.o \
mpi_test.o \
hmac_test.o \
des_test.o \
aes_test.o \
trivium_test.o \
hill_test.o \
affine_test.o \
crc_test.o \
hmac_test.o \
cmac_test.o \
# md5_test.o \
sha256_test.o \
cmac_test.o \
sum_test.o \
rsa_test.o \
rand_test.o \
......
#include "test.h"
#include <cry/cmac.h>
#include <cry/aes.h>
struct cmac_param {
unsigned int keylen;
unsigned int msglen;
unsigned int maclen;
unsigned char key[256];
unsigned char msg[256];
unsigned char mac[64];
};
static void param_init(struct cmac_param *par, int argc, char *argv[])
{
memset(par, 0, sizeof(*par));
par->keylen = raw_init(par->key, sizeof(par->key), argv[0]);
par->msglen = raw_init(par->msg, sizeof(par->msg), argv[1]);
par->maclen = raw_init(par->mac, sizeof(par->mac), argv[2]);
}
static const struct cry_ciph_itf g_aes_itf = {
NULL, /* init */
NULL, /* clean */
(cry_ciph_key_set_f) cry_aes_key_set,
NULL, /* ivset */
(cry_ciph_encrypt_f) cry_aes_encrypt,
NULL /* decrypt */
};
static void cmac_aes_digest(int argc, char *argv[])
{
struct cmac_param par;
cry_cmac_ctx cmac;
cry_aes_ctx aes;
unsigned char mac[16];
ASSERT(argc == 3);
param_init(&par, argc, argv);
cry_cmac_init(&cmac, &aes, &g_aes_itf, par.key, par.keylen);
cry_cmac_update(&cmac, par.msg, par.msglen);
cry_cmac_digest(&cmac, mac);
ASSERT(memcmp(mac, par.mac, par.maclen) == 0);
}
static void dispatch(int argc, char *argv[])
{
char *test = *argv;
argv++;
argc--;
if (strcmp(test, "cmac_aes_digest") == 0)
cmac_aes_digest(argc, argv);
else
printf("Test '%s' not defined\n", test);
}
#define KEY "0123456789abcdef"
#define MSG "HelloWorld"
#define LEN strlen(MSG)
#define MSG "LoremipsumdolorsitametconsecteturadipiscingelitV"
#define LEN (sizeof(MSG)-1)
#define MAC "\x70\xa7\x85\xad\x19\x62\xa7\x59\x7d\x1f\x0f\x0f\x2c\xfa\xd8\x57"
#define MAC2 "\x3a\x20\x0f\x07\x78\xf8\x57\x42\xd8\x64\x7d\x46\x73\xd5\xb6\xc7"
struct slice {
const unsigned char *ptr;
int len;
};
static void cmac_aes_sliced(struct slice *slices, int nslices,
unsigned char *mac2)
{
cry_cmac_ctx cmac;
cry_aes_ctx aes;
unsigned char mac[16];
int i;
cry_cmac_init(&cmac, &aes, &g_aes_itf, (unsigned char *)KEY, 16);
for (i = 0; i < nslices; i++)
cry_cmac_update(&cmac, slices[i].ptr, slices[i].len);
cry_cmac_digest(&cmac, mac);
ASSERT_EQ_BUF(mac, mac2, 16);
}
/*
* [ Lor emipsumdolors ] [ itametconsectetu ] [ radipiscingelitV ]
*/
static void cmac_aes_first_sliced1(void)
{
struct slice slices[] = {
{ (unsigned char *)MSG, 3 },
{ (unsigned char *)MSG + 3, LEN - 3 }
};
cmac_aes_sliced(slices, 2, (unsigned char *)MAC);
}
/*
* [ Lor emipsumdol ors ] [ itametconsectetu ] [ radipiscingelitV ]
*/
static void cmac_aes_first_sliced2(void)
{
struct slice slices[] = {
{ (unsigned char *)MSG, 3 },
{ (unsigned char *)MSG + 3, 10 },
{ (unsigned char *)MSG + 13, LEN - 13 },
};
cmac_aes_sliced(slices, 3, (unsigned char *)MAC);
}
/*
* [ Loremipsumdolors ] [ ita metconsectetu ] [ radipiscingelitV ]
*/
static void cmac_aes_mid_sliced(void)
{
struct slice slices[] = {
{ (unsigned char *)MSG, 19 },
{ (unsigned char *)MSG + 19, LEN - 19 }
};
cmac_aes_sliced(slices, 2, (unsigned char *)MAC);
}
/*
* [ Loremipsumdolors ] [ itametconsectetu ] [ rad ipiscingelitV ]
*/
static void cmac_aes_last_sliced(void)
{
struct slice slices[] = {
{ (unsigned char *)MSG, 35 },
{ (unsigned char *)MSG + 35, LEN - 35 }
};
cmac_aes_sliced(slices, 2, (unsigned char *)MAC);
}
/*
* [ Loremipsumdolors ] [ ita metconsectetu ] [ rad ]
*/
static void cmac_aes_last_incomplete(void)
{
struct slice slices[] = {
{ (unsigned char *)MSG, 19 },
{ (unsigned char *)MSG + 19, LEN - 19 - 13 }
};
cmac_aes_sliced(slices, 2, (unsigned char *)MAC2);
}
void cmac_test(void)
{
cry_cmac_digest(buf, MSG, strlen(MSG), KEY, strlen(KEY));
printf("* CMAC Tests\n");
run("CMAC-AES First Sliced #1", cmac_aes_first_sliced1, NULL, NULL);
run("CMAC-AES First Sliced #2", cmac_aes_first_sliced2, NULL, NULL);
run("CMAC-AES Mid Sliced #1", cmac_aes_mid_sliced, NULL, NULL);
run("CMAC-AES Last Sliced #1", cmac_aes_last_sliced, NULL, NULL);
run("CMAC-AES Last Incomplete", cmac_aes_last_incomplete, NULL, NULL);
PRINT_HEX("cmac", buf, 16);
func_test("cmac_test.data", dispatch);
printf("\n");
}
CMAC-AES Single Block #1 - empty block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
NULL
bb1d6929e95937287fa37d129b756746
CMAC-AES Single Block #2 - 16 octets block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
6bc1bee22e409f96e93d7e117393172a
070a16b46b4d4144f79bdd9dd04a287c
CMAC-AES Single Block #3 - 16 octets block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
6bc1bee22e409f96e93d7e117393172a
070a16b46b4d4144f79bdd9dd04a287c
CMAC-AES Single Block #4 - 64 octets block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
51f0bebf7e3b9d92fc49741779363cfe
CMAC-AES Single Block #5 - 64 octets block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
51f0bebf7e3b9d92fc49741779363cfe
CMAC-AES Single Block #6 - 64 octets block
cmac_aes_digest
2b7e151628aed2a6abf7158809cf4f3c
6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
51f0bebf7e3b9d92fc49741779363cfe
......@@ -4,13 +4,14 @@ void version_test(void);
void memxor_test(void);
void base64_test(void);
void mpi_test(void);
void hmac_test(void);
void des_test(void);
void aes_test(void);
void trivium_test(void);
void hill_test(void);
void affine_test(void);
void crc_test(void);
void hmac_test(void);
void cmac_test(void);
static int g_runs;
......@@ -28,42 +29,28 @@ struct sub_test {
struct sub_test g_tests[] = {
SUB_TEST(version),
#if 1
SUB_TEST(memxor),
SUB_TEST(base64),
SUB_TEST(mpi),
SUB_TEST(hmac),
SUB_TEST(des),
SUB_TEST(aes),
SUB_TEST(trivium),
SUB_TEST(hill),
SUB_TEST(affine),
SUB_TEST(crc),
#endif
SUB_TEST(hmac),
SUB_TEST(cmac),
#if 0
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(cmac),
TEST_ELEM(sum),
TEST_ELEM(rsa),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
TEST_ELEM(crc),
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(cmac),
TEST_ELEM(sum),
TEST_ELEM(rsa),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
#endif
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment