From: rasky Date: Thu, 30 Sep 2010 11:56:25 +0000 (+0000) Subject: SEC: Add OMAC1/2 message authentication. X-Git-Tag: 2.6.0~22 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=ae3571e0d7273f8642468c6a0958c29c05dc7b2a;p=bertos.git SEC: Add OMAC1/2 message authentication. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4379 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/sec/mac/omac.c b/bertos/sec/mac/omac.c new file mode 100644 index 00000000..570c04bc --- /dev/null +++ b/bertos/sec/mac/omac.c @@ -0,0 +1,193 @@ +/** + * \file + * + * + * \brief OMAC implementation + * \author Giovanni Bajo + */ + +#include "omac.h" +#include +#include + +static void omac_set_key(Mac *ctx_, const void* key, size_t len) +{ + OmacContext *ctx = (OmacContext *)ctx_; + cipher_set_vkey(ctx->c, key, len); +} + +static void omac_begin(Mac *ctx_) +{ + OmacContext *ctx = (OmacContext *)ctx_; + + ctx->acc = 0; + + memset(ctx->Y, 0, cipher_block_len(ctx->c)); + cipher_cbc_begin(ctx->c, ctx->Y); +} + +static void omac_update(Mac *ctx_, const void *data_, size_t len) +{ + OmacContext *ctx = (OmacContext *)ctx_; + size_t blen = cipher_block_len(ctx->c); + const uint8_t *data = (const uint8_t *)data_; + + while (len) + { + ASSERT(ctx->acc <= blen); + if (ctx->acc == blen) + { + cipher_cbc_encrypt(ctx->c, ctx->accum); + ctx->acc = 0; + } + + size_t L = MIN(len, blen - ctx->acc); + memcpy(ctx->accum + ctx->acc, data, L); + data += L; + len -= L; + ctx->acc += L; + } +} + +static void omac_shift_left(uint8_t *L, size_t len) +{ + int firstbit = L[0] >> 7; + size_t i; + + for (i=0; i> 7); + L[i] <<= 1; + + if (firstbit) + { + if (len == 16) + L[i] ^= 0x87; + else if (len == 8) + L[i] ^= 0x1B; + else + ASSERT(0); + } +} + +static void omac_shift_right(uint8_t *L, size_t len) +{ + int firstbit = L[len-1] & 1; + size_t i; + + for (i=len-1; i>0; --i) + L[i] = (L[i] >> 1) | (L[i-1] << 7); + L[i] >>= 1; + + if (firstbit) + { + L[i] |= 0x80; + if (len == 16) + L[len-1] ^= 0x43; + else if (len == 8) + L[len-1] ^= 0x0D; + else + ASSERT(0); + } +} + +static uint8_t *omac1_final(Mac *ctx_) +{ + OmacContext *ctx = (OmacContext *)ctx_; + size_t blen = cipher_block_len(ctx->c); + + uint8_t L[blen]; + memset(L, 0, blen); + cipher_ecb_encrypt(ctx->c, L); + + omac_shift_left(L, blen); + if (ctx->acc < blen) + { + ctx->accum[ctx->acc++] = 0x80; + memset(ctx->accum + ctx->acc, 0, blen - ctx->acc); + omac_shift_left(L, blen); + } + + xor_block(ctx->accum, ctx->accum, L, blen); + cipher_cbc_encrypt(ctx->c, ctx->accum); + return ctx->accum; +} + +static uint8_t *omac2_final(Mac *ctx_) +{ + OmacContext *ctx = (OmacContext *)ctx_; + size_t blen = cipher_block_len(ctx->c); + + uint8_t L[blen]; + memset(L, 0, blen); + cipher_ecb_encrypt(ctx->c, L); + + if (ctx->acc < blen) + { + ctx->accum[ctx->acc++] = 0x80; + memset(ctx->accum + ctx->acc, 0, blen - ctx->acc); + omac_shift_right(L, blen); + } + else + omac_shift_left(L, blen); + + xor_block(ctx->accum, ctx->accum, L, blen); + cipher_cbc_encrypt(ctx->c, ctx->accum); + return ctx->accum; +} + + +/****************************************************************************/ + +static void omac_init(OmacContext *ctx, BlockCipher *c) +{ + ctx->mac.set_key = omac_set_key; + ctx->mac.begin = omac_begin; + ctx->mac.update = omac_update; + ctx->mac.key_len = cipher_key_len(c); + ctx->mac.digest_len = cipher_block_len(c); + ctx->c = c; + + ASSERT(cipher_block_len(c) == 8 || cipher_block_len(c) == 16); + ASSERT(sizeof(ctx->Y) >= cipher_block_len(c)); + ASSERT(sizeof(ctx->accum) >= cipher_block_len(c)); +} + +void omac1_init(OmacContext *ctx, BlockCipher *c) +{ + omac_init(ctx, c); + ctx->mac.final = omac1_final; +} + +void omac2_init(OmacContext *ctx, BlockCipher *c) +{ + omac_init(ctx, c); + ctx->mac.final = omac2_final; +} diff --git a/bertos/sec/mac/omac.h b/bertos/sec/mac/omac.h new file mode 100644 index 00000000..a09d91ac --- /dev/null +++ b/bertos/sec/mac/omac.h @@ -0,0 +1,64 @@ +/** + * \file + * + * + * \brief OMAC implementation + * \author Giovanni Bajo + */ + +#ifndef SEC_MAC_OMAC_H +#define SEC_MAC_OMAC_H + +#include +#include + +typedef struct OmacContext +{ + Mac mac; + BlockCipher *c; + uint8_t Y[16]; + uint8_t accum[16]; + uint8_t acc; +} OmacContext; + +void omac1_init(OmacContext *ctx, BlockCipher *c); +void omac2_init(OmacContext *ctx, BlockCipher *c); + +#define omac1_stackinit(...) \ + ({ OmacContext *ctx = alloca(sizeof(OmacContext)); omac1_init(ctx, ##__VA_ARGS__); &ctx->mac; }) +#define omac2_stackinit(...) \ + ({ OmacContext *ctx = alloca(sizeof(OmacContext)); omac2_init(ctx, ##__VA_ARGS__); &ctx->mac; }) + +int omac_testSetup(void); +int omac_testTearDown(void); +int omac_testRun(void); + +#endif /* SEC_MAC_OMAC_H */ diff --git a/bertos/sec/mac/omac_test.c b/bertos/sec/mac/omac_test.c new file mode 100644 index 00000000..40b81d72 --- /dev/null +++ b/bertos/sec/mac/omac_test.c @@ -0,0 +1,270 @@ + +#include +#include +#include +#include +#include + +int omac_testSetup(void) +{ + kdbg_init(); + return 0; +} + +int omac_testTearDown(void) +{ + return 0; +} + +struct OmacTest +{ + void *key; + size_t klen; + uint8_t *msg; + size_t mlen; + uint8_t digest[16*2]; +}; + +static const struct OmacTest tests1_aes128[] = +{ + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "", 0, + "bb1d6929e95937287fa37d129b756746", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "6bc1bee22e409f96e93d7e117393172a", 16, + "070a16b46b4d4144f79bdd9dd04a287c", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "51f0bebf7e3b9d92fc49741779363cfe", + }, +}; + +static const struct OmacTest tests1_aes192[] = +{ + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "", 0, + "d17ddf46adaacde531cac483de7a9367", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a", 16, + "9e99a7bf31e710900662f65e617c5184", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", 40, + "8a1de5be2eb31aad089a82e6ee908b0e", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "a1d5df0eed790f794d77589659f39a11", + }, +}; + +static const struct OmacTest tests1_aes256[] = +{ + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "", 0, + "028962f61b7bf89efc6b551f4667d983", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a", 16, + "28a7023f452e8f82bd4bf28d8c37c35c", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", 40, + "aaf3d8f1de5640c232f5b169b9c911e6", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "e1992190549f6ed5696a2c056c315410", + }, +}; + +static const struct OmacTest tests2_aes128[] = +{ + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "", 0, + "f6bc6a41f4f84593809e59b719299cfe", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "6bc1bee22e409f96e93d7e117393172a", 16, + "070a16b46b4d4144f79bdd9dd04a287c", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", 40, + "23fdaa0831cd314491ce4b25acb6023b", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", 16, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "51f0bebf7e3b9d92fc49741779363cfe", + }, +}; + +static const struct OmacTest tests2_aes192[] = +{ + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "", 0, + "149f579df2129d45a69266898f55aeb2", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a", 16, + "9e99a7bf31e710900662f65e617c5184", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", 40, + "b35e2d1b73aed49b78bdbdfe61f646df", + }, + { + "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", 24, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "a1d5df0eed790f794d77589659f39a11", + }, +}; + +static const struct OmacTest tests2_aes256[] = +{ + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "", 0, + "47fbde71866eae6080355b5fc7ff704c", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a", 16, + "28a7023f452e8f82bd4bf28d8c37c35c", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411", 40, + "f018e6053611b34bc872d6b7ff24749f", + }, + { + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", 32, + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", 64, + "e1992190549f6ed5696a2c056c315410", + }, +}; + +static void hexunlify(uint8_t *out, const uint8_t *in, size_t len) +{ + #define TO_DEC(x) ((x >= '0' && x <= '9') ? x-'0' : \ + (x >= 'a' && x <= 'f') ? x-'a'+10 : \ + (x >= 'A' && x <= 'F') ? x-'A'+10 : 0) + while (len--) + { + *out++ = TO_DEC(in[0])*16 + TO_DEC(in[1]); + in += 2; + } +} + +static void runTest(Mac *m, const struct OmacTest *t, size_t num) +{ + for (size_t i=0; iklen]; + hexunlify(key, t->key, t->klen); + + uint8_t msg[t->mlen]; + hexunlify(msg, t->msg, t->mlen); + + uint8_t digest[16]; + hexunlify(digest, t->digest, 16); + + mac_set_key(m, key, t->klen); + mac_begin(m); + mac_update(m, msg, t->mlen); + uint8_t *result = mac_final(m); + + ASSERT(memcmp(result, digest, 16) == 0); + } +} + +int omac_testRun(void) +{ + if (1) + { + Mac *m = omac1_stackinit(AES128_stackinit()); + runTest(m, tests1_aes128, countof(tests1_aes128)); + } + + if (1) + { + Mac *m = omac1_stackinit(AES192_stackinit()); + runTest(m, tests1_aes192, countof(tests1_aes192)); + } + + if (1) + { + Mac *m = omac1_stackinit(AES256_stackinit()); + runTest(m, tests1_aes256, countof(tests1_aes256)); + } + + if (1) + { + Mac *m = omac2_stackinit(AES128_stackinit()); + runTest(m, tests2_aes128, countof(tests2_aes128)); + } + + if (1) + { + Mac *m = omac2_stackinit(AES192_stackinit()); + runTest(m, tests2_aes192, countof(tests2_aes192)); + } + + if (1) + { + Mac *m = omac2_stackinit(AES256_stackinit()); + runTest(m, tests2_aes256, countof(tests2_aes256)); + } + + return 0; +} + +TEST_MAIN(omac);