cast5 does now work
authorWerner Koch <wk@gnupg.org>
Sat, 4 Apr 1998 20:16:55 +0000 (20:16 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 4 Apr 1998 20:16:55 +0000 (20:16 +0000)
22 files changed:
NEWS
VERSION
cipher/ChangeLog
cipher/Makefile.am
cipher/Makefile.in
cipher/cast5.c
cipher/cast5.h
cipher/misc.c
doc/DETAILS
g10/ChangeLog
g10/build-packet.c
g10/cipher.c
g10/encr-data.c
g10/filter.h
g10/passphrase.c
g10/pubkey-enc.c
g10/seckey-cert.c
g10/seskey.c
include/cipher.h
tools/Makefile.am
tools/Makefile.in
tools/cast5test.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 330651d..c73652e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Noteworthy changes in version 0.2.15
+------------------------------------
+
+    * CAST5 works (using the PGP's special CFB mode).
+
+
+
+
 Noteworthy changes in version 0.2.14
 ------------------------------------
 
diff --git a/VERSION b/VERSION
index 769ed6a..160dada 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2.14
+0.2.14a
index 3d2bf7c..d768465 100644 (file)
@@ -1,6 +1,10 @@
+Sat Apr  4 19:52:08 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * cast5.c: Implemented and tested.
+
 Wed Apr  1 16:38:27 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
-       * elgamla.c (elg_generate): Faster generation of x in some cases.
+       * elgamal.c (elg_generate): Faster generation of x in some cases.
 
 Thu Mar 19 13:54:48 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
index 926d084..ff2e9f3 100644 (file)
@@ -8,6 +8,8 @@ noinst_LIBRARIES = libcipher.a
 
 libcipher_a_SOURCES = blowfish.c     \
                 blowfish.h     \
+                cast5.c        \
+                cast5.h        \
                 elgamal.c      \
                 elgamal.h      \
                 md5.c          \
index 981fd99..91ed0a9 100644 (file)
@@ -99,6 +99,8 @@ noinst_LIBRARIES = libcipher.a
 
 libcipher_a_SOURCES = blowfish.c     \
                 blowfish.h     \
+                cast5.c        \
+                cast5.h        \
                 elgamal.c      \
                 elgamal.h      \
                 md5.c          \
@@ -129,8 +131,8 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I..
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
-libcipher_a_OBJECTS =  blowfish.o elgamal.o md5.o primegen.o random.o \
-rmd160.o sha1.o dsa.o md.o misc.o smallprime.o
+libcipher_a_OBJECTS =  blowfish.o cast5.o elgamal.o md5.o primegen.o \
+random.o rmd160.o sha1.o dsa.o md.o misc.o smallprime.o
 AR = ar
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
@@ -142,9 +144,9 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP = --best
-DEP_FILES =  .deps/blowfish.P .deps/dsa.P .deps/elgamal.P .deps/md.P \
-.deps/md5.P .deps/misc.P .deps/primegen.P .deps/random.P .deps/rmd160.P \
-.deps/sha1.P .deps/smallprime.P
+DEP_FILES =  .deps/blowfish.P .deps/cast5.P .deps/dsa.P .deps/elgamal.P \
+.deps/md.P .deps/md5.P .deps/misc.P .deps/primegen.P .deps/random.P \
+.deps/rmd160.P .deps/sha1.P .deps/smallprime.P
 SOURCES = $(libcipher_a_SOURCES)
 OBJECTS = $(libcipher_a_OBJECTS)
 
index 4d6d840..a14abaa 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+/* Test vectors:
+ *
+ * 128-bit key        = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
+ *        plaintext   = 01 23 45 67 89 AB CD EF
+ *        ciphertext  = 23 8B 4F E5 84 7E 44 B2
+ *
+ * 80-bit  key        = 01 23 45 67 12 34 56 78 23 45
+ *                    = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
+ *        plaintext   = 01 23 45 67 89 AB CD EF
+ *        ciphertext  = EB 6A 71 1A 2C 02 27 1B
+ *
+ * 40-bit  key        = 01 23 45 67 12
+ *                    = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
+ *        plaintext   = 01 23 45 67 89 AB CD EF
+ *        ciphertext  = 7A C8 16 D1 6E 9B 30 2E
+ */
+
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,6 +43,7 @@
 #include "util.h"
 #include "types.h"
 #include "cast5.h"
+#include "random.h"
 
 static const u32 s1[256] = {
 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
@@ -301,171 +319,251 @@ static const u32 s8[256] = {
 };
 
 
-
-
-
-static u32
-function_F( CAST5_context *bc, u32 x )
+#if defined(__GNUC__) && defined(__i386__)
+static inline u32
+rol(int n, u32 x)
 {
-    u16 a, b, c, d, y;
-
-    d = x & 0x00ff;
-    x >>= 8;
-    c = x & 0x00ff;
-    x >>= 8;
-    b = x & 0x00ff;
-    x >>= 8;
-    a = x & 0x00ff;
-    y = bc->s0[a] + bc->s1[b];
-    y ^= bc->s2[c];
-    y += bc->s3[d];
-
-    return y;
+       __asm__("roll %%cl,%0"
+               :"=r" (x)
+               :"0" (x),"c" (n));
+       return x;
 }
+#else
+  #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
+#endif
 
+#define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
+    (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
+#define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
+    (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
+#define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
+    (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 static void
-encrypt( CAST5_context *bc, u32 *ret_xl, u32 *ret_xr )
+encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
 {
-    u32 xl, xr, temp;
-    int i;
+    u32 l, r, t;
+    u32 I;   /* used by the Fx macros */
+    u32 *Km;
+    byte *Kr;
+
+    Km = c->Km;
+    Kr = c->Kr;
 
     /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and
      * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
      */
-    xl = *ret_xl;
-    xr = *ret_xr;
-
-    for(i=0; i < 16; i++ ) {
-       /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
-       *  Li = Ri-1;
-       *  Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
-       * (f is of Type 1, Type 2, or Type 3, depending on i).
-       */
-       xl ^= bc->p[i];
-       xr ^= function_F(bc, xl);
-       temp = xl;
-       xl = xr;
-       xr = temp;
-    }
+    l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
+    r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
+
+    /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
+     * Li = Ri-1;
+     * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
+     * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
+     * Rounds 2, 5, 8, 11, and 14 use f function Type 2.
+     * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
+     */
+
+    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
+    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
+    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
+    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
+    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
+    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
+    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
+    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
+    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
+    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
+    t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+    t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
+    t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
+    t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
+    t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
+    t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
 
     /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
      * concatenate to form the ciphertext.) */
-    temp = xl;
-    xl = xr;
-    xr = temp;
-
-    xr ^= bc->p[CAST5_ROUNDS];
-    xl ^= bc->p[CAST5_ROUNDS+1];
-
-    *ret_xl = xl;
-    *ret_xr = xr;
+    outbuf[0] = (r >> 24) & 0xff;
+    outbuf[1] = (r >> 16) & 0xff;
+    outbuf[2] = (r >>  8) & 0xff;
+    outbuf[3] =  r       & 0xff;
+    outbuf[4] = (l >> 24) & 0xff;
+    outbuf[5] = (l >> 16) & 0xff;
+    outbuf[6] = (l >>  8) & 0xff;
+    outbuf[7] =  l       & 0xff;
 }
 
 static void
-decrypted(  CAST5_context *bc, u32 *ret_xl, u32 *ret_xr )
+decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
 {
-    u32 xl, xr, temp;
-    int i;
-
-    xl = *ret_xl;
-    xr = *ret_xr;
-
-    for(i=CAST5_ROUNDS+1; i > 1; i-- ) {
-       xl ^= bc->p[i];
-       xr ^= function_F(bc, xl);
-       temp = xl;
-       xl = xr;
-       xr = temp;
-    }
-
-    temp = xl;
-    xl = xr;
-    xr = temp;
+    u32 l, r, t;
+    u32 I;
+    u32 *Km;
+    byte *Kr;
+
+    Km = c->Km;
+    Kr = c->Kr;
+
+    l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
+    r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
+
+    t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
+    t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
+    t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
+    t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
+    t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
+    t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
+    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
+    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
+    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
+    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
+    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
+    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
+    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
+    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
+    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
+
+    outbuf[0] = (r >> 24) & 0xff;
+    outbuf[1] = (r >> 16) & 0xff;
+    outbuf[2] = (r >>  8) & 0xff;
+    outbuf[3] =  r       & 0xff;
+    outbuf[4] = (l >> 24) & 0xff;
+    outbuf[5] = (l >> 16) & 0xff;
+    outbuf[6] = (l >>  8) & 0xff;
+    outbuf[7] =  l       & 0xff;
+}
 
-    xr ^= bc->p[1];
-    xl ^= bc->p[0];
 
-    *ret_xl = xl;
-    *ret_xr = xr;
-}
 
 static void
-encrypted_block( CAST5_context *bc, byte *outbuf, byte *inbuf )
+selftest()
 {
-    u32 d1, d2;
+    CAST5_context c;
+    byte key[16]  = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+                     0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A  };
+    byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
+    byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 };
+    byte buffer[8];
+
+    cast5_setkey( &c, key, 16 );
+    encrypt_block( &c, buffer, plain );
+    if( memcmp( buffer, cipher, 8 ) )
+       log_error("wrong cast5-128 encryption\n");
+    decrypt_block( &c, buffer, buffer );
+    if( memcmp( buffer, plain, 8 ) )
+       log_bug("cast5-128 failed\n");
+
+  #if 0 /* full maintenance test */
+    {
+       int i;
+       byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
+                       0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
+       byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
+                       0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
+       byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6,
+                       0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 };
+       byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71,
+                       0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E };
+
+       for(i=0; i < 1000000; i++ ) {
+           cast5_setkey( &c, b0, 16 );
+           encrypt_block( &c, a0, a0 );
+           encrypt_block( &c, a0+8, a0+8 );
+           cast5_setkey( &c, a0, 16 );
+           encrypt_block( &c, b0, b0 );
+           encrypt_block( &c, b0+8, b0+8 );
+       }
+       if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) )
+           log_bug("cast5-128 maintenance test failed\n");
 
