]> git.cryptolib.org Git - avr-crypto-lib.git/blob - khazad/khazad.c
form changes (nothing of importance)
[avr-crypto-lib.git] / khazad / khazad.c
1 /* khazad.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2011 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdint.h>
21 #include <avr/pgmspace.h>
22 #include <string.h>
23 #include "gf256mul.h"
24 #include "memxor.h"
25 #include "khazad.h"
26
27 /*
28   | | | |     | | | |
29   V V V V     V V V V
30  +-------+   +-------+
31  |   P   |   |   Q   |
32  +-------+   +-------+
33   | | \ \     / / | |
34   | |  \ \   / /  | |
35   | |   \ \ / /   | |
36   | |    \ X /    | |
37   | |     X X     | |
38   | |    / X \    | |
39   | |   / / \ \   | |
40   | |  / /   \ \  | |
41   | | / /     \ \ | |
42   | | | |     | | | |
43   V V V V     V V V V
44  +-------+   +-------+
45  |   Q   |   |   P   |
46  +-------+   +-------+
47   | | \ \     / / | |
48   | |  \ \   / /  | |
49   | |   \ \ / /   | |
50   | |    \ X /    | |
51   | |     X X     | |
52   | |    / X \    | |
53   | |   / / \ \   | |
54   | |  / /   \ \  | |
55   | | / /     \ \ | |
56   | | | |     | | | |
57   V V V V     V V V V
58  +-------+   +-------+
59  |   P   |   |   Q   |
60  +-------+   +-------+
61   | | | |    | | | |
62   V V V V    V V V V
63
64
65 P:
66 3x Fx Ex 0x 5x 4x Bx Cx Dx Ax 9x 6x 7x 8x 2x 1x
67 Q:
68 9x Ex 5x 6x Ax 2x 3x Cx Fx 0x 4x Dx 7x Bx 1x 8x
69 */
70
71 static const uint8_t pq_lut[16] PROGMEM = {
72         0x39, 0xFE, 0xE5, 0x06, 0x5A, 0x42, 0xB3, 0xCC,
73         0xDF, 0xA0, 0x94, 0x6D, 0x77, 0x8B, 0x21, 0x18
74 };
75
76 uint8_t khazad_sbox(uint8_t a){
77         uint8_t b,c,d,e;
78         b = pgm_read_byte(pq_lut+(a>>4))&0xf0;
79         c = pgm_read_byte(pq_lut+(a&0xf))&0x0f;
80         d = (b>>2)&0x0c;
81         e = (c<<2)&0x30;
82         b = (b&0xc0)|e;
83         c = (c&0x03)|d;
84         b = pgm_read_byte(pq_lut+(b>>4))<<4;
85         c = pgm_read_byte(pq_lut+(c&0xf))>>4;
86         d = (b>>2)&0x0c;
87         e = (c<<2)&0x30;
88         b = (b&0xc0)|e;
89         c = (c&0x03)|d;
90         b = pgm_read_byte(pq_lut+(b>>4))&0xf0;
91         c = pgm_read_byte(pq_lut+(c&0xf))&0x0f;
92         return b|c;
93 }
94
95 static void gamma_1(uint8_t* a){
96         uint8_t i;
97         for(i=0; i<8; ++i){
98                 *a = khazad_sbox(*a);
99                 a++;
100         }
101 }
102
103 /******************************************************************************/
104 /* p8 (x) = x^8 + x^4 + x^3 + x^2 + 1 */
105 #define POLYNOM 0x1D
106
107 /*
108  * 01x 03x 04x 05x 06x 08x 0Bx 07x
109  * 03x 01x 05x 04x 08x 06x 07x 0Bx
110  * 04x 05x 01x 03x 0Bx 07x 06x 08x
111  * 05x 04x 03x 01x 07x 0Bx 08x 06x
112  * 06x 08x 0Bx 07x 01x 03x 04x 05x
113  * 08x 06x 07x 0Bx 03x 01x 05x 04x
114  * 0Bx 07x 06x 08x 04x 05x 01x 03x
115  * 07x 0Bx 08x 06x 05x 04x 03x 01x
116  */
117
118 static const uint8_t h[8][4] PROGMEM = {
119         { 0x13, 0x45, 0x68, 0xB7 },
120         { 0x31, 0x54, 0x86, 0x7B },
121         { 0x45, 0x13, 0xB7, 0x68 },
122         { 0x54, 0x31, 0x7B, 0x86 },
123         { 0x68, 0xB7, 0x13, 0x45 },
124         { 0x86, 0x7B, 0x31, 0x54 },
125         { 0xB7, 0x68, 0x45, 0x13 },
126         { 0x7B, 0x86, 0x54, 0x31 }
127 };
128
129 static void theta(uint8_t* a){
130         uint8_t i,j,x,accu;
131         uint8_t c[8];
132         uint8_t *hp;
133         hp = (uint8_t*)h;
134         for(i=0; i<8; ++i){
135                 accu = 0;
136                 for(j=0; j<4; ++j){
137                         x = pgm_read_byte(hp++);
138                         accu ^= gf256mul(*a++, x>>4, POLYNOM);
139                         accu ^= gf256mul(*a++, x&0xf, POLYNOM);
140                 }
141                 a -= 8;
142                 c[i] = accu;
143         }
144         memcpy(a, c, 8);
145 }
146
147 /******************************************************************************/
148
149 static void khazad_round(uint8_t* a, const uint8_t* k){
150         gamma_1(a);
151         theta(a);
152         memxor(a, k, 8);
153 }
154
155 /******************************************************************************/
156
157 void khazad_init(const void* key, khazad_ctx_t* ctx){
158         uint8_t c[8];
159         uint8_t i,r=0;
160         for(i=0; i<8; ++i){
161                 c[i] = khazad_sbox(r*8+i);
162         }
163         memcpy(ctx->k[r], (uint8_t*)key+8, 8);
164         khazad_round(ctx->k[r], c);
165         memxor(ctx->k[r], (uint8_t*)key, 8);
166         r=1;
167         for(i=0; i<8; ++i){
168                         c[i] = khazad_sbox(r*8+i);
169         }
170         memcpy(ctx->k[r], ctx->k[r-1], 8);
171         khazad_round(ctx->k[r], c);
172         memxor(ctx->k[r], (uint8_t*)key+8, 8);
173         for(r=2; r<9; ++r){
174                 for(i=0; i<8; ++i){
175                                 c[i] = khazad_sbox(r*8+i);
176                 }
177                 memcpy(ctx->k[r], ctx->k[r-1], 8);
178                 khazad_round(ctx->k[r], c);
179                 memxor(ctx->k[r], ctx->k[r-2], 8);
180         }
181 }
182
183 /******************************************************************************/
184
185 void khazad_enc(void* buffer, const khazad_ctx_t* ctx){
186         uint8_t r;
187         memxor(buffer, ctx->k[0], 8);
188         for(r=1; r<8; ++r){
189                 khazad_round(buffer, ctx->k[r]);
190         }
191         gamma_1(buffer);
192         memxor(buffer, ctx->k[8], 8);
193 }
194
195 /******************************************************************************/
196
197 void khazad_dec(void* buffer, const khazad_ctx_t* ctx){
198         uint8_t r=7;
199         memxor(buffer, ctx->k[8], 8);
200         gamma_1(buffer);
201         do{
202                 memxor(buffer, ctx->k[r--], 8);
203                 theta(buffer);
204                 gamma_1(buffer);
205         }while(r);
206         memxor(buffer, ctx->k[0], 8);
207 }
208
209
210
211