IDEA support
Ulrich Mueller
ulm at gentoo.org
Wed Jan 11 07:49:14 CET 2012
>>>>> On Mon, 09 Jan 2012, Werner Koch wrote:
> Well, we could now use it but there is not much point besides
> reading of old backups. Maybe I give it a try and add IDEA
> decryption support in 2.1.
Please find a patch included below. It applies cleanly to the trunk
as well as to 1.5.0. I've tested it both with keys and files generated
with PGP 2.6.3in.
Thanks,
Ulrich
https://bugs.gentoo.org/159870
Re-add support for the IDEA cipher.
Based on a patch created by Kristian Fiskerstrand and subsequently
modified by Alon Bar-Lev:
http://www.kfwebs.net/articles/article/42/GnuPG-2.0---IDEA-support
The idea.c file is based on the idea.c file used for gnupg version 1.
which again is based on an implementation from Bruce Schneier:
Applied Cryptography. John Wiley & Sons, 1996. ISBN 0-471-11709-9.
idea.c in gnupg version 1 was copyrighted by Werner Koch and
distributed under a MIT/X11 license.
Patents on IDEA have expired at the time of writing (2012-01-09).
--- libgcrypt-1.5.0-orig/cipher/Makefile.am
+++ libgcrypt-1.5.0/cipher/Makefile.am
@@ -51,6 +51,7 @@
dsa.c \
elgamal.c \
ecc.c \
+idea.c \
md4.c \
md5.c \
rijndael.c rijndael-tables.h \
--- libgcrypt-1.5.0-orig/cipher/cipher.c
+++ libgcrypt-1.5.0/cipher/cipher.c
@@ -112,6 +112,10 @@
{ &_gcry_cipher_spec_camellia256,
&dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 },
#endif
+#ifdef USE_IDEA
+ { &_gcry_cipher_spec_idea,
+ &dummy_extra_spec, GCRY_CIPHER_IDEA },
+#endif
{ NULL }
};
--- libgcrypt-1.5.0-orig/cipher/idea.c
+++ libgcrypt-1.5.0/cipher/idea.c
@@ -0,0 +1,272 @@
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for memcmp() */
+#include <assert.h>
+
+#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,
+ };
--- libgcrypt-1.5.0-orig/configure.ac
+++ libgcrypt-1.5.0/configure.ac
@@ -156,7 +156,7 @@
# Definitions for symmetric ciphers.
available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed"
-available_ciphers="$available_ciphers camellia"
+available_ciphers="$available_ciphers camellia idea"
enabled_ciphers=""
# Definitions for public-key ciphers.
@@ -1047,6 +1047,12 @@
AC_DEFINE(USE_CAMELLIA, 1, [Defined if this module should be included])
fi
+LIST_MEMBER(idea, $enabled_ciphers)
+if test "$found" = "1" ; then
+ GCRYPT_CIPHERS="$GCRYPT_CIPHERS idea.lo"
+ AC_DEFINE(USE_IDEA, 1, [Defined if this module should be included])
+fi
+
LIST_MEMBER(dsa, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo"
--- libgcrypt-1.5.0-orig/src/cipher.h
+++ libgcrypt-1.5.0/src/cipher.h
@@ -135,6 +135,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;
--- libgcrypt-1.5.0-orig/tests/basic.c
+++ libgcrypt-1.5.0/tests/basic.c
@@ -1494,6 +1494,9 @@
GCRY_CIPHER_CAMELLIA192,
GCRY_CIPHER_CAMELLIA256,
#endif
+#if USE_IDEA
+ GCRY_CIPHER_IDEA,
+#endif
0
};
static int algos2[] = {
More information about the Gcrypt-devel
mailing list