From f4846928f6228bf405d28a06b8eeb6fd012942d6 Mon Sep 17 00:00:00 2001 From: provos <> Date: Tue, 21 Jul 1998 22:23:20 +0000 Subject: [PATCH] Add CAST encryption, implementation by Steve Reid . Man pages will come soon, I hope. --- src/include/Makefile | 6 +- src/include/cast.h | 25 ++++ src/lib/libc/crypt/Makefile.inc | 4 +- src/lib/libc/crypt/cast.c | 240 ++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 src/include/cast.h create mode 100644 src/lib/libc/crypt/cast.c diff --git a/src/include/Makefile b/src/include/Makefile index 008358e7..9c3a1215 100644 --- a/src/include/Makefile +++ b/src/include/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.52 1998/07/17 22:47:46 espie Exp $ +# $OpenBSD: Makefile,v 1.53 1998/07/21 22:23:18 provos Exp $ # $NetBSD: Makefile,v 1.59 1996/05/15 21:36:43 jtc Exp $ # @(#)Makefile 5.45.1.1 (Berkeley) 5/6/91 @@ -8,8 +8,8 @@ # Missing: mp.h -FILES= a.out.h ar.h assert.h bitstring.h blf.h bm.h cpio.h ctype.h db.h \ - des.h dirent.h disktab.h elf_abi.h err.h fnmatch.h fstab.h fts.h \ +FILES= a.out.h ar.h assert.h bitstring.h blf.h bm.h cast.h cpio.h ctype.h \ + db.h des.h dirent.h disktab.h elf_abi.h err.h fnmatch.h fstab.h fts.h \ glob.h grp.h ieeefp.h inttypes.h iso646.h kvm.h langinfo.h libgen.h \ limits.h locale.h malloc.h math.h md4.h md5.h memory.h mpool.h ndbm.h \ netdb.h netgroup.h nlist.h nl_types.h olf_abi.h paths.h poll.h pwd.h \ diff --git a/src/include/cast.h b/src/include/cast.h new file mode 100644 index 00000000..539a727b --- /dev/null +++ b/src/include/cast.h @@ -0,0 +1,25 @@ +/* $OpenBSD: cast.h,v 1.1 1998/07/21 22:23:17 provos Exp $ */ +/* + * CAST-128 in C + * Written by Steve Reid + * 100% Public Domain - no warranty + * Released 1997.10.11 + */ + +#ifndef _CAST_H_ +#define _CAST_H_ + +typedef unsigned char u8; /* 8-bit unsigned */ +typedef unsigned long u32; /* 32-bit unsigned */ + +typedef struct { + u32 xkey[32]; /* Key, after expansion */ + int rounds; /* Number of rounds to use, 12 or 16 */ +} cast_key; + +void cast_setkey(cast_key* key, u8* rawkey, int keybytes); +void cast_encrypt(cast_key* key, u8* inblock, u8* outblock); +void cast_decrypt(cast_key* key, u8* inblock, u8* outblock); + +#endif /* ifndef _CAST_H_ */ + diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc index 7866f46a..9d96d657 100644 --- a/src/lib/libc/crypt/Makefile.inc +++ b/src/lib/libc/crypt/Makefile.inc @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile.inc,v 1.9 1997/04/16 12:11:27 deraadt Exp $ +# $OpenBSD: Makefile.inc,v 1.10 1998/07/21 22:23:20 provos Exp $ .PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt -SRCS+= crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c +SRCS+= cast.c crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c SRCS+= bcrypt.c MAN+= crypt.3 blowfish.3 arc4random.3 diff --git a/src/lib/libc/crypt/cast.c b/src/lib/libc/crypt/cast.c new file mode 100644 index 00000000..69dad6b6 --- /dev/null +++ b/src/lib/libc/crypt/cast.c @@ -0,0 +1,240 @@ +/* $OpenBSD: cast.c,v 1.1 1998/07/21 22:23:19 provos Exp $ */ +/* + * CAST-128 in C + * Written by Steve Reid + * 100% Public Domain - no warranty + * Released 1997.10.11 + */ + +#include +#include + +/* Macros to access 8-bit bytes out of a 32-bit word */ +#define U8a(x) ( (u8) (x>>24) ) +#define U8b(x) ( (u8) ((x>>16)&255) ) +#define U8c(x) ( (u8) ((x>>8)&255) ) +#define U8d(x) ( (u8) ((x)&255) ) + +/* Circular left shift */ +#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) ) + +/* CAST-128 uses three different round functions */ +#define F1(l, r, i) \ + t = ROL(key->xkey[i] + r, key->xkey[i+16]); \ + l ^= ((cast_sbox1[U8a(t)] ^ cast_sbox2[U8b(t)]) - \ + cast_sbox3[U8c(t)]) + cast_sbox4[U8d(t)]; +#define F2(l, r, i) \ + t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \ + l ^= ((cast_sbox1[U8a(t)] - cast_sbox2[U8b(t)]) + \ + cast_sbox3[U8c(t)]) ^ cast_sbox4[U8d(t)]; +#define F3(l, r, i) \ + t = ROL(key->xkey[i] - r, key->xkey[i+16]); \ + l ^= ((cast_sbox1[U8a(t)] + cast_sbox2[U8b(t)]) ^ \ + cast_sbox3[U8c(t)]) - cast_sbox4[U8d(t)]; + + +/***** Encryption Function *****/ + +void cast_encrypt(cast_key* key, u8* inblock, u8* outblock) +{ +u32 t, l, r; + + /* Get inblock into l,r */ + l = ((u32)inblock[0] << 24) | ((u32)inblock[1] << 16) | + ((u32)inblock[2] << 8) | (u32)inblock[3]; + r = ((u32)inblock[4] << 24) | ((u32)inblock[5] << 16) | + ((u32)inblock[6] << 8) | (u32)inblock[7]; + /* Do the work */ + F1(l, r, 0); + F2(r, l, 1); + F3(l, r, 2); + F1(r, l, 3); + F2(l, r, 4); + F3(r, l, 5); + F1(l, r, 6); + F2(r, l, 7); + F3(l, r, 8); + F1(r, l, 9); + F2(l, r, 10); + F3(r, l, 11); + /* Only do full 16 rounds if key length > 80 bits */ + if (key->rounds > 12) { + F1(l, r, 12); + F2(r, l, 13); + F3(l, r, 14); + F1(r, l, 15); + } + /* Put l,r into outblock */ + outblock[0] = U8a(r); + outblock[1] = U8b(r); + outblock[2] = U8c(r); + outblock[3] = U8d(r); + outblock[4] = U8a(l); + outblock[5] = U8b(l); + outblock[6] = U8c(l); + outblock[7] = U8d(l); + /* Wipe clean */ + t = l = r = 0; +} + + +/***** Decryption Function *****/ + +void cast_decrypt(cast_key* key, u8* inblock, u8* outblock) +{ +u32 t, l, r; + + /* Get inblock into l,r */ + r = ((u32)inblock[0] << 24) | ((u32)inblock[1] << 16) | + ((u32)inblock[2] << 8) | (u32)inblock[3]; + l = ((u32)inblock[4] << 24) | ((u32)inblock[5] << 16) | + ((u32)inblock[6] << 8) | (u32)inblock[7]; + /* Do the work */ + /* Only do full 16 rounds if key length > 80 bits */ + if (key->rounds > 12) { + F1(r, l, 15); + F3(l, r, 14); + F2(r, l, 13); + F1(l, r, 12); + } + F3(r, l, 11); + F2(l, r, 10); + F1(r, l, 9); + F3(l, r, 8); + F2(r, l, 7); + F1(l, r, 6); + F3(r, l, 5); + F2(l, r, 4); + F1(r, l, 3); + F3(l, r, 2); + F2(r, l, 1); + F1(l, r, 0); + /* Put l,r into outblock */ + outblock[0] = U8a(l); + outblock[1] = U8b(l); + outblock[2] = U8c(l); + outblock[3] = U8d(l); + outblock[4] = U8a(r); + outblock[5] = U8b(r); + outblock[6] = U8c(r); + outblock[7] = U8d(r); + /* Wipe clean */ + t = l = r = 0; +} + + +/***** Key Schedual *****/ + +void cast_setkey(cast_key* key, u8* rawkey, int keybytes) +{ +u32 t[4], z[4], x[4]; +int i; + + /* Set number of rounds to 12 or 16, depending on key length */ + key->rounds = (keybytes <= 10 ? 12 : 16); + + /* Copy key to workspace x */ + for (i = 0; i < 4; i++) { + x[i] = 0; + if ((i*4+0) < keybytes) x[i] = (u32)rawkey[i*4+0] << 24; + if ((i*4+1) < keybytes) x[i] |= (u32)rawkey[i*4+1] << 16; + if ((i*4+2) < keybytes) x[i] |= (u32)rawkey[i*4+2] << 8; + if ((i*4+3) < keybytes) x[i] |= (u32)rawkey[i*4+3]; + } + /* Generate 32 subkeys, four at a time */ + for (i = 0; i < 32; i+=4) { + switch (i & 4) { + case 0: + t[0] = z[0] = x[0] ^ cast_sbox5[U8b(x[3])] ^ + cast_sbox6[U8d(x[3])] ^ cast_sbox7[U8a(x[3])] ^ + cast_sbox8[U8c(x[3])] ^ cast_sbox7[U8a(x[2])]; + t[1] = z[1] = x[2] ^ cast_sbox5[U8a(z[0])] ^ + cast_sbox6[U8c(z[0])] ^ cast_sbox7[U8b(z[0])] ^ + cast_sbox8[U8d(z[0])] ^ cast_sbox8[U8c(x[2])]; + t[2] = z[2] = x[3] ^ cast_sbox5[U8d(z[1])] ^ + cast_sbox6[U8c(z[1])] ^ cast_sbox7[U8b(z[1])] ^ + cast_sbox8[U8a(z[1])] ^ cast_sbox5[U8b(x[2])]; + t[3] = z[3] = x[1] ^ cast_sbox5[U8c(z[2])] ^ + cast_sbox6[U8b(z[2])] ^ cast_sbox7[U8d(z[2])] ^ + cast_sbox8[U8a(z[2])] ^ cast_sbox6[U8d(x[2])]; + break; + case 4: + t[0] = x[0] = z[2] ^ cast_sbox5[U8b(z[1])] ^ + cast_sbox6[U8d(z[1])] ^ cast_sbox7[U8a(z[1])] ^ + cast_sbox8[U8c(z[1])] ^ cast_sbox7[U8a(z[0])]; + t[1] = x[1] = z[0] ^ cast_sbox5[U8a(x[0])] ^ + cast_sbox6[U8c(x[0])] ^ cast_sbox7[U8b(x[0])] ^ + cast_sbox8[U8d(x[0])] ^ cast_sbox8[U8c(z[0])]; + t[2] = x[2] = z[1] ^ cast_sbox5[U8d(x[1])] ^ + cast_sbox6[U8c(x[1])] ^ cast_sbox7[U8b(x[1])] ^ + cast_sbox8[U8a(x[1])] ^ cast_sbox5[U8b(z[0])]; + t[3] = x[3] = z[3] ^ cast_sbox5[U8c(x[2])] ^ + cast_sbox6[U8b(x[2])] ^ cast_sbox7[U8d(x[2])] ^ + cast_sbox8[U8a(x[2])] ^ cast_sbox6[U8d(z[0])]; + break; + } + switch (i & 12) { + case 0: + case 12: + key->xkey[i+0] = cast_sbox5[U8a(t[2])] ^ cast_sbox6[U8b(t[2])] ^ + cast_sbox7[U8d(t[1])] ^ cast_sbox8[U8c(t[1])]; + key->xkey[i+1] = cast_sbox5[U8c(t[2])] ^ cast_sbox6[U8d(t[2])] ^ + cast_sbox7[U8b(t[1])] ^ cast_sbox8[U8a(t[1])]; + key->xkey[i+2] = cast_sbox5[U8a(t[3])] ^ cast_sbox6[U8b(t[3])] ^ + cast_sbox7[U8d(t[0])] ^ cast_sbox8[U8c(t[0])]; + key->xkey[i+3] = cast_sbox5[U8c(t[3])] ^ cast_sbox6[U8d(t[3])] ^ + cast_sbox7[U8b(t[0])] ^ cast_sbox8[U8a(t[0])]; + break; + case 4: + case 8: + key->xkey[i+0] = cast_sbox5[U8d(t[0])] ^ cast_sbox6[U8c(t[0])] ^ + cast_sbox7[U8a(t[3])] ^ cast_sbox8[U8b(t[3])]; + key->xkey[i+1] = cast_sbox5[U8b(t[0])] ^ cast_sbox6[U8a(t[0])] ^ + cast_sbox7[U8c(t[3])] ^ cast_sbox8[U8d(t[3])]; + key->xkey[i+2] = cast_sbox5[U8d(t[1])] ^ cast_sbox6[U8c(t[1])] ^ + cast_sbox7[U8a(t[2])] ^ cast_sbox8[U8b(t[2])]; + key->xkey[i+3] = cast_sbox5[U8b(t[1])] ^ cast_sbox6[U8a(t[1])] ^ + cast_sbox7[U8c(t[2])] ^ cast_sbox8[U8d(t[2])]; + break; + } + switch (i & 12) { + case 0: + key->xkey[i+0] ^= cast_sbox5[U8c(z[0])]; + key->xkey[i+1] ^= cast_sbox6[U8c(z[1])]; + key->xkey[i+2] ^= cast_sbox7[U8b(z[2])]; + key->xkey[i+3] ^= cast_sbox8[U8a(z[3])]; + break; + case 4: + key->xkey[i+0] ^= cast_sbox5[U8a(x[2])]; + key->xkey[i+1] ^= cast_sbox6[U8b(x[3])]; + key->xkey[i+2] ^= cast_sbox7[U8d(x[0])]; + key->xkey[i+3] ^= cast_sbox8[U8d(x[1])]; + break; + case 8: + key->xkey[i+0] ^= cast_sbox5[U8b(z[2])]; + key->xkey[i+1] ^= cast_sbox6[U8a(z[3])]; + key->xkey[i+2] ^= cast_sbox7[U8c(z[0])]; + key->xkey[i+3] ^= cast_sbox8[U8c(z[1])]; + break; + case 12: + key->xkey[i+0] ^= cast_sbox5[U8d(x[0])]; + key->xkey[i+1] ^= cast_sbox6[U8d(x[1])]; + key->xkey[i+2] ^= cast_sbox7[U8a(x[2])]; + key->xkey[i+3] ^= cast_sbox8[U8b(x[3])]; + break; + } + if (i >= 16) { + key->xkey[i+0] &= 31; + key->xkey[i+1] &= 31; + key->xkey[i+2] &= 31; + key->xkey[i+3] &= 31; + } + } + /* Wipe clean */ + for (i = 0; i < 4; i++) { + t[i] = x[i] = z[i] = 0; + } +} + +/* Made in Canada */ +