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.

michael@107 1 #include <config.h>
michael@107 2 #include <stdio.h>
michael@107 3 #include <stdlib.h>
michael@107 4 #include <string.h> /* for memcmp() */
michael@107 5 #include <assert.h>
michael@107 6
michael@107 7 #include "types.h" /* for byte and u32 typedefs */
michael@107 8 #include "g10lib.h"
michael@107 9 #include "cipher.h"
michael@107 10
michael@107 11 /* configuration stuff */
michael@107 12 #ifdef __alpha__
michael@107 13 #define SIZEOF_UNSIGNED_LONG 8
michael@107 14 #else
michael@107 15 #define SIZEOF_UNSIGNED_LONG 4
michael@107 16 #endif
michael@107 17
michael@107 18 #if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \
michael@107 19 || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \
michael@107 20 || defined(__powerpc__) \
michael@107 21 || defined(__hpux__) /* should be replaced by the Macro for the PA */
michael@107 22 #define BIG_ENDIAN_HOST 1
michael@107 23 #else
michael@107 24 #define LITTLE_ENDIAN_HOST 1
michael@107 25 #endif
michael@107 26
michael@107 27 #ifndef DIM
michael@107 28 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
michael@107 29 #define DIMof(type,member) DIM(((type *)0)->member)
michael@107 30 #endif
michael@107 31
michael@107 32 /* imports */
michael@107 33 void g10_log_fatal( const char *fmt, ... );
michael@107 34
michael@107 35
michael@107 36 /* local stuff */
michael@107 37
michael@107 38 #define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
michael@107 39 #define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
michael@107 40
michael@107 41 #define IDEA_KEYSIZE 16
michael@107 42 #define IDEA_BLOCKSIZE 8
michael@107 43 #define IDEA_ROUNDS 8
michael@107 44 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
michael@107 45
michael@107 46 typedef struct {
michael@107 47 u16 ek[IDEA_KEYLEN];
michael@107 48 u16 dk[IDEA_KEYLEN];
michael@107 49 int have_dk;
michael@107 50 } IDEA_context;
michael@107 51
michael@107 52 static u16
michael@107 53 mul_inv( u16 x )
michael@107 54 {
michael@107 55 u16 t0, t1;
michael@107 56 u16 q, y;
michael@107 57
michael@107 58 if( x < 2 )
michael@107 59 return x;
michael@107 60 t1 = 0x10001L / x;
michael@107 61 y = 0x10001L % x;
michael@107 62 if( y == 1 )
michael@107 63 return (1-t1) & 0xffff;
michael@107 64
michael@107 65 t0 = 1;
michael@107 66 do {
michael@107 67 q = x / y;
michael@107 68 x = x % y;
michael@107 69 t0 += q * t1;
michael@107 70 if( x == 1 )
michael@107 71 return t0;
michael@107 72 q = y / x;
michael@107 73 y = y % x;
michael@107 74 t1 += q * t0;
michael@107 75 } while( y != 1 );
michael@107 76 return (1-t1) & 0xffff;
michael@107 77 }
michael@107 78
michael@107 79 static void
michael@107 80 cipher( byte *outbuf, const byte *inbuf, u16 *key )
michael@107 81 {
michael@107 82 u16 x1, x2, x3,x4, s2, s3;
michael@107 83 u16 *in, *out;
michael@107 84 int r = IDEA_ROUNDS;
michael@107 85 #define MUL(x,y) \
michael@107 86 do {u16 _t16; u32 _t32; \
michael@107 87 if( (_t16 = (y)) ) { \
michael@107 88 if( (x = (x)&0xffff) ) { \
michael@107 89 _t32 = (u32)x * _t16; \
michael@107 90 x = _t32 & 0xffff; \
michael@107 91 _t16 = _t32 >> 16; \
michael@107 92 x = ((x)-_t16) + (x<_t16?1:0); \
michael@107 93 } \
michael@107 94 else { \
michael@107 95 x = 1 - _t16; \
michael@107 96 } \
michael@107 97 } \
michael@107 98 else { \
michael@107 99 x = 1 - x; \
michael@107 100 } \
michael@107 101 } while(0)
michael@107 102
michael@107 103 in = (u16*)inbuf;
michael@107 104 x1 = *in++;
michael@107 105 x2 = *in++;
michael@107 106 x3 = *in++;
michael@107 107 x4 = *in;
michael@107 108 #ifdef LITTLE_ENDIAN_HOST
michael@107 109 x1 = (x1>>8) | (x1<<8);
michael@107 110 x2 = (x2>>8) | (x2<<8);
michael@107 111 x3 = (x3>>8) | (x3<<8);
michael@107 112 x4 = (x4>>8) | (x4<<8);
michael@107 113 #endif
michael@107 114 do {
michael@107 115 MUL(x1, *key++);
michael@107 116 x2 += *key++;
michael@107 117 x3 += *key++;
michael@107 118 MUL(x4, *key++ );
michael@107 119
michael@107 120 s3 = x3;
michael@107 121 x3 ^= x1;
michael@107 122 MUL(x3, *key++);
michael@107 123 s2 = x2;
michael@107 124 x2 ^=x4;
michael@107 125 x2 += x3;
michael@107 126 MUL(x2, *key++);
michael@107 127 x3 += x2;
michael@107 128
michael@107 129 x1 ^= x2;
michael@107 130 x4 ^= x3;
michael@107 131
michael@107 132 x2 ^= s3;
michael@107 133 x3 ^= s2;
michael@107 134 } while( --r );
michael@107 135 MUL(x1, *key++);
michael@107 136 x3 += *key++;
michael@107 137 x2 += *key++;
michael@107 138 MUL(x4, *key);
michael@107 139
michael@107 140 out = (u16*)outbuf;
michael@107 141 #ifdef LITTLE_ENDIAN_HOST
michael@107 142 *out++ = (x1>>8) | (x1<<8);
michael@107 143 *out++ = (x3>>8) | (x3<<8);
michael@107 144 *out++ = (x2>>8) | (x2<<8);
michael@107 145 *out = (x4>>8) | (x4<<8);
michael@107 146 #else
michael@107 147 *out++ = x1;
michael@107 148 *out++ = x3;
michael@107 149 *out++ = x2;
michael@107 150 *out = x4;
michael@107 151 #endif
michael@107 152 #undef MUL
michael@107 153 }
michael@107 154
michael@107 155 static void
michael@107 156 expand_key( const byte *userkey, u16 *ek )
michael@107 157 {
michael@107 158 int i,j;
michael@107 159
michael@107 160 for(j=0; j < 8; j++ ) {
michael@107 161 ek[j] = (*userkey << 8) + userkey[1];
michael@107 162 userkey += 2;
michael@107 163 }
michael@107 164 for(i=0; j < IDEA_KEYLEN; j++ ) {
michael@107 165 i++;
michael@107 166 ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7;
michael@107 167 ek += i & 8;
michael@107 168 i &= 7;
michael@107 169 }
michael@107 170 }
michael@107 171
michael@107 172 static void
michael@107 173 invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] )
michael@107 174 {
michael@107 175 int i;
michael@107 176 u16 t1, t2, t3;
michael@107 177 u16 temp[IDEA_KEYLEN];
michael@107 178 u16 *p = temp + IDEA_KEYLEN;
michael@107 179
michael@107 180 t1 = mul_inv( *ek++ );
michael@107 181 t2 = -*ek++;
michael@107 182 t3 = -*ek++;
michael@107 183 *--p = mul_inv( *ek++ );
michael@107 184 *--p = t3;
michael@107 185 *--p = t2;
michael@107 186 *--p = t1;
michael@107 187
michael@107 188 for(i=0; i < IDEA_ROUNDS-1; i++ ) {
michael@107 189 t1 = *ek++;
michael@107 190 *--p = *ek++;
michael@107 191 *--p = t1;
michael@107 192
michael@107 193 t1 = mul_inv( *ek++ );
michael@107 194 t2 = -*ek++;
michael@107 195 t3 = -*ek++;
michael@107 196 *--p = mul_inv( *ek++ );
michael@107 197 *--p = t2;
michael@107 198 *--p = t3;
michael@107 199 *--p = t1;
michael@107 200 }
michael@107 201 t1 = *ek++;
michael@107 202 *--p = *ek++;
michael@107 203 *--p = t1;
michael@107 204
michael@107 205 t1 = mul_inv( *ek++ );
michael@107 206 t2 = -*ek++;
michael@107 207 t3 = -*ek++;
michael@107 208 *--p = mul_inv( *ek++ );
michael@107 209 *--p = t3;
michael@107 210 *--p = t2;
michael@107 211 *--p = t1;
michael@107 212 memcpy(dk, temp, sizeof(temp) );
michael@107 213 memset(temp, 0, sizeof(temp) ); /* burn temp */
michael@107 214 }
michael@107 215
michael@107 216 static int
michael@107 217 do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
michael@107 218 {
michael@107 219 assert(keylen == 16);
michael@107 220 c->have_dk = 0;
michael@107 221 expand_key( key, c->ek );
michael@107 222 invert_key( c->ek, c->dk );
michael@107 223 return 0;
michael@107 224 }
michael@107 225
michael@107 226 static gcry_err_code_t
michael@107 227 idea_setkey (void *context, const byte *key, unsigned int keylen)
michael@107 228 {
michael@107 229 IDEA_context *ctx = context;
michael@107 230 int rc = do_idea_setkey (ctx, key, keylen);
michael@107 231 _gcry_burn_stack (23+6*sizeof(void*));
michael@107 232 return rc;
michael@107 233 }
michael@107 234
michael@107 235 static void
michael@107 236 do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
michael@107 237 {
michael@107 238 cipher( outbuf, inbuf, c->ek );
michael@107 239 }
michael@107 240
michael@107 241 static void
michael@107 242 idea_encrypt (void *context, byte *out, const byte *in)
michael@107 243 {
michael@107 244 IDEA_context *ctx = context;
michael@107 245 do_idea_encrypt (ctx, out, in);
michael@107 246 _gcry_burn_stack (24+3*sizeof (void*));
michael@107 247 }
michael@107 248
michael@107 249 static void
michael@107 250 do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf )
michael@107 251 {
michael@107 252 if( !c->have_dk ) {
michael@107 253 c->have_dk = 1;
michael@107 254 invert_key( c->ek, c->dk );
michael@107 255 }
michael@107 256 cipher( outbuf, inbuf, c->dk );
michael@107 257 }
michael@107 258
michael@107 259 static void
michael@107 260 idea_decrypt (void *context, byte *out, const byte *in)
michael@107 261 {
michael@107 262 IDEA_context *ctx = context;
michael@107 263
michael@107 264 do_idea_decrypt (ctx, out, in);
michael@107 265 _gcry_burn_stack (24+3*sizeof (void*));
michael@107 266 }
michael@107 267
michael@107 268 gcry_cipher_spec_t _gcry_cipher_spec_idea =
michael@107 269 {
michael@107 270 "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context),
michael@107 271 idea_setkey, idea_encrypt, idea_decrypt,
michael@107 272 };

mercurial