| |
1 #include <config.h> |
| |
2 #include <stdio.h> |
| |
3 #include <stdlib.h> |
| |
4 #include <string.h> /* for memcmp() */ |
| |
5 #include <assert.h> |
| |
6 |
| |
7 #include "types.h" /* for byte and u32 typedefs */ |
| |
8 #include "g10lib.h" |
| |
9 #include "cipher.h" |
| |
10 |
| |
11 /* configuration stuff */ |
| |
12 #ifdef __alpha__ |
| |
13 #define SIZEOF_UNSIGNED_LONG 8 |
| |
14 #else |
| |
15 #define SIZEOF_UNSIGNED_LONG 4 |
| |
16 #endif |
| |
17 |
| |
18 #if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \ |
| |
19 || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \ |
| |
20 || defined(__powerpc__) \ |
| |
21 || defined(__hpux__) /* should be replaced by the Macro for the PA */ |
| |
22 #define BIG_ENDIAN_HOST 1 |
| |
23 #else |
| |
24 #define LITTLE_ENDIAN_HOST 1 |
| |
25 #endif |
| |
26 |
| |
27 #ifndef DIM |
| |
28 #define DIM(v) (sizeof(v)/sizeof((v)[0])) |
| |
29 #define DIMof(type,member) DIM(((type *)0)->member) |
| |
30 #endif |
| |
31 |
| |
32 /* imports */ |
| |
33 void g10_log_fatal( const char *fmt, ... ); |
| |
34 |
| |
35 |
| |
36 /* local stuff */ |
| |
37 |
| |
38 #define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) |
| |
39 #define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f)) |
| |
40 |
| |
41 #define IDEA_KEYSIZE 16 |
| |
42 #define IDEA_BLOCKSIZE 8 |
| |
43 #define IDEA_ROUNDS 8 |
| |
44 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4) |
| |
45 |
| |
46 typedef struct { |
| |
47 u16 ek[IDEA_KEYLEN]; |
| |
48 u16 dk[IDEA_KEYLEN]; |
| |
49 int have_dk; |
| |
50 } IDEA_context; |
| |
51 |
| |
52 static u16 |
| |
53 mul_inv( u16 x ) |
| |
54 { |
| |
55 u16 t0, t1; |
| |
56 u16 q, y; |
| |
57 |
| |
58 if( x < 2 ) |
| |
59 return x; |
| |
60 t1 = 0x10001L / x; |
| |
61 y = 0x10001L % x; |
| |
62 if( y == 1 ) |
| |
63 return (1-t1) & 0xffff; |
| |
64 |
| |
65 t0 = 1; |
| |
66 do { |
| |
67 q = x / y; |
| |
68 x = x % y; |
| |
69 t0 += q * t1; |
| |
70 if( x == 1 ) |
| |
71 return t0; |
| |
72 q = y / x; |
| |
73 y = y % x; |
| |
74 t1 += q * t0; |
| |
75 } while( y != 1 ); |
| |
76 return (1-t1) & 0xffff; |
| |
77 } |
| |
78 |
| |
79 static void |
| |
80 cipher( byte *outbuf, const byte *inbuf, u16 *key ) |
| |
81 { |
| |
82 u16 x1, x2, x3,x4, s2, s3; |
| |
83 u16 *in, *out; |
| |
84 int r = IDEA_ROUNDS; |
| |
85 #define MUL(x,y) \ |
| |
86 do {u16 _t16; u32 _t32; \ |
| |
87 if( (_t16 = (y)) ) { \ |
| |
88 if( (x = (x)&0xffff) ) { \ |
| |
89 _t32 = (u32)x * _t16; \ |
| |
90 x = _t32 & 0xffff; \ |
| |
91 _t16 = _t32 >> 16; \ |
| |
92 x = ((x)-_t16) + (x<_t16?1:0); \ |
| |
93 } \ |
| |
94 else { \ |
| |
95 x = 1 - _t16; \ |
| |
96 } \ |
| |
97 } \ |
| |
98 else { \ |
| |
99 x = 1 - x; \ |
| |
100 } \ |
| |
101 } while(0) |
| |
102 |
| |
103 in = (u16*)inbuf; |
| |
104 x1 = *in++; |
| |
105 x2 = *in++; |
| |
106 x3 = *in++; |
| |
107 x4 = *in; |
| |
108 #ifdef LITTLE_ENDIAN_HOST |
| |
109 x1 = (x1>>8) | (x1<<8); |
| |
110 x2 = (x2>>8) | (x2<<8); |
| |
111 x3 = (x3>>8) | (x3<<8); |
| |
112 x4 = (x4>>8) | (x4<<8); |
| |
113 #endif |
| |
114 do { |
| |
115 MUL(x1, *key++); |
| |
116 x2 += *key++; |
| |
117 x3 += *key++; |
| |
118 MUL(x4, *key++ ); |
| |
119 |
| |
120 s3 = x3; |
| |
121 x3 ^= x1; |
| |
122 MUL(x3, *key++); |
| |
123 s2 = x2; |
| |
124 x2 ^=x4; |
| |
125 x2 += x3; |
| |
126 MUL(x2, *key++); |
| |
127 x3 += x2; |
| |
128 |
| |
129 x1 ^= x2; |
| |
130 x4 ^= x3; |
| |
131 |
| |
132 x2 ^= s3; |
| |
133 x3 ^= s2; |
| |
134 } while( --r ); |
| |
135 MUL(x1, *key++); |
| |
136 x3 += *key++; |
| |
137 x2 += *key++; |
| |
138 MUL(x4, *key); |
| |
139 |
| |
140 out = (u16*)outbuf; |
| |
141 #ifdef LITTLE_ENDIAN_HOST |
| |
142 *out++ = (x1>>8) | (x1<<8); |
| |
143 *out++ = (x3>>8) | (x3<<8); |
| |
144 *out++ = (x2>>8) | (x2<<8); |
| |
145 *out = (x4>>8) | (x4<<8); |
| |
146 #else |
| |
147 *out++ = x1; |
| |
148 *out++ = x3; |
| |
149 *out++ = x2; |
| |
150 *out = x4; |
| |
151 #endif |
| |
152 #undef MUL |
| |
153 } |
| |
154 |
| |
155 static void |
| |
156 expand_key( const byte *userkey, u16 *ek ) |
| |
157 { |
| |
158 int i,j; |
| |
159 |
| |
160 for(j=0; j < 8; j++ ) { |
| |
161 ek[j] = (*userkey << 8) + userkey[1]; |
| |
162 userkey += 2; |
| |
163 } |
| |
164 for(i=0; j < IDEA_KEYLEN; j++ ) { |
| |
165 i++; |
| |
166 ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; |
| |
167 ek += i & 8; |
| |
168 i &= 7; |
| |
169 } |
| |
170 } |
| |
171 |
| |
172 static void |
| |
173 invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) |
| |
174 { |
| |
175 int i; |
| |
176 u16 t1, t2, t3; |
| |
177 u16 temp[IDEA_KEYLEN]; |
| |
178 u16 *p = temp + IDEA_KEYLEN; |
| |
179 |
| |
180 t1 = mul_inv( *ek++ ); |
| |
181 t2 = -*ek++; |
| |
182 t3 = -*ek++; |
| |
183 *--p = mul_inv( *ek++ ); |
| |
184 *--p = t3; |
| |
185 *--p = t2; |
| |
186 *--p = t1; |
| |
187 |
| |
188 for(i=0; i < IDEA_ROUNDS-1; i++ ) { |
| |
189 t1 = *ek++; |
| |
190 *--p = *ek++; |
| |
191 *--p = t1; |
| |
192 |
| |
193 t1 = mul_inv( *ek++ ); |
| |
194 t2 = -*ek++; |
| |
195 t3 = -*ek++; |
| |
196 *--p = mul_inv( *ek++ ); |
| |
197 *--p = t2; |
| |
198 *--p = t3; |
| |
199 *--p = t1; |
| |
200 } |
| |
201 t1 = *ek++; |
| |
202 *--p = *ek++; |
| |
203 *--p = t1; |
| |
204 |
| |
205 t1 = mul_inv( *ek++ ); |
| |
206 t2 = -*ek++; |
| |
207 t3 = -*ek++; |
| |
208 *--p = mul_inv( *ek++ ); |
| |
209 *--p = t3; |
| |
210 *--p = t2; |
| |
211 *--p = t1; |
| |
212 memcpy(dk, temp, sizeof(temp) ); |
| |
213 memset(temp, 0, sizeof(temp) ); /* burn temp */ |
| |
214 } |
| |
215 |
| |
216 static int |
| |
217 do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) |
| |
218 { |
| |
219 assert(keylen == 16); |
| |
220 c->have_dk = 0; |
| |
221 expand_key( key, c->ek ); |
| |
222 invert_key( c->ek, c->dk ); |
| |
223 return 0; |
| |
224 } |
| |
225 |
| |
226 static gcry_err_code_t |
| |
227 idea_setkey (void *context, const byte *key, unsigned int keylen) |
| |
228 { |
| |
229 IDEA_context *ctx = context; |
| |
230 int rc = do_idea_setkey (ctx, key, keylen); |
| |
231 _gcry_burn_stack (23+6*sizeof(void*)); |
| |
232 return rc; |
| |
233 } |
| |
234 |
| |
235 static void |
| |
236 do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) |
| |
237 { |
| |
238 cipher( outbuf, inbuf, c->ek ); |
| |
239 } |
| |
240 |
| |
241 static void |
| |
242 idea_encrypt (void *context, byte *out, const byte *in) |
| |
243 { |
| |
244 IDEA_context *ctx = context; |
| |
245 do_idea_encrypt (ctx, out, in); |
| |
246 _gcry_burn_stack (24+3*sizeof (void*)); |
| |
247 } |
| |
248 |
| |
249 static void |
| |
250 do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) |
| |
251 { |
| |
252 if( !c->have_dk ) { |
| |
253 c->have_dk = 1; |
| |
254 invert_key( c->ek, c->dk ); |
| |
255 } |
| |
256 cipher( outbuf, inbuf, c->dk ); |
| |
257 } |
| |
258 |
| |
259 static void |
| |
260 idea_decrypt (void *context, byte *out, const byte *in) |
| |
261 { |
| |
262 IDEA_context *ctx = context; |
| |
263 |
| |
264 do_idea_decrypt (ctx, out, in); |
| |
265 _gcry_burn_stack (24+3*sizeof (void*)); |
| |
266 } |
| |
267 |
| |
268 gcry_cipher_spec_t _gcry_cipher_spec_idea = |
| |
269 { |
| |
270 "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context), |
| |
271 idea_setkey, idea_encrypt, idea_decrypt, |
| |
272 }; |