diff --git a/NEWS b/NEWS index 330651d21..c73652e66 100644 --- 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 769ed6ae7..160dadac6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.14 +0.2.14a diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 3d2bf7cad..d76846591 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -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) diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 926d084bd..ff2e9f37f 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -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 \ diff --git a/cipher/Makefile.in b/cipher/Makefile.in index 981fd9957..91ed0a95b 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -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) diff --git a/cipher/cast5.c b/cipher/cast5.c index 4d6d8408c..a14abaa37 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -18,6 +18,23 @@ * 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 #include #include @@ -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; + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - 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; - } + /* (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; + u32 l, r, t; + u32 I; + u32 *Km; + byte *Kr; - xl = *ret_xl; - xr = *ret_xr; + 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; +} + + + +static void +selftest() +{ + 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"); - 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; - - xr ^= bc->p[1]; - xl ^= bc->p[0]; - - *ret_xl = xl; - *ret_xr = xr; + #endif } -static void -encrypted_block( CAST5_context *bc, byte *outbuf, byte *inbuf ) -{ - u32 d1, d2; - - d1 = ((u32*)inbuf)[0]; - d2 = ((u32*)inbuf)[1]; - encrypted( bc, &d1, &d2 ); - ((u32*)outbuf)[0] = d1; - ((u32*)outbuf)[1] = d2; -} 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; + static int initialized; + int i; + u32 x[4]; + u32 z[4]; + u32 k[16]; - 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]; + if( !initialized ) { + initialized = 1; + selftest(); } + fast_random_poll(); - 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; - } + 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]; - 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; - } + 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; + } +} + + diff --git a/cipher/cast5.h b/cipher/cast5.h index 125112829..4afaf2a8a 100644 --- a/cipher/cast5.h +++ b/cipher/cast5.h @@ -25,11 +25,8 @@ #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*/ diff --git a/cipher/misc.c b/cipher/misc.c index ad937fcfe..d251955ee 100644 --- a/cipher/misc.c +++ b/cipher/misc.c @@ -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; diff --git a/doc/DETAILS b/doc/DETAILS index 4b8eda8ed..6f1d895ad 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -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 +PUT +DELETE + + +The format of a response is: + +------ +"GNUPG/1.0" status-code status-text +"Content-length:" digits +CRLF +------------ +followed by 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 + + + diff --git a/g10/ChangeLog b/g10/ChangeLog index b82ceae28..e16f15550 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -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 diff --git a/g10/build-packet.c b/g10/build-packet.c index 85278af1c..4d0a7d69f 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -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 ); } diff --git a/g10/cipher.c b/g10/cipher.c index 52da03b58..8e6c91aa9 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -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"; diff --git a/g10/encr-data.c b/g10/encr-data.c index a1b4be0e9..4f8aa897d 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -28,13 +28,16 @@ #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; diff --git a/g10/filter.h b/g10/filter.h index 2fa3b8c45..fac1e0e2b 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -61,6 +61,7 @@ typedef struct { DEK *dek; u32 datalen; BLOWFISH_context *bf_ctx; + CAST5_context *cast5_ctx; int header; } cipher_filter_context_t; diff --git a/g10/passphrase.c b/g10/passphrase.c index ee5d4105b..46ff83163 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -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; diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 8ffa6483c..f19af2189 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -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; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 49870dcd9..dada0fd20 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -31,7 +31,10 @@ #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; diff --git a/g10/seskey.c b/g10/seskey.c index 314347a8b..b17302ea5 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -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; diff --git a/include/cipher.h b/include/cipher.h index 9987fdec9..6135929cf 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -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" diff --git a/tools/Makefile.am b/tools/Makefile.am index ed1e83dfb..e9bf4782e 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -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) diff --git a/tools/Makefile.in b/tools/Makefile.in index a9ceae455..9b99174e0 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -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 index 000000000..04e24d7e5 --- /dev/null +++ b/tools/cast5test.c @@ -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 +#include +#include +#include +#ifdef __MINGW32__ + #include + #include +#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; +} +