gcrypt/idea.c

changeset 107
2f8ffdf7658b
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gcrypt/idea.c	Sat Feb 21 16:39:01 2009 +0100
     1.3 @@ -0,0 +1,272 @@
     1.4 +#include <config.h>
     1.5 +#include <stdio.h>
     1.6 +#include <stdlib.h>
     1.7 +#include <string.h> /* for memcmp() */
     1.8 +#include <assert.h>
     1.9 +
    1.10 +#include "types.h"  /* for byte and u32 typedefs */
    1.11 +#include "g10lib.h"
    1.12 +#include "cipher.h"
    1.13 +
    1.14 +/* configuration stuff */
    1.15 +#ifdef __alpha__
    1.16 +  #define SIZEOF_UNSIGNED_LONG 8
    1.17 +#else
    1.18 +  #define SIZEOF_UNSIGNED_LONG 4
    1.19 +#endif
    1.20 +
    1.21 +#if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \
    1.22 +    || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \
    1.23 +    || defined(__powerpc__) \
    1.24 +    || defined(__hpux__) /* should be replaced by the Macro for the PA */
    1.25 +  #define BIG_ENDIAN_HOST 1
    1.26 +#else
    1.27 +  #define LITTLE_ENDIAN_HOST 1
    1.28 +#endif
    1.29 +
    1.30 +#ifndef DIM
    1.31 +  #define DIM(v) (sizeof(v)/sizeof((v)[0]))
    1.32 +  #define DIMof(type,member)   DIM(((type *)0)->member)
    1.33 +#endif
    1.34 +
    1.35 +/* imports */
    1.36 +void g10_log_fatal( const char *fmt, ... );
    1.37 +
    1.38 +
    1.39 +/* local stuff */
    1.40 +
    1.41 +#define FNCCAST_SETKEY(f)  ((int(*)(void*, byte*, unsigned))(f))
    1.42 +#define FNCCAST_CRYPT(f)   ((void(*)(void*, byte*, byte*))(f))
    1.43 +
    1.44 +#define IDEA_KEYSIZE 16
    1.45 +#define IDEA_BLOCKSIZE 8
    1.46 +#define IDEA_ROUNDS 8
    1.47 +#define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
    1.48 +
    1.49 +typedef struct {
    1.50 +    u16 ek[IDEA_KEYLEN];
    1.51 +    u16 dk[IDEA_KEYLEN];
    1.52 +    int have_dk;
    1.53 +} IDEA_context;
    1.54 +
    1.55 +static u16
    1.56 +mul_inv( u16 x )
    1.57 +{
    1.58 +    u16 t0, t1;
    1.59 +    u16 q, y;
    1.60 +
    1.61 +    if( x < 2 )
    1.62 +	return x;
    1.63 +    t1 = 0x10001L / x;
    1.64 +    y =  0x10001L % x;
    1.65 +    if( y == 1 )
    1.66 +	return (1-t1) & 0xffff;
    1.67 +
    1.68 +    t0 = 1;
    1.69 +    do {
    1.70 +	q = x / y;
    1.71 +	x = x % y;
    1.72 +	t0 += q * t1;
    1.73 +	if( x == 1 )
    1.74 +	    return t0;
    1.75 +	q = y / x;
    1.76 +	y = y % x;
    1.77 +	t1 += q * t0;
    1.78 +    } while( y != 1 );
    1.79 +    return (1-t1) & 0xffff;
    1.80 +}
    1.81 +
    1.82 +static void
    1.83 +cipher( byte *outbuf, const byte *inbuf, u16 *key )
    1.84 +{
    1.85 +    u16 x1, x2, x3,x4, s2, s3;
    1.86 +    u16 *in, *out;
    1.87 +    int r = IDEA_ROUNDS;
    1.88 +  #define MUL(x,y) \
    1.89 +	do {u16 _t16; u32 _t32; 		    \
    1.90 +	    if( (_t16 = (y)) ) {		    \
    1.91 +		if( (x = (x)&0xffff) ) {	    \
    1.92 +		    _t32 = (u32)x * _t16;	    \
    1.93 +		    x = _t32 & 0xffff;		    \
    1.94 +		    _t16 = _t32 >> 16;		    \
    1.95 +		    x = ((x)-_t16) + (x<_t16?1:0);  \
    1.96 +		}				    \
    1.97 +		else {				    \
    1.98 +		    x = 1 - _t16;		    \
    1.99 +		}				    \
   1.100 +	    }					    \
   1.101 +	    else {				    \
   1.102 +		x = 1 - x;			    \
   1.103 +	    }					    \
   1.104 +	} while(0)
   1.105 +
   1.106 +    in = (u16*)inbuf;
   1.107 +    x1 = *in++;
   1.108 +    x2 = *in++;
   1.109 +    x3 = *in++;
   1.110 +    x4 = *in;
   1.111 +  #ifdef LITTLE_ENDIAN_HOST
   1.112 +    x1 = (x1>>8) | (x1<<8);
   1.113 +    x2 = (x2>>8) | (x2<<8);
   1.114 +    x3 = (x3>>8) | (x3<<8);
   1.115 +    x4 = (x4>>8) | (x4<<8);
   1.116 +  #endif
   1.117 +    do {
   1.118 +	MUL(x1, *key++);
   1.119 +	x2 += *key++;
   1.120 +	x3 += *key++;
   1.121 +	MUL(x4, *key++ );
   1.122 +
   1.123 +	s3 = x3;
   1.124 +	x3 ^= x1;
   1.125 +	MUL(x3, *key++);
   1.126 +	s2 = x2;
   1.127 +	x2 ^=x4;
   1.128 +	x2 += x3;
   1.129 +	MUL(x2, *key++);
   1.130 +	x3 += x2;
   1.131 +
   1.132 +	x1 ^= x2;
   1.133 +	x4 ^= x3;
   1.134 +
   1.135 +	x2 ^= s3;
   1.136 +	x3 ^= s2;
   1.137 +    } while( --r );
   1.138 +    MUL(x1, *key++);
   1.139 +    x3 += *key++;
   1.140 +    x2 += *key++;
   1.141 +    MUL(x4, *key);
   1.142 +
   1.143 +    out = (u16*)outbuf;
   1.144 +  #ifdef LITTLE_ENDIAN_HOST
   1.145 +    *out++ = (x1>>8) | (x1<<8);
   1.146 +    *out++ = (x3>>8) | (x3<<8);
   1.147 +    *out++ = (x2>>8) | (x2<<8);
   1.148 +    *out   = (x4>>8) | (x4<<8);
   1.149 +  #else
   1.150 +    *out++ = x1;
   1.151 +    *out++ = x3;
   1.152 +    *out++ = x2;
   1.153 +    *out   = x4;
   1.154 +  #endif
   1.155 +  #undef MUL
   1.156 +}
   1.157 +
   1.158 +static void
   1.159 +expand_key( const byte *userkey, u16 *ek )
   1.160 +{
   1.161 +    int i,j;
   1.162 +
   1.163 +    for(j=0; j < 8; j++ ) {
   1.164 +	ek[j] = (*userkey << 8) + userkey[1];
   1.165 +	userkey += 2;
   1.166 +    }
   1.167 +    for(i=0; j < IDEA_KEYLEN; j++ ) {
   1.168 +	i++;
   1.169 +	ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7;
   1.170 +	ek += i & 8;
   1.171 +	i &= 7;
   1.172 +    }
   1.173 +}
   1.174 +
   1.175 +static void
   1.176 +invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] )
   1.177 +{
   1.178 +    int i;
   1.179 +    u16 t1, t2, t3;
   1.180 +    u16 temp[IDEA_KEYLEN];
   1.181 +    u16 *p = temp + IDEA_KEYLEN;
   1.182 +
   1.183 +    t1 = mul_inv( *ek++ );
   1.184 +    t2 = -*ek++;
   1.185 +    t3 = -*ek++;
   1.186 +    *--p = mul_inv( *ek++ );
   1.187 +    *--p = t3;
   1.188 +    *--p = t2;
   1.189 +    *--p = t1;
   1.190 +
   1.191 +    for(i=0; i < IDEA_ROUNDS-1; i++ ) {
   1.192 +	t1 = *ek++;
   1.193 +	*--p = *ek++;
   1.194 +	*--p = t1;
   1.195 +
   1.196 +	t1 = mul_inv( *ek++ );
   1.197 +	t2 = -*ek++;
   1.198 +	t3 = -*ek++;
   1.199 +	*--p = mul_inv( *ek++ );
   1.200 +	*--p = t2;
   1.201 +	*--p = t3;
   1.202 +	*--p = t1;
   1.203 +    }
   1.204 +    t1 = *ek++;
   1.205 +    *--p = *ek++;
   1.206 +    *--p = t1;
   1.207 +
   1.208 +    t1 = mul_inv( *ek++ );
   1.209 +    t2 = -*ek++;
   1.210 +    t3 = -*ek++;
   1.211 +    *--p = mul_inv( *ek++ );
   1.212 +    *--p = t3;
   1.213 +    *--p = t2;
   1.214 +    *--p = t1;
   1.215 +    memcpy(dk, temp, sizeof(temp) );
   1.216 +    memset(temp, 0, sizeof(temp) );  /* burn temp */
   1.217 +}
   1.218 +
   1.219 +static int
   1.220 +do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
   1.221 +{
   1.222 +    assert(keylen == 16);
   1.223 +    c->have_dk = 0;
   1.224 +    expand_key( key, c->ek );
   1.225 +    invert_key( c->ek, c->dk );
   1.226 +    return 0;
   1.227 +}
   1.228 +
   1.229 +static gcry_err_code_t
   1.230 +idea_setkey (void *context, const byte *key, unsigned int keylen)
   1.231 +{
   1.232 +  IDEA_context *ctx = context;
   1.233 +  int rc = do_idea_setkey (ctx, key, keylen);
   1.234 +  _gcry_burn_stack (23+6*sizeof(void*));
   1.235 +  return rc;
   1.236 +}
   1.237 +
   1.238 +static void
   1.239 +do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
   1.240 +{
   1.241 +    cipher( outbuf, inbuf, c->ek );
   1.242 +}
   1.243 +
   1.244 +static void
   1.245 +idea_encrypt (void *context, byte *out, const byte *in)
   1.246 +{
   1.247 +  IDEA_context *ctx = context;
   1.248 +  do_idea_encrypt (ctx, out, in);
   1.249 +  _gcry_burn_stack (24+3*sizeof (void*));
   1.250 +}
   1.251 +
   1.252 +static void
   1.253 +do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
   1.254 +{
   1.255 +    if( !c->have_dk ) {
   1.256 +       c->have_dk = 1;
   1.257 +       invert_key( c->ek, c->dk );
   1.258 +    }
   1.259 +    cipher( outbuf, inbuf, c->dk );
   1.260 +}
   1.261 +
   1.262 +static void
   1.263 +idea_decrypt (void *context, byte *out, const byte *in)
   1.264 +{
   1.265 +  IDEA_context *ctx = context;
   1.266 +
   1.267 +  do_idea_decrypt (ctx, out, in);
   1.268 +  _gcry_burn_stack (24+3*sizeof (void*));
   1.269 +}
   1.270 +
   1.271 +gcry_cipher_spec_t _gcry_cipher_spec_idea =
   1.272 +{
   1.273 +    "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context),
   1.274 +    idea_setkey, idea_encrypt, idea_decrypt,
   1.275 +};

mercurial