]> git.cryptolib.org Git - avr-crypto-lib.git/blob - cast6/cast6.c
adjusting test system debug uart reference
[avr-crypto-lib.git] / cast6 / cast6.c
1 /* 
2  * File:        cast6.c
3  * Author:      Daniel Otte
4  * Date:        09.09.2006
5  * License: GPL
6  * Description: Implementation of the CAST6 (aka CAST-256) cipher algorithm as described in RFC 2612
7  * 
8  */
9
10 #include <stdint.h>
11 #include <string.h>
12 #include <avr/pgmspace.h>
13 #include "cast6.h"
14 #include "cast6-sbox.h"
15
16 #define CHANGE_ENDIAN32(x) (((x)<<24 | (x)>>24 | ((x)&0xff00)<<8 | ((x)&0xff0000)>>8)&0xffffffff)
17
18 static uint8_t kr(uint8_t i, const cast6_ctx_t *ctx)
19 {
20     uint8_t ret;
21     ret = ctx->krx[i / 2];
22     if (i & 1) {
23         ret >>= 4;
24     } else {
25         ret &= 0x0f;
26     }
27     /* now get the high bit */
28     ret |= ((ctx->krx[24 + i / 8]) & (1 << (i % 8))) ? 0x10 : 0x00;
29     return ret;
30 }
31
32 static
33 void set_kr(uint8_t value, uint8_t i, cast6_ctx_t *ctx)
34 {
35     value &= 0x1F;
36
37     (ctx->krx[i / 2]) &= 0xF0 >> ((i & 1) * 4); /* clear the location where v should go */
38     (ctx->krx[i / 2]) |= (value & 0x0f) << ((i & 1) * 4);
39
40     /* now set the high bit */
41     (ctx->krx[24 + i / 8]) &= ~(1 << (i % 8)); /* clear the location where v should go */
42     (ctx->krx[24 + i / 8]) |= (value >> 4) << (i % 8);
43 }
44
45 #define ROTL32(a,n) (((a)<<(n))|((a)>>(32-(n))))
46 #define ROTR32(a,n) (((a)>>(n))|((a)<<(32-(n))))
47
48 #define S1(a) (pgm_read_dword(&(s1[(a)])))
49 #define S2(a) (pgm_read_dword(&(s2[(a)])))
50 #define S3(a) (pgm_read_dword(&(s3[(a)])))
51 #define S4(a) (pgm_read_dword(&(s4[(a)])))
52
53 #define A ((uint8_t)(v>>(8*3)))
54 #define B ((uint8_t)(v>>(8*2)))
55 #define C ((uint8_t)(v>>(8*1)))
56 #define D ((uint8_t)(v>>(8*0)))
57
58 static uint32_t f1(uint32_t v, uint8_t kri, uint32_t kmi)
59 {
60     uint32_t o;
61     kri &= 0x1F;
62     v = ROTL32(kmi + v, kri);
63     o = S1(A);
64     o ^= S2(B);
65     o -= S3(C);
66     o += S4(D);
67     return o;
68 }
69
70 static uint32_t f2(uint32_t v, uint8_t kri, uint32_t kmi)
71 {
72     uint32_t o;
73     kri &= 0x1F;
74     v = ROTL32(kmi ^ v, kri);
75     o = S1(A);
76     o -= S2(B);
77     o += S3(C);
78     o ^= S4(D);
79     return o;
80 }
81
82 static uint32_t f3(uint32_t v, uint8_t kri, uint32_t kmi)
83 {
84     uint32_t o;
85     kri &= 0x1F;
86     v = ROTL32(kmi - v, kri);
87     o = S1(A);
88     o += S2(B);
89     o ^= S3(C);
90     o -= S4(D);
91     return o;
92 }
93
94 #undef A
95 #undef B
96 #undef C
97 #undef D
98
99 #define A (((uint32_t*)buffer)[0])
100 #define B (((uint32_t*)buffer)[1])
101 #define C (((uint32_t*)buffer)[2])
102 #define D (((uint32_t*)buffer)[3])
103
104 static
105 void q(void *buffer, uint8_t i, const cast6_ctx_t *ctx)
106 {
107     C ^= f1(D, kr(i * 4 + 0, ctx), ctx->km[i][0]);
108     B ^= f2(C, kr(i * 4 + 1, ctx), ctx->km[i][1]);
109     A ^= f3(B, kr(i * 4 + 2, ctx), ctx->km[i][2]);
110     D ^= f1(A, kr(i * 4 + 3, ctx), ctx->km[i][3]);
111 }
112
113 static
114 void qbar(void *buffer, uint8_t i, const cast6_ctx_t *ctx)
115 {
116     D ^= f1(A, kr(i * 4 + 3, ctx), ctx->km[i][3]);
117     A ^= f3(B, kr(i * 4 + 2, ctx), ctx->km[i][2]);
118     B ^= f2(C, kr(i * 4 + 1, ctx), ctx->km[i][1]);
119     C ^= f1(D, kr(i * 4 + 0, ctx), ctx->km[i][0]);
120 }
121
122 void cast6_enc(void *buffer, const cast6_ctx_t *ctx)
123 {
124     uint8_t i;
125     for (i = 0; i < 32 / 4; ++i) {
126         ((uint32_t*) buffer)[i] = CHANGE_ENDIAN32(((uint32_t* )buffer)[i]);
127     }
128     for (i = 0; i < 6; ++i) {
129         q(buffer, i, ctx);
130     }
131     for (i = 6; i < 12; ++i) {
132         qbar(buffer, i, ctx);
133     }
134     for (i = 0; i < 32 / 4; ++i) {
135         ((uint32_t*) buffer)[i] = CHANGE_ENDIAN32(((uint32_t* )buffer)[i]);
136     }
137 }
138
139 void cast6_dec(void *buffer, const cast6_ctx_t *ctx)
140 {
141     uint8_t i;
142     for (i = 0; i < 32 / 4; ++i) {
143         ((uint32_t*) buffer)[i] = CHANGE_ENDIAN32(((uint32_t* )buffer)[i]);
144     }
145     for (i = 12; i > 6; --i) {
146         q(buffer, i - 1, ctx);
147     }
148     for (i = 6; i > 0; --i) {
149         qbar(buffer, i - 1, ctx);
150     }
151     for (i = 0; i < 32 / 4; ++i) {
152         ((uint32_t*) buffer)[i] = CHANGE_ENDIAN32(((uint32_t* )buffer)[i]);
153     }
154 }
155
156 #undef A
157 #undef B
158 #undef C
159 #undef D
160
161 #define A (((uint32_t*)buffer)[0])
162 #define B (((uint32_t*)buffer)[1])
163 #define C (((uint32_t*)buffer)[2])
164 #define D (((uint32_t*)buffer)[3])
165 #define E (((uint32_t*)buffer)[4])
166 #define F (((uint32_t*)buffer)[5])
167 #define G (((uint32_t*)buffer)[6])
168 #define H (((uint32_t*)buffer)[7])
169
170 /*
171  * we might later make it optional to use this small thing
172  static
173  void w(void *buffer, uint8_t *tr, uint32_t *tm){
174  G ^= f1(H, (tr[0]&0x0f)+(tr[5]&0x01)?0x10:0x00, tm[0]);
175  F ^= f2(G, (tr[0]>>4)  +(tr[5]&0x02)?0x10:0x00, tm[1]);
176  E ^= f3(F, (tr[1]&0x0f)+(tr[5]&0x04)?0x10:0x00, tm[2]);
177  D ^= f1(E, (tr[1]>>4)  +(tr[5]&0x08)?0x10:0x00, tm[3]);
178  C ^= f2(D, (tr[2]&0x0f)+(tr[5]&0x10)?0x10:0x00, tm[4]);
179  B ^= f3(C, (tr[2]>>4)  +(tr[5]&0x20)?0x10:0x00, tm[5]);
180  A ^= f1(B, (tr[3]&0x0f)+(tr[5]&0x40)?0x10:0x00, tm[6]);
181  H ^= f2(A, (tr[3]>>4)  +(tr[5]&0x80)?0x10:0x00, tm[7]);
182  }
183  */
184 static
185 void w(void *buffer, uint8_t *tr, uint32_t *tm)
186 {
187     G ^= f1(H, tr[0], tm[0]);
188     F ^= f2(G, tr[1], tm[1]);
189     E ^= f3(F, tr[2], tm[2]);
190     D ^= f1(E, tr[3], tm[3]);
191     C ^= f2(D, tr[4], tm[4]);
192     B ^= f3(C, tr[5], tm[5]);
193     A ^= f1(B, tr[6], tm[6]);
194     H ^= f2(A, tr[7], tm[7]);
195 }
196
197 /*
198  void dump_ctx(const cast6_ctx_t *ctx){
199  uint8_t i,t;
200  cli_putstr_P(PSTR("\r\n DBG:"));
201  for(i=0; i<12; ++i){
202  cli_putstr_P(PSTR("\r\n DBG:"));
203  cli_putstr_P(PSTR(" rotk1="));
204  t=kr(i*4+0, ctx);
205  cli_hexdump(&t,1);
206  cli_putstr_P(PSTR("          rotk2="));
207  t=kr(i*4+1, ctx);
208  cli_hexdump(&t,1);
209  cli_putstr_P(PSTR("          rotk3="));
210  t=kr(i*4+2, ctx);
211  cli_hexdump(&t,1);
212  cli_putstr_P(PSTR("          rotk4="));
213  t=kr(i*4+3, ctx);
214  cli_hexdump(&t,1);
215  cli_putstr_P(PSTR("\r\n     "));
216  cli_putstr_P(PSTR(" mask1="));
217  cli_hexdump(&(ctx->km[i][0]),4);
218  cli_putstr_P(PSTR(" mask2="));
219  cli_hexdump(&(ctx->km[i][1]),4);
220  cli_putstr_P(PSTR(" mask3="));
221  cli_hexdump(&(ctx->km[i][2]),4);
222  cli_putstr_P(PSTR(" mask4="));
223  cli_hexdump(&(ctx->km[i][3]),4);
224  cli_putstr_P(PSTR("\r\n;-----"));
225  }
226  }
227  */
228
229 #define CR 19
230 #define CM 0x5A827999
231 #define MR 17 
232 #define MM 0x6ED9EBA1
233
234 void cast6_init(const void *key, uint16_t keysize_b, cast6_ctx_t *ctx)
235 {
236     uint8_t buffer[32];
237     uint8_t cr = CR, tr[8];
238     uint32_t cm = CM, tm[8];
239     uint8_t i, j;
240
241     memset(buffer, 0, 32);
242     memcpy(buffer, key, (keysize_b + 7) / 8);
243     for (i = 0; i < 32 / 4; ++i) {
244         ((uint32_t*) buffer)[i] = CHANGE_ENDIAN32(((uint32_t* )buffer)[i]);
245     }
246
247     for (i = 0; i < 24; ++i) {
248         for (j = 0; j < 8; ++j) {
249             tm[j] = cm;
250             cm += MM;
251             tr[j] = cr & 0x1F;
252             cr += MR;
253         }
254         w(buffer, tr, tm);
255
256         if (i & 1) {
257             j = i / 2;
258             ctx->km[j][0] = H;
259             ctx->km[j][1] = F;
260             ctx->km[j][2] = D;
261             ctx->km[j][3] = B;
262             set_kr(buffer[0 * 4], j * 4 + 0, ctx);
263             set_kr(buffer[2 * 4], j * 4 + 1, ctx);
264             set_kr(buffer[4 * 4], j * 4 + 2, ctx);
265             set_kr(buffer[6 * 4], j * 4 + 3, ctx);
266         }
267     }
268 }
269