Coverage Report

Created: 2022-12-08 06:09

/src/libgcrypt/cipher/idea.c
Line
Count
Source (jump to first uncovered line)
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
#include "cipher-internal.h"
52
53
54
#define IDEA_KEYSIZE 16
55
#define IDEA_BLOCKSIZE 8
56
0
#define IDEA_ROUNDS 8
57
0
#define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
58
59
typedef struct {
60
    u16 ek[IDEA_KEYLEN];
61
    u16 dk[IDEA_KEYLEN];
62
    int have_dk;
63
} IDEA_context;
64
65
static const char *selftest(void);
66
67
68
static u16
69
mul_inv( u16 x )
70
0
{
71
0
    u16 t0, t1;
72
0
    u16 q, y;
73
74
0
    if( x < 2 )
75
0
  return x;
76
0
    t1 = 0x10001UL / x;
77
0
    y =  0x10001UL % x;
78
0
    if( y == 1 )
79
0
  return (1-t1) & 0xffff;
80
81
0
    t0 = 1;
82
0
    do {
83
0
  q = x / y;
84
0
  x = x % y;
85
0
  t0 += q * t1;
86
0
  if( x == 1 )
87
0
      return t0;
88
0
  q = y / x;
89
0
  y = y % x;
90
0
  t1 += q * t0;
91
0
    } while( y != 1 );
92
0
    return (1-t1) & 0xffff;
93
0
}
94
95
96
97
static void
98
expand_key( const byte *userkey, u16 *ek )
99
0
{
100
0
    int i,j;
101
102
0
    for(j=0; j < 8; j++ ) {
103
0
  ek[j] = (*userkey << 8) + userkey[1];
104
0
  userkey += 2;
105
0
    }
106
0
    for(i=0; j < IDEA_KEYLEN; j++ ) {
107
0
  i++;
108
0
  ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7;
109
0
  ek += i & 8;
110
0
  i &= 7;
111
0
    }
112
0
}
113
114
115
static void
116
invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] )
117
0
{
118
0
    int i;
119
0
    u16 t1, t2, t3;
120
0
    u16 temp[IDEA_KEYLEN];
121
0
    u16 *p = temp + IDEA_KEYLEN;
122
123
0
    t1 = mul_inv( *ek++ );
124
0
    t2 = -*ek++;
125
0
    t3 = -*ek++;
126
0
    *--p = mul_inv( *ek++ );
127
0
    *--p = t3;
128
0
    *--p = t2;
129
0
    *--p = t1;
130
131
0
    for(i=0; i < IDEA_ROUNDS-1; i++ ) {
132
0
  t1 = *ek++;
133
0
  *--p = *ek++;
134
0
  *--p = t1;
135
136
0
  t1 = mul_inv( *ek++ );
137
0
  t2 = -*ek++;
138
0
  t3 = -*ek++;
139
0
  *--p = mul_inv( *ek++ );
140
0
  *--p = t2;
141
0
  *--p = t3;
142
0
  *--p = t1;
143
0
    }
144
0
    t1 = *ek++;
145
0
    *--p = *ek++;
146
0
    *--p = t1;
147
148
0
    t1 = mul_inv( *ek++ );
149
0
    t2 = -*ek++;
150
0
    t3 = -*ek++;
151
0
    *--p = mul_inv( *ek++ );
152
0
    *--p = t3;
153
0
    *--p = t2;
154
0
    *--p = t1;
155
0
    memcpy(dk, temp, sizeof(temp) );
156
0
    wipememory(temp, sizeof(temp));
157
0
}
158
159
160
static void
161
cipher( byte *outbuf, const byte *inbuf, u16 *key )
162
0
{
163
0
    u16 s2, s3;
164
0
    u16 in[4];
165
0
    int r = IDEA_ROUNDS;
166
0
#define x1 (in[0])
167
0
#define x2 (in[1])
168
0
#define x3 (in[2])
169
0
#define x4 (in[3])
170
0
#define MUL(x,y) \
171
0
  do {u16 _t16; u32 _t32;        \
172
0
      if( (_t16 = (y)) ) {       \
173
0
    if( (x = (x)&0xffff) ) {     \
174
0
        _t32 = (u32)x * _t16;     \
175
0
        x = _t32 & 0xffff;        \
176
0
        _t16 = _t32 >> 16;        \
177
0
        x = ((x)-_t16) + (x<_t16?1:0);  \
178
0
    }           \
179
0
    else {           \
180
0
        x = 1 - _t16;       \
181
0
    }            \
182
0
      }             \
183
0
      else {           \
184
0
    x = 1 - x;          \
185
0
      }              \
186
0
  } while(0)
187
188
0
    memcpy (in, inbuf, sizeof in);
189
0
#ifndef WORDS_BIGENDIAN
190
0
    x1 = (x1>>8) | (x1<<8);
191
0
    x2 = (x2>>8) | (x2<<8);
192
0
    x3 = (x3>>8) | (x3<<8);
193
0
    x4 = (x4>>8) | (x4<<8);
194
0
#endif
195
0
    do {
196
0
  MUL(x1, *key++);
197
0
  x2 += *key++;
198
0
  x3 += *key++;
199
0
  MUL(x4, *key++ );
200
201
0
  s3 = x3;
202
0
  x3 ^= x1;
203
0
  MUL(x3, *key++);
204
0
  s2 = x2;
205
0
  x2 ^=x4;
206
0
  x2 += x3;
207
0
  MUL(x2, *key++);
208
0
  x3 += x2;
209
210
0
  x1 ^= x2;
211
0
  x4 ^= x3;
212
213
0
  x2 ^= s3;
214
0
  x3 ^= s2;
215
0
    } while( --r );
216
0
    MUL(x1, *key++);
217
0
    x3 += *key++;
218
0
    x2 += *key++;
219
0
    MUL(x4, *key);
220
221
0
#ifndef WORDS_BIGENDIAN
222
0
    x1 = (x1>>8) | (x1<<8);
223
0
    x2 = (x2>>8) | (x2<<8);
224
0
    x3 = (x3>>8) | (x3<<8);
225
0
    x4 = (x4>>8) | (x4<<8);
226
0
#endif
227
0
    memcpy (outbuf+0, &x1, 2);
228
0
    memcpy (outbuf+2, &x3, 2);
229
0
    memcpy (outbuf+4, &x2, 2);
230
0
    memcpy (outbuf+6, &x4, 2);
231
0
#undef MUL
232
0
#undef x1
233
0
#undef x2
234
0
#undef x3
235
0
#undef x4
236
0
}
237
238
239
static int
240
do_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
241
0
{
242
0
    static int initialized = 0;
243
0
    static const char *selftest_failed = 0;
244
245
0
    if( !initialized ) {
246
0
  initialized = 1;
247
0
  selftest_failed = selftest();
248
0
  if( selftest_failed )
249
0
      log_error( "%s\n", selftest_failed );
250
0
    }
251
0
    if( selftest_failed )
252
0
  return GPG_ERR_SELFTEST_FAILED;
253
254
0
    if (keylen != 16)
255
0
      return GPG_ERR_INV_KEYLEN;
256
257
0
    c->have_dk = 0;
258
0
    expand_key( key, c->ek );
259
0
    invert_key( c->ek, c->dk );
260
0
    return 0;
261
0
}
262
263
static gcry_err_code_t
264
idea_setkey (void *context, const byte *key, unsigned int keylen,
265
             cipher_bulk_ops_t *bulk_ops)
