--- /dev/null
+/* khazad.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2006-2011 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "gf256mul.h"
+#include "memxor.h"
+#include "khazad.h"
+
+/*
+ | | | | | | | |
+ V V V V V V V V
+ +-------+ +-------+
+ | P | | Q |
+ +-------+ +-------+
+ | | \ \ / / | |
+ | | \ \ / / | |
+ | | \ \ / / | |
+ | | \ X / | |
+ | | X X | |
+ | | / X \ | |
+ | | / / \ \ | |
+ | | / / \ \ | |
+ | | / / \ \ | |
+ | | | | | | | |
+ V V V V V V V V
+ +-------+ +-------+
+ | Q | | P |
+ +-------+ +-------+
+ | | \ \ / / | |
+ | | \ \ / / | |
+ | | \ \ / / | |
+ | | \ X / | |
+ | | X X | |
+ | | / X \ | |
+ | | / / \ \ | |
+ | | / / \ \ | |
+ | | / / \ \ | |
+ | | | | | | | |
+ V V V V V V V V
+ +-------+ +-------+
+ | P | | Q |
+ +-------+ +-------+
+ | | | | | | | |
+ V V V V V V V V
+
+
+P:
+3x Fx Ex 0x 5x 4x Bx Cx Dx Ax 9x 6x 7x 8x 2x 1x
+Q:
+9x Ex 5x 6x Ax 2x 3x Cx Fx 0x 4x Dx 7x Bx 1x 8x
+*/
+
+static const uint8_t pq_lut[16] = {
+ 0x39, 0xFE, 0xE5, 0x06, 0x5A, 0x42, 0xB3, 0xCC,
+ 0xDF, 0xA0, 0x94, 0x6D, 0x77, 0x8B, 0x21, 0x18
+};
+
+uint8_t khazad_sbox(uint8_t a){
+ uint8_t b,c,d,e;
+ b = pq_lut[a>>4] & 0xf0;
+ c = pq_lut[a&0xf] & 0x0f;
+ d = (b>>2)&0x0c;
+ e = (c<<2)&0x30;
+ b = (b&0xc0)|e;
+ c = (c&0x03)|d;
+ b = pq_lut[b>>4] << 4;
+ c = pq_lut[c&0xf] >> 4;
+ d = (b>>2)&0x0c;
+ e = (c<<2)&0x30;
+ b = (b&0xc0)|e;
+ c = (c&0x03)|d;
+ b = pq_lut[b>>4] & 0xf0;
+ c = pq_lut[c&0xf] & 0x0f;
+ return b|c;
+}
+
+static void gamma_x(uint8_t* a){
+ uint8_t i;
+ for(i=0; i<8; ++i){
+ *a = khazad_sbox(*a);
+ a++;
+ }
+}
+
+/******************************************************************************/
+/* p8 (x) = x^8 + x^4 + x^3 + x^2 + 1 */
+#define POLYNOM 0x1D
+
+/*
+ * 01x 03x 04x 05x 06x 08x 0Bx 07x
+ * 03x 01x 05x 04x 08x 06x 07x 0Bx
+ * 04x 05x 01x 03x 0Bx 07x 06x 08x
+ * 05x 04x 03x 01x 07x 0Bx 08x 06x
+ * 06x 08x 0Bx 07x 01x 03x 04x 05x
+ * 08x 06x 07x 0Bx 03x 01x 05x 04x
+ * 0Bx 07x 06x 08x 04x 05x 01x 03x
+ * 07x 0Bx 08x 06x 05x 04x 03x 01x
+ */
+
+static const uint8_t h[8][4] = {
+ { 0x13, 0x45, 0x68, 0xB7 },
+ { 0x31, 0x54, 0x86, 0x7B },
+ { 0x45, 0x13, 0xB7, 0x68 },
+ { 0x54, 0x31, 0x7B, 0x86 },
+ { 0x68, 0xB7, 0x13, 0x45 },
+ { 0x86, 0x7B, 0x31, 0x54 },
+ { 0xB7, 0x68, 0x45, 0x13 },
+ { 0x7B, 0x86, 0x54, 0x31 }
+};
+
+static void theta(uint8_t* a){
+ uint8_t i,j,x,accu;
+ uint8_t c[8];
+ uint8_t *hp;
+ hp = (uint8_t*)h;
+ for(i=0; i<8; ++i){
+ accu = 0;
+ for(j=0; j<4; ++j){
+ x = *hp++;
+ accu ^= gf256mul(*a++, x>>4, POLYNOM);
+ accu ^= gf256mul(*a++, x&0xf, POLYNOM);
+ }
+ a -= 8;
+ c[i] = accu;
+ }
+ memcpy(a, c, 8);
+}
+
+/******************************************************************************/
+
+static void khazad_round(uint8_t* a, const uint8_t* k){
+ gamma_x(a);
+ theta(a);
+ memxor(a, k, 8);
+}
+
+/******************************************************************************/
+
+void khazad_init(const void* key, khazad_ctx_t* ctx){
+ uint8_t c[8];
+ uint8_t i,r=0;
+ for(i=0; i<8; ++i){
+ c[i] = khazad_sbox(r*8+i);
+ }
+ memcpy(ctx->k[r], (uint8_t*)key+8, 8);
+ khazad_round(ctx->k[r], c);
+ memxor(ctx->k[r], (uint8_t*)key, 8);
+ r=1;
+ for(i=0; i<8; ++i){
+ c[i] = khazad_sbox(r*8+i);
+ }
+ memcpy(ctx->k[r], ctx->k[r-1], 8);
+ khazad_round(ctx->k[r], c);
+ memxor(ctx->k[r], (uint8_t*)key+8, 8);
+ for(r=2; r<9; ++r){
+ for(i=0; i<8; ++i){
+ c[i] = khazad_sbox(r*8+i);
+ }
+ memcpy(ctx->k[r], ctx->k[r-1], 8);
+ khazad_round(ctx->k[r], c);
+ memxor(ctx->k[r], ctx->k[r-2], 8);
+ }
+}
+
+/******************************************************************************/
+
+void khazad_enc(void* buffer, const khazad_ctx_t* ctx){
+ uint8_t r;
+ memxor(buffer, ctx->k[0], 8);
+ for(r=1; r<8; ++r){
+ khazad_round(buffer, ctx->k[r]);
+ }
+ gamma_x(buffer);
+ memxor(buffer, ctx->k[8], 8);
+}
+
+/******************************************************************************/
+
+void khazad_dec(void* buffer, const khazad_ctx_t* ctx){
+ uint8_t r=7;
+ memxor(buffer, ctx->k[8], 8);
+ gamma_x(buffer);
+ do{
+ memxor(buffer, ctx->k[r--], 8);
+ theta(buffer);
+ gamma_x(buffer);
+ }while(r);
+ memxor(buffer, ctx->k[0], 8);
+}
+
+
+
+