Pass cipher object pointer to setkey functions
[libgcrypt.git] / cipher / idea.c
1 /* idea.c  -  IDEA function
2  * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn)
3  * Copyright 2013 g10 Code GmbH
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Except as contained in this notice, the name of Werner Koch shall not be
23  * used in advertising or otherwise to promote the sale, use or other dealings
24  * in this Software without prior written authorization from Werner Koch.
25  *
26  * Patents on IDEA have expired:
27  *   Europe: EP0482154 on 2011-05-16,
28  *   Japan:  JP3225440 on 2011-05-16,
29  *   U.S.:   5,214,703 on 2012-01-07.
30  */
31
32 /*
33  * Please see http://www.noepatents.org/ to learn why software patents
34  * are bad for society and what you can do to fight them.
35  *
36  * The code herein is based on the one from:
37  *   Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
38  *   ISBN 0-471-11709-9.
39  */
40
41
42 #include <config.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <assert.h>
47
48 #include "types.h"  /* for byte and u32 typedefs */
49 #include "g10lib.h"
50 #include "cipher.h"
51
52
53 #define IDEA_KEYSIZE 16
54 #define IDEA_BLOCKSIZE 8
55 #define IDEA_ROUNDS 8
56 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
57
58 typedef struct {
59     u16 ek[IDEA_KEYLEN];
60     u16 dk[IDEA_KEYLEN];
61     int have_dk;
62 } IDEA_context;
63
64 static const char *selftest(void);
65
66
67 static u16
68 mul_inv( u16 x )
69 {
70     u16 t0, t1;
71     u16 q, y;
72
73     if( x < 2 )
74         return x;
75     t1 = 0x10001UL / x;
76     y =  0x10001UL % x;
77     if( y == 1 )
78         return (1-t1) & 0xffff;
79
80     t0 = 1;
81     do {
82         q = x / y;
83         x = x % y;
84         t0 += q * t1;
85         if( x == 1 )
86             return t0;
87         q = y / x;
88         y = y % x;
89         t1 += q * t0;
90     } while( y != 1 );
91     return (1-t1) & 0xffff;
92 }
93
94
95
96 static void
97 expand_key( const byte *userkey, u16 *ek )
98 {
99     int i,j;
100
101     for(j=0; j < 8; j++ ) {
102         ek[j] = (*userkey << 8) + userkey[1];
103         userkey += 2;
104     }
105     for(i=0; j < IDEA_KEYLEN; j++ ) {
106         i++;
107         ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7;
108         ek += i & 8;
109         i &= 7;
110     }
111 }
112
113
114 static void
115 invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] )
116 {
117     int i;
118     u16 t1, t2, t3;
119     u16 temp[IDEA_KEYLEN];
120     u16 *p = temp + IDEA_KEYLEN;
121
122     t1 = mul_inv( *ek++ );
123     t2 = -*ek++;
124     t3 = -*ek++;
125     *--p = mul_inv( *ek++ );
126     *--p = t3;
127     *--p = t2;
128     *--p = t1;
129
130     for(i=0; i < IDEA_ROUNDS-1; i++ ) {
131         t1 = *ek++;
132         *--p = *ek++;
133         *--p = t1;
134
135         t1 = mul_inv( *ek++ );
136         t2 = -*ek++;
137         t3 = -*ek++;
138         *--p = mul_inv( *ek++ );
139         *--p = t2;
140         *--p = t3;
141         *--p = t1;
142     }
143     t1 = *ek++;
144     *--p = *ek++;
145     *--p = t1;
146
147     t1 = mul_inv( *ek++ );
148     t2 = -*ek++;
149     t3 = -*ek++;
150     *--p = mul_inv( *ek++ );
151     *--p = t3;
152     *--p = t2;
153     *--p = t1;
154     memcpy(dk, temp, sizeof(temp) );
155     wipememory(temp, sizeof(temp));
156 }
157
158
159 static void
160 cipher( byte *outbuf, const byte *inbuf, u16 *key )
161 {
162     u16 s2, s3;
163     u16 in[4];
164     int r = IDEA_ROUNDS;
165 #define x1 (in[0])
166 #define x2 (in[1])
167 #define x3 (in[2])
168 #define x4 (in[3])
169 #define MUL(x,y) \
170         do {u16 _t16; u32 _t32;                     \
171             if( (_t16 = (y)) ) {                    \
172                 if( (x = (x)&0xffff) ) {            \
173                     _t32 = (u32)x * _t16;           \
174                     x = _t32 & 0xffff;              \
175                     _t16 = _t32 >> 16;              \
176                     x = ((x)-_t16) + (x<_t16?1:0);  \
177                 }                                   \
178                 else {                              \
179                     x = 1 - _t16;                   \
180                 }                                   \
181             }                                       \
182             else {                                  \
183                 x = 1 - x;                          \
184             }                                       \
185         } while(0)
186
187     memcpy (in, inbuf, sizeof in);
188 #ifndef WORDS_BIGENDIAN
189     x1 = (x1>>8) | (x1<<8);
190     x2 = (x2>>8) | (x2<<8);
191     x3 = (x3>>8) | (x3<<8);
192     x4 = (x4>>8) | (x4<<8);
193 #endif
194     do {
195         MUL(x1, *key++);
196         x2 += *key++;
197         x3 += *key++;
198         MUL(x4, *key++ );
199
200         s3 = x3;
201         x3 ^= x1;
202         MUL(x3, *key++);
203         s2 = x2;
204         x2 ^=x4;
205         x2 += x3;
206         MUL(x2, *key++);
207         x3 += x2;
208
209         x1 ^= x2;
210         x4 ^= x3;
211
212         x2 ^= s3;
213         x3 ^= s2;
214     } while( --r );
215     MUL(x1, *key++);
216     x3 += *key++;
217     x2 += *key++;
218     MUL(x4, *key);
219
220 #ifndef WORDS_BIGENDIAN
221     x1 = (x1>>8) | (x1<<8);
222     x2 = (x2>>8) | (x2<<8);
223     x3 = (x3>>8) | (x3<<8);
224     x4 = (x4>>8) | (x4<<8);
225 #endif
226     memcpy (outbuf+0, &x1, 2);
227     memcpy (outbuf+2, &x3, 2);
228     memcpy (outbuf+4, &x2, 2);
229     memcpy (outbuf+6, &x4, 2);
230 #undef MUL
231 #undef x1
232 #undef x2
233 #undef x3
234 #undef x4
235 }
236
237
238 static int
239 do_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
240 {
241     static int initialized = 0;
242     static const char *selftest_failed = 0;
243
244     if( !initialized ) {
245         initialized = 1;
246         selftest_failed = selftest();
247         if( selftest_failed )
248             log_error( "%s\n", selftest_failed );
249     }
250     if( selftest_failed )
251         return GPG_ERR_SELFTEST_FAILED;
252
253     assert(keylen == 16);
254     c->have_dk = 0;
255     expand_key( key, c->ek );
256     invert_key( c->ek, c->dk );
257     return 0;
258 }
259
260 static gcry_err_code_t
261 idea_setkey (void *context, const byte *key, unsigned int keylen,
262              gcry_cipher_hd_t hd)
263 {
264     IDEA_context *ctx = context;
265     int rc = do_setkey (ctx, key, keylen);
266     (void)hd;
267     _gcry_burn_stack (23+6*sizeof(void*));
268     return rc;
269 }
270
271 static void
272 encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
273 {
274     cipher( outbuf, inbuf, c->ek );
275 }
276
277 static unsigned int
278 idea_encrypt (void *context, byte *out, const byte *in)
279 {
280     IDEA_context *ctx = context;
281     encrypt_block (ctx, out, in);
282     return /*burn_stack*/ (24+3*sizeof (void*));
283 }
284
285 static void
286 decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
287 {
288     if( !c->have_dk ) {
289        c->have_dk = 1;
290        invert_key( c->ek, c->dk );
291     }
292     cipher( outbuf, inbuf, c->dk );
293 }
294
295 static unsigned int
296 idea_decrypt (void *context, byte *out, const byte *in)
297 {
298     IDEA_context *ctx = context;
299     decrypt_block (ctx, out, in);
300     return /*burn_stack*/ (24+3*sizeof (void*));
301 }
302
303
304 static const char *
305 selftest( void )
306 {
307 static struct {
308     byte key[16];
309     byte plain[8];
310     byte cipher[8];
311 } test_vectors[] = {
312     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
313         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
314       { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 },
315       { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } },
316     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
317         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
318       { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
319       { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } },
320     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
321         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
322       { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF },
323       { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } },
324     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
325         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
326       { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 },
327       { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } },
328     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
329         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
330       { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E },
331       { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } },
332     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
333         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
334       { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 },
335       { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } },
336     { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
337         0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
338       { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 },
339       { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } },
340     { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14,
341         0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 },
342       { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
343       { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } },
344     { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3,
345         0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 },
346       { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
347       { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } },
348     { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90,
349         0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 },
350       { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA },
351       { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } },
352     { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A,
353         0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 },
354       { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 },
355       { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } }
356 };
357     IDEA_context c;
358     byte buffer[8];
359     int i;
360
361     for(i=0; i < DIM(test_vectors); i++ ) {
362         do_setkey( &c, test_vectors[i].key, 16 );
363         encrypt_block( &c, buffer, test_vectors[i].plain );
364         if( memcmp( buffer, test_vectors[i].cipher, 8 ) )
365             return "IDEA test encryption failed.";
366         decrypt_block( &c, buffer, test_vectors[i].cipher );
367         if( memcmp( buffer, test_vectors[i].plain, 8 ) )
368             return "IDEA test decryption failed.";
369     }
370
371     return NULL;
372 }
373
374
375 gcry_cipher_spec_t _gcry_cipher_spec_idea =
376   {
377     GCRY_CIPHER_IDEA, {0, 0},
378     "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128,
379     sizeof (IDEA_context),
380     idea_setkey, idea_encrypt, idea_decrypt
381   };