diff --git a/avr-asm-macros.S b/avr-asm-macros.S index afaf78c..9d6ecc6 100644 --- a/avr-asm-macros.S +++ b/avr-asm-macros.S @@ -63,6 +63,7 @@ .endif .endm +/* !warning the pointer will point one below the allocated area! */ .macro stack_alloc size:req, reg1=r30, reg2=r31 in r0, _SFR_IO_ADDR(SREG) in \reg1, _SFR_IO_ADDR(SPL) diff --git a/mkfiles/picipher_c.mk b/mkfiles/picipher_c.mk new file mode 100644 index 0000000..5da4e6c --- /dev/null +++ b/mkfiles/picipher_c.mk @@ -0,0 +1,13 @@ +# Makefile for pi-cipher +ALGO_NAME := PICIPHER_C + +# comment out the following line for removement of noekeon from the build process +AEAD_CIPHERS += $(ALGO_NAME) + +$(ALGO_NAME)_DIR := pi-cipher/ +$(ALGO_NAME)_INCDIR := arcfour/ +$(ALGO_NAME)_OBJ := pi16cipher.o pi16cipher-asm.o pi32cipher.o pi64cipher.o +$(ALGO_NAME)_TESTBIN := main-picipher-test.o arcfour-asm.o $(CLI_STD) performance_test.o +$(ALGO_NAME)_NESSIE_TEST := test nessie +$(ALGO_NAME)_PERFORMANCE_TEST := performance + diff --git a/pi-cipher/pi-cipher.c b/pi-cipher/pi-cipher.c new file mode 100644 index 0000000..bb92f3c --- /dev/null +++ b/pi-cipher/pi-cipher.c @@ -0,0 +1,755 @@ +/* pi-cipher.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) + + 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 "pi-cipher.h" + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define DEBUG 0 + +#if (PI_WORD_SIZE == 16) +# define load_word_little(mem) load_u16_little(mem) +# define store_word_little(mem, val) store_u16_little((mem), (val)) +# define PRI_xw "04"PRIx16 + + +static uint16_t load_u16_little(const void *mem) +{ + uint16_t ret; + const uint8_t *x = (const uint8_t *)mem; + ret = x[0] << 0 + | x[1] << 8; + return ret; +} + +static void store_u16_little(void *mem, uint16_t val) +{ + uint8_t *x = (uint8_t *)mem; + x[0] = val & 0xff; val >>= 8; + x[1] = val & 0xff; +} + +#elif (PI_WORD_SIZE == 32) +# define load_word_little(mem) load_u32_little(mem) +# define store_word_little(mem, val) store_u32_little((mem), (val)) +# define PRI_xw "08"PRIx32 + +static uint32_t load_u32_little(const void *mem) +{ + uint32_t ret; + const uint8_t *x = (const uint8_t *)mem; + ret = (uint32_t)x[0] << 0 + | (uint32_t)x[1] << 8 + | (uint32_t)x[2] << 16 + | (uint32_t)x[3] << 24; + return ret; +} + +static void store_u32_little(void *mem, uint32_t val) +{ + uint8_t *x = (uint8_t *)mem; + x[0] = val & 0xff; val >>= 8; + x[1] = val & 0xff; val >>= 8; + x[2] = val & 0xff; val >>= 8; + x[3] = val & 0xff; +} + +#elif (PI_WORD_SIZE == 64) +# define load_word_little(mem) load_u64_little(mem) +# define store_word_little(mem, val) store_u64_little((mem), (val)) +# define PRI_xw "016"PRIx64 + +static uint64_t load_u64_little(const void *mem) +{ + uint64_t ret; + const uint8_t *x = (const uint8_t *)mem; + ret = (uint64_t)x[0] << 0 + | (uint64_t)x[1] << 8 + | (uint64_t)x[2] << 16 + | (uint64_t)x[3] << 24 + | (uint64_t)x[4] << 32 + | (uint64_t)x[5] << 40 + | (uint64_t)x[6] << 48 + | (uint64_t)x[7] << 56; + return ret; +} + +static void store_u64_little(void *mem, uint64_t val) +{ + uint8_t *x = (uint8_t *)mem; + x[0] = val & 0xff; val >>= 8; + x[1] = val & 0xff; val >>= 8; + x[2] = val & 0xff; val >>= 8; + x[3] = val & 0xff; val >>= 8; + x[4] = val & 0xff; val >>= 8; + x[5] = val & 0xff; val >>= 8; + x[6] = val & 0xff; val >>= 8; + x[7] = val & 0xff; +} + +#endif + + +typedef word_t state_t[4][4]; +const char* PI_CIPHER_NAME_X = XSTR(PI_CIPHER_NAME); + + +#if DEBUG +#include +#include + +size_t dbg_l; +const uint8_t *dbg_x; +uint8_t dump; + + +static +void hexdump_block( + const void *data, + size_t length, + unsigned short indent, + unsigned short width) +{ + unsigned short column = 0; + char f = 0; + while (length--) { + if (column == 0) { + unsigned short i; + if (f) { + putchar('\n'); + } else { + f = 1; + } + for (i = 0; i < indent; ++i) { + putchar(' '); + } + column = width; + } + column -= 1; + printf("%02x ", *((unsigned char *)data)); + data = (void *)((char *)data + 1); + } +} + + + +static void dump_state(const word_t* a) +{ + if (dump || 1) { + printf("\tCIS:\n"); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 0], a[ 1], a[ 2], a[ 3]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 4], a[ 5], a[ 6], a[ 7]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 8], a[ 9], a[10], a[11]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n\n", a[12], a[13], a[14], a[15]); + } +} +#else +#define printf(...) +#endif + + +static word_t rotl(word_t x, uint8_t n) +{ + return (x << n) | (x >> ((PI_WORD_SIZE) - n)); +} + +static void phi( + word_t dest[4], + const word_t x[4], + const word_t c[4], + const uint8_t v[8], + const uint8_t rot[4]) +{ + word_t sum = 0; + uint8_t i; + i = 4; + do { + --i; + sum += x[i]; + } while (i); + i = 4; + do { + --i; + dest[i] = rotl(pgm_read_word(&c[i]) + sum - x[pgm_read_byte(&v[i])], pgm_read_byte(&rot[i]) ); + } while (i); + sum = 0; + i = 4; + do { + --i; + sum ^= dest[i]; + } while (i); + i = 4; + do { + --i; + dest[i] ^= sum; + } while (i); +} + +static const word_t mu_const[4] PROGMEM = PI_MU_CONST; + +static const uint8_t mu_v_const[4] PROGMEM = PI_MU_V_CONST; + +static const uint8_t mu_rot_const[4] PROGMEM = PI_MU_ROT_CONST; + +static const word_t ny_const[4] PROGMEM = PI_NY_CONST; + +static const uint8_t ny_v_const[4] PROGMEM = PI_NY_V_CONST; + +static const uint8_t ny_rot_const[4] PROGMEM = PI_NY_ROT_CONST; + +static const word_t pi_const[8][4] PROGMEM = PI_CONST; + +static void mu( + word_t dest[4], + const word_t x[4]) +{ + word_t t[4]; + phi(t, x, mu_const, mu_v_const, mu_rot_const); + dest[0] = t[2]; + dest[1] = t[3]; + dest[2] = t[0]; + dest[3] = t[1]; +} + +static void ny( + word_t dest[4], + const word_t x[4]) +{ + phi(dest, x, ny_const, ny_v_const, ny_rot_const); +} + +static void sigma( + word_t dest[4], + const word_t x1[4], + const word_t x2[4] ) +{ + dest[3] = x1[0] + x2[0]; + dest[0] = x1[1] + x2[1]; + dest[1] = x1[2] + x2[2]; + dest[2] = x1[3] + x2[3]; +} + +static void ast( + word_t dest[4], + const word_t x[4], + const word_t y[4] ) +{ + word_t a[4], b[4]; + mu(a, x); + ny(b, y); + sigma(dest, a, b); +} + +static void e1( + word_t *dest, + const word_t c[4], + const word_t *i ) +{ + uint8_t n = PI_N - 1; + { + word_t t[4]; + memcpy_P(t, c, sizeof(word_t) * 4); + ast(dest, t, i); + } + do { + i = &i[4]; + ast(&dest[4], dest, i); + dest = &dest[4]; + } while (--n); +} + +static void e2( + word_t *dest, + const word_t c[4], + const word_t *i ) +{ + uint8_t n = PI_N - 1; + { + word_t t[4]; + memcpy_P(t, c, sizeof(word_t) * 4); + ast(&dest[4 * n], &i[4 * n], t); + } + while (n--) { + ast(&dest[4 * n], &i[4 * n], &dest[4 * (n + 1)]); + } +} + +static void pi( + word_t *a ) +{ + uint8_t r = PI_ROUNDS; + word_t t[4 * 4]; + const word_t *c = (const word_t *)pi_const; + do { + e1(t, c, a); + c = &c[4]; + e2(a, c, t); + c = &c[4]; + } while (--r); +} + +static void add_tag( + PI_CTX *ctx, + state_t a ) +{ + uint8_t i; + i = 3; + do { + ctx->tag[i + 0] += a[0][i]; + ctx->tag[i + 4] += a[2][i]; + } while(i--); +} + +static void ctr_trans( + const PI_CTX *ctx, + state_t a, + unsigned long ctr ) +{ + uint64_t t; + int i; + if ((void *)ctx->cis != (void *)a) { + memcpy(a, ctx->cis, sizeof(state_t)); + } + t = ctx->ctr + ctr; + for (i = 0; i * PI_WORD_SIZE < 64; ++i) { + a[0][i] ^= (word_t)t; +# if PI_WORD_SIZE < 64 + t >>= PI_WORD_SIZE; +# endif + } + + pi((word_t*)a); +} + +static void inject_tag( + state_t a, + const word_t x[8] ) +{ + int i; + for (i = 0; i < 4; ++i) { + a[0][i] ^= x[i]; + } + for (; i < 8; ++i) { + a[2][i - 4] ^= x[i]; + } +} + +static void extract_block( + void *block, + state_t a) +{ + int i; + for (i = 0; i < 4; ++i) { + store_word_little(&((word_t *)block)[i], a[0][i]); + } + for (; i < 8; ++i) { + store_word_little(&((word_t *)block)[i], a[2][i - 4]); + } +} + +static void inject_block( + state_t a, + const void *block ) +{ + word_t x; + int i; + for (i = 0; i < 4; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[0][i] ^= x; + } + for (; i < 8; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[2][i - 4] ^= x; + } +} + +static void inject_last_block( + state_t a, + const void *block, + size_t length_b ) +{ + uint8_t t[PI_RATE_BYTES]; + if (length_b >= PI_RATE_BITS) { + /* error */ + printf("ERROR <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + memset(t, 0, sizeof(t)); + memcpy(t, block, (length_b + 7) / 8); + t[length_b / 8] |= 1 << (length_b & 7); + inject_block(a, t); +} + +static void replace_block( + state_t a, + const void *block ) +{ + word_t x; + int i; + for (i = 0; i < 4; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[0][i] = x; + } + for (; i < 8; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[2][i - 4] = x; + } +} + +static void replace_last_block( + state_t a, + const void *block, + size_t length_b ) +{ + uint8_t t[PI_RATE_BYTES]; + if (length_b >= PI_RATE_BITS) { + /* error */ + printf("ERROR <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + extract_block(t, a); + memcpy(t, block, length_b / 8); + if (length_b % 8 != 0) { + t[length_b / 8] &= 0xff << (length_b % 8); + t[length_b / 8] |= ((uint8_t *)block)[length_b / 8]; + } +// t[length_b / 8] ^= 1 << (length_b % 8); + replace_block(a, t); +} + + +int PI_INIT( + PI_CTX *ctx, + const void *key, + size_t key_length_b, + const void *pmn, + size_t pmn_length_b) +{ + int i; + uint8_t setup_buf[PI_IS_BITS / 8]; + if ((key_length_b % 8 != 0) || (pmn_length_b % 8 != 0)) { + return -1; + } + if (key_length_b / 8 + pmn_length_b / 8 + 1 >= PI_IS_BITS / 8) { + return -1; + } + memset(ctx->tag, 0, sizeof(ctx->tag)); + memset(setup_buf, 0, sizeof(setup_buf)); + memcpy(setup_buf, key, key_length_b / 8); + memcpy(&setup_buf[key_length_b / 8], pmn, pmn_length_b / 8); + setup_buf[key_length_b / 8 + pmn_length_b / 8] = 1; + for (i = 0; i < 16; ++i) { + ctx->cis[i / 4][i % 4] = load_word_little(&setup_buf[i * PI_WORD_SIZE / 8]); + } + pi((word_t*)ctx->cis); + ctx->ctr = 0; + for (i = 0; i * PI_WORD_SIZE < 64; ++i) { + ctx->ctr |= (uint64_t)ctx->cis[1][i] << (i * PI_WORD_SIZE); + } + return 0; +} + +void PI_PROCESS_AD_BLOCK( + PI_CTX *ctx, + const void *ad, + unsigned long ad_num ) +{ + state_t a; + ctr_trans(ctx, a, ad_num); + inject_block(a, ad); + pi((word_t*)a); + add_tag(ctx, a); +} + +void PI_PROCESS_AD_LAST_BLOCK( + PI_CTX *ctx, + const void *ad, + size_t ad_length_b, + unsigned long ad_num ) +{ + state_t a; + while (ad_length_b >= PI_AD_BLOCK_LENGTH_BITS) { + PI_PROCESS_AD_BLOCK(ctx, ad, ad_num); + ad_num++; + ad_length_b -= PI_AD_BLOCK_LENGTH_BITS; + ad = &((uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + + ctr_trans(ctx, a, ad_num); + inject_last_block(a, ad, ad_length_b); + pi((word_t*)a); + add_tag(ctx, a); + ctx->ctr += ad_num; + inject_tag(ctx->cis, ctx->tag); + pi((word_t*)ctx->cis); +} + +void PI_ENCRYPT_SMN( + PI_CTX *ctx, + void *c0, + const void *smn) +{ + ctx->ctr++; + ctr_trans(ctx, ctx->cis, 0); + inject_block(ctx->cis, smn); + if (c0) { + extract_block(c0, ctx->cis); + } + pi((word_t*)ctx->cis); + add_tag(ctx, ctx->cis); +} + +void PI_DECRYPT_SMN( + PI_CTX *ctx, + void *smn, + const void *c0) +{ + ctx->ctr++; + ctr_trans(ctx, ctx->cis, 0); + inject_block(ctx->cis, c0); + if (smn) { + extract_block(smn, ctx->cis); + } + replace_block(ctx->cis, c0); + pi((word_t*)ctx->cis); + add_tag(ctx, ctx->cis); +} + +void PI_ENCRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_block(a, src); + if (dest) { + extract_block(dest, a); + } + pi((word_t*)a); + add_tag(ctx, a); +} + +void PI_ENCRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ) +{ + state_t a; + while (length_b >= PI_PT_BLOCK_LENGTH_BITS) { + PI_ENCRYPT_BLOCK(ctx, dest, src, num); + num++; + length_b -= PI_PT_BLOCK_LENGTH_BITS; + src = &((uint8_t*)src)[PI_PT_BLOCK_LENGTH_BYTES]; + if (dest) { + dest = &((uint8_t*)dest)[PI_CT_BLOCK_LENGTH_BYTES]; + } + } + ctr_trans(ctx, a, num); + inject_last_block(a, src, length_b); + if (dest) { + uint8_t tmp[PI_PT_BLOCK_LENGTH_BYTES]; + extract_block(tmp, a); + memcpy(dest, tmp, (length_b + 7) / 8); + } + pi((word_t*)a); + add_tag(ctx, a); +} + +void PI_EXTRACT_TAG( + PI_CTX *ctx, + void *dest ) +{ + uint8_t buf[8 * PI_WORD_SIZE / 8]; + int i; + for (i = 0; i < 8; ++i) { + store_word_little(&buf[i * PI_WORD_SIZE / 8], ctx->tag[i]); + } + memcpy(dest, buf, PI_TAG_BYTES); +} + +void PI_DECRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_block(a, src); + if (dest) { + extract_block(dest, a); + } + replace_block(a, src); + pi((word_t*)a); + add_tag(ctx, a); +} + +#define GET_BIT(buf, addr) ((((uint8_t*)(buf))[(addr) / 8] >> (addr & 7)) & 1) + +void PI_DECRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_B, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_last_block(a, src, length_B * 8); + if (dest) { + uint8_t tmp[PI_PT_BLOCK_LENGTH_BYTES]; + extract_block(tmp, a); + memcpy(dest, tmp, length_B); + } + replace_last_block(a, src, length_B * 8); + pi((word_t*)a); + add_tag(ctx, a); +} + +void PI_ENCRYPT_SIMPLE( + void *cipher, + size_t *cipher_len_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + if (PI_INIT(&ctx, key, key_len_B * 8, nonce_public, nonce_public_len_B * 8)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B * 8, i); + *cipher_len_B = 0; + if (nonce_secret) { + PI_ENCRYPT_SMN(&ctx, cipher, nonce_secret); + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; + while (msg_len_B >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_ENCRYPT_BLOCK(&ctx, cipher, msg, i++); + msg = &((const uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + msg_len_B -= PI_PT_BLOCK_LENGTH_BYTES; + } + PI_ENCRYPT_LAST_BLOCK(&ctx, cipher, msg, msg_len_B * 8, i); + cipher = &((uint8_t*)cipher)[msg_len_B]; + *cipher_len_B += msg_len_B + PI_TAG_BYTES; + PI_EXTRACT_TAG(&ctx, cipher); +} + +int PI_DECRYPT_SIMPLE( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + + unsigned long clen = cipher_len_B, alen = ad_len_B; + uint8_t bck_c[clen], bck_ad[alen]; + memcpy(bck_c, cipher, clen); + memcpy(bck_ad, ad, alen); + + uint8_t tmp_tag[PI_TAG_BYTES]; + if (nonce_secret && (cipher_len_B < PI_CT_BLOCK_LENGTH_BYTES + PI_TAG_BYTES)) { + return -3; + } + if (PI_INIT(&ctx, key, key_len_B * 8, nonce_public, nonce_public_len_B * 8)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return -2; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B * 8, i); + *msg_len_B = 0; + if (nonce_secret) { + PI_DECRYPT_SMN(&ctx, nonce_secret, cipher); + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; + while (cipher_len_B - PI_TAG_BYTES >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_DECRYPT_BLOCK(&ctx, msg, cipher, i++); + msg = &((uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + *msg_len_B += PI_PT_BLOCK_LENGTH_BYTES; + } + PI_DECRYPT_LAST_BLOCK(&ctx, msg, cipher, cipher_len_B - PI_TAG_BYTES, i); + *msg_len_B += cipher_len_B - PI_TAG_BYTES; + cipher = &((uint8_t*)cipher)[cipher_len_B - PI_TAG_BYTES]; + PI_EXTRACT_TAG(&ctx, tmp_tag); + if (memcmp(tmp_tag, cipher, PI_TAG_BYTES)) { +#if DEBUG + printf("DBG: verification failed: clen = %lu; alen = %lu\n", clen, alen); + printf("Key:\n"); + hexdump_block(key, key_len_B, 4, 16); + printf("\nNonce:\n"); + hexdump_block(nonce_public, nonce_public_len_B, 4, 16); + printf("\nAD:\n"); + hexdump_block(bck_ad, alen, 4, 16); + printf("\nCiphertext:\n"); + hexdump_block(bck_c, clen, 4, 16); + printf("\nShould-Tag:\n"); + hexdump_block(cipher, PI_TAG_BYTES, 4, 16); + printf("\nIS-Tag:\n"); + hexdump_block(tmp_tag, PI_TAG_BYTES, 4, 16); + puts(""); +#endif /* DEBUG */ + return -1; + } + return 0; +} diff --git a/pi-cipher/pi-cipher.h b/pi-cipher/pi-cipher.h new file mode 100644 index 0000000..40aeb00 --- /dev/null +++ b/pi-cipher/pi-cipher.h @@ -0,0 +1,210 @@ +/* pi-cipher.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 PI_CIPHER_H_ +#define PI_CIPHER_H_ + +/* please define PI_SIZE acoording to the primitive to implement (pi16cipher, pi32cipher or pi64cipher) */ +/* # define PI_SIZE 16 */ + +#ifdef SUPERCOP +#include "ecrypt-portable.h" +typedef u8 uint8_t; +typedef u16 uint16_t; +typedef u32 uint32_t; +typedef u64 uint64_t; +#else +#include +#endif + +#include + +#if PI_SIZE == 16 +#include "pi16_parameter.h" +#elif PI_SIZE == 32 +#include "pi32_parameter.h" +#elif PI_SIZE == 64 +#include "pi64_parameter.h" +#else +#error please define PI_SIZE +#endif + +#define PI_N 4 + +#define PI_IS_BITS (4 * PI_N * PI_WORD_SIZE) +#define PI_IS_BYTES PI_IS_BITS / 8 + +#define PI_RATE_BITS (PI_IS_BITS / 2) +#define PI_CAPACITY_BITS PI_BITS - PI_RATE_BITS + +#define PI_RATE_BYTES (PI_RATE_BITS / 8) +#define PI_CAPACITY_BYTES (PI_CAPACITY_BITS / 8) + +#define PI_SMN_LENGTH_BITS PI_RATE_BITS +#define PI_SMN_LENGTH_BYTES (PI_RATE_BITS / 8) + +#define PI_AD_BLOCK_LENGTH_BITS PI_RATE_BITS +#define PI_AD_BLOCK_LENGTH_BYTES (PI_AD_BLOCK_LENGTH_BITS / 8) + +#define PI_PT_BLOCK_LENGTH_BITS PI_RATE_BITS +#define PI_PT_BLOCK_LENGTH_BYTES (PI_PT_BLOCK_LENGTH_BITS / 8) + +#define PI_CT_BLOCK_LENGTH_BITS PI_RATE_BITS +#define PI_CT_BLOCK_LENGTH_BYTES (PI_CT_BLOCK_LENGTH_BITS / 8) + +#define PI_ROUNDS 3 + +#define PI_MU_V_CONST { 3, 2, 1, 0 } +#define PI_NY_V_CONST { 1, 0, 3, 2 } + + +#define XSTR(x) STR(x) +#define STR(x) #x + +#define CTX_NAME(x) pi ## x ## _ctx_t +#define INIT_NAME(x) pi ## x ## _init +#define PROCESS_AD_BLOCK_NAME(x) pi ## x ## _process_ad_block +#define PROCESS_AD_LAST_BLOCK_NAME(x) pi ## x ## _process_ad_last_block +#define ENCRYPT_SMN_NAME(x) pi ## x ## _encrypt_smn +#define DECRYPT_SMN_NAME(x) pi ## x ## _decrypt_smn +#define ENCRYPT_BLOCK_NAME(x) pi ## x ## _encrypt_block +#define ENCRYPT_LAST_BLOCK_NAME(x) pi ## x ## _encrypt_last_block +#define EXTRACT_TAG_NAME(x) pi ## x ## _extract_tag +#define DECRYPT_BLOCK_NAME(x) pi ## x ## _decrypt_block +#define DECRYPT_LAST_BLOCK_NAME(x) pi ## x ## _decrypt_last_block +#define ENCRYPT_SIMPLE_NAME(x) pi ## x ## _encrypt_simple +#define DECRYPT_SIMPLE_NAME(x) pi ## x ## _decrypt_simple +#define CIPHER_NAME(x) pi ## x ## cipher +#define CIPHER_NAME_X(x) pi ## x ## _cipher_name + +#define NAME(f,x) f(x) + +#define PI_CTX NAME(CTX_NAME, PI_WORD_SIZE) +#define PI_INIT NAME(INIT_NAME, PI_WORD_SIZE) +#define PI_PROCESS_AD_BLOCK NAME(PROCESS_AD_BLOCK_NAME, PI_WORD_SIZE) +#define PI_PROCESS_AD_LAST_BLOCK NAME(PROCESS_AD_LAST_BLOCK_NAME, PI_WORD_SIZE) +#define PI_ENCRYPT_SMN NAME(ENCRYPT_SMN_NAME, PI_WORD_SIZE) +#define PI_DECRYPT_SMN NAME(DECRYPT_SMN_NAME, PI_WORD_SIZE) +#define PI_ENCRYPT_BLOCK NAME(ENCRYPT_BLOCK_NAME, PI_WORD_SIZE) +#define PI_ENCRYPT_LAST_BLOCK NAME(ENCRYPT_LAST_BLOCK_NAME, PI_WORD_SIZE) +#define PI_EXTRACT_TAG NAME(EXTRACT_TAG_NAME, PI_WORD_SIZE) +#define PI_DECRYPT_BLOCK NAME(DECRYPT_BLOCK_NAME, PI_WORD_SIZE) +#define PI_DECRYPT_LAST_BLOCK NAME(DECRYPT_LAST_BLOCK_NAME, PI_WORD_SIZE) +#define PI_ENCRYPT_SIMPLE NAME(ENCRYPT_SIMPLE_NAME, PI_WORD_SIZE) +#define PI_DECRYPT_SIMPLE NAME(DECRYPT_SIMPLE_NAME, PI_WORD_SIZE) +#define PI_CIPHER_NAME NAME(CIPHER_NAME, PI_WORD_SIZE) +#define PI_CIPHER_NAME_X NAME(CIPHER_NAME_X, PI_WORD_SIZE) + + + +extern const char* PI_CIPHER_NAME_X; + +typedef struct { + word_t cis[4][4]; + word_t tag[8]; + uint64_t ctr; +} PI_CTX; + +int PI_INIT( + PI_CTX *ctx, + const void *key, + size_t key_length_b, + const void *pmn, + size_t pmn_length_b); + +void PI_PROCESS_AD_BLOCK( + PI_CTX *ctx, + const void *ad, + unsigned long ad_num ); + +void PI_PROCESS_AD_LAST_BLOCK( + PI_CTX *ctx, + const void *ad, + size_t ad_length_b, + unsigned long ad_num ); + +void PI_ENCRYPT_SMN( + PI_CTX *ctx, + void *c0, + const void *smn); + +void PI_DECRYPT_SMN( + PI_CTX *ctx, + void *smn, + const void *c0); + +void PI_ENCRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ); + +void PI_ENCRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void PI_EXTRACT_TAG( + PI_CTX *ctx, + void *dest ); + +void PI_DECRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ); + +void PI_DECRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void PI_ENCRYPT_SIMPLE( + void *cipher, + size_t *cipher_len_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +int PI_DECRYPT_SIMPLE( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +#endif /* PI_CIPHER_H_ */ diff --git a/pi-cipher/pi16_parameter.h b/pi-cipher/pi16_parameter.h new file mode 100644 index 0000000..04bf843 --- /dev/null +++ b/pi-cipher/pi16_parameter.h @@ -0,0 +1,19 @@ +/* + * pi16_parameter.h + * + * Created on: 07.09.2015 + * Author: bg + */ + +#ifndef PI16_PARAMETER_H_ +#define PI16_PARAMETER_H_ + +typedef uint16_t word_t; + +#define PI_WORD_SIZE 16 + +#define PI_TAG_BITS 128 +#define PI_TAG_BYTES (PI_TAG_BITS / 8) + + +#endif /* PI16_PARAMETER_H_ */ diff --git a/pi-cipher/pi16cipher-asm.S b/pi-cipher/pi16cipher-asm.S new file mode 100644 index 0000000..aabcb09 --- /dev/null +++ b/pi-cipher/pi16cipher-asm.S @@ -0,0 +1,2017 @@ +/* pi16cipher-asm.S */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2015 Daniel Otte (bg@nerilex.org) + + 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 "avr-asm-macros.S" + + .struct 0 +ctx: +ctx_state: + .struct ctx_state + 4 * 4 * 2 +ctx_tag: + .struct ctx_tag + 4 * 2 * 2 +ctx_ctr: + .struct ctx_ctr + 8 +ctx_end: +ctx_size: + +.text +/* +void phi16( + word_t dest[4], + const word_t x[4], + const word_t c[4], + const uint8_t v[8], + const uint8_t rot[4]) +{ + word_t sum = 0; + uint8_t i; + i = 4; + do { + --i; + sum += x[i]; + } while (i); + i = 4; + do { + --i; + dest[i] = rotl(pgm_read_word(&c[i]) + sum - x[pgm_read_byte(&v[i])], pgm_read_byte(&rot[i]) ); + } while (i); + sum = 0; + i = 4; + do { + --i; + sum ^= dest[i]; + } while (i); + i = 4; + do { + --i; + dest[i] ^= sum; + } while (i); +} + +*/ + +.global phi16 + +/* + r24:r25 - destination + r22:r23 - input + r20:r21 - constants + r18:r19 - drop constants (v) + r16:r17 - rotation constants +*/ +phi16: + movw r28, r24 + movw r26, r22 + movw r6, r16 + ldi r16, 3 + ld r24, X+ + ld r25, X+ +1: + ld r0, X+ + add r24, r0 + ld r0, X+ + adc r25, r0 + dec r16 + brne 1b + sbiw r26, 8 + movw r2, r26 + /* --- */ + ldi r16, 4 +2: + movw r30, r20 + lpm r22, Z+ + lpm r23, Z+ + movw r20, r30 + add r22, r24 + adc r23, r25 + movw r30, r18 + lpm r0, Z+ + movw r18, r30 + movw r26, r2 + add r26, r0 + adc r27, r1 + ld r4, X+ + ld r5, X+ + sub r22, r4 + sbc r23, r5 + movw r30, r6 + lpm r0, Z+ + movw r6, r30 +5: + mov r17, r23 + lsl r17 + rol r22 + rol r23 + dec r0 + brne 5b + /* --- */ + st Y+, r22 + st Y+, r23 + dec r16 + brne 2b + /* --- */ + sbiw r28, 8 + movw r26, r28 + ldi r16, 3 + ld r24, X+ + ld r25, X+ +1: + ld r0, X+ + eor r24, r0 + ld r0, X+ + eor r25, r0 + dec r16 + brne 1b + /* --- */ + ldi r16, 4 +1: + ld r0, Y + eor r0, r24 + st Y+, r0 + ld r0, Y + eor r0, r25 + st Y+, r0 + dec r16 + brne 1b + sbiw r28, 8 + ret + + +/******************************************************************************/ +/* +static void ny( + word_t dest[4], + const word_t x[4]) +{ + phi16(dest, x, ny_const, ny_v_const, ny_rot_const); +} +*/ + +ny16_const: + .word 0xD1CC, 0xCAC9, 0xC6C5, 0xC3B8 + +ny16_v_const: + .byte 1 * 2, 0 * 2, 3 * 2, 2 * 2 + +ny16_rot_const: + .byte 2, 5, 7, 13 + +/******************************************************************************/ +/* +static void mu( + word_t dest[4], + const word_t x[4]) +{ + phi16(dest, x, mu_const, mu_v_const, mu_rot_const); +} +*/ +mu16_const: + .word 0xF0E8, 0xE4E2, 0xE1D8, 0xD4D2 + +mu16_v_const: + .byte 3 * 2, 2 * 2, 1 * 2, 0 * 2 + +mu16_rot_const: + .byte 1, 4, 9, 11 + + +.global ast16 + +ast16: + push_range 2, 7 + push r16 + push r17 + push r28 + push r29 + stack_alloc 8 ; pointer to stack space is stored in Z + adiw r30, 1 + push r20 + push r21 + push r30 + push r31 +mu16: + ldi r16, lo8(mu16_rot_const) + ldi r17, hi8(mu16_rot_const) + ldi r18, lo8(mu16_v_const) + ldi r19, hi8(mu16_v_const) + ldi r20, lo8(mu16_const) + ldi r21, hi8(mu16_const) + rcall phi16 + pop r25 + pop r24 + pop r23 + pop r22 + push r28 + push r29 +ny16: + ldi r16, lo8(ny16_rot_const) + ldi r17, hi8(ny16_rot_const) + ldi r18, lo8(ny16_v_const) + ldi r19, hi8(ny16_v_const) + ldi r20, lo8(ny16_const) + ldi r21, hi8(ny16_const) + rcall phi16 + pop r31 + pop r30 + ldd r16, Z + 0 + ldd r17, Z + 1 + + ldd r18, Z + 3 * 2 + 0 + ldd r19, Z + 3 * 2 + 1 + ldd r20, Y + 1 * 2 + 0 + ldd r21, Y + 1 * 2 + 1 + add r18, r20 + adc r19, r21 + std Z + 0 * 2 + 0, r18 + std Z + 0 * 2 + 1, r19 + + ldd r18, Z + 2 * 2 + 0 + ldd r19, Z + 2 * 2 + 1 + ldd r20, Y + 0 * 2 + 0 + ldd r21, Y + 0 * 2 + 1 + add r18, r20 + adc r19, r21 + std Z + 3 * 2 + 0, r18 + std Z + 3 * 2 + 1, r19 + + ldd r18, Z + 1 * 2 + 0 + ldd r19, Z + 1 * 2 + 1 + ldd r20, Y + 3 * 2 + 0 + ldd r21, Y + 3 * 2 + 1 + add r18, r20 + adc r19, r21 + std Z + 2 * 2 + 0, r18 + std Z + 2 * 2 + 1, r19 + + movw r18, r16 + ldd r20, Y + 2 * 2 + 0 + ldd r21, Y + 2 * 2 + 1 + add r18, r20 + adc r19, r21 + std Z + 1 * 2 + 0, r18 + std Z + 1 * 2 + 1, r19 + + stack_free 8, reg1 = r26, reg2 = r27 + pop r29 + pop r28 + pop r17 + pop r16 + pop_range 2, 7 + ret + +/******************************************************************************/ +/* +void e1_16( + word_t *dest, + const word_t c[4], + const word_t *i ) +{ + uint8_t n = PI_N - 1; + { + word_t t[4]; + memcpy_P(t, c, sizeof(word_t) * 4); + ast16(dest, t, i); + } + do { + i = &i[4]; + ast16(&dest[4], dest, i); + dest = &dest[4]; + } while (--n); +} +*/ + +.global e1_16 + +e1_16: + push_range 8, 10 + movw r8, r20 + movw r30, r22 + stack_alloc 8, reg1=r26, reg2=r27 + adiw r26, 1 + movw r22, r26 + ldi r18, 8 +1: + lpm r0, Z+ + st X+, r0 + dec r18 + brne 1b + /* --- */ + ldi r18, 3 + mov r10, r18 + rcall ast16 +1: + movw r22, r30 + adiw r30, 8 + movw r24, r30 + movw r26, r8 + adiw r26, 8 + movw r20, r26 + movw r8, r26 + rcall ast16 + dec r10 + brne 1b + sbiw r30, 3 * 4 * 2 + /* --- */ + stack_free 8, reg1=r26, reg2=r27 + pop_range 8, 10 + ret + +/******************************************************************************/ +/* +void e2_16( + word_t *dest, + const word_t c[4], + const word_t *i ) +{ + uint8_t n = PI_N - 1; + { + word_t t[4]; + memcpy_P(t, c, sizeof(word_t) * 4); + ast16(&dest[4 * n], &i[4 * n], t); + } + while (n--) { + ast16(&dest[4 * n], &i[4 * n], &dest[4 * (n + 1)]); + } +} +*/ + +.global e2_16 + +e2_16: + push_range 8, 10 + movw r30, r22 + movw r26, r20 + adiw r26, 24 + movw r8, r26 + movw r22, r26 + stack_alloc 8, reg1 = r26, reg2 = r27 + adiw r26, 1 + movw r20, r26 + ldi r18, 8 +1: + lpm r0, Z+ + st X+, r0 + dec r18 + brne 1b + /* --- */ + ldi r18, 3 + mov r10, r18 + adiw r24, 24 + rcall ast16 +1: + movw r20, r30 + sbiw r30, 8 + movw r24, r30 + movw r26, r8 + sbiw r26, 8 + movw r22, r26 + movw r8, r26 + rcall ast16 + dec r10 + brne 1b + /* --- */ + stack_free 8, reg1 = r26, reg2 = r27 + pop_range 8, 10 + ret + + +/******************************************************************************/ +/* +void pi( + word_t *a ) +{ + uint8_t r = PI_ROUNDS; + word_t t[4 * 4]; + const word_t *c = (const word_t *)pi_const; + do { + e1_16(t, c, a); + c = &c[4]; + e2_16(a, c, t); + c = &c[4]; + } while (--r); +} +*/ + +PI_CONST: + .word 0xB4B2, 0xB1AC, 0xAAA9, 0xA6A5 + .word 0xA39C, 0x9A99, 0x9695, 0x938E + .word 0x8D8B, 0x8778, 0x7472, 0x716C + .word 0x6A69, 0x6665, 0x635C, 0x5A59 + .word 0x5655, 0x534E, 0x4D4B, 0x473C + .word 0x3A39, 0x3635, 0x332E, 0x2D2B + .word 0x271E, 0x1D1B, 0x170F, 0xF0E8 + .word 0xE4E2, 0xE1D8, 0xD4D2, 0xD1CC + + +/******************************************************************************/ +/* +void ctr_trans( + const PI_CTX *ctx, + state_t a, + unsigned long ctr ) +{ + uint64_t t; + int i; + if ((void *)ctx->cis != (void *)a) { + memcpy(a, ctx->cis, sizeof(state_t)); + } + t = ctx->ctr + ctr; + for (i = 0; i * PI_WORD_SIZE < 64; ++i) { + a[0][i] ^= (word_t)t; + t >>= PI_WORD_SIZE; + } + pi((word_t*)a); +} +*/ + +.global ctr_trans + +ctr_trans: + push_range 16, 17 + push r28 + push r29 + movw r30, r24 + movw r26, r22 + cp r24, r22 + cpc r25, r23 + breq 2f + ldi r22, 32 +1: + ld r0, Z+ + st X+, r0 + dec r22 + brne 1b + /* --- */ + sbiw r30, 32 + sbiw r26, 32 +2: + movw r16, r18 + movw r18, r20 + clr r20 + clr r21 + movw r22, r20 + adiw r30, ctx_ctr ; Z points at lsb of ctr + ldi r28, 16 ; Y points at r16 + clr r29 + clc + ldi r25, 8 +3: + ld r0, Y+ + ld r24, Z+ + adc r24, r0 + ld r0, X + eor r0, r24 + st X+, r0 + dec r25 + brne 3b + /* --- */ + sbiw r26, 8 + movw r24, r26 + pop r29 + pop r28 + pop_range 16, 17 +; rjmp pi + +/* at the end of pi dest is in Z */ + +.global pi +pi: + push r6 + push r7 + push r16 + push r28 + push r29 + stack_alloc 32, reg1 = r28, reg2 = r29 + adiw r28, 1 + movw r6, r28 + ldi r28, lo8(PI_CONST - 8) + ldi r29, hi8(PI_CONST - 8) + ldi r16, 3 + movw r30, r24 +1: + movw r24, r6 + movw r6, r30 + movw r20, r30 + adiw r28, 8 + movw r22, r28 + rcall e1_16 + + movw r24, r6 + movw r6, r30 + movw r20, r30 + adiw r28, 8 + movw r22, r28 + rcall e2_16 + dec r16 + brne 1b + /* --- */ + stack_free 32, reg1 = r26, reg2 = r27 + pop r29 + pop r28 + pop r16 + pop r7 + pop r6 + ret + + +/******************************************************************************/ +/* +void add_tag( + PI_CTX *ctx, + state_t a ) +{ + uint8_t i; + i = 3; + do { + ctx->tag[i + 0] += a[0][i]; + ctx->tag[i + 4] += a[2][i]; + } while(i--); +} +*/ + +.global add_tag +add_tag: + push r28 + push r29 + movw r30, r24 + adiw r30, ctx_tag + movw r28, r22 + ldi r19, 2 +1: + ldi r18, 4 +2: + ld r24, Y+ + ld r25, Y+ + ldd r22, Z + 0 + ldd r23, Z + 1 + add r24, r22 + adc r25, r23 + st Z+, r24 + st Z+, r25 + dec r18 + brne 2b + adiw r28, 8 + dec r19 + brne 1b + /* --- */ + pop r29 + pop r28 + ret + + +/******************************************************************************/ +/* +void inject_tag( + state_t a, + const word_t x[8] ) +{ + int i; + for (i = 0; i < 4; ++i) { + a[0][i] ^= x[i]; + } + for (; i < 8; ++i) { + a[2][i - 4] ^= x[i]; + } +} +*/ +.global inject_block +.global inject_tag + + +inject_block: +inject_tag: + movw r30, r24 + movw r26, r22 + ldi r23, 2 +1: + ldi r22, 8 +2: + ld r24, Z + ld r25, X+ + eor r24, r25 + st Z+, r24 + dec r22 + brne 2b + adiw r30, 8 + dec r23 + brne 1b + ret + +/******************************************************************************/ +/* +void extract_block( + void *block, + state_t a) +{ + int i; + for (i = 0; i < 4; ++i) { + store_word_little(&((word_t *)block)[i], a[0][i]); + } + for (; i < 8; ++i) { + store_word_little(&((word_t *)block)[i], a[2][i - 4]); + } +} +*/ + +.global extract_block + +extract_block: + movw r26, r24 + movw r30, r22 + ldi r23, 2 +1: + ldi r22, 8 +2: + ld r24, Z+ + st X+, r24 + dec r22 + brne 2b + adiw r30, 8 + dec r23 + brne 1b + ret + + +/******************************************************************************/ +/* +void replace_block( + state_t a, + const void *block ) +{ + word_t x; + int i; + for (i = 0; i < 4; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[0][i] = x; + } + for (; i < 8; ++i) { + x = load_word_little(&((const word_t *)block)[i]); + a[2][i - 4] = x; + } +} +*/ +/* +.global replace_block + +replace_block: + movw r30, r24 + movw r26, r22 + ldi r23, 2 +1: + ldi r22, 8 +2: + ld r24, X+ + st Z+, r24 + dec r22 + brne 2b + adiw r30, 8 + dec r23 + brne 1b + ret +*/ +/******************************************************************************/ +/* +void inject_last_block( + state_t a, + const void *block, + size_t length_Bb ) +{ + uint8_t t[PI_RATE_BYTES]; + if (length_b >= PI_RATE_BITS) { + / * error * / + printf("ERROR <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + memset(t, 0, sizeof(t)); + memcpy(t, block, (length_b + 7) / 8); + t[length_b / 8] |= 1 << (length_b & 7); + inject_block(a, t); +} +*/ + +.global inject_last_block + +inject_last_block: + movw r30, r24 + movw r26, r22 + ldi r23, 2 +1: + ldi r22, 8 +2: + tst r20 + brne 3f + ld r24, Z + ldi r25, 1 + eor r24, r25 + st Z, r24 +return: + ret +3: + dec r20 + ld r25, X+ + ld r24, Z + eor r24, r25 + st Z+, r24 + dec r22 + brne 2b + adiw r30, 8 + dec r23 + brne 1b +; ret ; this should never been reached + +/******************************************************************************/ +/* +void replace_last_block( + state_t a, + const void *block, + size_t length_B ) +{ + uint8_t t[PI_RATE_BYTES]; + if (length_B >= PI_RATE_BYTES) { + / * error * / + printf("ERROR <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + extract_block(t, a); + memcpy(t, block, length_B); + replace_block(a, t); +} +*/ + +.global replace_last_block +.global replace_block + +replace_block: + ldi r20, 32 +replace_last_block: + movw r30, r24 + movw r26, r22 + ldi r23, 2 +1: + ldi r22, 8 +2: + tst r20 + breq return + dec r20 + ld r24, X+ + st Z+, r24 + dec r22 + brne 2b + adiw r30, 8 + dec r23 + brne 1b + ret + +/******************************************************************************/ +/* +int PI_INIT( + PI_CTX *ctx, + const void *key, + size_t key_length_B, + const void *pmn, + size_t pmn_length_B) +{ + int i; + uint8_t setup_buf[PI_IS_BYTES]; + if (key_length_B + pmn_length_B + 1 > PI_IS_BYTES) { + return -1; + } + memset(ctx->tag, 0, sizeof(ctx->tag)); + memset(setup_buf, 0, sizeof(setup_buf)); + memcpy(setup_buf, key, key_length_B); + memcpy(&setup_buf[key_length_B], pmn, pmn_length_B); + setup_buf[key_length_B + pmn_length_B] = 1; + for (i = 0; i < 16; ++i) { + ctx->cis[i / 4][i % 4] = load_word_little(&setup_buf[i * PI_WORD_SIZE / 8]); + } + pi((word_t*)ctx->cis); + ctx->ctr = 0; + for (i = 0; i * PI_WORD_SIZE < 64; ++i) { + ctx->ctr |= (uint64_t)ctx->cis[1][i] << (i * PI_WORD_SIZE); + } + return 0; +} +*/ + +.global pi16_init + +pi16_init: + movw r26, 20 + add r26, r16 + adc r27, r17 + mov r21, r26 ; r21 = key_len + nonce_len + sbiw r26, 32 + brmi 1f +return_error: + ser r24 + ser r25 + ret +1: + push r16 + ldi r17, 32 + 16 - 1 ; state_size + tag_size - 1 + sub r17, r21 ; r17 = rest of state to clear + movw r30, r24 ; Z points at ctx->cis + movw r26, r22 ; X points at key +3: + tst r20 + brne 5f + movw r26, r18 ; set X to pi´oint at nonce +5: + dec r20 + ld r0, X+ + st Z+, r0 + dec r21 + brne 3b + /* --- */ + ldi r21, 1 + st Z+, r21 ; store padding '1' +6: + st Z+, r1 + dec r17 + brne 6b + /* --- */ + movw r24, r30 + sbiw r24, 32 + 16 + rcall pi + movw r26, r30 + adiw r26, 32 + 16 ; X points at ctx->ctr + adiw r30, 8 ; Z points at ctx->cis[1][0] + ldi r24, 8 +1: + ld r0, Z+ + st X+, r0 + dec r24 + brne 1b + pop r16 + clr r25 + ret + + +/******************************************************************************/ +/* +void PI_PROCESS_AD_BLOCK( + PI_CTX *ctx, + const void *ad, + unsigned long ad_num ) +{ + state_t a; + ctr_trans(ctx, a, ad_num); + inject_block(a, ad); + pi((word_t*)a); + add_tag(ctx, a); +} +*/ + +.global pi16_process_ad_block + +pi16_process_ad_block: + push r28 + push r29 + stack_alloc 32, reg1 = r28, reg2 = r29 + adiw r28, 1 + push r24 + push r25 + push r22 + push r23 + movw r22, r28 + rcall ctr_trans + movw r24, r28 + pop r23 + pop r22 + rcall inject_block + movw r24, r28 + rcall pi + movw r22, r28 + pop r25 + pop r24 + rcall add_tag + stack_free 32, reg1 = r28, reg2 = r29 + pop r29 + pop r28 + ret + +/******************************************************************************/ +/* +void PI_PROCESS_AD_LAST_BLOCK( + PI_CTX *ctx, + const void *ad, + size_t ad_length_B, + unsigned long ad_num ) +{ + state_t a; + while (ad_length_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(ctx, ad, ad_num); + ad_num++; + ad_length_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + + ctr_trans(ctx, a, ad_num); + inject_last_block(a, ad, ad_length_B); + pi((word_t*)a); + add_tag(ctx, a); + ctx->ctr += ad_num; + inject_tag(ctx->cis, ctx->tag); + pi((word_t*)ctx->cis); +} +*/ + +.global pi16_process_ad_last_block + +pi16_process_ad_last_block: + push_range 10, 17 + push r28 + push r29 + movw r10, r24 ; ctx + movw r12, r22 ; ad + movw r14, r16 ; lo16(ad_num) + movw r16, r18 ; hi16(ad_num) + movw r28, r20 ; r28:r29 contains ad_length_B +1: + sbiw r28, 16 + brmi 6f + movw r18, r14 + movw r20, r16 + movw r22, r12 + movw r24, r10 + rcall pi16_process_ad_block + ; increment num_counter + sec + adc r14, r1 + adc r15, r1 + adc r16, r1 + adc r17, r1 + ldi r24, 16 + add r12, r24 + adc r13, r1 + rjmp 1b + /* --- */ +6: + adiw r28, 16 + stack_alloc 32, reg1 = r30, reg2 = r31 + adiw r30, 1 + push r28 + movw r28, r30 ; Y points at a (on stack) + movw r18, r14 + movw r20, r16 + movw r22, r28 + movw r24, r10 + rcall ctr_trans + movw r24, r28 + movw r22, r12 + clr r21 + pop r20 + rcall inject_last_block + movw r24, r28 + rcall pi + movw r24, r10 + movw r22, r28 + rcall add_tag + stack_free 32, reg1 = r30, reg2 = r31 + movw r30, r10 + adiw r30, ctx_ctr + clr r0 + movw r18, r0 ; clear top 4 bytes to have 64-bit ad_num in register-file + movw r20, r0 + ldi r28, 14 ; Y points to r14 (ad_num) + clr r29 + ldi r25, 8 +1: + ld r24, Y+ + ld r0, Z + adc r0, r24 + st Z+, r0 + dec r25 + brne 1b + + sbiw r30, 8 + 16 + movw r22, r30 + movw r24, r10 + rcall inject_tag + movw r24, r10 + + pop r29 + pop r28 + pop_range 10, 17 + rjmp pi + +/******************************************************************************/ +/* +void PI_PROCESS_SMN( + PI_CTX *ctx, + void *c0, + const void *smn) +{ + ctx->ctr++; + ctr_trans(ctx, ctx->cis, 0); + inject_block(ctx->cis, smn); + if (c0) { + extract_block(c0, ctx->cis); + } + pi((word_t*)ctx->cis); + add_tag(ctx, ctx->cis); +} +*/ + +.global pi16_encrypt_smn + +pi16_encrypt_smn: + clt +pi16_process_smn: + push_range 12, 17 + movw r12, r24 ; ctx + movw r14, r22 ; c0 + movw r16, r20 ; smn + movw r26, r24 + adiw r26, ctx_ctr + ldi r18, 8 + sec +1: + ld r0, X + adc r0, r1 + st X+, r0 + dec r18 + brne 1b + + movw r22, r24 + clr r0 + movw r20, r0 + movw r18, r0 + rcall ctr_trans + + movw r24, r12 + movw r22, r16 + rcall inject_block + + cp r14, r1 + cpc r15, r1 + breq 4f + + movw r24, r14 + movw r22, r12 + rcall extract_block +4: + brtc 5f + movw r24, r12 + movw r22, r16 + rcall replace_block +5: + movw r24, r12 + rcall pi + + movw r22, r12 + movw r24, r12 + pop_range 12, 17 + rjmp add_tag + +/******************************************************************************/ +/* +void PI_DECRYPT_SMN( + PI_CTX *ctx, + void *smn, + const void *c0) +{ + ctx->ctr++; + ctr_trans(ctx, ctx->cis, 0); + inject_block(ctx->cis, c0); + if (smn) { + extract_block(smn, ctx->cis); + } + replace_block(ctx->cis, c0); + pi((word_t*)ctx->cis); + add_tag(ctx, ctx->cis); +} +*/ + +.global pi16_decrypt_smn + +pi16_decrypt_smn: + set + rjmp pi16_process_smn +/* + push_range 12, 17 + movw r12, r24 ; ctx + movw r14, r22 ; smn + movw r16, r20 ; c0 + movw r26, r24 + adiw r26, ctx_ctr + ldi r18, 8 + sec +1: + ld r0, X + adc r0, r1 + st X+, r0 + dec r18 + brne 1b + + movw r22, r24 + clr r0 + movw r20, r0 + movw r18, r0 + rcall ctr_trans + + movw r24, r12 + movw r22, r16 + rcall inject_block + + cp r14, r1 + cpc r15, r1 + breq 4f + + movw r24, r14 + movw r22, r12 + rcall extract_block + +4: + movw r24, r12 + movw r22, r16 + rcall replace_block + + movw r24, r12 + rcall pi + + movw r22, r12 + movw r24, r12 + pop_range 12, 17 + rjmp add_tag +*/ + +/******************************************************************************/ +/* +void PI_EXTRACT_TAG( + PI_CTX *ctx, + void *dest ) +{ + uint8_t buf[8 * PI_WORD_SIZE / 8]; + int i; + for (i = 0; i < 8; ++i) { + store_word_little(&buf[i * PI_WORD_SIZE / 8], ctx->tag[i]); + } + memcpy(dest, buf, PI_TAG_BYTES); +} +*/ + +.global pi16_extract_tag + +pi16_extract_tag: + movw r30, r24 + movw r26, r22 + adiw r30, ctx_tag + ldi r24, 16 +1: + ld r0, Z+ + st X+, r0 + dec r24 + brne 1b + ret + +/******************************************************************************/ +/* +void PI_ENCRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_block(a, src); + if (dest) { + extract_block(dest, a); + } + pi((word_t*)a); + add_tag(ctx, a); +} +*/ +.global pi16_encrypt_block + +pi16_encrypt_block: + clt +pi16_process_block: + push_range 8, 17 + push r28 + push r29 + stack_alloc 32, reg1 = r28, reg2 = r29 + adiw r28, 1 + movw r8, r24 ; ctx + movw r10, r22 ; dest + movw r12, r20 ; src + + movw r22, r28 + movw r20, r18 + movw r18, r16 + rcall ctr_trans + + movw r24, r30 + movw r22, r12 + rcall inject_block + + cp r10, r1 + cpc r11, r1 + breq 4f + + movw r24, r10 + movw r22, r28 + rcall extract_block + +4: + brtc 5f + movw r24, r28 + movw r22, r12 + rcall replace_block +5: + movw r24, r28 + rcall pi + + movw r22, r28 + movw r24, r8 + rcall add_tag + + stack_free 32, reg1 = r30, reg2 = r31 + pop r29 + pop r28 + pop_range 8, 17 + ret + +/******************************************************************************/ +/* +void PI_DECRYPT_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_block(a, src); + if (dest) { + extract_block(dest, a); + } + replace_block(a, src); + pi((word_t*)a); + add_tag(ctx, a); +} +*/ +.global pi16_decrypt_block + +pi16_decrypt_block: + set + rjmp pi16_process_block +/* + push_range 8, 17 + push r28 + push r29 + stack_alloc 32, reg1 = r28, reg2 = r29 + adiw r28, 1 + movw r8, r24 ; ctx + movw r10, r22 ; dest + movw r12, r20 ; src + + movw r22, r28 + movw r20, r18 + movw r18, r16 + rcall ctr_trans + + movw r24, r30 + movw r22, r12 + rcall inject_block + + cp r10, r1 + cpc r11, r1 + breq 4f + + movw r24, r10 + movw r22, r28 + rcall extract_block + +4: + movw r24, r28 + movw r22, r12 + rcall replace_block + + movw r24, r28 + rcall pi + + movw r22, r28 + movw r24, r8 + rcall add_tag + + stack_free 32, reg1 = r30, reg2 = r31 + pop r29 + pop r28 + pop_range 8, 17 + ret +*/ +/******************************************************************************/ +/* +void PI_ENCRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_B, + unsigned long num ) +{ + state_t a; + while (length_B >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_ENCRYPT_BLOCK(ctx, dest, src, num); + num++; + length_B -= PI_PT_BLOCK_LENGTH_BYTES; + src = &((uint8_t*)src)[PI_PT_BLOCK_LENGTH_BYTES]; + if (dest) { + dest = &((uint8_t*)dest)[PI_CT_BLOCK_LENGTH_BYTES]; + } + } + ctr_trans(ctx, a, num); + inject_last_block(a, src, length_B); + if (dest) { + uint8_t tmp[PI_PT_BLOCK_LENGTH_BYTES]; + extract_block(tmp, a); + memcpy(dest, tmp, length_B); + } + pi((word_t*)a); + add_tag(ctx, a); +} +*/ +.global pi16_encrypt_last_block + +pi16_encrypt_last_block: + clt +pi16_process_last_block: + push r28 + push r29 + push_range 4, 15 + movw r4, r24 ; ctx + movw r6, r22 ; dest + movw r8, r20 ; src + movw r10, r18 ; len + movw r12, r14 ; lo16(num) + movw r14, r16 ; hi16(num) + movw r28, r18 +1: + sbiw r28, 16 + brmi 4f + movw r24, r4 + movw r22, r6 + movw r20, r8 + movw r18, r14 + movw r16, r12 + brts 2f + rcall pi16_encrypt_block + rjmp 3f +2: rcall pi16_decrypt_block +3: + sec + adc r12, r1 + adc r13, r1 + adc r14, r1 + adc r15, r1 + ldi r24, 16 + add r8, r24 + adc r9, r1 + cp r6, r1 + cpc r7, r1 + breq 1b + add r6, r24 + adc r7, r1 + rjmp 1b +4: + stack_alloc 32 + 16, reg1 = r30, reg2 = r31 + adiw r28, 16 + movw r10, r28 + adiw r30, 1 + movw r28, r30 + + movw r24, r4 + movw r22, r28 + movw r20, r14 + movw r18, r12 + rcall ctr_trans + + movw r24, r28 + movw r22, r8 + movw r20, r10 + rcall inject_last_block + + cp r6, r1 + cpc r7, r1 + breq 6f + tst r10 + breq 6f + + movw r24, r28 + adiw r24, 32 + movw r22, r28 + rcall extract_block + movw r30, r28 + adiw r30, 32 + movw r26, r6 + mov r24, r10 +3: + ld r0, Z+ + st X+, r0 + dec r24 + brne 3b +6: + brtc 7f + movw r24, r28 + movw r22, r8 + movw r20, r10 + rcall replace_last_block +7: + movw r24, r28 + rcall pi + + movw r24, r4 + movw r22, r28 + rcall add_tag + + stack_free 32 + 16 + pop_range 4, 15 + pop r29 + pop r28 + ret + +/******************************************************************************/ +/* +void PI_DECRYPT_LAST_BLOCK( + PI_CTX *ctx, + void *dest, + const void *src, + size_t length_B, + unsigned long num ) +{ + state_t a; + ctr_trans(ctx, a, num); + inject_last_block(a, src, length_B); + if (dest) { + uint8_t tmp[PI_PT_BLOCK_LENGTH_BYTES]; + extract_block(tmp, a); + memcpy(dest, tmp, length_B); + } + replace_last_block(a, src, length_B); + pi((word_t*)a); + add_tag(ctx, a); +} +*/ +.global pi16_decrypt_last_block + +pi16_decrypt_last_block: + set + rjmp pi16_process_last_block +/* + push r28 + push r29 + push_range 4, 15 + movw r4, r24 ; ctx + movw r6, r22 ; dest + movw r8, r20 ; src + movw r10, r18 ; len + movw r12, r14 ; lo16(num) + movw r14, r16 ; hi16(num) + movw r28, r18 +1: + sbiw r28, 16 + brmi 2f + movw r24, r4 + movw r22, r6 + movw r20, r8 + movw r18, r14 + ; movw r16, r16 + rcall pi16_encrypt_block + + sec + adc r12, r1 + adc r13, r1 + adc r14, r1 + adc r15, r1 + ldi r24, 16 + add r8, r24 + adc r9, r1 + cp r6, r1 + cpc r7, r1 + breq 1b + add r6, r24 + adc r7, r1 + rjmp 1b +2: + stack_alloc 32 + 16, reg1 = r30, reg2 = r31 + adiw r28, 16 + movw r10, r28 + adiw r30, 1 + movw r28, r30 + + movw r24, r4 + movw r22, r28 + movw r20, r14 + movw r18, r12 + rcall ctr_trans + + movw r24, r28 + movw r22, r8 + movw r20, r10 + rcall inject_last_block + + cp r6, r1 + cpc r7, r1 + breq 6f + tst r10 + breq 6f + + movw r24, r28 + adiw r24, 32 + movw r22, r28 + rcall extract_block + movw r30, r28 + adiw r30, 32 + movw r26, r6 + mov r24, r10 +3: + ld r0, Z+ + st X+, r0 + dec r24 + brne 3b +6: + movw r24, r28 + movw r22, r8 + movw r20, r10 + rcall replace_last_block + + movw r24, r28 + rcall pi + + movw r24, r4 + movw r22, r28 + rcall add_tag + + stack_free 32 + 16 + pop_range 4, 15 + pop r29 + pop r28 + ret +*/ + + +/******************************************************************************/ +/* +void PI_ENCRYPT_SIMPLE( + void *cipher, + size_t *cipher_len_B, + void *tag, + size_t *tag_length_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + if (PI_INIT(&ctx, key, key_len_B, nonce_public, nonce_public_len_B)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B, i); + *cipher_len_B = 0; + if (nonce_secret) { + PI_PROCESS_SMN(&ctx, cipher, nonce_secret); + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; + while (msg_len_B >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_ENCRYPT_BLOCK(&ctx, cipher, msg, i++); + msg = &((const uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + msg_len_B -= PI_PT_BLOCK_LENGTH_BYTES; + } + PI_ENCRYPT_LAST_BLOCK(&ctx, cipher, msg, msg_len_B, i); + *cipher_len_B += msg_len_B; + PI_EXTRACT_TAG(&ctx, tag); + if (tag_length_B) { + *tag_length_B = PI_TAG_BYTES; + } +} +*/ +/* + void *cipher, -- r24:r25 -- Y[16] + size_t *cipher_len_B, -- r22:r23 -- Y[14] + const void *msg, -- r20:r21 -- Y[12] + size_t msg_len_B, -- r18:r19 -- Y[10] + const void *ad, -- r16:r17 -- Y[ 8] + size_t ad_len_B, -- r14:r15 -- Y[ 6] + const void *nonce_secret, -- r12:r13 -- Y[ 4] + const void *nonce_public, -- r10:r11 -- Y[ 2] + size_t nonce_public_len_B, -- r8: r9 -- Y[ 0] + const void *key, -- SP[2] -- Y[22] + size_t key_len_B -- SP[4] -- Y[24] +*/ +.equ cipher, 16 +.equ cipher_len_B, 14 +.equ msg, 12 +.equ msg_len_B, 10 +.equ ad, 8 +.equ ad_len_B, 6 +.equ nonce_secret, 4 +.equ nonce_public, 2 +.equ nonce_public_len_B, 0 +.equ key, 22 +.equ key_len_B, 24 + +.global pi16_encrypt_simple +pi16_encrypt_simple: + push r28 + push r29 + stack_alloc_large ctx_size + 9 * 2, reg1 = r30, reg2 = r31 + adiw r30, 1 + ctx_size + ldi r26, 18 + clr r29 + ldi r28, 8 + +1: + ld r0, Y+ + st Z+, r0 + dec r26 + brne 1b + sbiw r30, 18 + movw r28, r30 ; Y points at var backup + sbiw r30, ctx_size ; Z points at ctx + movw r8, r30 + + movw r24, r8 + ldd r22, Y + key ; load key + ldd r23, Y + key + 1 ; + ldd r20, Y + key_len_B ; load key_len_B + ldd r21, Y + key_len_B + 1 ; + ldd r18, Y + nonce_public ; load nonce_public + ldd r19, Y + nonce_public + 1 ; + ldd r16, Y + nonce_public_len_B ; load nonce_public_len_B + ldd r17, Y + nonce_public_len_B + 1 ; + rcall pi16_init + or r25, 24 + brne encrypt_simple_init_fault + + movw r24, r8 + ldd r22, Y + ad ; load ad + ldd r23, Y + ad + 1 ; + ldd r20, Y + ad_len_B ; ad_len_B + ldd r21, Y + ad_len_B + 1 ; + clr r18 + clr r19 + ldi r16, 1 ; set num = 1 + clr r17 + rcall pi16_process_ad_last_block + + ldd r26, Y + cipher_len_B ; load cipher_len_B + ldd r27, Y + cipher_len_B + 1 ; load cipher_len_B + ldi r16, 16 + st X+, r16 + st X+, r1 ; set cipher_len_B = 0 + ldd r10, Y + cipher ; load *cipher + ldd r11, Y + cipher + 1 + movw r24, r10 + + ldd r20, Y + nonce_secret ; load smn + ldd r21, Y + nonce_secret + 1 + cp r20, r1 + cpc r21, r1 + breq 2f + + sbiw r26, 2 + ldi r16, 32 + st X+, r16 ; store "incermented" cipher counter + movw r22, r10 + movw r24, r8 + rcall pi16_encrypt_smn + movw r24, r10 + adiw r24, 16 +2: + movw r22, r24 + movw r24, r8 + ldd r18, Y + msg_len_B ; load msg_len_B + ldd r19, Y + msg_len_B + 1 ; + ldd r20, Y + msg ; load msg + ldd r21, Y + msg + 1 ; + ldd r26, Y + cipher_len_B ; load cipher_len_B + ldd r27, Y + cipher_len_B + 1 ; load cipher_len_B + ld r16, X + add r16, r18 + st X+, r16 + ld r17, X + adc r17, r19 + st X+, r17 + movw r12, r22 + add r12, r18 + adc r13, r19 + clr r17 + clr r16 + clr r15 + clr r14 + inc r14 ; set num = 1 + rcall pi16_encrypt_last_block + + movw r24, r8 + movw r22, r12 + rcall pi16_extract_tag + + rjmp 1f +; Y must point at var backup! +encrypt_simple_init_fault: + ldd r26, Y + cipher_len_B ; load cipher_len_B + ldd r27, Y + cipher_len_B + 1 ; load cipher_len_B + st X+, r1 + st X+, r1 + +1: + ldi r26, 18 + clr r31 + ldi r30, 8 + +1: + ld r0, Y+ + st Z+, r0 + dec r26 + brne 1b + + stack_free_large ctx_size + 9 * 2 + pop r29 + pop r28 + ret + + +/******************************************************************************/ +/* +int PI_DECRYPT_SIMPLE( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + + unsigned long clen = cipher_len_B, alen = ad_len_B; + uint8_t bck_c[clen], bck_ad[alen]; + memcpy(bck_c, cipher, clen); + memcpy(bck_ad, ad, alen); + + uint8_t tmp_tag[PI_TAG_BYTES]; + if (nonce_secret && (cipher_len_B < PI_CT_BLOCK_LENGTH_BYTES + PI_TAG_BYTES)) { + return -3; + } + if (PI_INIT(&ctx, key, key_len_B, nonce_public, nonce_public_len_B)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return -2; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B, i); + *msg_len_B = 0; + if (nonce_secret) { + PI_DECRYPT_SMN(&ctx, nonce_secret, cipher); + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; + while (cipher_len_B - PI_TAG_BYTES >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_DECRYPT_BLOCK(&ctx, msg, cipher, i++); + msg = &((uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + *msg_len_B += PI_PT_BLOCK_LENGTH_BYTES; + } + PI_DECRYPT_LAST_BLOCK(&ctx, msg, cipher, cipher_len_B - PI_TAG_BYTES, i); + *msg_len_B += cipher_len_B - PI_TAG_BYTES; + cipher = &((uint8_t*)cipher)[cipher_len_B - PI_TAG_BYTES]; + PI_EXTRACT_TAG(&ctx, tmp_tag); + if (memcmp(tmp_tag, cipher, PI_TAG_BYTES)) { +#if DEBUG + printf("DBG: verification failed: clen = %lu; alen = %lu\n", clen, alen); + printf("Key:\n"); + hexdump_block(key, key_len_B, 4, 16); + printf("\nNonce:\n"); + hexdump_block(nonce_public, nonce_public_len_B, 4, 16); + printf("\nAD:\n"); + hexdump_block(bck_ad, alen, 4, 16); + printf("\nCiphertext:\n"); + hexdump_block(bck_c, clen, 4, 16); + printf("\nShould-Tag:\n"); + hexdump_block(cipher, PI_TAG_BYTES, 4, 16); + printf("\nIS-Tag:\n"); + hexdump_block(tmp_tag, PI_TAG_BYTES, 4, 16); + puts(""); +#endif + return -1; + } + return 0; +} +*/ + +/* + void *msg, -- r24:r25 -- Y[16] + size_t *msg_len_B, -- r22:r23 -- Y[14] + void *nonce_secret, -- r20:r21 -- Y[12] + const void *cipher, -- r18:r19 -- Y[10] + size_t cipher_len_B, -- r16:r17 -- Y[ 8] + const void *ad, -- r14:r15 -- Y[ 6] + size_t ad_len_B, -- r12:r13 -- Y[ 4] + const void *nonce_public, -- r10:r11 -- Y[ 2] + size_t nonce_public_len_B, -- r8: r9 -- Y[ 0] + const void *key, -- SP[2] -- Y[22] + size_t key_len_B -- SP[4] -- Y[24] +*/ +.equ msg, 16 +.equ msg_len_B, 14 +.equ nonce_secret, 12 +.equ cipher, 10 +.equ cipher_len_B, 8 +.equ ad, 6 +.equ ad_len_B, 4 +.equ nonce_public, 2 +.equ nonce_public_len_B, 0 +.equ key, 22 +.equ key_len_B, 24 + +.global pi16_decrypt_simple +pi16_decrypt_simple: + push r28 + push r29 + stack_alloc_large ctx_size + 9 * 2, reg1 = r30, reg2 = r31 + adiw r30, 1 + ctx_size + ldi r26, 18 + clr r29 + ldi r28, 8 + +1: + ld r0, Y+ + st Z+, r0 + dec r26 + brne 1b + sbiw r30, 18 + movw r28, r30 ; Y points at var backup + sbiw r30, ctx_size ; Z points at ctx + movw r8, r30 + + movw r24, r8 + ldd r22, Y + key ; load key + ldd r23, Y + key + 1 ; + ldd r20, Y + key_len_B ; load key_len_B + ldd r21, Y + key_len_B + 1 ; + ldd r18, Y + nonce_public ; load nonce_public + ldd r19, Y + nonce_public + 1 ; + ldd r16, Y + nonce_public_len_B ; load nonce_public_len_B + ldd r17, Y + nonce_public_len_B + 1 ; + rcall pi16_init + or r25, 24 + breq 1f + rjmp decrypt_simple_init_fault +1: + + movw r24, r8 + ldd r22, Y + ad ; load ad + ldd r23, Y + ad + 1 ; + ldd r20, Y + ad_len_B ; ad_len_B + ldd r21, Y + ad_len_B + 1 ; + ldi r16, 1 ; set num = 1 + clr r17 + clr r18 + clr r19 + rcall pi16_process_ad_last_block + + ldd r26, Y + cipher_len_B ; load cipher_len_B + ldd r27, Y + cipher_len_B + 1 ; load cipher_len_B + ldd r10, Y + cipher ; load *cipher + ldd r11, Y + cipher + 1 + movw r24, r10 + ldd r22, Y + nonce_secret ; load smn + ldd r23, Y + nonce_secret + 1 + cp r22, r1 + cpc r23, r1 + breq 2f + + movw r20, r10 + movw r24, r8 + rcall pi16_decrypt_smn + movw r24, r10 + adiw r24, 16 + ldd r26, Y + cipher_len_B ; load cipher_len_B + ldd r27, Y + cipher_len_B + 1 ; load cipher_len_B + sbiw r26, 16 +2: + sbiw r26, 16 ; subtract 16 for tag + movw r20, r24 ; transfer cipher + movw r24, r8 + movw r18, r26 + ldd r22, Y + msg ; load msg + ldd r23, Y + msg + 1 ; + ldd r26, Y + msg_len_B ; load msg_len_B + ldd r27, Y + msg_len_B + 1 ; load msg_len_B + st X+, r18 + st X+, r19 + movw r12, r20 + add r12, r18 + adc r13, r19 + clr r17 + clr r16 + clr r15 + clr r14 + inc r14 ; set num = 1 + rcall pi16_decrypt_last_block + + ldi r24, 16 + movw r30, r12 + sbiw r28, ctx_size - ctx_tag + clr r25 +1: + ld r0, Z+ + ld r16, Y+ + eor r0, r16 + or r25, r0 + dec r24 + brne 1b + + adiw r28, ctx_size - ctx_ctr + + tst r25 + brne 1f + push r1 + push r1 + rjmp 2f +1: + ser r24 + ser r25 +; Y must point at var backup! + rjmp 1f +decrypt_simple_init_fault: + ldd r26, Y + msg_len_B ; load cipher_len_B + ldd r27, Y + msg_len_B ; load cipher_len_B + st X+, r1 + st X+, r1 + ser r24 + ser r25 + sbiw r24, 1 +1: + push r24 + push r25 +2: + ldi r26, 18 + clr r31 + ldi r30, 8 + +1: + ld r0, Y+ + st Z+, r0 + dec r26 + brne 1b + + pop r25 + pop r24 + stack_free_large ctx_size + 9 * 2 + pop r29 + pop r28 + ret + + + + + diff --git a/pi-cipher/pi16cipher.c b/pi-cipher/pi16cipher.c new file mode 100644 index 0000000..daf4c1b --- /dev/null +++ b/pi-cipher/pi16cipher.c @@ -0,0 +1,325 @@ +/* pi16cipher.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) + + 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 . +*/ + +#define PI_SIZE 16 + + +#include +#include +#include +#include "pi-cipher.h" + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define DEBUG 0 + +#if (PI_WORD_SIZE == 16) +# define load_word_little(mem) load_u16_little(mem) +# define store_word_little(mem, val) store_u16_little((mem), (val)) +# define PRI_xw "04"PRIx16 + + +#elif (PI_WORD_SIZE == 32) +# define load_word_little(mem) load_u32_little(mem) +# define store_word_little(mem, val) store_u32_little((mem), (val)) +# define PRI_xw "08"PRIx32 + +static uint32_t load_u32_little(const void *mem) +{ + uint32_t ret; + const uint8_t *x = (const uint8_t *)mem; + ret = (uint32_t)x[0] << 0 + | (uint32_t)x[1] << 8 + | (uint32_t)x[2] << 16 + | (uint32_t)x[3] << 24; + return ret; +} + +static void store_u32_little(void *mem, uint32_t val) +{ + uint8_t *x = (uint8_t *)mem; + x[0] = val & 0xff; val >>= 8; + x[1] = val & 0xff; val >>= 8; + x[2] = val & 0xff; val >>= 8; + x[3] = val & 0xff; +} + +#elif (PI_WORD_SIZE == 64) +# define load_word_little(mem) load_u64_little(mem) +# define store_word_little(mem, val) store_u64_little((mem), (val)) +# define PRI_xw "016"PRIx64 + +static uint64_t load_u64_little(const void *mem) +{ + uint64_t ret; + const uint8_t *x = (const uint8_t *)mem; + ret = (uint64_t)x[0] << 0 + | (uint64_t)x[1] << 8 + | (uint64_t)x[2] << 16 + | (uint64_t)x[3] << 24 + | (uint64_t)x[4] << 32 + | (uint64_t)x[5] << 40 + | (uint64_t)x[6] << 48 + | (uint64_t)x[7] << 56; + return ret; +} + +static void store_u64_little(void *mem, uint64_t val) +{ + uint8_t *x = (uint8_t *)mem; + x[0] = val & 0xff; val >>= 8; + x[1] = val & 0xff; val >>= 8; + x[2] = val & 0xff; val >>= 8; + x[3] = val & 0xff; val >>= 8; + x[4] = val & 0xff; val >>= 8; + x[5] = val & 0xff; val >>= 8; + x[6] = val & 0xff; val >>= 8; + x[7] = val & 0xff; +} + +#endif + + +typedef word_t state_t[4][4]; +const char* PI_CIPHER_NAME_X = XSTR(PI_CIPHER_NAME); + + +#if DEBUG +#include +#include + +size_t dbg_l; +const uint8_t *dbg_x; +uint8_t dump; + + +static +void hexdump_block( + const void *data, + size_t length, + unsigned short indent, + unsigned short width) +{ + unsigned short column = 0; + char f = 0; + while (length--) { + if (column == 0) { + unsigned short i; + if (f) { + putchar('\n'); + } else { + f = 1; + } + for (i = 0; i < indent; ++i) { + putchar(' '); + } + column = width; + } + column -= 1; + printf("%02x ", *((unsigned char *)data)); + data = (void *)((char *)data + 1); + } +} + +//static +void dump_state(const word_t* a) +{ + if (dump || 1) { + printf("\tCIS:\n"); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 0], a[ 1], a[ 2], a[ 3]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 4], a[ 5], a[ 6], a[ 7]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n", a[ 8], a[ 9], a[10], a[11]); + printf("\t%"PRI_xw" %"PRI_xw" %"PRI_xw" %"PRI_xw"\n\n", a[12], a[13], a[14], a[15]); + } +} +#else +#define printf(...) +#endif + +void pi( + word_t *a ); + +void add_tag( + PI_CTX *ctx, + state_t a ); + +void ctr_trans( + const PI_CTX *ctx, + state_t a, + uint32_t ctr ); + +void inject_tag( + state_t a, + const word_t x[8] ); + + +void extract_block( + void *block, + state_t a); + +void inject_block( + state_t a, + const void *block ); + +void inject_last_block( + state_t a, + const void *block, + size_t length_B ); + +void replace_block( + state_t a, + const void *block ); + +void replace_last_block( + state_t a, + const void *block, + size_t length_B ); +/* +void PI_ENCRYPT_SIMPLE( + void *cipher, + size_t *cipher_len_B, + void *tag, + size_t *tag_length_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + if (PI_INIT(&ctx, key, key_len_B, nonce_public, nonce_public_len_B)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B, i); + *cipher_len_B = 0; + if (nonce_secret) { + PI_ENCRYPT_SMN(&ctx, cipher, nonce_secret); + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; +/ * + while (msg_len_B >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_ENCRYPT_BLOCK(&ctx, cipher, msg, i++); + msg = &((const uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + *cipher_len_B += PI_CT_BLOCK_LENGTH_BYTES; + msg_len_B -= PI_PT_BLOCK_LENGTH_BYTES; + } +* / + PI_ENCRYPT_LAST_BLOCK(&ctx, cipher, msg, msg_len_B, i); + *cipher_len_B += msg_len_B; + PI_EXTRACT_TAG(&ctx, tag); + if (tag_length_B) { + *tag_length_B = PI_TAG_BYTES; + } +} +*/ +/* +int PI_DECRYPT_SIMPLE( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ) +{ + unsigned i; + PI_CTX ctx; + + unsigned long clen = cipher_len_B, alen = ad_len_B; + uint8_t bck_c[clen], bck_ad[alen]; + memcpy(bck_c, cipher, clen); + memcpy(bck_ad, ad, alen); + + uint8_t tmp_tag[PI_TAG_BYTES]; + if (nonce_secret && (cipher_len_B < PI_CT_BLOCK_LENGTH_BYTES + PI_TAG_BYTES)) { + return -3; + } + if (PI_INIT(&ctx, key, key_len_B, nonce_public, nonce_public_len_B)) { + printf("ERROR! <%s %s %d>\n", __FILE__, __func__, __LINE__); + return -2; + } + i = 1; + while (ad_len_B >= PI_AD_BLOCK_LENGTH_BYTES) { + PI_PROCESS_AD_BLOCK(&ctx, ad, i++); + ad_len_B -= PI_AD_BLOCK_LENGTH_BYTES; + ad = &((const uint8_t*)ad)[PI_AD_BLOCK_LENGTH_BYTES]; + } + PI_PROCESS_AD_LAST_BLOCK(&ctx, ad, ad_len_B, i); + *msg_len_B = 0; + if (nonce_secret) { + PI_DECRYPT_SMN(&ctx, nonce_secret, cipher); + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + } + i = 1; + while (cipher_len_B - PI_TAG_BYTES >= PI_PT_BLOCK_LENGTH_BYTES) { + PI_DECRYPT_BLOCK(&ctx, msg, cipher, i++); + msg = &((uint8_t*)msg)[PI_PT_BLOCK_LENGTH_BYTES]; + cipher = &((uint8_t*)cipher)[PI_CT_BLOCK_LENGTH_BYTES]; + cipher_len_B -= PI_CT_BLOCK_LENGTH_BYTES; + *msg_len_B += PI_PT_BLOCK_LENGTH_BYTES; + } + PI_DECRYPT_LAST_BLOCK(&ctx, msg, cipher, cipher_len_B - PI_TAG_BYTES, i); + *msg_len_B += cipher_len_B - PI_TAG_BYTES; + cipher = &((uint8_t*)cipher)[cipher_len_B - PI_TAG_BYTES]; + PI_EXTRACT_TAG(&ctx, tmp_tag); + if (memcmp(tmp_tag, cipher, PI_TAG_BYTES)) { +#if DEBUG + printf("DBG: verification failed: clen = %lu; alen = %lu\n", clen, alen); + printf("Key:\n"); + hexdump_block(key, key_len_B, 4, 16); + printf("\nNonce:\n"); + hexdump_block(nonce_public, nonce_public_len_B, 4, 16); + printf("\nAD:\n"); + hexdump_block(bck_ad, alen, 4, 16); + printf("\nCiphertext:\n"); + hexdump_block(bck_c, clen, 4, 16); + printf("\nShould-Tag:\n"); + hexdump_block(cipher, PI_TAG_BYTES, 4, 16); + printf("\nIS-Tag:\n"); + hexdump_block(tmp_tag, PI_TAG_BYTES, 4, 16); + puts(""); +#endif + return -1; + } + return 0; +} +*/ diff --git a/pi-cipher/pi16cipher.h b/pi-cipher/pi16cipher.h new file mode 100644 index 0000000..9310ad3 --- /dev/null +++ b/pi-cipher/pi16cipher.h @@ -0,0 +1,146 @@ +/* pi16cipher.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 PI16CIPHER_H_ +#define PI16CIPHER_H_ + +#include +#include + +#define PI16_WORD_SIZE 16 +#define PI16_N 4 + +#define PI16_IS_BITS (4 * PI16_N * PI16_WORD_SIZE) + +#define PI16_RATE_BITS (PI16_IS_BITS / 2) +#define PI16_CAPACITY_BITS PI16_BITS - PI16_RATE_BITS + +#define PI16_RATE_BYTES (PI16_RATE_BITS / 8) +#define PI16_CAPACITY_BYTES (PI16_CAPACITY_BITS / 8) + +#define PI16_SMN_LENGTH_BITS PI16_RATE_BITS +#define PI16_SMN_LENGTH_BYTES (PI16_RATE_BITS / 8) + +#define PI16_AD_BLOCK_LENGTH_BITS PI16_RATE_BITS +#define PI16_AD_BLOCK_LENGTH_BYTES (PI16_AD_BLOCK_LENGTH_BITS / 8) + +#define PI16_PT_BLOCK_LENGTH_BITS PI16_RATE_BITS +#define PI16_PT_BLOCK_LENGTH_BYTES (PI16_PT_BLOCK_LENGTH_BITS / 8) + +#define PI16_CT_BLOCK_LENGTH_BITS PI16_RATE_BITS +#define PI16_CT_BLOCK_LENGTH_BYTES (PI16_CT_BLOCK_LENGTH_BITS / 8) + +#define PI16_ROUNDS 3 + +extern const char* pi16_cipher_name; + +typedef struct { + uint16_t cis[4][4]; + uint16_t tag[8]; + uint64_t ctr; +} pi16_ctx_t; + +int pi16_init( + pi16_ctx_t *ctx, + const void *key, + size_t key_length_b, + const void *pmn, + size_t pmn_length_b); + +void pi16_process_ad_block( + pi16_ctx_t *ctx, + const void *ad, + unsigned long ad_num ); + +void pi16_process_ad_last_block( + pi16_ctx_t *ctx, + const void *ad, + size_t ad_length_b, + unsigned long ad_num ); + +void pi16_encrypt_smn( + pi16_ctx_t *ctx, + void *c0, + const void *smn); + +void pi16_decrypt_smn( + pi16_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi16_encrypt_block( + pi16_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi16_encrypt_last_block( + pi16_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi16_extract_tag( + pi16_ctx_t *ctx, + void *dest ); + +void pi16_decrypt_block( + pi16_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi16_decrypt_last_block( + pi16_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi16_encrypt_simple( + void *cipher, + size_t *cipher_len_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +int pi16_decrypt_simple( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +#endif /* PI16CIPHER_H_ */ diff --git a/pi-cipher/pi32_parameter.h b/pi-cipher/pi32_parameter.h new file mode 100644 index 0000000..55887ad --- /dev/null +++ b/pi-cipher/pi32_parameter.h @@ -0,0 +1,67 @@ +/* + * pi32_parameter.h + * + * Created on: 2015-09-11 + * Author: bg + */ + +#ifndef PI32_PARAMETER_H_ +#define PI32_PARAMETER_H_ + +typedef uint32_t word_t; + +#define PI_WORD_SIZE 32 + +#define PI_TAG_BITS 256 +#define PI_TAG_BYTES (PI_TAG_BITS / 8) + + +/*mu-transformation*/ \ +#define PI_MU_CONST { \ + 0xF0E8E4E2, \ + 0xE1D8D4D2, \ + 0xD1CCCAC9, \ + 0xC6C5C3B8 \ +} + +/*nu-transformation*/ \ +#define PI_NY_CONST { \ + 0xB4B2B1AC, \ + 0xAAA9A6A5, \ + 0xA39C9A99, \ + 0x9695938E \ +} + + +/* FIXME */ +#if 0 +#define PI_MU_CONST { \ + 0x8D8B8778, \ + 0x7472716C, \ + 0x6A696665, \ + 0x635C5A59 \ +} + +#define PI_NY_CONST { \ + 0x5655534E, \ + 0x4D4B473C, \ + 0x3A393635, \ + 0x332E2D2B \ +} +#endif + +#define PI_MU_ROT_CONST { 5, 11, 17, 23 } + +#define PI_NY_ROT_CONST { 3, 10, 19, 29 } + +#define PI_CONST { \ + { 0x8D8B8778, 0x7472716C, 0x6A696665, 0x635C5A59 }, \ + { 0x5655534E, 0x4D4B473C, 0x3A393635, 0x332E2D2B }, \ + { 0x271E1D1B, 0x170FF0E8, 0xE4E2E1D8, 0xD4D2D1CC }, \ + { 0xCAC9C6C5, 0xC3B8B4B2, 0xB1ACAAA9, 0xA6A5A39C }, \ + { 0x9A999695, 0x938E8D8B, 0x87787472, 0x716C6A69 }, \ + { 0x6665635C, 0x5A595655, 0x534E4D4B, 0x473C3A39 } \ +} + + +#endif /* PI32_PARAMETER_H_ */ diff --git a/pi-cipher/pi32cipher.c b/pi-cipher/pi32cipher.c new file mode 100644 index 0000000..11b468f --- /dev/null +++ b/pi-cipher/pi32cipher.c @@ -0,0 +1,3 @@ + +#define PI_SIZE 32 +#include "pi-cipher.c" diff --git a/pi-cipher/pi32cipher.h b/pi-cipher/pi32cipher.h new file mode 100644 index 0000000..dbb92da --- /dev/null +++ b/pi-cipher/pi32cipher.h @@ -0,0 +1,146 @@ +/* pi32cipher.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 PI32CIPHER_H_ +#define PI32CIPHER_H_ + +#include +#include + +#define PI32_WORD_SIZE 32 +#define PI32_N 4 + +#define PI32_IS_BITS (4 * PI32_N * PI32_WORD_SIZE) + +#define PI32_RATE_BITS (PI32_IS_BITS / 2) +#define PI32_CAPACITY_BITS PI32_BITS - PI32_RATE_BITS + +#define PI32_RATE_BYTES (PI32_RATE_BITS / 8) +#define PI32_CAPACITY_BYTES (PI32_CAPACITY_BITS / 8) + +#define PI32_SMN_LENGTH_BITS PI32_RATE_BITS +#define PI32_SMN_LENGTH_BYTES (PI32_RATE_BITS / 8) + +#define PI32_AD_BLOCK_LENGTH_BITS PI32_RATE_BITS +#define PI32_AD_BLOCK_LENGTH_BYTES (PI32_AD_BLOCK_LENGTH_BITS / 8) + +#define PI32_PT_BLOCK_LENGTH_BITS PI32_RATE_BITS +#define PI32_PT_BLOCK_LENGTH_BYTES (PI32_PT_BLOCK_LENGTH_BITS / 8) + +#define PI32_CT_BLOCK_LENGTH_BITS PI32_RATE_BITS +#define PI32_CT_BLOCK_LENGTH_BYTES (PI32_CT_BLOCK_LENGTH_BITS / 8) + +#define PI32_ROUNDS 3 + +extern const char* pi32_cipher_name; + +typedef struct { + uint32_t cis[4][4]; + uint32_t tag[8]; + uint64_t ctr; +} pi32_ctx_t; + +int pi32_init( + pi32_ctx_t *ctx, + const void *key, + size_t key_length_b, + const void *pmn, + size_t pmn_length_b); + +void pi32_process_ad_block( + pi32_ctx_t *ctx, + const void *ad, + unsigned long ad_num ); + +void pi32_process_last_ad_block( + pi32_ctx_t *ctx, + const void *ad, + size_t ad_length_b, + unsigned long ad_num ); + +void pi32_process_smn( + pi32_ctx_t *ctx, + void *c0, + const void *smn); + +void pi32_decrypt_smn( + pi32_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi32_encrypt_block( + pi32_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi32_encrypt_last_block( + pi32_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi32_extract_tag( + pi32_ctx_t *ctx, + void *dest ); + +void pi32_decrypt_block( + pi32_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi32_decrypt_last_block( + pi32_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi32_encrypt_simple( + void *cipher, + size_t *cipher_len_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +int pi32_decrypt_simple( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +#endif /* PI32CIPHER_H_ */ diff --git a/pi-cipher/pi64_parameter.h b/pi-cipher/pi64_parameter.h new file mode 100644 index 0000000..56a2e8a --- /dev/null +++ b/pi-cipher/pi64_parameter.h @@ -0,0 +1,46 @@ +/* + * pi64_parameter.h + * + * Created on: 2015-09-12 + * Author: bg + */ + +#ifndef PI64_PARAMETER_H_ +#define PI64_PARAMETER_H_ + +typedef uint64_t word_t; + +#define PI_WORD_SIZE 64 + +#define PI_TAG_BITS 512 +#define PI_TAG_BYTES (PI_TAG_BITS / 8) + +#define PI_MU_CONST { \ + 0xF0E8E4E2E1D8D4D2, \ + 0xD1CCCAC9C6C5C3B8, \ + 0xB4B2B1ACAAA9A6A5, \ + 0xA39C9A999695938E \ +} + +#define PI_MU_ROT_CONST { 7, 19, 31, 53 } + +#define PI_NY_CONST { \ + 0x8D8B87787472716C, \ + 0x6A696665635C5A59, \ + 0x5655534E4D4B473C, \ + 0x3A393635332E2D2B \ +} + +#define PI_NY_ROT_CONST { 11, 23, 37, 59 } + +#define PI_CONST { \ + { 0x271E1D1B170FF0E8, 0xE4E2E1D8D4D2D1CC, 0xCAC9C6C5C3B8B4B2, 0xB1ACAAA9A6A5A39C }, \ + { 0x9A999695938E8D8B, 0x87787472716C6A69, 0x6665635C5A595655, 0x534E4D4B473C3A39 }, \ + { 0x3635332E2D2B271E, 0x1D1B170FF0E8E4E2, 0xE1D8D4D2D1CCCAC9, 0xC6C5C3B8B4B2B1AC }, \ + { 0xAAA9A6A5A39C9A99, 0x9695938E8D8B8778, 0x7472716C6A696665, 0x635C5A595655534E }, \ + { 0x4D4B473C3A393635, 0x332E2D2B271E1D1B, 0x170FF0E8E4E2E1D8, 0xD4D2D1CCCAC9C6C5 }, \ + { 0xC3B8B4B2B1ACAAA9, 0xA6A5A39C9A999695, 0x938E8D8B87787472, 0x716C6A696665635C } \ +} + + +#endif /* PI64_PARAMETER_H_ */ diff --git a/pi-cipher/pi64cipher.c b/pi-cipher/pi64cipher.c new file mode 100644 index 0000000..468beb2 --- /dev/null +++ b/pi-cipher/pi64cipher.c @@ -0,0 +1,3 @@ + +#define PI_SIZE 64 +#include "pi-cipher.c" diff --git a/pi-cipher/pi64cipher.h b/pi-cipher/pi64cipher.h new file mode 100644 index 0000000..bd4ef27 --- /dev/null +++ b/pi-cipher/pi64cipher.h @@ -0,0 +1,146 @@ +/* pi64cipher.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 PI64CIPHER_H_ +#define PI64CIPHER_H_ + +#include +#include + +#define PI64_WORD_SIZE 64 +#define PI64_N 4 + +#define PI64_IS_BITS (4 * PI64_N * PI64_WORD_SIZE) + +#define PI64_RATE_BITS (PI64_IS_BITS / 2) +#define PI64_CAPACITY_BITS PI64_BITS - PI64_RATE_BITS + +#define PI64_RATE_BYTES (PI64_RATE_BITS / 8) +#define PI64_CAPACITY_BYTES (PI64_CAPACITY_BITS / 8) + +#define PI64_SMN_LENGTH_BITS PI64_RATE_BITS +#define PI64_SMN_LENGTH_BYTES (PI64_RATE_BITS / 8) + +#define PI64_AD_BLOCK_LENGTH_BITS PI64_RATE_BITS +#define PI64_AD_BLOCK_LENGTH_BYTES (PI64_AD_BLOCK_LENGTH_BITS / 8) + +#define PI64_PT_BLOCK_LENGTH_BITS PI64_RATE_BITS +#define PI64_PT_BLOCK_LENGTH_BYTES (PI64_PT_BLOCK_LENGTH_BITS / 8) + +#define PI64_CT_BLOCK_LENGTH_BITS PI64_RATE_BITS +#define PI64_CT_BLOCK_LENGTH_BYTES (PI64_CT_BLOCK_LENGTH_BITS / 8) + +#define PI64_ROUNDS 3 + +extern const char* pi64_cipher_name; + +typedef struct { + uint64_t cis[4][4]; + uint64_t tag[8]; + uint64_t ctr; +} pi64_ctx_t; + +int pi64_init( + pi64_ctx_t *ctx, + const void *key, + size_t key_length_b, + const void *pmn, + size_t pmn_length_b); + +void pi64_process_ad_block( + pi64_ctx_t *ctx, + const void *ad, + unsigned long ad_num ); + +void pi64_process_last_ad_block( + pi64_ctx_t *ctx, + const void *ad, + size_t ad_length_b, + unsigned long ad_num ); + +void pi64_process_smn( + pi64_ctx_t *ctx, + void *c0, + const void *smn); + +void pi64_decrypt_smn( + pi64_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi64_encrypt_block( + pi64_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi64_encrypt_last_block( + pi64_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi64_extract_tag( + pi64_ctx_t *ctx, + void *dest ); + +void pi64_decrypt_block( + pi64_ctx_t *ctx, + void *dest, + const void *src, + unsigned long num ); + +void pi64_decrypt_last_block( + pi64_ctx_t *ctx, + void *dest, + const void *src, + size_t length_b, + unsigned long num ); + +void pi64_encrypt_simple( + void *cipher, + size_t *cipher_len_B, + const void *msg, + size_t msg_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_secret, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +int pi64_decrypt_simple( + void *msg, + size_t *msg_len_B, + void *nonce_secret, + const void *cipher, + size_t cipher_len_B, + const void *ad, + size_t ad_len_B, + const void *nonce_public, + size_t nonce_public_len_B, + const void *key, + size_t key_len_B + ); + +#endif /* PI64CIPHER_H_ */ diff --git a/test_src/main-picipher-test.c b/test_src/main-picipher-test.c new file mode 100644 index 0000000..8bde5e6 --- /dev/null +++ b/test_src/main-picipher-test.c @@ -0,0 +1,318 @@ +/* main-picipher-test.c */ +/* + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) + + 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 "main-test-common.h" + +#include +#include +#include + +#include +#include "performance_test.h" + +char *algo_name = "pi16cipher"; + +/***************************************************************************** + * additional validation-functions * + *****************************************************************************/ + +#define DUMP_LEN(x, s) do { \ + printf("%s", "\n\n" #x ":"); \ + cli_hexdump_block((x), (s), 4, 16); \ + uart0_flush(); \ +} while (0) + +#define DUMP(x) DUMP_LEN((x), (sizeof(x))) + +arcfour_ctx_t prng; + +static +void fill_random(void *buf, size_t length) { + while (length--) { + *(uint8_t *)buf = arcfour_gen(&prng); + buf = (uint8_t *)buf + 1; + } +} + +void testrun_performance_pi16cipher(void){ + pi16_ctx_t ctx; + uint32_t t; + const uint8_t key[16] = { 15, 14, 13, 12 , 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + uint8_t msg[19] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; + const uint8_t ad[17] = { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; + uint8_t nsec[16] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; + const uint8_t npub[4] = { 10, 11, 12, 13 }; + uint8_t crypt[16 + 19 + 16]; + uint8_t *tag = &crypt[16 + 19]; +// size_t crypt_len, tag_len, msg_len = sizeof(msg); +// int v; + + calibrateTimer(); + print_overhead(); + + uart0_flush(); + startTimer(1); + pi16_init(&ctx, key, sizeof(key), npub, sizeof(npub)); + t = stopTimer(); + printf_P(PSTR("\tinit time (16 + 4) : %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_process_ad_block(&ctx, ad, 1); + t = stopTimer(); + printf_P(PSTR("\tprocess ad(16) : %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_process_ad_last_block(&ctx, &ad[16], 1, 2); + t = stopTimer(); + printf_P(PSTR("\tprocess last ad(1) : %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_encrypt_smn(&ctx, crypt, nsec); + t = stopTimer(); + printf_P(PSTR("\tprocess smn(16) : %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_encrypt_block(&ctx, &crypt[16], msg, 1); + t = stopTimer(); + printf_P(PSTR("\tprocess encrypt block(16) : %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_encrypt_last_block(&ctx, &crypt[32], &msg[16], 3, 2); + t = stopTimer(); + printf_P(PSTR("\tprocess encrypt last block(3): %10"PRIu32"\n"), t); + uart0_flush(); + startTimer(1); + pi16_extract_tag(&ctx, tag); + t = stopTimer(); + printf_P(PSTR("\tprocess extract tag(16) : %10"PRIu32"\n"), t); +} + +void testrun_pi16(void) +{ + const uint8_t key[16] = { 15, 14, 13, 12 , 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + uint8_t msg[19] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; + const uint8_t ad[17] = { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; + uint8_t nsec[16] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; + const uint8_t npub[4] = { 10, 11, 12, 13 }; + uint8_t crypt[16 + 19 + 16]; + size_t crypt_len, msg_len = sizeof(msg); + int v; +// printf("crypt = %p, crypt_len = %d, tag = %p, tag_len = %d\n", crypt, crypt_len, tag, tag_len); + pi16_encrypt_simple(crypt, &crypt_len, msg, sizeof(msg), ad, sizeof(ad), nsec, npub, sizeof(npub), key, sizeof(key)); +// printf("crypt = %p, crypt_len = %d, tag = %p, tag_len = %d\n", crypt, crypt_len, tag, tag_len); + DUMP(key); + DUMP(msg); + DUMP(ad); + DUMP(nsec); + DUMP(npub); + DUMP_LEN(crypt, crypt_len); + puts(""); + crypt[0] ^= 0; + v = pi16_decrypt_simple(msg, &msg_len, nsec, crypt, crypt_len, ad, sizeof(ad), npub, sizeof(npub), key, sizeof(key)); + DUMP(key); + DUMP(msg); + DUMP(ad); + DUMP(nsec); + DUMP(npub); + DUMP_LEN(crypt, crypt_len); + printf("\nverification: >> %s (%d) <<\n", v ? "FAILED!" : "ok", v); + puts(""); +} + +void testrun_pi32(void) +{ + const uint8_t key[16] = { 0 }; + const uint8_t msg[1] = { 0xf }; + const uint8_t ad[1] = { 0 }; + const uint8_t nsec[PI32_SMN_LENGTH_BYTES] = { 0 }; + const uint8_t npub[16] = { 0 }; + uint8_t crypt[sizeof(nsec) + sizeof(msg) + 32]; + uint16_t crypt_len; + pi32_encrypt_simple(crypt, &crypt_len, msg, sizeof(msg), ad, sizeof(ad), nsec, npub, sizeof(npub), key, sizeof(key)); + DUMP(key); + DUMP(msg); + DUMP(ad); + DUMP(nsec); + DUMP(npub); + DUMP(crypt); +} + +void testrun_pi64(void) +{ + const uint8_t key[16] = { 0 }; + const uint8_t msg[1] = { 0xf }; + const uint8_t ad[1] = { 0 }; + const uint8_t nsec[PI64_SMN_LENGTH_BYTES] = { 0 }; + const uint8_t npub[16] = { 0 }; + uint8_t crypt[sizeof(nsec) + sizeof(msg) + 64]; + uint16_t crypt_len; + pi64_encrypt_simple(crypt, &crypt_len, msg, sizeof(msg), ad, sizeof(ad), nsec, npub, sizeof(npub), key, sizeof(key)); + DUMP(key); + DUMP(msg); + DUMP(ad); + DUMP(nsec); + DUMP(npub); + DUMP(crypt); +} + +void testrun(void) { + testrun_pi16(); + testrun_pi32(); + testrun_pi64(); +} + +static +void print_item(const char *label, const void* data, size_t length) { + printf("%s (%u) = ", label, length); + while (length--) { + printf("%02X", *(uint8_t*)data); + data = (uint8_t*)data + 1; + } + putchar('\n'); +} + +void generate_single_testvector( + const uint8_t *m, size_t mlen, + const uint8_t *ad, size_t adlen, + const uint8_t *nsec, + const uint8_t *npub, size_t npub_len, + const uint8_t *key, size_t key_len, + void(*encrypt)(void*, size_t*, const void*, size_t, const void*, size_t, const void*, const void*, size_t, const void*, size_t), + int(*decrypt)(void*, size_t*, void*, const void*, size_t, const void*, size_t, const void*, size_t, const void*, size_t), + size_t block_length + ) { + uint8_t c[block_length + mlen + block_length]; + uint8_t m_check[mlen]; + uint8_t nsec_check[block_length]; + size_t clen, mlen_check; + int v; + + print_item("KEY", key, key_len); + print_item("NPUB", npub, npub_len); + print_item("NSEC", nsec, block_length); + print_item("MSG", m, mlen); + print_item("AD", ad, adlen); + + fflush(stdout); + encrypt(c, &clen, m, mlen, ad, adlen, nsec, npub, npub_len, key, key_len); + + print_item("CIPHER", c, clen); + fflush(stdout); + + v = decrypt(m_check, &mlen_check, nsec_check, c, clen, ad, adlen, npub, npub_len, key, key_len); + + if (v) { + printf("!verification failed (%d)\n", v); + } + + if (mlen != mlen_check || memcmp(m, m_check, mlen)) { + print_item("!ERROR MSG", m_check, mlen_check); + } + if (memcmp(nsec, nsec_check, block_length)) { + print_item("!ERROR MSG", m_check, mlen_check); + } + putchar('\n'); + fflush(stdout); +} + +void generate_testvectors( + size_t key_len, size_t npub_len, + void(*encrypt)(void*, size_t*, const void*, size_t, const void*, size_t, const void*, const void*, size_t, const void*, size_t), + int(*decrypt)(void*, size_t*, void*, const void*, size_t, const void*, size_t, const void*, size_t, const void*, size_t), + size_t block_length, const char *cipher_name) { + size_t ad_len, msg_len, i, c = 1; + uint8_t ad[3 * block_length / 2]; + uint8_t msg[3 * block_length / 2]; + uint8_t key[key_len]; + uint8_t npub[npub_len]; + uint8_t nsec[block_length]; + { + char seed[64]; + snprintf(seed, sizeof(seed), "%s%03uv2 (%u byte nonce)", cipher_name, key_len * 8, npub_len); + arcfour_init(seed, strlen(seed) * 8, &prng); + } + for (msg_len = 0; msg_len <= sizeof(msg); ++msg_len) { + for (ad_len = 0; ad_len <= sizeof(ad); ++ad_len) { + printf("[msg_len = %u]\n", msg_len); + printf("[ad_len = %u]\n\n", ad_len); + for (i = 0; i < 8; ++i) { + printf("[vector #%u (%u)]\n", c, i + 1); + ++c; + fill_random(key, sizeof(key)); + fill_random(npub, sizeof(npub)); + fill_random(nsec, sizeof(nsec)); + fill_random(ad, ad_len); + fill_random(msg, msg_len); + generate_single_testvector(msg, msg_len, ad, ad_len, nsec, npub, npub_len, key, key_len, encrypt, decrypt, block_length); + } + } + } +} + +void tv16(void) { + puts("\n=====\n"); + printf("# Testvectors for %s\n", pi16_cipher_name); + printf("# key size: %u bits\n", 128); + printf("# nonce size: %u bits\n\n", 32); + generate_testvectors(16, 4, pi16_encrypt_simple, pi16_decrypt_simple, PI16_PT_BLOCK_LENGTH_BYTES, pi16_cipher_name); + puts("\n=====\n"); +} + +/***************************************************************************** + * main * + *****************************************************************************/ + +const char nessie_str[] PROGMEM = "nessie"; +const char test_str[] PROGMEM = "test"; +const char tv16_str[] PROGMEM = "tv16"; +const char test16_str[] PROGMEM = "test16"; +const char test32_str[] PROGMEM = "test32"; +const char test64_str[] PROGMEM = "test64"; +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}, + { tv16_str, NULL, tv16}, + { test16_str, NULL, testrun_pi16}, + { test32_str, NULL, testrun_pi32}, + { test64_str, NULL, testrun_pi64}, +// { ftest_str, NULL, testrun_f32}, +// { gtest_str, NULL, testrun_g32}, + { performance_str, NULL, testrun_performance_pi16cipher}, + { echo_str, (void*)1, (void_fpt)echo_ctrl}, + { NULL, NULL, NULL} +}; + +int main(void) { + main_setup(); + + for(;;){ + welcome_msg(algo_name); + cmd_interface(cmdlist); + } + +} + +