# HG changeset patch # User Michael Schloh von Bennewitz # Date 1235230741 -3600 # Node ID 2f8ffdf7658b77c54b6f3af490562237e935d951 # Parent 5e7005042079232a970f83c5a3bf5fb62387cfa4 Patch gnupg and its dependency gcrypt to accept use of the IDEA cipher. This effort seems to be flawed, as runtime tests of generating a revokation certificate for a IDEA encrypted key were inconclusive. Suspicion rests on a flawed implementation or patch logic. diff -r 5e7005042079 -r 2f8ffdf7658b gcrypt/gcrypt.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcrypt/gcrypt.patch Sat Feb 21 16:39:01 2009 +0100 @@ -0,0 +1,41 @@ +Index: cipher/cipher.c +diff -Nau cipher/cipher.c.orig cipher/cipher.c +--- cipher/cipher.c.orig 2008-09-12 15:23:37.000000000 +0200 ++++ cipher/cipher.c 2009-02-18 19:07:30.388253084 +0100 +@@ -97,6 +97,10 @@ + { &_gcry_cipher_spec_rfc2268_40, + &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 }, + #endif ++#if USE_IDEA ++ { &_gcry_cipher_spec_idea, ++ &dummy_extra_spec, GCRY_CIPHER_IDEA }, ++#endif + #if USE_SEED + { &_gcry_cipher_spec_seed, + &dummy_extra_spec, GCRY_CIPHER_SEED }, +Index: src/cipher.h +diff -Nau src/cipher.h.orig src/cipher.h +--- src/cipher.h.orig 2008-09-03 12:04:42.000000000 +0200 ++++ src/cipher.h 2009-02-18 19:09:20.193397539 +0100 +@@ -105,6 +105,7 @@ + extern gcry_cipher_spec_t _gcry_cipher_spec_camellia128; + extern gcry_cipher_spec_t _gcry_cipher_spec_camellia192; + extern gcry_cipher_spec_t _gcry_cipher_spec_camellia256; ++extern gcry_cipher_spec_t _gcry_cipher_spec_idea; + + extern cipher_extra_spec_t _gcry_cipher_extraspec_tripledes; + extern cipher_extra_spec_t _gcry_cipher_extraspec_aes; +Index: tests/basic.c +diff -Nau tests/basic.c.orig tests/basic.c +--- tests/basic.c.orig 2008-09-18 16:35:57.000000000 +0200 ++++ tests/basic.c 2009-02-18 19:10:14.460255272 +0100 +@@ -1028,6 +1028,9 @@ + GCRY_CIPHER_CAMELLIA192, + GCRY_CIPHER_CAMELLIA256, + #endif ++#if USE_IDEA ++ GCRY_CIPHER_IDEA, ++#endif + 0 + }; + static int algos2[] = { diff -r 5e7005042079 -r 2f8ffdf7658b gcrypt/gcrypt.spec --- a/gcrypt/gcrypt.spec Wed Feb 18 16:40:58 2009 +0100 +++ b/gcrypt/gcrypt.spec Sat Feb 21 16:39:01 2009 +0100 @@ -32,10 +32,15 @@ Group: Cryptography License: LGPL Version: 1.4.3 -Release: 20080921 +Release: 20090106 + +# package options +%option with_idea no # list of sources Source0: ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-%{version}.tar.gz +Source1: idea.c +Patch0: gcrypt.patch # build information Prefix: %{l_prefix} @@ -57,6 +62,22 @@ %prep %setup -q -n libgcrypt-%{version} + %patch -p0 +%if "%{with_idea}" == "yes" + echo $PWD + pwd + echo `pwd` + cp %{SOURCE idea.c} cipher/ + %{l_shtool} subst \ + -e 's;^\(EXTRA_libcipher_la_SOURCES =\);\1 idea.c;' \ + -e 's;^\(GCRYPT_MODULES = .*[^\ \t]\)[\ \t]*$;\1 idea.lo;' \ + -e 's;^\(GCRYPT_CIPHERS = .*[^\ \t]\)[\ \t]*$;\1 idea.lo;' \ + -e 's;^\(LIBGCRYPT_CIPHERS = .*[^\ \t]\)[\ \t]*$;\1 idea;' \ + cipher/Makefile.in + %{l_shtool} subst \ + -e 's;^\(available_ciphers="arcfour [^"][^"]*\)";\1 idea";' \ + configure +%endif %build ( echo "ac_cv_lib_pthread_pthread_create=no" @@ -64,6 +85,9 @@ ) >config.cache CC="%{l_cc}" \ CFLAGS="%{l_cflags -O}" \ +%if "%{with_idea}" == "yes" + CPPFLAGS="-DUSE_IDEA $CPPFLAGS" \ +%endif GREP="grep" \ ./configure \ --cache-file=./config.cache \ diff -r 5e7005042079 -r 2f8ffdf7658b gcrypt/idea.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcrypt/idea.c Sat Feb 21 16:39:01 2009 +0100 @@ -0,0 +1,272 @@ +#include +#include +#include +#include /* for memcmp() */ +#include + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +/* configuration stuff */ +#ifdef __alpha__ + #define SIZEOF_UNSIGNED_LONG 8 +#else + #define SIZEOF_UNSIGNED_LONG 4 +#endif + +#if defined(__mc68000__) || defined (__sparc__) || defined (__PPC__) \ + || (defined(__mips__) && (defined(MIPSEB) || defined (__MIPSEB__)) ) \ + || defined(__powerpc__) \ + || defined(__hpux__) /* should be replaced by the Macro for the PA */ + #define BIG_ENDIAN_HOST 1 +#else + #define LITTLE_ENDIAN_HOST 1 +#endif + +#ifndef DIM + #define DIM(v) (sizeof(v)/sizeof((v)[0])) + #define DIMof(type,member) DIM(((type *)0)->member) +#endif + +/* imports */ +void g10_log_fatal( const char *fmt, ... ); + + +/* local stuff */ + +#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) +#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(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 u16 +mul_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 void +cipher( byte *outbuf, const byte *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 void +expand_key( const byte *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 void +invert_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 int +do_idea_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) +{ + assert(keylen == 16); + c->have_dk = 0; + expand_key( key, c->ek ); + invert_key( c->ek, c->dk ); + return 0; +} + +static gcry_err_code_t +idea_setkey (void *context, const byte *key, unsigned int keylen) +{ + IDEA_context *ctx = context; + int rc = do_idea_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + +static void +do_idea_encrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + cipher( outbuf, inbuf, c->ek ); +} + +static void +idea_encrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + do_idea_encrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +static void +do_idea_decrypt( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + if( !c->have_dk ) { + c->have_dk = 1; + invert_key( c->ek, c->dk ); + } + cipher( outbuf, inbuf, c->dk ); +} + +static void +idea_decrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + + do_idea_decrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +gcry_cipher_spec_t _gcry_cipher_spec_idea = +{ + "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context), + idea_setkey, idea_encrypt, idea_decrypt, +}; diff -r 5e7005042079 -r 2f8ffdf7658b gnupg/gnupg.patch --- a/gnupg/gnupg.patch Wed Feb 18 16:40:58 2009 +0100 +++ b/gnupg/gnupg.patch Sat Feb 21 16:39:01 2009 +0100 @@ -33,3 +33,18 @@ cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF +Index: configure +--- g10/seckey-cert.c.orig 2008-03-18 17:46:32.000000000 +0100 ++++ g10/seckey-cert.c 2009-02-18 21:25:25.508715635 +0100 +@@ -209,6 +209,11 @@ + csum += checksum (buffer, ndata); + gcry_mpi_release (sk->skey[i]); + ++ if (sk->protect.algo==CIPHER_ALGO_IDEA) { ++ buffer[0] = 0; ++ buffer[1] = 0; ++ } ++ + err = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP, + buffer, ndata, &ndata ); + xfree (buffer); diff -r 5e7005042079 -r 2f8ffdf7658b gnupg/gnupg.spec --- a/gnupg/gnupg.spec Wed Feb 18 16:40:58 2009 +0100 +++ b/gnupg/gnupg.spec Sat Feb 21 16:39:01 2009 +0100 @@ -37,10 +37,10 @@ # package options %option with_curl yes %option with_ldap no +%option with_idea no # list of sources Source0: ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-%{version}.tar.bz2 -Source1: ftp://ftp.gnupg.dk/pub/contrib-dk/idea.c.gz Patch0: gnupg.patch # build information @@ -60,6 +60,10 @@ BuildPreReq: openldap, openssl PreReq: openldap, openssl %endif +%if "%{with_idea}" == "yes" +BuildPreReq: gcrypt::with_idea +PreReq: gcrypt::with_idea +%endif AutoReq: no AutoReqProv: no @@ -107,6 +111,9 @@ export CC="%{l_cc}" export CFLAGS="%{l_cflags -O}" export CPPFLAGS="%{l_cppflags}" +%if "%{with_idea}" == "yes" + export CPPFLAGS="-DUSE_IDEA $CPPFLAGS" +%endif export LDFLAGS="%{l_ldflags}" ./configure \ --prefix=%{l_prefix} \