266
0
{
267
0
    IDEA_context *ctx = context;
268
0
    int rc = do_setkey (ctx, key, keylen);
269
0
    (void)bulk_ops;
270
0
    _gcry_burn_stack (23+6*sizeof(void*));
271
0
    return rc;
272
0
}
273
274
static void
275
encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
276
0
{
277
0
    cipher( outbuf, inbuf, c->ek );
278
0
}
279
280
static unsigned int
281
idea_encrypt (void *context, byte *out, const byte *in)
282
0
{
283
0
    IDEA_context *ctx = context;
284
0
    encrypt_block (ctx, out, in);
285
0
    return /*burn_stack*/ (24+3*sizeof (void*));
286
0
}
287
288
static void
289
decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf )
290
0
{
291
0
    if( !c->have_dk ) {
292
0
       c->have_dk = 1;
293
0
       invert_key( c->ek, c->dk );
294
0
    }
295
0
    cipher( outbuf, inbuf, c->dk );
296
0
}
297
298
static unsigned int
299
idea_decrypt (void *context, byte *out, const byte *in)
300
0
{
301
0
    IDEA_context *ctx = context;
302
0
    decrypt_block (ctx, out, in);
303
0
    return /*burn_stack*/ (24+3*sizeof (void*));
304
0
}
305
306
307
static const char *
308
selftest( void )
309
0
{
310
0
static struct {
311
0
    byte key[16];
312
0
    byte plain[8];
313
0
    byte cipher[8];
314
0
} test_vectors[] = {
315
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
316
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
317
0
      { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 },
318
0
      { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } },
319
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
320
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
321
0
      { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
322
0
      { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } },
323
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
324
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
325
0
      { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF },
326
0
      { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } },
327
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
328
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
329
0
      { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 },
330
0
      { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } },
331
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
332
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
333
0
      { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E },
334
0
      { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } },
335
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
336
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
337
0
      { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 },
338
0
      { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } },
339
0
    { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
340
0
  0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },
341
0
      { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 },
342
0
      { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } },
343
0
    { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14,
344
0
  0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 },
345
0
      { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
346
0
      { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } },
347
0
    { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3,
348
0
  0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 },
349
0
      { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
350
0
      { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } },
351
0
    { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90,
352
0
  0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 },
353
0
      { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA },
354
0
      { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } },
355
0
    { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A,
356
0
  0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 },
357
0
      { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 },
358
0
      { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } }
359
0
};
360
0
    IDEA_context c;
361
0
    byte buffer[8];
362
0
    int i;
363
364
0
    for(i=0; i < DIM(test_vectors); i++ ) {
365
0
  do_setkey( &c, test_vectors[i].key, 16 );
366
0
  encrypt_block( &c, buffer, test_vectors[i].plain );
367
0
  if( memcmp( buffer, test_vectors[i].cipher, 8 ) )
368
0
      return "IDEA test encryption failed.";
369
0
  decrypt_block( &c, buffer, test_vectors[i].cipher );
370
0
  if( memcmp( buffer, test_vectors[i].plain, 8 ) )
371
0
      return "IDEA test decryption failed.";
372
0
    }
373
374
0
    return NULL;
375
0
}
376
377
378
gcry_cipher_spec_t _gcry_cipher_spec_idea =
379
  {
380
    GCRY_CIPHER_IDEA, {0, 0},
381
    "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128,
382
    sizeof (IDEA_context),
383
    idea_setkey, idea_encrypt, idea_decrypt
384
  };