6 * Description: Implementation of the CAST6 (aka CAST-256) cipher algorithm as described in RFC 2612
13 #include "cast6_sboxes.h"
15 #define CHANGE_ENDIAN32(x) (((x)<<24 | (x)>>24 | ((x)&0xff00)<<8 | ((x)&0xff0000)>>8)&0xffffffff)
19 uint8_t kr(uint8_t i, const cast6_ctx_t* ctx){
27 /* now get the high bit */
28 ret |= ((ctx->krx[24+i/8])&(1<<(i%8)))?0x10:0x00;
33 void set_kr(uint8_t value, uint8_t i, cast6_ctx_t* ctx){
36 (ctx->krx[i/2]) &= 0xF0>>((i&1)*4); /* clear the location where v should go */
37 (ctx->krx[i/2]) |= (value&0x0f)<<((i&1)*4);
39 /* now set the high bit */
40 (ctx->krx[24+i/8]) &= ~(1<<(i%8)); /* clear the location where v should go */
41 (ctx->krx[24+i/8]) |= (value>>4)<<(i%8);
44 #define ROTL32(a,n) (((a)<<(n))|((a)>>(32-(n))))
45 #define ROTR32(a,n) (((a)>>(n))|((a)<<(32-(n))))
47 #define S1(a) (s1[(a)])
48 #define S2(a) (s2[(a)])
49 #define S3(a) (s3[(a)])
50 #define S4(a) (s4[(a)])
52 #define A ((uint8_t)(v>>(8*3)))
53 #define B ((uint8_t)(v>>(8*2)))
54 #define C ((uint8_t)(v>>(8*1)))
55 #define D ((uint8_t)(v>>(8*0)))
59 uint32_t f1(uint32_t v, uint8_t kri, uint32_t kmi){
62 v = ROTL32(kmi+v, kri);
71 uint32_t f2(uint32_t v, uint8_t kri, uint32_t kmi){
74 v = ROTL32(kmi^v, kri);
83 uint32_t f3(uint32_t v, uint8_t kri, uint32_t kmi){
86 v = ROTL32(kmi-v, kri);
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])
105 void q(void* buffer, uint8_t i, const cast6_ctx_t* ctx){
106 C ^= f1(D, kr(i*4+0, ctx), ctx->km[i][0]);
107 B ^= f2(C, kr(i*4+1, ctx), ctx->km[i][1]);
108 A ^= f3(B, kr(i*4+2, ctx), ctx->km[i][2]);
109 D ^= f1(A, kr(i*4+3, ctx), ctx->km[i][3]);
113 void qbar(void* buffer, uint8_t i, const cast6_ctx_t* ctx){
114 D ^= f1(A, kr(i*4+3, ctx), ctx->km[i][3]);
115 A ^= f3(B, kr(i*4+2, ctx), ctx->km[i][2]);
116 B ^= f2(C, kr(i*4+1, ctx), ctx->km[i][1]);
117 C ^= f1(D, kr(i*4+0, ctx), ctx->km[i][0]);
120 void cast6_enc(void* buffer, const cast6_ctx_t* ctx){
122 for(i=0; i<32/4; ++i){
123 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
129 qbar(buffer, i, ctx);
131 for(i=0; i<32/4; ++i){
132 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
136 void cast6_dec(void* buffer, const cast6_ctx_t* ctx){
138 for(i=0; i<32/4; ++i){
139 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
145 qbar(buffer, i-1, ctx);
147 for(i=0; i<32/4; ++i){
148 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
158 #define A (((uint32_t*)buffer)[0])
159 #define B (((uint32_t*)buffer)[1])
160 #define C (((uint32_t*)buffer)[2])
161 #define D (((uint32_t*)buffer)[3])
162 #define E (((uint32_t*)buffer)[4])
163 #define F (((uint32_t*)buffer)[5])
164 #define G (((uint32_t*)buffer)[6])
165 #define H (((uint32_t*)buffer)[7])
168 * we might later make it optional to use this small thing
170 void w(void* buffer, uint8_t* tr, uint32_t* tm){
171 G ^= f1(H, (tr[0]&0x0f)+(tr[5]&0x01)?0x10:0x00, tm[0]);
172 F ^= f2(G, (tr[0]>>4) +(tr[5]&0x02)?0x10:0x00, tm[1]);
173 E ^= f3(F, (tr[1]&0x0f)+(tr[5]&0x04)?0x10:0x00, tm[2]);
174 D ^= f1(E, (tr[1]>>4) +(tr[5]&0x08)?0x10:0x00, tm[3]);
175 C ^= f2(D, (tr[2]&0x0f)+(tr[5]&0x10)?0x10:0x00, tm[4]);
176 B ^= f3(C, (tr[2]>>4) +(tr[5]&0x20)?0x10:0x00, tm[5]);
177 A ^= f1(B, (tr[3]&0x0f)+(tr[5]&0x40)?0x10:0x00, tm[6]);
178 H ^= f2(A, (tr[3]>>4) +(tr[5]&0x80)?0x10:0x00, tm[7]);
182 void w(void* buffer, uint8_t* tr, uint32_t* tm){
183 G ^= f1(H, tr[0], tm[0]);
184 F ^= f2(G, tr[1], tm[1]);
185 E ^= f3(F, tr[2], tm[2]);
186 D ^= f1(E, tr[3], tm[3]);
187 C ^= f2(D, tr[4], tm[4]);
188 B ^= f3(C, tr[5], tm[5]);
189 A ^= f1(B, tr[6], tm[6]);
190 H ^= f2(A, tr[7], tm[7]);
194 void dump_ctx(const cast6_ctx_t* ctx){
196 cli_putstr("\r\n DBG:");
198 cli_putstr("\r\n DBG:");
199 cli_putstr(" rotk1=");
202 cli_putstr(" rotk2=");
205 cli_putstr(" rotk3=");
208 cli_putstr(" rotk4=");
212 cli_putstr(" mask1=");
213 cli_hexdump(&(ctx->km[i][0]),4);
214 cli_putstr(" mask2=");
215 cli_hexdump(&(ctx->km[i][1]),4);
216 cli_putstr(" mask3=");
217 cli_hexdump(&(ctx->km[i][2]),4);
218 cli_putstr(" mask4=");
219 cli_hexdump(&(ctx->km[i][3]),4);
220 cli_putstr("\r\n;-----");
226 #define CM 0x5A827999
228 #define MM 0x6ED9EBA1
230 void cast6_init(const void* key, uint16_t keysize_b, cast6_ctx_t* ctx){
232 uint8_t cr=CR, tr[8];
233 uint32_t cm=CM, tm[8];
236 memset(buffer, 0, 32);
237 memcpy(buffer, key, (keysize_b+7)/8);
238 for(i=0; i<32/4; ++i){
239 ((uint32_t*)buffer)[i] = CHANGE_ENDIAN32(((uint32_t*)buffer)[i]);
257 set_kr((uint8_t)A,j*4+0,ctx);
258 set_kr((uint8_t)C,j*4+1,ctx);
259 set_kr((uint8_t)E,j*4+2,ctx);
260 set_kr((uint8_t)G,j*4+3,ctx);