5 * \brief SEED parts in C for AVR
11 #include <avr/pgmspace.h>
13 #include "seed_sbox.h"
18 static uint64_t f_function(uint64_t a, uint32_t k0, uint32_t k1);
19 static uint32_t g_function(uint32_t x);
21 /******************************************************************************/
23 void changeendian32(uint32_t * a){
24 *a = (*a & 0x000000FF) << 24 |
25 (*a & 0x0000FF00) << 8 |
26 (*a & 0x00FF0000) >> 8 |
27 (*a & 0xFF000000) >> 24;
30 /******************************************************************************/
32 void changeendian64(uint64_t * a){
33 *a = (*a & 0x00000000000000FFLL) << 56 |
34 (*a & 0x000000000000FF00LL) << 40 |
35 (*a & 0x0000000000FF0000LL) << 24 |
36 (*a & 0x00000000FF000000LL) << 8 |
37 (*a & 0x000000FF00000000LL) >> 8 |
38 (*a & 0x0000FF0000000000LL) >> 24 |
39 (*a & 0x00FF000000000000LL) >> 40 |
40 (*a & 0xFF00000000000000LL) >> 56 ;
43 /******************************************************************************/
45 uint32_t bigendian_sum32(uint32_t a, uint32_t b);/*{
53 /******************************************************************************/
55 uint32_t bigendian_sub32(uint32_t a, uint32_t b);/*{
63 /******************************************************************************/
65 uint64_t bigendian_rotl8_64(uint64_t a){
68 a = (a<<8) | (a>>(64-8));
71 a = (a>>8) | (a<<(64-8));
75 /******************************************************************************/
77 uint64_t bigendian_rotr8_64(uint64_t a){
80 a = (a>>8) | (a<<(64-8));
83 a = (a<<8) | (a>>(64-8));
87 /******************************************************************************/
89 uint64_t f_function(uint64_t a, uint32_t k0, uint32_t k1){
92 c = a & 0x00000000FFFFFFFFLL;
93 d = (a>>32) & 0x00000000FFFFFFFFLL;
98 c = bigendian_sum32(c,d);
100 d = bigendian_sum32(c,d);
102 c = bigendian_sum32(c,d);
103 a = ((uint64_t)d << 32) | c;
107 /******************************************************************************/
113 #define X3 (((uint8_t*)(&x))[0])
114 #define X2 (((uint8_t*)(&x))[1])
115 #define X1 (((uint8_t*)(&x))[2])
116 #define X0 (((uint8_t*)(&x))[3])
118 #define Z3 (((uint8_t*)(&z))[0])
119 #define Z2 (((uint8_t*)(&z))[1])
120 #define Z1 (((uint8_t*)(&z))[2])
121 #define Z0 (((uint8_t*)(&z))[3])
124 uint32_t g_function(uint32_t x){
126 /* sbox substitution */
127 X3 = pgm_read_byte(&(seed_sbox2[X3]));
128 X2 = pgm_read_byte(&(seed_sbox1[X2]));
129 X1 = pgm_read_byte(&(seed_sbox2[X1]));
130 X0 = pgm_read_byte(&(seed_sbox1[X0]));
131 /* now the permutation */
132 Z0 = (X0 & M0) ^ (X1 & M1) ^ (X2 & M2) ^ (X3 & M3);
133 Z1 = (X0 & M1) ^ (X1 & M2) ^ (X2 & M3) ^ (X3 & M0);
134 Z2 = (X0 & M2) ^ (X1 & M3) ^ (X2 & M0) ^ (X3 & M1);
135 Z3 = (X0 & M3) ^ (X1 & M0) ^ (X2 & M1) ^ (X3 & M2);
138 /******************************************************************************/
143 keypair_t getnextkeys(uint32_t *keystate, uint8_t curround){
149 /* ret.k0 = g_function(keystate[0] + keystate[2] - pgm_read_dword(&(seed_kc[curround])));
150 ret.k1 = g_function(keystate[1] - keystate[3] + pgm_read_dword(&(seed_kc[curround]))); */
151 ret.k0 = bigendian_sum32(keystate[0], keystate[2]);
152 ret.k0 = bigendian_sub32(ret.k0, pgm_read_dword(&(seed_kc[curround])));
153 ret.k0 = g_function(ret.k0);
154 ret.k1 = bigendian_sub32(keystate[1], keystate[3]);
155 ret.k1 = bigendian_sum32(ret.k1, pgm_read_dword(&(seed_kc[curround])));
156 ret.k1 = g_function(ret.k1);
159 /* odd round (1,3,5, ...) */
160 ((uint64_t*)keystate)[1] = bigendian_rotl8_64( ((uint64_t*)keystate)[1] );
162 /* even round (0,2,4, ...) */
163 ((uint64_t*)keystate)[0] = bigendian_rotr8_64(((uint64_t*)keystate)[0]);
170 /******************************************************************************/
172 keypair_t getprevkeys(uint32_t *keystate, uint8_t curround){
179 /* odd round (1,3,5, ..., 15) */
180 ((uint64_t*)keystate)[1] = bigendian_rotr8_64( ((uint64_t*)keystate)[1] );
182 /* even round (0,2,4, ..., 14) */
183 ((uint64_t*)keystate)[0] = bigendian_rotl8_64(((uint64_t*)keystate)[0]);
185 /* ret.k0 = g_function(keystate[0] + keystate[2] - pgm_read_dword(&(seed_kc[curround])));
186 ret.k1 = g_function(keystate[1] - keystate[3] + pgm_read_dword(&(seed_kc[curround]))); */
187 ret.k0 = bigendian_sum32(keystate[0], keystate[2]);
188 ret.k0 = bigendian_sub32(ret.k0, pgm_read_dword(&(seed_kc[curround])));
189 ret.k0 = g_function(ret.k0);
190 ret.k1 = bigendian_sub32(keystate[1], keystate[3]);
191 ret.k1 = bigendian_sum32(ret.k1, pgm_read_dword(&(seed_kc[curround])));
192 ret.k1 = g_function(ret.k1);
197 /******************************************************************************/
203 /******************************************************************************/
205 void seed_init(seed_ctx_t * ctx, uint8_t * key){
206 memcpy(ctx->k, key, 128/8);
209 /******************************************************************************/
211 #define L (((uint64_t*)buffer)[0])
212 #define R (((uint64_t*)buffer)[1])
214 void seed_encrypt(seed_ctx_t * ctx, void * buffer){
218 k = getnextkeys(ctx->k, 2*r);
220 DEBUG_S("\r\n\tDBG ka,0: "); uart_hexdump(&k.k0, 4);
221 DEBUG_S("\r\n\tDBG ka,1: "); uart_hexdump(&k.k1, 4);
222 DEBUG_S("\r\n\t DBG L: "); uart_hexdump((uint8_t*)buffer+0, 8);
223 DEBUG_S("\r\n\t DBG R: "); uart_hexdump((uint8_t*)buffer+8, 8);
225 L ^= f_function(R,k.k0,k.k1);
227 k = getnextkeys(ctx->k, 2*r+1);
229 DEBUG_S("\r\n\tDBG kb,0: "); uart_hexdump(&k.k0, 4);
230 DEBUG_S("\r\n\tDBG kb,1: "); uart_hexdump(&k.k1, 4);
231 DEBUG_S("\r\n\t DBG L: "); uart_hexdump((uint8_t*)buffer+8, 8);
232 DEBUG_S("\r\n\t DBG R: "); uart_hexdump((uint8_t*)buffer+0, 8);
234 R ^= f_function(L,k.k0,k.k1);
236 /* just an exchange without temp. variable */
242 /******************************************************************************/
244 #define L (((uint64_t*)buffer)[0])
245 #define R (((uint64_t*)buffer)[1])
247 void seed_decrypt(seed_ctx_t * ctx, void * buffer){
251 k = getprevkeys(ctx->k, 2*r+1);
253 DEBUG_S("\r\n\tDBG ka,0: "); uart_hexdump(&k.k0, 4);
254 DEBUG_S("\r\n\tDBG ka,1: "); uart_hexdump(&k.k1, 4);
255 DEBUG_S("\r\n\t DBG L: "); uart_hexdump((uint8_t*)buffer+0, 8);
256 DEBUG_S("\r\n\t DBG R: "); uart_hexdump((uint8_t*)buffer+8, 8);
258 L ^= f_function(R,k.k0,k.k1);
260 k = getprevkeys(ctx->k, 2*r+0);
262 DEBUG_S("\r\n\tDBG kb,0: "); uart_hexdump(&k.k0, 4);
263 DEBUG_S("\r\n\tDBG kb,1: "); uart_hexdump(&k.k1, 4);
264 DEBUG_S("\r\n\t DBG L: "); uart_hexdump((uint8_t*)buffer+8, 8);
265 DEBUG_S("\r\n\t DBG R: "); uart_hexdump((uint8_t*)buffer+0, 8);
267 R ^= f_function(L,k.k0,k.k1);
269 /* just an exchange without temp. variable */