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);
+ }
+
+}
+
+