-    d1 = ((u32*)inbuf)[0];
-    d2 = ((u32*)inbuf)[1];
-    encrypted( bc, &d1, &d2 );
-    ((u32*)outbuf)[0] = d1;
-    ((u32*)outbuf)[1] = d2;
+    }
+  #endif
 }
 
+
 static void
-decrypted_block( CAST5_context *bc, byte *outbuf, byte *inbuf )
+key_schedule( u32 *x, u32 *z, u32 *k )
 {
-    u32 d1, d2;
 
-    d1 = ((u32*)inbuf)[0];
-    d2 = ((u32*)inbuf)[1];
-    decrypted( bc, &d1, &d2 );
-    ((u32*)outbuf)[0] = d1;
-    ((u32*)outbuf)[1] = d2;
+  #define xi(i)   ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
+  #define zi(i)   ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
+
+    z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
+    z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
+    z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
+    z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
+    k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)];
+    k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)];
+    k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)];
+    k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)];
+
+    x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
+    x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
+    x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
+    x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
+    k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)];
+    k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)];
+    k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)];
+    k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)];
+
+    z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
+    z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
+    z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
+    z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
+    k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)];
+    k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)];
+    k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)];
+    k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)];
+
+    x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
+    x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
+    x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
+    x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
+    k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)];
+    k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)];
+    k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)];
+    k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)];
+
+  #undef xi
+  #undef zi
 }
 
 
 void
 cast5_setkey( CAST5_context *c, byte *key, unsigned keylen )
 {
-    int i, j, k;
-    u32 data, datal, datar;
-
-    for(i=0; i < CAST5_ROUNDS+2; i++ )
-       c->p[i] = ps[i];
-    for(i=0; i < 256; i++ ) {
-       c->s0[i] = ks0[i];
-       c->s1[i] = ks1[i];
-       c->s2[i] = ks2[i];
-       c->s3[i] = ks3[i];
-    }
-
-    for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) {
-       data = 0;
-       for(k=0; k < 4; k++) {
-           data = (data << 8) | key[j];
-           if( ++j >= keylen )
-               j = 0;
-       }
-       c->p[i] ^= data;
-    }
+  static int initialized;
+    int i;
+    u32 x[4];
+    u32 z[4];
+    u32 k[16];
 
