gcrypt/idea.c

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     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