www.pudn.com > truecrypt.zip > IDEA.C


/* IDEA source code.  This code came from a number of sources, the original 
   was written by Masayasu Kumagai , but was 
   severely hacked for speed and portability on non-Intel machines using code 
   from the book "PGP - Source Code and Internals", Phil Zimmermann, MIT 
   Press 1995, ISBN 0-262-24039-4 (note that the equivalent code in Applied 
   Cryptography has bugs and won't work properly).  Extra optimizations were 
   contributed by Paulo Barreto , everything was put 
   together by Peter Gutmann  */ 
 
#include  
#include "idea.h" 
 
#pragma warning( disable : 4244 ) 
 
 
/* Compute the multiplicative inverse of x mod 65537.  Slightly optimised 
   version based on the "PGP - Source Code and Internals" code */ 
 
static word16 mulInv( word16 x ) 
	{ 
	word16 t0, t1; 
	word16 q, y; 
 
	if( x <= 1 ) 
		return x;		/* 0 and 1 are self-inverse */ 
	t1 = ( word16 ) ( 0x10001L / x );	/* Since x >= 2, this fits into 16 bits */ 
	y = ( word16 ) ( 0x10001L % x ); 
	if( y == 1 ) 
		return( ( word16 ) ( 1 - t1 ) ); 
	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( ( word16 ) ( 1 - t1 ) ); 
	} 
 
/* Expand the 128-bit user key into the encryption and decryption keys */ 
 
void _cdecl ideaExpandKey( unsigned char const *userkey, word16 *eKey, word16 *dKey ) 
	{ 
	word16 *eKeyPtr = eKey; 
	int i, j, k, p, r; 
 
	/* Create the expanded encryption key */ 
	for( j = 0; j < 8; j++ ) 
		{ 
		eKey[ j ] = ( userkey[ 0 ] << 8 ) + userkey[ 1 ]; 
		userkey += 2; 
		} 
	for( i = 0; j < IDEA_KEYLEN; j++ ) 
		{ 
		i++; 
		eKey[ i + 7 ] = ( eKey[ i & 7 ] << 9 ) | ( eKey[ i + 1 & 7 ] >> 7 ); 
		eKey += i & 8; 
		i &= 7; 
		} 
	eKey = eKeyPtr; 
 
	/* Create the decryption key from the encryption key */ 
	p = IDEA_KEYLEN; 
	dKey[ p - 1 ] = mulInv( eKey[ 3 ] ); 
	dKey[ p - 2 ] = -( signed ) ( eKey[ 2 ] ); 
	dKey[ p - 3 ] = -( signed ) ( eKey[ 1 ] ); 
	dKey[ p - 4 ] = mulInv( eKey[ 0 ] ); 
	k = 4; 
	p -= 4; 
	for( r = IDEA_ROUNDS - 1; r > 0; r-- ) 
		{ 
		dKey[ p - 1 ] = eKey[ k + 1 ]; 
		dKey[ p - 2 ] = eKey[ k ]; 
		dKey[ p - 3 ] = mulInv( eKey[ k + 5 ] ); 
		dKey[ p - 4 ] = -( signed ) ( eKey[ k + 3 ] ); 
		dKey[ p - 5 ] = -( signed ) ( eKey[ k + 4 ] ); 
		dKey[ p - 6 ] = mulInv( eKey[ k + 2 ] ); 
		k += 6; p -= 6; 
		} 
	dKey[ p - 1 ] = eKey[ k + 1 ]; 
	dKey[ p - 2 ] = eKey[ k ]; 
	dKey[ p - 3 ] = mulInv( eKey[ k + 5 ] ); 
	dKey[ p - 4 ] = -( signed ) ( eKey[ k + 4 ] ); 
	dKey[ p - 5 ] = -( signed ) ( eKey[ k + 3 ] ); 
	dKey[ p - 6 ] = mulInv( eKey[ k + 2 ] ); 
	} 
 
#ifndef __WIN32__ 
 
/* Compute x * y mod 65537, from "PGP - Source Code and Internals" */ 
 
#define mul( x, y ) \ 
	( ( t16 = ( y ) ) ? \ 
		( x ) ? \ 
			t32 = ( unsigned long ) x * t16, \ 
			x = ( word16 ) t32, \ 
			t16 = ( word16 ) ( t32 >> 16 ), \ 
			x = ( x - t16 ) + ( x < t16 ) \ 
		: ( x = 1 - t16 ) \ 
	: ( x = 1 - x ) ) 
 