-    datal = datar = 0;
-    for(i=0; i < CAST5_ROUNDS+2; i += 2 ) {
-       encrypted( c, &datal, &datar );
-       c->p[i]   = datal;
-       c->p[i+1] = datar;
-    }
-    for(i=0; i < 256; i += 2 ) {
-       encrypted( c, &datal, &datar );
-       c->s0[i]   = datal;
-       c->s0[i+1] = datar;
-    }
-    for(i=0; i < 256; i += 2 ) {
-       encrypted( c, &datal, &datar );
-       c->s1[i]   = datal;
-       c->s1[i+1] = datar;
-    }
-    for(i=0; i < 256; i += 2 ) {
-       encrypted( c, &datal, &datar );
-       c->s2[i]   = datal;
-       c->s2[i+1] = datar;
-    }
-    for(i=0; i < 256; i += 2 ) {
-       encrypted( c, &datal, &datar );
-       c->s3[i]   = datal;
-       c->s3[i+1] = datar;
+    if( !initialized ) {
+       initialized = 1;
+       selftest();
     }
+    fast_random_poll();
+
+    assert(keylen==16);
+    x[0] = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];
+    x[1] = key[4]  << 24 | key[5]  << 16 | key[6]  << 8 | key[7];
+    x[2] = key[8]  << 24 | key[9]  << 16 | key[10] << 8 | key[11];
+    x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15];
+
+    key_schedule( x, z, k );
+    for(i=0; i < 16; i++ )
+       c->Km[i] = k[i];
+    key_schedule( x, z, k );
+    for(i=0; i < 16; i++ )
+       c->Kr[i] = k[i] & 0x1f;
+
+    memset(&x,0, sizeof x);
+    memset(&z,0, sizeof z);
+    memset(&k,0, sizeof k);
+
+  #undef xi
+  #undef zi
 }
 
 
@@ -477,7 +575,7 @@ cast5_setiv( CAST5_context *c, byte *iv )
     else
        memset( c->iv, 0, CAST5_BLOCKSIZE );
     c->count = 0;
-    encrypted_block( c, c->eniv, c->iv );
+    encrypt_block( c, c->eniv, c->iv );
 }
 
 
