|
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 }; |