Fri, 03 Aug 2012 15:56:30 +0200
Use upstream man pages to avoid local help2man failures, likely due to
shell capability assumptions or cross platform environment variance.
The upstream man pages are probably better formatted anyway.
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 | }; |