@@ -488,7 +586,7 @@ cast5_encode( CAST5_context *c, byte *outbuf, byte *inbuf,
     unsigned n;
 
     for(n=0; n < nblocks; n++ ) {
-       encrypted_block( c, outbuf, inbuf );
+       encrypt_block( c, outbuf, inbuf );
        inbuf  += CAST5_BLOCKSIZE;;
        outbuf += CAST5_BLOCKSIZE;
     }
@@ -501,7 +599,7 @@ cast5_decode( CAST5_context *c, byte *outbuf, byte *inbuf,
     unsigned n;
 
     for(n=0; n < nblocks; n++ ) {
-       decrypted_block( c, outbuf, inbuf );
+       decrypt_block( c, outbuf, inbuf );
        inbuf  += CAST5_BLOCKSIZE;;
        outbuf += CAST5_BLOCKSIZE;
     }
@@ -527,9 +625,10 @@ xorblock( byte *out, byte *a, byte *b, unsigned count )
  */
 void
 cast5_encode_cfb( CAST5_context *c, byte *outbuf,
-                                         byte *inbuf, unsigned nbytes)
+                                      byte *inbuf, unsigned nbytes)
 {
     unsigned n;
+    int is_aligned;
 
     if( c->count ) {  /* must make a full block first */
        assert( c->count < CAST5_BLOCKSIZE );
@@ -544,17 +643,35 @@ cast5_encode_cfb( CAST5_context *c, byte *outbuf,
        outbuf += n;
        assert( c->count <= CAST5_BLOCKSIZE);
        if( c->count == CAST5_BLOCKSIZE ) {
-           encrypted_block( c, c->eniv, c->iv );
+           encrypt_block( c, c->eniv, c->iv );
            c->count = 0;
        }
        else
            return;
     }
     assert(!c->count);
+    is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG);
     while( nbytes >= CAST5_BLOCKSIZE ) {
-       xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
+       if( is_aligned ) {
+         #if SIZEOF_UNSIGNED_LONG == CAST5_BLOCKSIZE
+           *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf;
+         #elif (2*SIZEOF_UNSIGNED_LONG) == CAST5_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+         #elif (4*SIZEOF_UNSIGNED_LONG) == CAST5_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+           ((ulong*)outbuf)[2] = ((ulong*)c->eniv)[2] ^ ((ulong*)inbuf)[2];
+           ((ulong*)outbuf)[3] = ((ulong*)c->eniv)[3] ^ ((ulong*)inbuf)[3];
+         #else
+           #error Please remove this info line.
+           xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
+         #endif
+       }
+       else  /* not aligned */
+           xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
        memcpy( c->iv, outbuf, CAST5_BLOCKSIZE);
-       encrypted_block( c, c->eniv, c->iv );
+       encrypt_block( c, c->eniv, c->iv );
        nbytes -= CAST5_BLOCKSIZE;
        inbuf += CAST5_BLOCKSIZE;
        outbuf += CAST5_BLOCKSIZE;
@@ -571,9 +688,10 @@ cast5_encode_cfb( CAST5_context *c, byte *outbuf,
 
 void
 cast5_decode_cfb( CAST5_context *c, byte *outbuf,
-                                         byte *inbuf, unsigned nbytes)
+                                   byte *inbuf, unsigned nbytes)
 {
     unsigned n;
+    int is_aligned;
 
     if( c->count ) {  /* must make a full block first */
        assert( c->count < CAST5_BLOCKSIZE );
@@ -588,7 +706,7 @@ cast5_decode_cfb( CAST5_context *c, byte *outbuf,
        outbuf += n;
        assert( c->count <= CAST5_BLOCKSIZE);
        if( c->count == CAST5_BLOCKSIZE ) {
-           encrypted_block( c, c->eniv, c->iv );
+           encrypt_block( c, c->eniv, c->iv );
            c->count = 0;
        }
        else
@@ -596,10 +714,28 @@ cast5_decode_cfb( CAST5_context *c, byte *outbuf,
     }
 
     assert(!c->count);
+    is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG);
     while( nbytes >= CAST5_BLOCKSIZE ) {
        memcpy( c->iv, inbuf, CAST5_BLOCKSIZE);
-       xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
-       encrypted_block( c, c->eniv, c->iv );
+       if( is_aligned ) {
+         #if SIZEOF_UNSIGNED_LONG == CAST5_BLOCKSIZE
+           *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf;
+         #elif (2*SIZEOF_UNSIGNED_LONG) == CAST5_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+         #elif (4*SIZEOF_UNSIGNED_LONG) == CAST5_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+           ((ulong*)outbuf)[2] = ((ulong*)c->eniv)[2] ^ ((ulong*)inbuf)[2];
+           ((ulong*)outbuf)[3] = ((ulong*)c->eniv)[3] ^ ((ulong*)inbuf)[3];
+         #else
+           #error Please remove this info line.
+           xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
+         #endif
+       }
+       else  /* not aligned */
+           xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE);
+       encrypt_block( c, c->eniv, c->iv );
        nbytes -= CAST5_BLOCKSIZE;
        inbuf += CAST5_BLOCKSIZE;
        outbuf += CAST5_BLOCKSIZE;
@@ -613,3 +749,16 @@ cast5_decode_cfb( CAST5_context *c, byte *outbuf,
 
 }
 
+
+
+void
+cast5_sync_cfb( CAST5_context *c )
+{
+    if( c->count ) {
+       memmove(c->iv + c->count, c->iv, CAST5_BLOCKSIZE - c->count );
+       memcpy(c->iv, c->eniv + CAST5_BLOCKSIZE - c->count, c->count);
+       c->count = 0;
+    }
+}
+
+
index 1251128..4afaf2a 100644 (file)
 #define CAST5_BLOCKSIZE 8
 
 typedef struct {
-    u32 s0[256];
-    u32 s1[256];
-    u32 s2[256];
-    u32 s3[256];
-    u32 p[16+2];
+    u32  Km[16];
+    byte Kr[16];
     byte iv[CAST5_BLOCKSIZE];
     byte eniv[CAST5_BLOCKSIZE];
     int  count;
@@ -45,6 +42,7 @@ void cast5_encode_cfb( CAST5_context *c, byte *outbuf,
                                         byte *inbuf, unsigned nbytes);
 void cast5_decode_cfb( CAST5_context *c, byte *outbuf,
                                         byte *inbuf, unsigned nbytes);
+void cast5_sync_cfb( CAST5_context *c );
 
 
 #endif /*G10_CAST5_H*/
index ad937fc..d251955 100644 (file)
@@ -162,6 +162,7 @@ check_cipher_algo( int algo )
     switch( algo ) {
       case CIPHER_ALGO_BLOWFISH128:
       case CIPHER_ALGO_BLOWFISH:
+      case CIPHER_ALGO_CAST:
        return 0;
       default:
        return G10ERR_CIPHER_ALGO;
index 4b8eda8..6f1d895 100644 (file)
@@ -234,3 +234,52 @@ There is one enhavement used ith the old style packet headers:
 +  another packet version to tell the application that it can not assume,
 +  that this is the last packet.
 
+
+
+
+
+Keyserver Message Format
+-------------------------
+
+The keyserver may be contacted by a Unix Domain socket or via TCP.
+
+The Format of a request is:
+
+----
+command-tag
+"Content-length:" digits
+CRLF
+------
+
+Where command-tag is
+
+GET <user-name>
+PUT
+DELETE <user-name>
+
+
+The format of a response is:
+
+------
+"GNUPG/1.0" status-code status-text
+"Content-length:" digits
+CRLF
+------------
+followed by <digits> bytes of data
+
+
+Status codes are:
+
+     o 1xx: Informational - Request received, continuing process
+
+     o 2xx: Success - The action was successfully received, understood,
+       and accepted
+
+     o 4xx: Client Error - The request contains bad syntax or cannot be
+       fulfilled
+
+     o 5xx: Server Error - The server failed to fulfill an apparently
+       valid request
+
+
+
index b82ceae..e16f155 100644 (file)
@@ -1,3 +1,14 @@
+Sat Apr  4 20:07:01 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * cipher.c (cipher_filter): Support for CAST5
+       * encr-data.c (decode_filter): Ditto.
+       (decrypt_data): Ditto.
+       * seskey.c (make_session_key): Ditto.
+       * seckey-cert.c (check_elg, check_dsa): Ditto,
+       (protect_secret_key): Ditto.
+       * pubkey-enc.c (get_session_key): Ditto.
+       * passphrase.c (hash_passphrase): Ditto.
+
 Thu Apr  2 20:22:35 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * gpgd.c: New
index 85278af..4d0a7d6 100644 (file)
@@ -289,7 +289,8 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
        mpi_write(a, skc->d.rsa.rsa_n );
        mpi_write(a, skc->d.rsa.rsa_e );
        if( skc->is_protected ) {
-           assert( skc->protect.algo == CIPHER_ALGO_BLOWFISH );
+           assert( skc->protect.algo == CIPHER_ALGO_BLOWFISH
+                   || skc->protect.algo == CIPHER_ALGO_CAST );
            iobuf_put(a, skc->protect.algo );
            iobuf_write(a, skc->protect.iv, 8 );
        }
index 52da03b..8e6c91a 100644 (file)
@@ -74,6 +74,13 @@ cipher_filter( void *opaque, int control,
                blowfish_setiv( cfx->bf_ctx, NULL );
                blowfish_encode_cfb( cfx->bf_ctx, temp, temp, 10);
            }
+           else if( cfx->dek->algo == CIPHER_ALGO_CAST  ) {
+               cfx->cast5_ctx = m_alloc_secure( sizeof *cfx->cast5_ctx );
+               cast5_setkey( cfx->cast5_ctx, cfx->dek->key, cfx->dek->keylen );
+               cast5_setiv( cfx->cast5_ctx, NULL );
+               cast5_encode_cfb( cfx->cast5_ctx, temp, temp, 10);
+               cast5_sync_cfb( cfx->cast5_ctx );
+           }
            else
                log_bug("no cipher algo %d\n", cfx->dek->algo);
 
@@ -84,6 +91,9 @@ cipher_filter( void *opaque, int control,
        if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH
            || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 )
            blowfish_encode_cfb( cfx->bf_ctx, buf, buf, size);
+       else if( cfx->dek->algo == CIPHER_ALGO_CAST  )
+           cast5_encode_cfb( cfx->cast5_ctx, buf, buf, size);
+
        if( iobuf_write( a, buf, size ) )
            rc = G10ERR_WRITE_FILE;
     }
@@ -91,6 +101,8 @@ cipher_filter( void *opaque, int control,
        if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH
            || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 )
            m_free(cfx->bf_ctx);
+       else if( cfx->dek->algo == CIPHER_ALGO_CAST  )
+           m_free(cfx->cast5_ctx);
     }
     else if( control == IOBUFCTRL_DESC ) {
        *(char**)buf = "cipher_filter";
index a1b4be0..4f8aa89 100644 (file)
 #include "packet.h"
 #include "mpi.h"
 #include "cipher.h"
+#include "options.h"
 
 
 static int decode_filter( void *opaque, int control, IOBUF a,
                                        byte *buf, size_t *ret_len);
 
 typedef struct {
+    int is_cast5;
     BLOWFISH_context *bf_ctx;
+    CAST5_context *cast5_ctx;
 } decode_filter_ctx_t;
 
 
@@ -50,16 +53,32 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
     int c, i;
     byte temp[16];
 
-
+    if( opt.verbose ) {
+       const char *s = cipher_algo_to_string( dek->algo );
+       if( s )
+           log_info("%s encrypted data\n", s );
+       else
+           log_info("encrypted with unknown algorithm %d\n", dek->algo );
+    }
     if( dek->algo != CIPHER_ALGO_BLOWFISH
-       && dek->algo != CIPHER_ALGO_BLOWFISH128 )
+       && dek->algo != CIPHER_ALGO_BLOWFISH128
+       && dek->algo != CIPHER_ALGO_CAST       )
        return G10ERR_CIPHER_ALGO;
     if( ed->len && ed->len < 10 )
        log_bug("Nanu\n");   /* oops: found a bug */
 
-    dfx.bf_ctx = m_alloc_secure( sizeof *dfx.bf_ctx );
-    blowfish_setkey( dfx.bf_ctx, dek->key, dek->keylen );
-    blowfish_setiv( dfx.bf_ctx, NULL );
+    if( dek->algo == CIPHER_ALGO_CAST ) {
+       dfx.is_cast5 = 1;
+       dfx.cast5_ctx = m_alloc_secure( sizeof *dfx.cast5_ctx );
+       cast5_setkey( dfx.cast5_ctx, dek->key, dek->keylen  );
+       cast5_setiv( dfx.cast5_ctx, NULL );
+    }
+    else {
+       dfx.is_cast5 = 0;
+       dfx.bf_ctx = m_alloc_secure( sizeof *dfx.bf_ctx );
+       blowfish_setkey( dfx.bf_ctx, dek->key, dek->keylen  );
+       blowfish_setiv( dfx.bf_ctx, NULL );
+    }
 
     if( ed->len ) {
        iobuf_set_limit( ed->buf, ed->len );
@@ -74,7 +93,12 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
            else
                temp[i] = c;
     }
-    blowfish_decode_cfb( dfx.bf_ctx, temp, temp, 10);
+    if( dfx.is_cast5 ) {
+       cast5_decode_cfb( dfx.cast5_ctx, temp, temp, 10);
+       cast5_sync_cfb( dfx.cast5_ctx );
+    }
+    else
+       blowfish_decode_cfb( dfx.bf_ctx, temp, temp, 10);
     p = temp;
     if( p[6] != p[8] || p[7] != p[9] ) {
        m_free(dfx.bf_ctx);
@@ -108,8 +132,12 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
            buf[n] = c;
        }
 
-       if( n )
-           blowfish_decode_cfb( fc->bf_ctx, buf, buf, n);
+       if( n ) {
+           if( fc->is_cast5 )
+               cast5_decode_cfb( fc->cast5_ctx, buf, buf, n);
+           else
+               blowfish_decode_cfb( fc->bf_ctx, buf, buf, n);
+       }
        else
            rc = -1; /* eof */
        *ret_len = n;
index 2fa3b8c..fac1e0e 100644 (file)
@@ -61,6 +61,7 @@ typedef struct {
     DEK *dek;
     u32 datalen;
     BLOWFISH_context *bf_ctx;
+    CAST5_context *cast5_ctx;
     int header;
 } cipher_filter_context_t;
 
index ee5d410..46ff831 100644 (file)
@@ -156,6 +156,19 @@ hash_passphrase( DEK *dek, char *pw, byte *salt )
        memcpy( dek->key, md_read(md,0), dek->keylen );
        md_close(md);
     }
+    else if( dek->algo == CIPHER_ALGO_CAST ) {
+       MD_HANDLE md;
+
+       md = md_open(DIGEST_ALGO_SHA1, 1);
+       if( salt )
+           md_write( md, salt, 8 );
+       md_write( md, pw, strlen(pw) );
+       md_final( md );
+       /* use only the low 128 bits */
+       dek->keylen = 16;
+       memcpy( dek->key, md_read(md,0), dek->keylen );
+       md_close(md);
+    }
     else
        rc = G10ERR_UNSUPPORTED;
     return rc;
index 8ffa648..f19af21 100644 (file)
@@ -135,13 +135,16 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
            { rc = G10ERR_WRONG_SECKEY; goto leave; }
        break;
       case CIPHER_ALGO_BLOWFISH128:
+      case CIPHER_ALGO_CAST:
        if( dek->keylen != 16 )
            { rc = G10ERR_WRONG_SECKEY; goto leave; }
        break;
+    #if 0
       case CIPHER_ALGO_CAST:
        if( dek->keylen < 5 || dek->keylen > 16 )
            { rc = G10ERR_WRONG_SECKEY; goto leave; }
        break;
+    #endif
       default:
        dek->algo = 0;
        rc = G10ERR_CIPHER_ALGO;
index 49870dc..dada0fd 100644 (file)
 #include "cipher.h"
 
 #if  BLOWFISH_BLOCKSIZE != 8
-  #error unsupportted blocksize
+  #error unsupported blocksize
+#endif
+#if  CAST5_BLOCKSIZE != 8
+  #error unsupported blocksize
 #endif
 
 static u16
@@ -71,10 +74,12 @@ check_elg( PKT_secret_cert *cert )
        DEK *dek = NULL;
        MPI test_x;
        BLOWFISH_context *blowfish_ctx=NULL;
+       CAST5_context *cast5_ctx=NULL;
 
        switch( cert->protect.algo ) {
          case CIPHER_ALGO_NONE: BUG(); break;
          case CIPHER_ALGO_BLOWFISH:
+         case CIPHER_ALGO_CAST:
            keyid_from_skc( cert, keyid );
            if( cert->protect.s2k == 1 || cert->protect.s2k == 3 )
                dek = get_passphrase_hash( keyid, NULL,
@@ -82,23 +87,41 @@ check_elg( PKT_secret_cert *cert )
            else
                dek = get_passphrase_hash( keyid, NULL, NULL );
 
-           blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
-           blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+           if( cert->protect.algo == CIPHER_ALGO_CAST )
+               cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
+           else
+               blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+
+           if( blowfish_ctx ) {
+               blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+               blowfish_setiv( blowfish_ctx, NULL );
+           }
+           else {
+               cast5_setkey( cast5_ctx, dek->key, dek->keylen );
+               cast5_setiv( cast5_ctx, NULL );
+           }
            m_free(dek); /* pw is in secure memory, so m_free() burns it */
-           blowfish_setiv( blowfish_ctx, NULL );
            memcpy(save_iv, cert->protect.iv, 8 );
-           blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
-                                              cert->protect.iv, 8 );
+           if( blowfish_ctx )
+               blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
+                                                  cert->protect.iv, 8 );
+           else
+               cast5_decode_cfb( cast5_ctx, cert->protect.iv,
+                                               cert->protect.iv, 8 );
            mpi_set_secure(cert->d.elg.x );
            /*fixme: maybe it is better to set the buffer secure with a
             * new get_buffer_secure() function */
            buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
            csum = checksum_u16( nbytes*8 );
-           blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           if( blowfish_ctx )
+               blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           else
+               cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes );
            csum += checksum( buffer, nbytes );
            test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
            mpi_set_buffer( test_x, buffer, nbytes, 0 );
            m_free( buffer );
+           m_free( cast5_ctx );
            m_free( blowfish_ctx );
            /* now let's see wether we have used the right passphrase */
            if( csum != cert->csum ) {
@@ -155,10 +178,12 @@ check_dsa( PKT_secret_cert *cert )
        DEK *dek = NULL;
        MPI test_x;
        BLOWFISH_context *blowfish_ctx=NULL;
+       CAST5_context *cast5_ctx=NULL;
 
        switch( cert->protect.algo ) {
          case CIPHER_ALGO_NONE: BUG(); break;
          case CIPHER_ALGO_BLOWFISH:
+         case CIPHER_ALGO_CAST:
            keyid_from_skc( cert, keyid );
            if( cert->protect.s2k == 1 || cert->protect.s2k == 3 )
                dek = get_passphrase_hash( keyid, NULL,
@@ -166,24 +191,38 @@ check_dsa( PKT_secret_cert *cert )
            else
                dek = get_passphrase_hash( keyid, NULL, NULL );
 
-           blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
-           blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+           if( cert->protect.algo == CIPHER_ALGO_CAST ) {
+               cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
+               cast5_setkey( cast5_ctx, dek->key, dek->keylen );
+               cast5_setiv( cast5_ctx, NULL );
+           }
+           else {
+               blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+               blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+               blowfish_setiv( blowfish_ctx, NULL );
+           }
            m_free(dek); /* pw is in secure memory, so m_free() burns it */
-           blowfish_setiv( blowfish_ctx, NULL );
            memcpy(save_iv, cert->protect.iv, 8 );
-           blowfish_decode_cfb( blowfish_ctx,
-                                cert->protect.iv,
-                                cert->protect.iv, 8 );
+           if( blowfish_ctx )
+               blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
+                                                  cert->protect.iv, 8 );
+           else
+               cast5_decode_cfb( cast5_ctx, cert->protect.iv,
+                                            cert->protect.iv, 8 );
            mpi_set_secure(cert->d.dsa.x );
            /*fixme: maybe it is better to set the buffer secure with a
             * new get_buffer_secure() function */
            buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
            csum = checksum_u16( nbytes*8 );
-           blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           if( blowfish_ctx )
+               blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+           else
+               cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes );
            csum += checksum( buffer, nbytes );
            test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.dsa.x) );
            mpi_set_buffer( test_x, buffer, nbytes, 0 );
            m_free( buffer );
+           m_free( cast5_ctx );
            m_free( blowfish_ctx );
            /* now let's see wether we have used the right passphrase */
            if( csum != cert->csum ) {
@@ -399,6 +438,7 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek )
 
     if( !cert->is_protected ) { /* okay, apply the protection */
        BLOWFISH_context *blowfish_ctx=NULL;
+       CAST5_context *cast5_ctx=NULL;
 
        switch( cert->protect.algo ) {
          case CIPHER_ALGO_NONE: BUG(); break;
@@ -414,6 +454,18 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek )
            m_free( blowfish_ctx );
            break;
 
+         case CIPHER_ALGO_CAST:
+           cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
+           cast5_setkey( cast5_ctx, dek->key, dek->keylen );
+           cast5_setiv( cast5_ctx, NULL );
+           cast5_encode_cfb( cast5_ctx, cert->protect.iv,
+                                              cert->protect.iv, 8 );
+           if( !do_protect( (void (*)(void*,byte*,byte*,unsigned))
+                            &cast5_encode_cfb, cast5_ctx, cert ) )
+               cert->is_protected = 1;
+           m_free( cast5_ctx );
+           break;
+
          default:
            rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
            break;
index 314347a..b17302e 100644 (file)
@@ -41,6 +41,7 @@ make_session_key( DEK *dek )
        randomize_buffer( dek->key, dek->keylen, 1 );
        break;
       case CIPHER_ALGO_BLOWFISH128:
+      case CIPHER_ALGO_CAST:
        dek->keylen = 16;
        randomize_buffer( dek->key, dek->keylen, 1 );
        break;
index 9987fde..6135929 100644 (file)
@@ -33,6 +33,7 @@
   #include "../cipher/rsa.h"
 #endif
 #include "../cipher/blowfish.h"
+#include "../cipher/cast5.h"
 #include "../cipher/elgamal.h"
 #include "../cipher/dsa.h"
 #include "../cipher/random.h"
index ed1e83d..e9bf478 100644 (file)
@@ -1,19 +1,23 @@
 ## Process this file with automake to produce Makefile.in
 
 INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl
-needed_libs = ../cipher/libcipher.a  ../util/libutil.a ../mpi/libmpi.a ../util/libutil.a
+needed_libs = ../cipher/libcipher.a  ../util/libutil.a \
+             ../mpi/libmpi.a ../util/libutil.a
 
-noinst_PROGRAMS = mpicalc bftest clean-sat
+noinst_PROGRAMS = mpicalc bftest cast5test clean-sat
 
 mpicalc_SOURCES = mpicalc.c
 
 bftest_SOURCES = bftest.c
 
+cast5test_SOURCES = cast5test.c
+
 clean_sat_SOURCES  = clean-sat.c
 
 
 mpicalc_LDADD = @INTLLIBS@  $(needed_libs)
 bftest_LDADD = @INTLLIBS@  $(needed_libs)
+cast5test_LDADD = @INTLLIBS@  $(needed_libs)
 
-mpicalc bftest: $(needed_libs)
+mpicalc bftest cast5test: $(needed_libs)
 
index a9ceae4..9b99174 100644 (file)
@@ -93,18 +93,22 @@ ZLIBS = @ZLIBS@
 l = @l@
 
 INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl
-needed_libs = ../cipher/libcipher.a  ../util/libutil.a ../mpi/libmpi.a ../util/libutil.a
+needed_libs = ../cipher/libcipher.a  ../util/libutil.a \
+             ../mpi/libmpi.a ../util/libutil.a
 
-noinst_PROGRAMS = mpicalc bftest clean-sat
+noinst_PROGRAMS = mpicalc bftest cast5test clean-sat
 
 mpicalc_SOURCES = mpicalc.c
 
 bftest_SOURCES = bftest.c
 
+cast5test_SOURCES = cast5test.c
+
 clean_sat_SOURCES  = clean-sat.c
 
 mpicalc_LDADD = @INTLLIBS@  $(needed_libs)
 bftest_LDADD = @INTLLIBS@  $(needed_libs)
+cast5test_LDADD = @INTLLIBS@  $(needed_libs)
 mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
 CONFIG_HEADER = ../config.h
 CONFIG_CLEAN_FILES = 
@@ -123,6 +127,10 @@ bftest_OBJECTS =  bftest.o
 bftest_DEPENDENCIES =  ../cipher/libcipher.a ../util/libutil.a \
 ../mpi/libmpi.a ../util/libutil.a
 bftest_LDFLAGS = 
+cast5test_OBJECTS =  cast5test.o
+cast5test_DEPENDENCIES =  ../cipher/libcipher.a ../util/libutil.a \
+../mpi/libmpi.a ../util/libutil.a
+cast5test_LDFLAGS = 
 clean_sat_OBJECTS =  clean-sat.o
 clean_sat_LDADD = $(LDADD)
 clean_sat_DEPENDENCIES = 
@@ -137,9 +145,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP = --best
-DEP_FILES =  .deps/bftest.P .deps/clean-sat.P .deps/mpicalc.P
-SOURCES = $(mpicalc_SOURCES) $(bftest_SOURCES) $(clean_sat_SOURCES)
-OBJECTS = $(mpicalc_OBJECTS) $(bftest_OBJECTS) $(clean_sat_OBJECTS)
+DEP_FILES =  .deps/bftest.P .deps/cast5test.P .deps/clean-sat.P \
+.deps/mpicalc.P
+SOURCES = $(mpicalc_SOURCES) $(bftest_SOURCES) $(cast5test_SOURCES) $(clean_sat_SOURCES)
+OBJECTS = $(mpicalc_OBJECTS) $(bftest_OBJECTS) $(cast5test_OBJECTS) $(clean_sat_OBJECTS)
 
 default: all
 
@@ -186,6 +195,10 @@ bftest: $(bftest_OBJECTS) $(bftest_DEPENDENCIES)
        @rm -f bftest
        $(LINK) $(bftest_LDFLAGS) $(bftest_OBJECTS) $(bftest_LDADD) $(LIBS)
 
+cast5test: $(cast5test_OBJECTS) $(cast5test_DEPENDENCIES)
+       @rm -f cast5test
+       $(LINK) $(cast5test_LDFLAGS) $(cast5test_OBJECTS) $(cast5test_LDADD) $(LIBS)
+
 clean-sat: $(clean_sat_OBJECTS) $(clean_sat_DEPENDENCIES)
        @rm -f clean-sat
        $(LINK) $(clean_sat_LDFLAGS) $(clean_sat_OBJECTS) $(clean_sat_LDADD) $(LIBS)
@@ -320,7 +333,7 @@ installdirs mostlyclean-generic distclean-generic clean-generic \
 maintainer-clean-generic clean mostlyclean distclean maintainer-clean
 
 
-mpicalc bftest: $(needed_libs)
+mpicalc bftest cast5test: $(needed_libs)
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/tools/cast5test.c b/tools/cast5test.c
new file mode 100644 (file)
index 0000000..04e24d7
--- /dev/null
@@ -0,0 +1,108 @@
+/* cast5test.c - CAST5 test program
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUPG.
+ *
+ * GNUPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __MINGW32__
+  #include <io.h>
+  #include <fcntl.h>
+#endif
+
+#include "util.h"
+#include "cipher.h"
+#include "i18n.h"
+
+static void
+my_usage(void)
+{
+    fprintf(stderr, "usage: cast5test [-e][-d] key\n");
+    exit(1);
+}
+
+const char *
+strusage( int level )
+{
+    return default_strusage(level);
+}
+
+static void
+i18n_init(void)
+{
+  #ifdef ENABLE_NLS
+    #ifdef HAVE_LC_MESSAGES
+       setlocale( LC_MESSAGES, "" );
+    #else
+       setlocale( LC_ALL, "" );
+    #endif
+    bindtextdomain( PACKAGE, G10_LOCALEDIR );
+    textdomain( PACKAGE );
+  #endif
+}
+
+int
+main(int argc, char **argv)
+{
+    int encode=0;
+    CAST5_context ctx;
+    char buf[100];
+    int n, size=100;
+
+  #ifdef __MINGW32__
+    setmode( fileno(stdin), O_BINARY );
+    setmode( fileno(stdout), O_BINARY );
+  #endif
+
+    i18n_init();
+    if( argc > 1 && !strcmp(argv[1], "-e") ) {
+       encode++;
+       argc--; argv++;
+    }
+    else if( argc > 1 && !strcmp(argv[1], "-E") ) {
+       encode++;
+       argc--; argv++;
+       size = 10;
+    }
+    else if( argc > 1 && !strcmp(argv[1], "-d") ) {
+       argc--; argv++;
+    }
+    else if( argc > 1 && !strcmp(argv[1], "-D") ) {
+       argc--; argv++;
+       size = 10;
+    }
+    if( argc != 2 )
+       my_usage();
+    argc--; argv++;
+
+    cast5_setkey( &ctx, *argv, strlen(*argv) );
+    cast5_setiv( &ctx, NULL );
+    while( (n = fread( buf, 1, size, stdin )) > 0 ) {
+       if( encode )
+           cast5_encode_cfb( &ctx, buf, buf, n );
+       else
+           cast5_decode_cfb( &ctx, buf, buf, n );
+       if( fwrite( buf, 1, n, stdout) != n )
+           log_fatal("write error\n");
+    }
+
+    return 0;
+}
+