#ifdef __TURBOC__ 
  #pragma warn -pia		/* Turn off warnings for dodgy code in mul() macro */ 
#endif /* __TURBOC__ */ 
 
/* The basic IDEA round */ 
 
#define ideaRound( count ) \ 
	mul( x1, key[ ( count * 6 ) ] ); \ 
	x2 += key[ ( count * 6 ) + 1 ]; \ 
	x3 += key[ ( count * 6 ) + 2 ]; \ 
	mul( x4, key[ ( count * 6 ) + 3 ] ); \ 
	\ 
	s3 = x3; \ 
	x3 ^= x1; \ 
	mul( x3, key[ ( count * 6 ) + 4 ] ); \ 
	s2 = x2; \ 
	x2 ^= x4; \ 
	x2 += x3; \ 
	mul( x2, key[ ( count * 6 ) + 5 ] ); \ 
	x3 += x2; \ 
	\ 
	x1 ^= x2;  x4 ^= x3; \ 
	x2 ^= s3;  x3 ^= s2; 
 
/* Encrypt/decrypt a block of data with IDEA */ 
 
#if 0 
void _cdecl ideaCrypt( unsigned char const *in, unsigned char *out, word16 const *key ) 
	{ 
	register word16 x1, x2, x3, x4, s2, s3; 
	word16 *inPtr, *outPtr; 
	register word16 t16;	/* Needed by mul() macro */ 
	register unsigned long t32;		/* Needed by mul() macro */ 
 
	inPtr = ( word16 * ) in; 
	x1 = *inPtr++; x2 = *inPtr++; 
	x3 = *inPtr++; x4 = *inPtr++; 
#ifdef DATA_LITTLEENDIAN 
	x1 = ( x1 >> 8 ) | ( x1 << 8 ); 
	x2 = ( x2 >> 8 ) | ( x2 << 8 ); 
	x3 = ( x3 >> 8 ) | ( x3 << 8 ); 
	x4 = ( x4 >> 8 ) | ( x4 << 8 ); 
#endif /* DATA_LITTLEENDIAN */ 
 
	/* Perform 8 rounds of encryption */ 
	ideaRound( 0 ); 
	ideaRound( 1 ); 
	ideaRound( 2 ); 
	ideaRound( 3 ); 
	ideaRound( 4 ); 
	ideaRound( 5 ); 
	ideaRound( 6 ); 
	ideaRound( 7 ); 
 
	/* final semiround: */ 
	mul( x1, key[ 48 ] ); 
	x3 += key[ 49 ]; 
	x2 += key[ 50 ]; 
	mul( x4, key[ 51 ] ); 
 
	outPtr = ( word16 * ) out; 
#ifdef DATA_LITTLEENDIAN 
	*outPtr++ = ( x1 >> 8 ) | ( x1 << 8 ); 
	*outPtr++ = ( x3 >> 8 ) | ( x3 << 8 ); 
	*outPtr++ = ( x2 >> 8 ) | ( x2 << 8 ); 
	*outPtr++ = ( x4 >> 8 ) | ( x4 << 8 ); 
#else 
	*outPtr++ = x1; *outPtr++ = x3; 
	*outPtr++ = x2; *outPtr++ = x4; 
#endif /* DATA_LITTLEENDIAN */ 
	} 
#ifdef __TURBOC__ 
  #pragma warn +pia 
#endif /* __TURBOC__ */ 
 
#endif /* !__WIN32__ */ 
#endif 
 
 
#if 0 
#include  
 
void main( void ) 
	{ 
	unsigned char key[] = { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 
				   0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }; 
	unsigned char plain[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }; 
	unsigned char cipher[] = { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 }; 
	unsigned char temp[ 8 ] = { 0 }; 
	unsigned short eKey[ 52 ], dKey[ 52 ]; 
 
	ideaExpandKey( key, eKey, dKey ); 
	ideaCrypt( plain, temp, eKey ); 
	if( memcmp( temp, cipher, 8 ) ) 
		puts( "Encrypt bang." ); 
	ideaCrypt( temp, temp, dKey ); 
	if( memcmp( temp, plain, 8 ) ) 
		puts( "Decrypt bang." ); 
	} 
#endif /* 0 */