gcrypt/idea.c

Mon, 17 Sep 2012 19:10:10 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 17 Sep 2012 19:10:10 +0200
changeset 689
9fe04d4d4e5a
permissions
-rw-r--r--

Update to new version of vendor software although Oracle fails to deliver.
More specifically, newer db(3) patch revisions exist but Oracle has
removed them from the canonical download server URI for Berkely DB.

     1 #include <config.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <string.h> /* for memcmp() */
     5 #include <assert.h>
     7 #include "types.h"  /* for byte and u32 typedefs */
     8 #include "g10lib.h"
     9 #include "cipher.h"
    11 /* configuration stuff */
    12 #ifdef __alpha__
    13   #define SIZEOF_UNSIGNED_LONG 8
    14 #else
    15   #define SIZEOF_UNSIGNED_LONG 4
    16 #endif
    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
    27 #ifndef DIM
    28   #define DIM(v) (sizeof(v)/sizeof((v)[0]))
    29   #define DIMof(type,member)   DIM(((type *)0)->member)
    30 #endif
    32 /* imports */
    33 void g10_log_fatal( const char *fmt, ... );
    36 /* local stuff */
    38 #define FNCCAST_SETKEY(f)  ((int(*)(void*, byte*, unsigned))(f))
    39 #define FNCCAST_CRYPT(f)   ((void(*)(void*, byte*, byte*))(f))
    41 #define IDEA_KEYSIZE 16
    42 #define IDEA_BLOCKSIZE 8
    43 #define IDEA_ROUNDS 8
    44 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
    46 typedef struct {
    47     u16 ek[IDEA_KEYLEN];
    48     u16 dk[IDEA_KEYLEN];
    49     int have_dk;
    50 } IDEA_context;
    52 static u16
    53 mul_inv( u16 x )
    54 {
    55     u16 t0, t1;
    56     u16 q, y;
    58     if( x < 2 )
    59 	return x;
    60     t1 = 0x10001L / x;
    61     y =  0x10001L % x;
    62     if( y == 1 )
    63 	return (1-t1) & 0xffff;
    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 }
    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)
   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++ );
   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;
   129 	x1 ^= x2;
   130 	x4 ^= x3;
   132 	x2 ^= s3;
   133 	x3 ^= s2;
   134     } while( --r );
   135     MUL(x1, *key++);
   136     x3 += *key++;
   137     x2 += *key++;
   138     MUL(x4, *key);
   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 }
   155 static void
   156 expand_key( const byte *userkey, u16 *ek )
   157 {
   158     int i,j;
   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 }
   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;
   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;
   188     for(i=0; i < IDEA_ROUNDS-1; i++ ) {
   189 	t1 = *ek++;
   190 	*--p = *ek++;
   191 	*--p = t1;
   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;
   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 }
   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 }
   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 }
   235 static void
   236 do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
   237 {
   238     cipher( outbuf, inbuf, c->ek );
   239 }
   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 }
   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 }
   259 static void
   260 idea_decrypt (void *context, byte *out, const byte *in)
   261 {
   262   IDEA_context *ctx = context;
   264   do_idea_decrypt (ctx, out, in);
   265   _gcry_burn_stack (24+3*sizeof (void*));
   266 }
   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 };

mercurial