From: bg Date: Thu, 22 Jan 2015 01:03:49 +0000 (+0100) Subject: +gcm128 X-Git-Url: https://git.cryptolib.org/?a=commitdiff_plain;h=e542ff92d053ecf40b42364a44bc887431cecae2;p=avr-crypto-lib.git +gcm128 --- diff --git a/gcm/gcm128.c b/gcm/gcm128.c new file mode 100644 index 0000000..1f71046 --- /dev/null +++ b/gcm/gcm128.c @@ -0,0 +1,331 @@ +/* gcm128.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2015 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DUMP_LEN_LINE(x, len, line) do { \ + printf("\n\n (DBG <" __FILE__ " %s " #line ">)" #x ":", __func__); \ + cli_hexdump_block((x), (len), 4, 16); \ + uart0_flush(); } while (0) + +#define DUMP_dummy(x, len, v) DUMP_LEN_LINE(x, len, v) +#define DUMP_LEN(x, len) DUMP_dummy(x, len, __LINE__) + + +#define DUMP(x) DUMP_LEN(x, sizeof(x)) + + +#define BLOCK_BYTES GCM128_BLOCK_BYTES +#define BLOCK_BITS GCM128_BLOCK_BITS + +#define COUNT_BYTES GCM128_COUNT_BYTES +#define COUNT_BITS GCM128_COUNT_BITS + +#define POLY_BYTE 0xE1 + + +static uint8_t shift_block_right(void *a) +{ + uint8_t c1 = 0, c2; + uint8_t i = BLOCK_BYTES; + uint8_t *p = a; + do { + c2 = *p & 1; + *p = (*p >> 1) | c1; + p++; + c1 = c2 ? 0x80 : 0; + } while (--i); + return c2; +} + +static void gmul128( + void *dest, + const void *a, + const void *b) +{ + uint8_t c, v[BLOCK_BYTES], t, dummy[BLOCK_BYTES + 1], *(lut[2]); + const uint8_t *x = b; + uint8_t i, j; + memset(dest, 0, BLOCK_BYTES); + memset(dummy, 0, BLOCK_BYTES); + dummy[BLOCK_BYTES] = POLY_BYTE; + memcpy(v, a, BLOCK_BYTES); + lut[0] = dummy; + lut[1] = v; + i = BLOCK_BYTES; + do { + j = 8; + t = *x++; + do { + memxor(dest, lut[t >> 7], BLOCK_BYTES); + t <<= 1; + c = shift_block_right(v); + v[0] ^= dummy[15 + c]; + } while (--j); + } while (--i); +} + +static void ghash128_init(ghash128_ctx_t *ctx) +{ + memset(ctx->tag, 0, 16); +} + +static void ghash128_block( + ghash128_ctx_t *ctx, + const void *block) +{ + uint8_t tmp[BLOCK_BYTES]; + memcpy(tmp, ctx->tag, BLOCK_BYTES); + memxor(tmp, block, BLOCK_BYTES); + gmul128(ctx->tag, tmp, ctx->key); +} + +static void inc32(void *a) +{ + uint8_t c, *p = a; + c = (p[3]++ == 0); + c &= ((p[2] += c) == 0); + c &= ((p[1] += c) == 0); + p[0] +=c; +} + +int8_t gcm128_init( + gcm128_ctx_t *ctx, + const bcdesc_t *cipher, + const void *key, + uint16_t key_length_b, + const void *iv, + uint16_t iv_length_b) +{ + uint8_t r; + uint8_t tmp[BLOCK_BYTES]; + if (bcal_cipher_getBlocksize_b(cipher) != BLOCK_BITS) { + return -1; + } + if ((r = bcal_cipher_init(cipher, key, key_length_b, &ctx->cipher_ctx))) { + printf_P(PSTR("Error: return code: %"PRId8" key length: %"PRId16" <%s %s %d>\n"), r, key_length_b, __FILE__, __func__, __LINE__); + uart0_flush(); + return -2; + } + memset(ctx->ghash_ctx.key, 0, BLOCK_BYTES); + bcal_cipher_enc(ctx->ghash_ctx.key, &ctx->cipher_ctx); + ghash128_init(&ctx->ghash_ctx); + if (iv_length_b == BLOCK_BITS - COUNT_BITS) { + memcpy(ctx->ctr, iv, (BLOCK_BITS - COUNT_BITS) / 8); + memset(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES], 0, COUNT_BYTES - 1); + ctx->ctr[BLOCK_BYTES - 1] = 1; + } else { + uint16_t ctr = iv_length_b / BLOCK_BITS; + while (ctr--) + { + ghash128_block(&ctx->ghash_ctx, iv); + iv = &((uint8_t*)iv)[BLOCK_BYTES]; + } + memset(tmp, 0, BLOCK_BYTES); + memcpy(tmp, iv, (iv_length_b % BLOCK_BITS + 7) / 8); + if (iv_length_b & 7) { + tmp[(iv_length_b % BLOCK_BITS) / 8] &= 0xff << (8 - (iv_length_b & 7)); + } + ghash128_block(&ctx->ghash_ctx, tmp); + memset(tmp, 0, BLOCK_BYTES); + tmp[BLOCK_BYTES - 2] = iv_length_b >> 8; + tmp[BLOCK_BYTES - 1] = iv_length_b & 0xff; + ghash128_block(&ctx->ghash_ctx, tmp); + memcpy(ctx->ctr, ctx->ghash_ctx.tag, BLOCK_BYTES); + ghash128_init(&ctx->ghash_ctx); + } + memcpy(ctx->j0, &ctx->ctr[BLOCK_BYTES - COUNT_BYTES], COUNT_BYTES); + ctx->length_a = 0; + ctx->length_c = 0; + return 0; +} + +void gcm128_add_ad_block( + gcm128_ctx_t *ctx, + const void *block ) +{ + ghash128_block(&ctx->ghash_ctx, block); + ctx->length_a += BLOCK_BITS; +} + +void gcm128_add_ad_final_block( + gcm128_ctx_t *ctx, + const void *block, + uint16_t length_b ) +{ + uint8_t tmp[BLOCK_BYTES]; + while (length_b >= BLOCK_BITS) + { + gcm128_add_ad_block(ctx, block); + length_b -= BLOCK_BITS; + block = &((uint8_t*)block)[BLOCK_BYTES]; + } + if (length_b > 0) { + memset(tmp, 0, BLOCK_BYTES); + memcpy(tmp, block, (length_b + 7) / 8); + if (length_b & 7) { + tmp[length_b / 8] &= 0xff << (8 - (length_b & 7)); + } + ghash128_block(&ctx->ghash_ctx, tmp); + ctx->length_a += length_b; + } +} + +void gcm128_encrypt_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src) +{ + uint8_t tmp[BLOCK_BYTES]; + inc32(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES]); + memcpy(tmp, ctx->ctr, BLOCK_BYTES); + bcal_cipher_enc(tmp, &ctx->cipher_ctx); + memxor(tmp, src, BLOCK_BYTES); + ghash128_block(&ctx->ghash_ctx, tmp); + ctx->length_c += BLOCK_BITS; + if (dest) { + memcpy(dest, tmp, BLOCK_BYTES); + } +} + +void gcm128_encrypt_final_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src, + uint16_t length_b + ) +{ + uint8_t tmp[BLOCK_BYTES]; + while (length_b >= BLOCK_BITS) { + gcm128_encrypt_block(ctx, dest, src); + length_b -= BLOCK_BITS; + if (dest) { + dest = &((uint8_t*)dest)[BLOCK_BYTES]; + } + src = &((uint8_t*)src)[BLOCK_BYTES]; + } + if (length_b > 0) { + inc32(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES]); + memcpy(tmp, ctx->ctr, BLOCK_BYTES); + bcal_cipher_enc(tmp, &ctx->cipher_ctx); + memxor(tmp, src, BLOCK_BYTES); + memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8); + if (length_b & 7) { + tmp[length_b / 8] &= 0xff << (8 - (length_b & 7)); + } + ghash128_block(&ctx->ghash_ctx, tmp); + ctx->length_c += length_b; + if (dest) { + memcpy(dest, tmp, (length_b + 7) / 8); + } + } +} + +void gcm128_decrypt_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src) +{ + uint8_t tmp[BLOCK_BYTES]; + ghash128_block(&ctx->ghash_ctx, src); + inc32(&ctx->ctr[11]); + memcpy(tmp, ctx->ctr, BLOCK_BYTES); + bcal_cipher_enc(tmp, &ctx->cipher_ctx); + memxor(tmp, src, BLOCK_BYTES); + ctx->length_c += BLOCK_BITS; + if (dest) { + memcpy(dest, tmp, BLOCK_BYTES); + } +} + +void gcm128_decrypt_final_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src, + uint16_t length_b) +{ + uint8_t tmp[BLOCK_BYTES]; + while (length_b > BLOCK_BITS) { + gcm128_decrypt_block(ctx, dest, src); + length_b -= BLOCK_BITS; + if (dest) { + dest = &((uint8_t*)dest)[BLOCK_BYTES]; + } + src = &((uint8_t*)src)[BLOCK_BYTES]; + } + if (length_b > 0) { + memcpy(tmp, src, (length_b + 7) / 8); + memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8); + if (length_b & 7) { + tmp[length_b / 8] &= 0xff << (8 - (length_b & 7)); + } + ghash128_block(&ctx->ghash_ctx, tmp); + inc32(&ctx->ctr[11]); + memcpy(tmp, ctx->ctr, BLOCK_BYTES); + bcal_cipher_enc(tmp, &ctx->cipher_ctx); + memxor(tmp, src, BLOCK_BYTES); + memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8); + if (length_b & 7) { + tmp[length_b / 8] &= 0xff << (8 - (length_b & 7)); + } + ctx->length_c += length_b; + if (dest) { + memcpy(dest, tmp, (length_b + 7) / 8); + } + } +} + +void gcm128_finalize(gcm128_ctx_t *ctx, void *tag, uint16_t tag_length_b) +{ + uint8_t tmp[BLOCK_BYTES]; + memset(tmp, 0, BLOCK_BYTES); + tmp[4] = ctx->length_a >> 24; + tmp[5] = ctx->length_a >> 16; + tmp[6] = ctx->length_a >> 8; + tmp[7] = ctx->length_a; + tmp[12] = ctx->length_c >> 24; + tmp[13] = ctx->length_c >> 16; + tmp[14] = ctx->length_c >> 8; + tmp[15] = ctx->length_c; + ghash128_block(&ctx->ghash_ctx, tmp); + memcpy(tmp, ctx->ctr, BLOCK_BYTES - COUNT_BYTES); + memcpy(&tmp[BLOCK_BYTES - COUNT_BYTES], ctx->j0, COUNT_BYTES); + bcal_cipher_enc(tmp, &ctx->cipher_ctx); + bcal_cipher_free(&ctx->cipher_ctx); + memxor(tmp, ctx->ghash_ctx.tag, BLOCK_BYTES); + if (tag_length_b > BLOCK_BITS) { + tag_length_b = BLOCK_BITS; + } + if (tag_length_b & 7) { + tmp[tag_length_b / 8] &= 0xff << (8 - (tag_length_b & 7)); + } + if (tag) { + memcpy(tag, tmp, (tag_length_b + 7) / 8); + } +} diff --git a/gcm/gcm128.h b/gcm/gcm128.h new file mode 100644 index 0000000..755b75a --- /dev/null +++ b/gcm/gcm128.h @@ -0,0 +1,116 @@ +/* gcm128.h */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2015 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GCM_GCM128_H_ +#define GCM_GCM128_H_ + + +/* gcm128.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2015 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +#define GCM128_BLOCK_BYTES 16 +#define GCM128_BLOCK_BITS (GCM128_BLOCK_BYTES * 8) + +#define GCM128_COUNT_BYTES 4 +#define GCM128_COUNT_BITS (GCM128_COUNT_BYTES * 8) + + + +typedef struct { + uint8_t tag[GCM128_BLOCK_BYTES]; + uint8_t key[GCM128_BLOCK_BYTES]; +} ghash128_ctx_t; + +typedef struct { + ghash128_ctx_t ghash_ctx; + bcgen_ctx_t cipher_ctx; + uint8_t ctr[GCM128_BLOCK_BYTES]; + uint8_t j0[GCM128_COUNT_BYTES]; + uint32_t length_a; + uint32_t length_c; +} gcm128_ctx_t; + +int8_t gcm128_init( + gcm128_ctx_t *ctx, + const bcdesc_t *cipher, + const void *key, + uint16_t key_length_b, + const void *iv, + uint16_t iv_length_b); + +void gcm128_add_ad_block( + gcm128_ctx_t *ctx, + const void *block ); + +void gcm128_add_ad_final_block( + gcm128_ctx_t *ctx, + const void *block, + uint16_t length_b ); + +void gcm128_encrypt_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src); + +void gcm128_encrypt_final_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src, + uint16_t length_b); + +void gcm128_decrypt_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src); + +void gcm128_decrypt_final_block( + gcm128_ctx_t *ctx, + void *dest, + const void *src, + uint16_t length_b); + +void gcm128_finalize( + gcm128_ctx_t *ctx, + void *tag, + uint16_t tag_length_b); + +#endif /* GCM_GCM128_H_ */ diff --git a/mkfiles/gcm.mk b/mkfiles/gcm.mk new file mode 100644 index 0000000..2421a38 --- /dev/null +++ b/mkfiles/gcm.mk @@ -0,0 +1,18 @@ +# Makefile for AES +ALGO_NAME := GCM + +# comment out the following line for removement of AES from the build process +BLOCK_CIPHERS += $(ALGO_NAME) + +$(ALGO_NAME)_DIR := gcm/ +$(ALGO_NAME)_INCDIR := memxor/ aes/ gf256mul/ bcal/ +$(ALGO_NAME)_OBJ := gcm128.o \ + aes_enc-asm.o aes_dec-asm.o aes_sbox-asm.o aes_invsbox-asm.o \ + aes_keyschedule-asm.o +$(ALGO_NAME)_TESTBIN := main-gcm-test.o $(CLI_STD) $(BCAL_STD) \ + bcal_aes128.o bcal_aes192.o bcal_aes256.o \ + dump-asm.o dump-decl.o \ + memxor.o +$(ALGO_NAME)_NESSIE_TEST := test nessie +$(ALGO_NAME)_PERFORMANCE_TEST := performance + diff --git a/test_src/main-gcm-test.c b/test_src/main-gcm-test.c new file mode 100644 index 0000000..9834c2e --- /dev/null +++ b/test_src/main-gcm-test.c @@ -0,0 +1,301 @@ +/* main-gcm-test.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2014 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +/* + * GCM test-suit + * +*/ + + +#include "main-test-common.h" + +#include +#include +#include +#include +#include "performance_test.h" + +char *algo_name = "GCM-AES128"; + +/***************************************************************************** + * additional validation-functions * + *****************************************************************************/ + +#define DUMP_LEN(x, len) do { printf("%s", "\n\n" #x ":"); \ + cli_hexdump_block((x), (len), 4, 16); } while (0) + +#define DUMP(x) DUMP_LEN(x, sizeof(x)) + +#define elementsof(t) (sizeof(t) / sizeof(t[0])) + +/***************************************************************************** + * * + *****************************************************************************/ + +const uint8_t zero_block[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t key_b[] PROGMEM = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 +}; + + +const uint8_t ad_block[] PROGMEM = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; + +const uint8_t pt_block[] PROGMEM = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 +}; + +/*****************************************************************************/ + +const uint8_t iv_block[] PROGMEM = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; + +/*****************************************************************************/ + +const uint8_t iv_6[] PROGMEM = { + 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b +}; + +typedef struct { + const void *key; + uint16_t key_length_b; + const void *iv; + uint16_t iv_length_b; + const void *ad; + uint16_t ad_length_b; + const void *pt; + uint16_t pt_length_b; +} test_t; + +const test_t test_set[] PROGMEM = { + { zero_block, 128, zero_block, 96, NULL, 0, NULL, 0 }, + { zero_block, 128, zero_block, 96, NULL, 0, zero_block, 128 }, + { key_b, 128, iv_block, 96, NULL, 0, pt_block, 512 }, + { key_b, 128, iv_block, 96, ad_block, 160, pt_block, 480 }, + { key_b, 128, iv_block, 64, ad_block, 160, pt_block, 480 }, + { key_b, 128, iv_6, sizeof(iv_6) * 8, ad_block, 160, pt_block, 480 }, + + { zero_block, 192, zero_block, 96, NULL, 0, NULL, 0 }, + { zero_block, 192, zero_block, 96, NULL, 0, zero_block, 128 }, + { key_b, 192, iv_block, 96, NULL, 0, pt_block, 512 }, + { key_b, 192, iv_block, 96, ad_block, 160, pt_block, 480 }, + { key_b, 192, iv_block, 64, ad_block, 160, pt_block, 480 }, + { key_b, 192, iv_6, sizeof(iv_6) * 8, ad_block, 160, pt_block, 480 }, + + { zero_block, 256, zero_block, 96, NULL, 0, NULL, 0 }, + { zero_block, 256, zero_block, 96, NULL, 0, zero_block, 128 }, + { key_b, 256, iv_block, 96, NULL, 0, pt_block, 512 }, + { key_b, 256, iv_block, 96, ad_block, 160, pt_block, 480 }, + { key_b, 256, iv_block, 64, ad_block, 160, pt_block, 480 }, + { key_b, 256, iv_6, sizeof(iv_6) * 8, ad_block, 160, pt_block, 480 }, +}; + +/***************************************************************************** + * * + *****************************************************************************/ + + +int8_t gcm128_simple( + const void *key, + const void *iv, + uint16_t iv_length_b, + const void * ad, + uint16_t ad_length_b, + void *dest, + const void *src, + uint16_t src_length_b, + void *tag, + uint8_t tag_length_b) +{ + gcm128_ctx_t ctx; + DUMP_LEN(key, 16); + DUMP_LEN(iv, (iv_length_b + 7) / 8); + DUMP_LEN(ad, (ad_length_b + 7) / 8); + DUMP_LEN(src, (src_length_b + 7) / 8); + if (gcm128_init(&ctx, &aes128_desc, key, 128, iv, iv_length_b)) { + return -1; + } + gcm128_add_ad_final_block(&ctx, ad, ad_length_b); + gcm128_encrypt_final_block(&ctx, dest, src, src_length_b); + gcm128_finalize(&ctx, tag, tag_length_b); + if (dest) { + DUMP_LEN(dest, (src_length_b + 7) / 8); + } + DUMP_LEN(tag, (tag_length_b + 7) / 8); + return 0; +} + +int8_t gcm128_simple_progmem( + const void *key_p, + uint16_t key_length_b, + const void *iv_p, + uint16_t iv_length_b, + const void * ad_p, + uint16_t ad_length_b, + const void *src_p, + uint16_t src_length_b, + void *tag, + uint8_t tag_length_b) +{ + int8_t r; + gcm128_ctx_t ctx; + const bcdesc_t *cipher; + switch (key_length_b) { + case 128: cipher = &aes128_desc; break; + case 192: cipher = &aes192_desc; break; + case 256: cipher = &aes256_desc; break; + default: return -1; + } + { + uint8_t key[key_length_b / 8]; + uint8_t iv[(iv_length_b + 7) / 8]; + memcpy_P(key, key_p, key_length_b / 8); + memcpy_P(iv, iv_p, (iv_length_b + 7) / 8); + if ((r = gcm128_init(&ctx, cipher, key, key_length_b, iv, iv_length_b))) { + printf_P(PSTR("DBG: (Oooops) Error: %"PRId8"\n"), r); + uart0_flush(); + return -1; + } + + } + uint8_t tmp[GCM128_BLOCK_BYTES]; + while (ad_length_b >= GCM128_BLOCK_BITS) { + memcpy_P(tmp, ad_p, GCM128_BLOCK_BYTES); + ad_p = &((uint8_t*)ad_p)[GCM128_BLOCK_BYTES]; + ad_length_b -= GCM128_BLOCK_BITS; + gcm128_add_ad_block(&ctx, tmp); + } + memcpy_P(tmp, ad_p, (ad_length_b + 7) / 8); + gcm128_add_ad_final_block(&ctx, tmp, ad_length_b); + + while (src_length_b >= GCM128_BLOCK_BITS) { + memcpy_P(tmp, src_p, GCM128_BLOCK_BYTES); + src_p = &((uint8_t*)src_p)[GCM128_BLOCK_BYTES]; + src_length_b -= GCM128_BLOCK_BITS; + gcm128_encrypt_block(&ctx, tmp, tmp); +// DUMP(tmp); + } + memcpy_P(tmp, src_p, (src_length_b + 7) / 8); + gcm128_encrypt_final_block(&ctx, tmp, tmp, src_length_b); + if (src_length_b > 0) { +// DUMP_LEN(tmp, (src_length_b + 7) / 8); + } + + gcm128_finalize(&ctx, tag, tag_length_b); + return 0; +} + +void testrun_gcm128(void) +{ + uint8_t key[16]; + uint8_t iv[12]; + uint8_t tag[16]; + uint8_t plain[16]; + uint8_t cipher[16]; + memset(key, 0, sizeof(key)); + memset(iv, 0, sizeof(iv)); + memset(plain, 0, sizeof(plain)); + gcm128_simple(key, iv, 96, NULL, 0, NULL, NULL, 0, tag, 128); + gcm128_simple(key, iv, 96, NULL, 0, cipher, plain, 128, tag, 128); +} + + + +void testrun_gcm128_progmem(void) +{ + test_t t; + uint8_t tag[16]; + uint8_t i; + for (i = 0; i < elementsof(test_set); ++i) { + printf_P(PSTR("== Test %"PRId8" ==\n"), i + 1); + uart0_flush(); + memcpy_P(&t, &test_set[i], sizeof(t)); + gcm128_simple_progmem( + t.key, t.key_length_b, + t.iv, t.iv_length_b, + t.ad, t.ad_length_b, + t.pt, t.pt_length_b, + tag, 128); + DUMP(tag); + puts("\n\n"); + uart0_flush(); + } +} + +/***************************************************************************** + * main * + *****************************************************************************/ + +const char nessie_str[] PROGMEM = "nessie"; +const char test_str[] PROGMEM = "test"; +const char ftest_str[] PROGMEM = "ftest"; +const char gtest_str[] PROGMEM = "gtest"; +const char performance_str[] PROGMEM = "performance"; +const char echo_str[] PROGMEM = "echo"; + +const cmdlist_entry_t cmdlist[] PROGMEM = { +// { nessie_str, NULL, NULL }, + { test_str, NULL, testrun_gcm128_progmem}, +// { ftest_str, NULL, testrun_f32}, +// { gtest_str, NULL, testrun_g32}, +// { performance_str, NULL, testrun_performance_arcfour}, + { echo_str, (void*)1, (void_fpt)echo_ctrl}, + { NULL, NULL, NULL} +}; + +int main(void) { + main_setup(); + + for(;;){ + welcome_msg(algo_name); + cmd_interface(cmdlist); + } + +} + +