In case there is trouble with the FTP server with the IDEA cipher and people do want to include it, here's the copy I've obtained previously.idea.c:Code: [Select]/* idea.c - IDEA algorithm* Copyright (c) 1997, 1998, 1999, 2001, 2002 by Werner Koch (dd9jn)** Permission is hereby granted, free of charge, to any person obtaining a* copy of this software and associated documentation files (the "Software"),* to deal in the Software without restriction, including without limitation* the rights to use, copy, modify, merge, publish, distribute, sublicense,* and/or sell copies of the Software, and to permit persons to whom the* Software is furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** Except as contained in this notice, the name of Werner Koch shall not be* used in advertising or otherwise to promote the sale, use or other dealings* in this Software without prior written authorization from Werner Koch.** DUE TO PATENT CLAIMS THE DISTRIBUTION OF THE SOFTWARE IS NOT ALLOWED IN* THESE COUNTRIES: * AUSTRIA, FRANCE, GERMANY, ITALY, JAPAN, THE NETHERLANDS, * SPAIN, SWEDEN, SWITZERLAND, THE UK AND THE US.*//** Please see http://www.noepatents.org/ to learn why software patents* are bad for society and what you can do to fight them.** The code herein is based on the one from:* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.* ISBN 0-471-11709-9. .** To build a GnuPG with IDEA support, copy this file into the cipher/* directory of the gnupg distribution, and ./configure and make as* usual. IDEA will be built directly in to the GnuPG binary. This* is the recommended way to use this file.** If you are not building IDEA directly into GnuPG, and need to build* the dynamically loadable IDEA module, compile with: gcc -Wall -O2 -shared -fPIC -o idea idea.c** If you building the dynamically loadable IDEA module on a bigendian* platform (Sparc, PowerPC, etc.) and the endian detection does not* work properly for whatever reason, you will get an error like "idea* encryption (0) failed" when you use GnuPG. In that case, compile* with: gcc -Wall -O2 -shared -fPIC -DBIG_ENDIAN_HOST -o idea idea.c** How to build a Windows DLL using mingw32/cpd (see gnupg/doc/README.W32): echo EXPORTS >temp.def ; \ echo " idea_get_info" >>temp.def ; \ mingw32 gcc -c idea.c ; \ mingw32 dlltool -e temp.o --as `mingw32 --get-path as` \ --def temp.def idea.o ; \ mingw32 gcc -mdll -Wl,--base-file -Wl,temp.base \ -o idea.dll temp.o idea.o ; \ mingw32 dlltool -e temp.o --as `mingw32 --get-path as` \ --def temp.def --base-file temp.base idea.o ; \ mingw32 gcc -mdll -o idea.dll temp.o idea.o ; \ mingw32 strip idea.dll** 2001-06-08 wk Changed distribution conditions* 2001-06-11 wk Fixed invert_key (which is not used in CFB mode) * Thanks to Mark A. Borgerding. Added definition for* the PowerPC.* 2002-08-03 wk Removed dependeny to g10_log_fatal and perform selftest* in idea_get_info.* 2002-08-07 wk Removed unused macros and types etc.* 2002-09-13 wk Explained how to build a Windows DLL.* 2002-09-20 wk Made the DLL relocatable* 2002-12-11 wk __ppc__ is used on Darwin instead of __powerpc__.* 2003-02-15 dshaw Try and get endianness from config.h. Accept* __sparc and _POWER.*/#ifdef HAVE_CONFIG_H/* If we're building as part of GnuPG, we can get endianness from config.h */#include #endif#include #include #include #include #if !defined(BIG_ENDIAN_HOST) && !defined(LITTLE_ENDIAN_HOST)/* Try to handle endianness if we didn't get it from config.h */#if defined(__mc68000__) || defined (__sparc__) || defined (__sparc) \ || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \ || defined (__PPC__) || defined(__powerpc__) || defined(__ppc__) \ || defined (_POWER) \ || defined(__hpux__) /* should be replaced by the Macro for the PA */ #define BIG_ENDIAN_HOST 1#else #define LITTLE_ENDIAN_HOST 1#endif#endiftypedef unsigned short u16; /* Note: Make sure this is a 16 bit type. */typedef unsigned long u32; /* Note: Make sure this is a 32 bit type. *//* end configurable stuff */#ifndef DIM #define DIM(v) (sizeof(v)/sizeof((v)[0]))#endif/* local stuff */#define FNCCAST_SETKEY(f) ((int(*)(void*, unsigned char*, unsigned int))(f))#define FNCCAST_CRYPT(f) ((void(*)(void*, unsigned char*, unsigned char*))(f))#define IDEA_KEYSIZE 16#define IDEA_BLOCKSIZE 8#define IDEA_ROUNDS 8#define IDEA_KEYLEN (6*IDEA_ROUNDS+4)typedef struct { u16 ek[IDEA_KEYLEN]; u16 dk[IDEA_KEYLEN]; int have_dk;} IDEA_context;static int do_setkey( IDEA_context *c, unsigned char *key, unsigned keylen );static void encrypt_block( IDEA_context *bc, unsigned char *outbuf, unsigned char *inbuf );static void decrypt_block( IDEA_context *bc, unsigned char *outbuf, unsigned char *inbuf );static int selftest(int);static u16mul_inv( u16 x ){ u16 t0, t1; u16 q, y; if( x < 2 ) return x; t1 = 0x10001L / x; y = 0x10001L % x; if( y == 1 ) return (1-t1) & 0xffff; t0 = 1; do { q = x / y; x = x % y; t0 += q * t1; if( x == 1 ) return t0; q = y / x; y = y % x; t1 += q * t0; } while( y != 1 ); return (1-t1) & 0xffff;}static voidexpand_key( unsigned char *userkey, u16 *ek ){ int i,j; for(j=0; j < 8; j++ ) { ek[j] = (*userkey << 8) + userkey[1]; userkey += 2; } for(i=0; j < IDEA_KEYLEN; j++ ) { i++; ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; ek += i & 8; i &= 7; }}static voidinvert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ){ int i; u16 t1, t2, t3; u16 temp[IDEA_KEYLEN]; u16 *p = temp + IDEA_KEYLEN; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t3; *--p = t2; *--p = t1; for(i=0; i < IDEA_ROUNDS-1; i++ ) { t1 = *ek++; *--p = *ek++; *--p = t1; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t2; *--p = t3; *--p = t1; } t1 = *ek++; *--p = *ek++; *--p = t1; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t3; *--p = t2; *--p = t1; memcpy(dk, temp, sizeof(temp) ); memset(temp, 0, sizeof(temp) ); /* burn temp */}static voidcipher( unsigned char *outbuf, unsigned char *inbuf, u16 *key ){ u16 x1, x2, x3,x4, s2, s3; u16 *in, *out; int r = IDEA_ROUNDS;#define MUL(x,y) \ do {u16 _t16; u32 _t32; \ if( (_t16 = (y)) ) { \ if( (x = (x)&0xffff) ) { \ _t32 = (u32)x * _t16; \ x = _t32 & 0xffff; \ _t16 = _t32 >> 16; \ x = ((x)-_t16) + (x<_t16?1:0); \ } \ else { \ x = 1 - _t16; \ } \ } \ else { \ x = 1 - x; \ } \ } while(0) in = (u16*)inbuf; x1 = *in++; x2 = *in++; x3 = *in++; x4 = *in;#ifdef LITTLE_ENDIAN_HOST x1 = (x1>>8) | (x1<<8); x2 = (x2>>8) | (x2<<8); x3 = (x3>>8) | (x3<<8); x4 = (x4>>8) | (x4<<8);#endif do { MUL(x1, *key++); x2 += *key++; x3 += *key++; MUL(x4, *key++ ); s3 = x3; x3 ^= x1; MUL(x3, *key++); s2 = x2; x2 ^=x4; x2 += x3; MUL(x2, *key++); x3 += x2; x1 ^= x2; x4 ^= x3; x2 ^= s3; x3 ^= s2; } while( --r ); MUL(x1, *key++); x3 += *key++; x2 += *key++; MUL(x4, *key); out = (u16*)outbuf; #ifdef LITTLE_ENDIAN_HOST *out++ = (x1>>8) | (x1<<8); *out++ = (x3>>8) | (x3<<8); *out++ = (x2>>8) | (x2<<8); *out = (x4>>8) | (x4<<8); #else *out++ = x1; *out++ = x3; *out++ = x2; *out = x4; #endif #undef MUL}static intdo_setkey( IDEA_context *c, unsigned char *key, unsigned keylen ){ assert(keylen == 16); c->have_dk = 0; expand_key( key, c->ek ); invert_key( c->ek, c->dk ); return 0;}static voidencrypt_block( IDEA_context *c, unsigned char *outbuf, unsigned char *inbuf ){ cipher( outbuf, inbuf, c->ek );}static voiddecrypt_block( IDEA_context *c, unsigned char *outbuf, unsigned char *inbuf ){ if( !c->have_dk ) { c->have_dk = 1; invert_key( c->ek, c->dk ); } cipher( outbuf, inbuf, c->dk );}static intselftest( int check_decrypt ){static struct { unsigned char key[16]; unsigned char plain[8]; unsigned char cipher[8];} test_vectors[] = { { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } }}; IDEA_context c; unsigned char buffer[8]; int i; for(i=0; i < DIM(test_vectors); i++ ) { do_setkey( &c, test_vectors[i].key, 16 ); if( !check_decrypt ) { encrypt_block( &c, buffer, test_vectors[i].plain ); if( memcmp( buffer, test_vectors[i].cipher, 8 ) ) { fprintf (stderr, "idea encryption (%d) failed\n", i); return -1; } } else { decrypt_block( &c, buffer, test_vectors[i].cipher ); if( memcmp( buffer, test_vectors[i].plain, 8 ) ) { fprintf (stderr, "idea decryption (%d) failed\n", i); return -1; } } } return 0;}/***************** Return some information about the algorithm. We need algo here to* distinguish different flavors of the algorithm.* Returns: A pointer to string describing the algorithm or NULL if* the ALGO is invalid.*/const char *idea_get_info( int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey)( void *c, unsigned char *key, unsigned keylen ), void (**r_encrypt)( void *c, unsigned char *outbuf, unsigned char *inbuf ), void (**r_decrypt)( void *c, unsigned char *outbuf, unsigned char *inbuf ) ){ static int initialized = 0; if( !initialized ) { initialized = 1; if ( selftest(0) || selftest(1) ) return NULL; } *keylen = 128; *blocksize = 8; *contextsize = sizeof(IDEA_context); *r_setkey = FNCCAST_SETKEY(do_setkey); *r_encrypt= FNCCAST_CRYPT(encrypt_block); *r_decrypt= FNCCAST_CRYPT(decrypt_block); if( algo == 1 ) return "IDEA"; return NULL;}const char * const gnupgext_version = "IDEA ($Revision: 1.11 $)";static struct { int class; int version; int value; void (*func)(void);} func_table[] = { { 20, 1, 0, (void(*)(void))idea_get_info }, { 21, 1, 1 },};/***************** Enumerate the names of the functions together with informations about* this function. Set sequence to an integer with a initial value of 0 and* do not change it.* If what is 0 all kind of functions are returned.* Return values: class := class of function:* 10 = message digest algorithm info function* 11 = integer with available md algorithms* 20 = cipher algorithm info function* 21 = integer with available cipher algorithms* 30 = public key algorithm info function* 31 = integer with available pubkey algorithms* version = interface version of the function/pointer* (currently this is 1 for all functions)*/void *gnupgext_enum_func( int what, int *sequence, int *class, int *vers ){ void *ret; int i = *sequence; do { if( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = (void*)func_table[i].func; break; } i++; } while( what && what != *class ); *sequence = i; return ret;}