From 556285bd4d30a9d06508c2b67c01040ee6e5e363 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 31 Oct 1994 00:54:16 +0000 Subject: Initial revision --- config/site.def | 143 +++++++++++++++++++++ libdes/ChangeLog | 68 ++++++++++ libdes/Imakefile | 139 ++++++++++++++++++++ libdes/Makefile | 227 ++++++++++++++++++++++++++++++++ libdes/debug_decl.c | 19 +++ libdes/des.h | 56 ++++++++ libdes/desglue.c | 109 ++++++++++++++++ libdes/destest.c | 37 ++++++ libdes/enc.c | 127 ++++++++++++++++++ libdes/f_README | 69 ++++++++++ libdes/f_cbc.c | 198 ++++++++++++++++++++++++++++ libdes/f_cksum.c | 108 ++++++++++++++++ libdes/f_ecb.c | 95 ++++++++++++++ libdes/f_parity.c | 62 +++++++++ libdes/f_pcbc.c | 207 ++++++++++++++++++++++++++++++ libdes/f_sched.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++++ libdes/f_tables.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++ libdes/f_tables.h | 223 ++++++++++++++++++++++++++++++++ libdes/key_sched.c | 58 +++++++++ libdes/new_rnd_key.c | 207 ++++++++++++++++++++++++++++++ libdes/quad_cksum.c | 153 ++++++++++++++++++++++ libdes/random_key.c | 97 ++++++++++++++ libdes/read_password.c | 249 ++++++++++++++++++++++++++++++++++++ libdes/string_to_key.c | 123 ++++++++++++++++++ libdes/util.c | 36 ++++++ libdes/verify.c | 275 +++++++++++++++++++++++++++++++++++++++ libdes/weak_key.c | 73 +++++++++++ 27 files changed, 3834 insertions(+) create mode 100644 config/site.def create mode 100644 libdes/ChangeLog create mode 100644 libdes/Imakefile create mode 100644 libdes/Makefile create mode 100644 libdes/debug_decl.c create mode 100644 libdes/des.h create mode 100644 libdes/desglue.c create mode 100644 libdes/destest.c create mode 100644 libdes/enc.c create mode 100644 libdes/f_README create mode 100644 libdes/f_cbc.c create mode 100644 libdes/f_cksum.c create mode 100644 libdes/f_ecb.c create mode 100644 libdes/f_parity.c create mode 100644 libdes/f_pcbc.c create mode 100644 libdes/f_sched.c create mode 100644 libdes/f_tables.c create mode 100644 libdes/f_tables.h create mode 100644 libdes/key_sched.c create mode 100644 libdes/new_rnd_key.c create mode 100644 libdes/quad_cksum.c create mode 100644 libdes/random_key.c create mode 100644 libdes/read_password.c create mode 100644 libdes/string_to_key.c create mode 100644 libdes/util.c create mode 100644 libdes/verify.c create mode 100644 libdes/weak_key.c diff --git a/config/site.def b/config/site.def new file mode 100644 index 0000000..7537cb1 --- /dev/null +++ b/config/site.def @@ -0,0 +1,143 @@ +/* + * BSD 4.3 + */ +#if (defined(vax) && !defined(ultrix)) || defined(ibm032) +#define LintCFlag -C +#define ProfCcFlags -pg +#endif + +#if defined(vax) && !defined(ultrix) +#define AnsiCcCmd gcc -pipe +#define AnsiLdCmd gcc -pipe +#define CcFlags "-Dmemmove(a,b,c)=bcopy(b,a,c)" +#endif + +#ifdef ibm032 +#define AnsiCcCmd cc -Hon=read_only_strings +#define CcFlags +#endif + + +/* + * DECstation ULTRIX + */ + + +/* + * DEC Alpha OSF/1 + */ +#if defined(__alpha) +#define RanlibCmd ar -tsl +#define LintLibFlag -o +#define LintOpts -ax +#define LintFlags -DPOSIX -xv -std +#define CcFlags -DPOSIX -std1 +#define NOLINT /* Until I can install somewhere useful */ +#endif + + +/* + * IBM AIX + */ +#if defined(_AIX) && defined(_IBMR2) +#define NOLINT + +#ifdef _AIX32 +#define ARBinDir /usr/bin/athena +#endif + +#define BsdLibs -lbsd +#define BsdFlags -D_BSD + +#define NoBsdArgs \ + /*-Dindex=index_oops*/ /*-Drindex=rindex_oops*/ \ + -Dbcopy=bcopy_oops /*-Dbzero=bzero_oops*/ -Dbcmp=bcmp_oops \ + -Dsignal=signal_oops -Dsigsetmask=sigsetmask_oops \ + -Dsigblock=sigblock_oops -Dsigpause=sigpause_oops \ + /*-Dsetjmp=setjmp_oops*/ -Dlongjmp=longjmp_oops +#undef NoBsdArgs +#define NoBsdArgs + +#define LdLibs BsdLibs +#define LintFlags BsdFlags -DAIXV=AIXV -DPOSIX NoBsdArgs +#define CcFlags LintFlags +#define AnsiCcCmd xlc -qro -D_ALL_SOURCE +#define CcCmd xlc -qlanglvl=extended -D_ALL_SOURCE + +#if !defined(UseInstalled) || defined(UseSharedLibs) +#define LdPath -L$(ATHLIBDIR)/shared -L$(ATHLIBDIR) + +#define static_program(prog,objs,ldflags,libs) @@\ +all:: prog @@\ +prog:: objs @@\ + $(LD) ldflags $(LDFLAGS) -o prog objs -L$(ATHLIBDIR) libs $(LDLIBS) @@\ +clean:: @@\ + $(RM) prog +#endif + +clean:: + $(RM) bind.??* + +#endif /* _AIX */ + + +/* + * MAC A/UX + */ +#ifdef _AUX_SOURCE +#define NOLINT + +/* Do not use -ZP; this undefines other symbols used by the system .h files */ +#define CcFlags -DPOSIX -D_POSIX_SOURCE -D_BSD_SOURCE +#define LdLibs -lposix +#define RanLibCmd \: +#endif + + +/* + * Sun SOLARIS + */ +#if defined(sun) && defined(sparc) + +#define NoBsdArgs \ + -Dsignal=signal_oops -Dlongjmp=lonjmp_oops -Dsetjmp=setjmp_oops +#undef NoBsdArgs +#define NoBsdArgs -I/usr/ucbinclude + +#define NOLINT +#define CcFlags -DSOLARIS -DPOSIX \ + -Dsrandom=srand48 -Drandom=lrand48 NoBsdArgs \ + -I/usr/gcc/include -I/usr/openwin/include +#define ProfCcFlags -pg +#define CDebugFlags -O2 +#define LdPath -L/usr/gcc/lib -L/usr/ccs/lib -L/usr/openwin/lib -L$(ATHLIBDIR) +#define LdLibs /usr/athena/lib/libresolv.a -lsocket -lnsl -lucb -lelf +#define AnsiCcCmd /usr/gcc/bin/gcc -B/usr/gcc/lib/ -traditional +#define AnsiLdCmd /usr/gcc/bin/gcc -B/usr/gcc/lib/ +#define CcCmd AnsiCcCmd +#define LdCmd AnsiLdCmd +#define RanLibCmd \: +#define AfsDir /usr/transarc +#define ExtraXLibs -lm +#endif + + +/* + * Linux + */ +#ifdef linux +#define NOLINT +#define NOPROF +#endif + + +/* + * AFS configuration + */ +#if !defined(AfsDir) && !defined(NoAFS) +#ifdef UseInstalled +#define AfsDir /mit/afsuser/@sys +#else +#define AfsDir $(TOP)/third/common/afs/@sys/dest +#endif +#endif diff --git a/libdes/ChangeLog b/libdes/ChangeLog new file mode 100644 index 0000000..ea3a9c0 --- /dev/null +++ b/libdes/ChangeLog @@ -0,0 +1,68 @@ +Tue Nov 8 12:12:32 1988 William Sommerfeld (wesommer at binkley) + + * (util) Remove \ before { and } characters (causes RT + compiler warning) + + * (read_password) Print a newline after saying "try again". + + * (read_password) Merge in changes by Jim Bloom to do a clearerr + after a read fails, and protect against an RTM attack by + changing gets to fgets. + +Fri Sep 16 16:26:55 1988 Bill Sommerfeld (wesommer at ra) + + * (read_password) fix dependancies for BSDUNIX. + +Mon Sep 12 14:55:23 1988 Bill Sommerfeld (wesommer at ra) + + * (*) debug->des_debug + + * (*) debug_print() -> des_debug_print() + + * (Makefile) add dbg_prt.o to list of files included in build. + + * (des.c) remove debug_print; it's in dbg_prt.c + + * (des_internal.h) contains definitions of AUTH_DES_ITER, + s-box structures, which aren't part of the encryption interface. + + * (*) #include "conf.h" -> #include "des_internal.h" + + * (*) C_Block -> des_cblock + + * (*) Key_schedule -> des_key_schedule + + * (noop.c) remove #includes for unused include files. + + * (des.c, random_key.c, string_to_key.c) add #include of "des_conf.h" + +Fri Sep 9 15:46:13 1988 Bill Sommerfeld (wesommer at ra) + + * (*) string_to_key() -> des_string_to_key() + + * (*) read_pw_string() -> des_read_pw_string() + + * (*) random_key() -> des_random_key() + + * (*) pcbc_encrypt() -> des_pcbc_encrypt() + + * (*) key_sched() -> des_key_sched() + + * (*) cbc_encrypt() -> des_cbc_encrypt() + + * (*) cbc_cksum() -> des_cbc_cksum() + + * (quad_cksum.c) make {four,two}_bytes_vax_to_nets be static to + avoid namespace pollution. + + * (*.c) Rename C_Block_print() to des_cblock_print(). + + * (make_key_perm.c) Make "key_perm" be static to avoid namespace + pollution. + + * (quad_cksum.c) Make "short_conv" and "long_conv" local + variables, to avoid namespace pollution. + + + + diff --git a/libdes/Imakefile b/libdes/Imakefile new file mode 100644 index 0000000..880ca04 --- /dev/null +++ b/libdes/Imakefile @@ -0,0 +1,139 @@ +# $Id$ +# +# Copyright 1987, 1993 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, +# please see the file . +# +# Imakefile for DES library +# + +all:: $(BINC)/des.h + +$(BINC)/des.h: des.h + $(RM) $@; $(CP) des.h $@ + +#ifdef MIT_DES +OTHEROBJS= cbc_encrypt.o cksum.o pcbc_encrypt.o make_key_sched.o des.o \ + key_parity.o +#else +OTHEROBJS= f_cbc.o f_cksum.o f_pcbc.o f_sched.o f_ecb.o f_parity.o f_tables.o +#endif +DESOBJS= $(OTHEROBJS) key_sched.o debug_decl.o \ + quad_cksum.o random_key.o read_password.o \ + string_to_key.o weak_key.o new_rnd_key.o util.o $(OLDOBJS) + +#ifdef ATHENA_RULES + +SimpleLibrary(des,$(DESOBJS),$(ATHLIBDIR)) + +build_program(enc,enc.o libdes.a,,) +build_program(destest,destest.o libdes.a,,) +build_program(verify,verify.o libdes.a,,) + +#ifdef MIT_DES +build_program(make_key_perm,make_key_perm.o misc.o,,) +build_program(make_odd,make_odd.o misc.o,,) +build_program(make_p_table,make_p_table.o misc.o,,) +build_program(make_s_table,make_s_table.o misc.o,,) +build_program(make_p,make_p.o misc.o,,) +build_program(make_fp,make_fp.o misc.o,,) +build_program(make_ip,make_ip.o misc.o,,) + +key_perm.h: make_key_perm + ./make_key_perm key_perm.h +odd.h: make_odd + ./make_odd odd.h +p_table.h: make_p_table + ./make_p_table p_table.h +s_table.h: make_s_table + ./make_s_table s_table.h +p.c: make_p + ./make_p p.c +fp.c: make_fp + ./make_fp fp.c +ip.c: make_ip + ./make_ip ip.c + +clean:: + $(RM) ip.c fp.c p.c s_table.h p_table.h odd.h key_perm.h + +key_parity.o: odd.h +key_sched.o: key_perm.h +des.o: s_table.h p_table.h ip.c fp.c p.c +misc.o: des_internal.h + +make_s_table:: tables.h des_internal.h +make_p_table:: tables.h des_internal.h +make_key_perm:: des_internal.h +make_s:: s_table.h des_internal.h +#endif + +#else /* ATHENA_RULES */ + +#ifdef OLD_COMPAT +OLDSRCS= desglue.c +OLDOBJS= desglue.o +#else +OLDSRCS= +OLDOBJS= +#endif +DESSRCS= key_sched.c des.c cbc_encrypt.c pcbc_encrypt.c debug_decl.c \ + cksum.c quad_cksum.c random_key.c read_password.c \ + string_to_key.c weak_key.c key_parity.c new_rnd_key.c util.c $(OLDSRCS) + +SRCS= des_internal.h make_key_perm.c make_ip.c make_fp.c make_e.c make_p.c make_s.c \ + make_s_table.c make_p_table.c make_odd.c misc.c \ + key_test.c testit.c verify.c epc_encrypt.c \ + cbc_noop.c enc.c ${DESSRCS} + +SRCDIR=$(SRCTOP)/lib/des +CODE=$(SRCS) Imakefile tables.h des.vaxasm + +library_obj_rule() + +install_library_target(des,$(DESOBJS),$(DESSRCS),) + +library_ro_object(dbg_prt) + +/* add other assembler versions here, if you come up with them. */ +#ifdef VAXASM +library_asm_object(des.o,des.vaxasm) +#else +library_ro_object(des) +library_ro_object(key_sched) +#endif +/* + * misc.o is used by all of the header generators. + */ + +host_simple_object(misc.o,misc.c) +/* + * Generate include files for use by key_sched & friends. + */ + +generate_depend(key_perm.h,make_key_perm,misc.o) +generate_depend(odd.h,make_odd,misc.o) +generate_depend(p_table.h,make_p_table,misc.o) +generate_depend(s_table.h,make_s_table,misc.o) +generate_depend(p.c,make_p,misc.o) +generate_depend(fp.c,make_fp,misc.o) +generate_depend(ip.c,make_ip,misc.o) + +misc.o: des_internal.h +make_s_table: tables.h des_internal.h +make_p_table: tables.h des_internal.h +make_key_perm: des_internal.h +make_s: s_table.h des_internal.h + + +/* + * verify that the library correctly implements the DES standard. + * Run this after any change to the source. + */ + +test(verify,libdes.a,) +test(key_test,libdes.a,) +test(testit,libdes.a,) + +#endif /* ATHENA_RULES */ diff --git a/libdes/Makefile b/libdes/Makefile new file mode 100644 index 0000000..3e12ea0 --- /dev/null +++ b/libdes/Makefile @@ -0,0 +1,227 @@ +# Makefile generated by imake - do not edit! +# $XConsortium: imake.c,v 1.86 93/10/11 12:12:36 rws Exp $ + +all:: + +SHELL=/bin/sh +MAKESHELL=/bin/sh + +TOP = ../. +CWD = ./libdes +CONFIGSRC = /mit/opssrc/zephyr.sunos/production/config +DESTDIR= + +IRULESRC = $(CONFIGSRC) + +PTOP = $(TOP)/. + +IMAKE= imake +IFLAGS= -I$(IRULESRC) $(IFLAGS_SH) $(OTHER_IFLAGS) -DTOPDIR=/mit/opssrc/zephyr.sunos/production +XIFLAGS= -I$(ATHXLIBDIR)/X11/config -DUseInstalled + +ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \ + $(IRULESRC)/site.def Imakefile $(PRULEDEP) +MKDIRHIER= sh $(IRULESRC)/mkdirhier.sh + +ATHVERS = $(IRULESRC)/update.conf + +ATHBASEDIR=/usr/athena + +ATHLIBDIR=$(ATHBASEDIR)/lib +ATHBINDIR=$(ATHBASEDIR)/bin +ATHINCDIR=$(ATHBASEDIR)/include +ATHETCDIR=$(ATHBASEDIR)/etc +ATHCONFDIR=/etc/athena +ATHMANDIR=$(ATHBASEDIR)/man +ATHRBINDIR=/bin/athena +ATHRETCDIR=/etc/athena + +ATHNEWDIR=$(ATHBINDIR) + +ATHXAPPDIR=/usr/athena/lib/X11/app-defaults +ATHXBITDIR=/usr/athena/lib/X11/bitmaps +ATHXINCDIR=/usr/athena/include +ATHXLIBDIR=/usr/athena/lib + +AFSDIR=/mit/afsuser/@sys + +LINTCFLAG=-o +LINTFLAGS=-DPOSIX $(DEFINES) -I/usr/athena/include + +INSTALL=install -c +RANLIB=ranlib +CC=cc +LD=cc +AS=as +RM=rm -f +CP=cp -p + +ETCMD=compile_et +SSCMD=mk_cmds + +LIB_ET = -lcom_err +LIB_SS = -lss +LIB_HES = -lhesiod +LIB_KRB = -lkrb -ldes +LIB_ZEPHYR = -lzephyr -lkrb -ldes -lcom_err +LIB_X = -lX11 -lXext +LIB_XT = -lXt -lX11 -lXext +LIB_XAW = -lXaw -lXmu -lXt -lX11 -lXext + +CDEBUG=-O2 + +CFLAGS=$(CDEBUG) -DPOSIX $(DEFINES) -I/usr/athena/include +LDFLAGS= $(LDDEFS) +LDPATH=-L$(ATHLIBDIR) +LDLIBS= + +install:: install_dirs +install_dirs:: +install:: +install.man:: + +clean:: +depend:: + +FRC:: + +########################################################################### +# start of Imakefile +########################################################################### + +# Copyright 1993 Massachusetts Institute of Technology +# For copying and distribution information, see the file +# "mit-copyright.h" +# +# $Id$ + +CDEFS_KRB = -DKERBEROS +ZLIB_KRB = $(LIB_KRB) + +CDEFS_HES = -DHESIOD +ZLIB_HES = $(LIB_HES) + +ZPIDDIR = /etc/athena +ZETCDIR = $(ATHCONFDIR)/zephyr +ZLIBDIR = $(ATHLIBDIR)/zephyr +ZINCDIR = $(ATHINCDIR)/zephyr +ZACLDIR = $(ZETCDIR)/acl + +BINC = $(PTOP)/h + +ZLIB = $(PTOP)/lib/libzephyr.a +ZLIBDES = $(PTOP)/libdes/libdes.a +ZLIBS = $(ZLIB_KRB) $(LIB_ET) $(ZLIB_HES) +DYN_LIB = $(PTOP)/libdyn/libdyn.a + +DEFINES = $(XDEFS) -I$(BINC) \ + $(CDEFS_KRB) $(CDEFS_HES) $(CDEFS_ET) $(CDEFS_SS) \ + $(MACHDEFS) + +CC=cc +LD=cc + +ATHBINDIR = /mit/zephyr/@sys/bin +ATHLIBDIR = /mit/zephyr/@sys/lib +ATHINCDIR = /mit/zephyr/include +ATHMANDIR = /mit/zephyr/man + +ZLIBDIR = /mit/zephyr/configs +ATHCONFDIR = $(ZLIBDIR) +ATHETCDIR = $(ATHBINDIR) +ATHRETCDIR = $(ATHBINDIR) + +LDPATH = -L/usr/athena/lib/shared -L/usr/athena/lib + +# $Id$ +# +# Copyright 1987, 1993 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, +# please see the file . +# +# Imakefile for DES library +# + +all:: $(BINC)/des.h + +$(BINC)/des.h: des.h + $(RM) $@; $(CP) des.h $@ + +OTHEROBJS= f_cbc.o f_cksum.o f_pcbc.o f_sched.o f_ecb.o f_parity.o f_tables.o + +DESOBJS= $(OTHEROBJS) key_sched.o debug_decl.o \ + quad_cksum.o random_key.o read_password.o \ + string_to_key.o weak_key.o new_rnd_key.o util.o $(OLDOBJS) + +all:: libdes.a + libdes.a:: $(DESOBJS) + ar cru libdes.a $(DESOBJS) + $(RANLIB) libdes.a +all-prof:: libdes_p.a + libdes_p.a: $(DESOBJS) + cd profiled; ar cru ../libdes_p.a $(DESOBJS) + $(RANLIB) libdes_p.a + +install:: + $(RM) $(DESTDIR)$(ATHLIBDIR)/libdes.a + $(INSTALL) -m 0644 libdes.a $(DESTDIR)$(ATHLIBDIR) + $(RANLIB) $(DESTDIR)$(ATHLIBDIR)/libdes.a +inst-prof:: + $(RM) $(DESTDIR)$(ATHLIBDIR)/libdes_p.a + $(INSTALL) -m 0644 libdes_p.a $(DESTDIR)$(ATHLIBDIR) + $(RANLIB) $(DESTDIR)$(ATHLIBDIR)/libdes_p.a + +all:: enc +enc:: enc.o libdes.a + $(LD) $(LDFLAGS) -o enc enc.o libdes.a $(LDPATH) $(LDLIBS) +clean:: + $(RM) enc + +all:: destest +destest:: destest.o libdes.a + $(LD) $(LDFLAGS) -o destest destest.o libdes.a $(LDPATH) $(LDLIBS) +clean:: + $(RM) destest + +all:: verify +verify:: verify.o libdes.a + $(LD) $(LDFLAGS) -o verify verify.o libdes.a $(LDPATH) $(LDLIBS) +clean:: + $(RM) verify + +PRULES = "config/zephyr.rules" +PINC = -DProjectRules=\"$(PRULES)\" -DProjectRuleDep=$(PRULES) + +PRULEDEP = $(PTOP)/config/zephyr.rules + +PTOP = $(TOP)/. +IPROJ = -DProject -DProjectTop=. -I$(PTOP) $(PINC) + +IFLAGS_SH = -DUseSharedLibs + +Makefile:: $(ICONFIGFILES) + -@if [ -f Makefile ]; then \ + echo " $(RM) Makefile.bak; mv Makefile Makefile.bak"; \ + $(RM) Makefile.bak; mv Makefile Makefile.bak; \ + else exit 0; fi + $(IMAKE) $(IPROJ) $(IFLAGS) -DNEWTOP=$(TOP) -DNEWCWD=$(CWD) + +XMakefile:: + -@if [ -f Makefile ]; then \ + echo " $(RM) Makefile.bak; mv Makefile Makefile.bak"; \ + $(RM) Makefile.bak; mv Makefile Makefile.bak; \ + else exit 0; fi + $(IMAKE) $(XIFLAGS) + +clean:: + $(RM) *~ *.o *.a core a.out Makefile.bak + $(RM) -r profiled + +all-prof inst-prof:: + +Makefiles:: + +########################################################################### +# dependencies generated by makedepend + diff --git a/libdes/debug_decl.c b/libdes/debug_decl.c new file mode 100644 index 0000000..30401dc --- /dev/null +++ b/libdes/debug_decl.c @@ -0,0 +1,19 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Declaration of debugging flag. + */ + +#ifndef lint +static char rcsid_debug_decl_c[] = + "$Id$"; +#endif + +#include +int des_debug = 0; diff --git a/libdes/des.h b/libdes/des.h new file mode 100644 index 0000000..412aba4 --- /dev/null +++ b/libdes/des.h @@ -0,0 +1,56 @@ +/* + * $Source$ + * $Author$ + * $Header$ + * + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Include file for the Data Encryption Standard library. + */ + +/* only do the whole thing once */ +#ifndef DES_DEFS +#define DES_DEFS + +#include + +typedef unsigned char des_cblock[8]; /* crypto-block size */ +/* Key schedule */ +typedef struct des_ks_struct { union { long pad; des_cblock _;} __; } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#ifndef NCOMPAT +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define key_sched des_key_sched +#define cbc_encrypt des_cbc_encrypt +#define cbc_cksum des_cbc_cksum +#define C_Block_print des_cblock_print +#define quad_cksum des_quad_cksum +typedef struct des_ks_struct bit_64; +#endif + +#define des_cblock_print(x) des_cblock_print_file(x, stdout) + +#if defined(__alpha) || defined(cray) +typedef int int32; +typedef unsigned int u_int32; +#else +typedef long int32; +typedef unsigned long u_int32; +#endif + +#endif /* DES_DEFS */ diff --git a/libdes/desglue.c b/libdes/desglue.c new file mode 100644 index 0000000..4238b65 --- /dev/null +++ b/libdes/desglue.c @@ -0,0 +1,109 @@ +/* + * $Source$ + * $Author$ + * $Header$ + * + * Copyright (C) 1988 by the Massachusetts Institute of Technology + * + * For copying and distribution information, please see the file + * . + * + * Backwards compatibility module. + */ + +#ifndef lint +static char *rcsid_desglue_c = "$Header$"; +#endif /* lint */ + +#ifndef NCOMPAT +#include + +#undef string_to_key +#undef read_pw_string +#undef random_key +#undef pcbc_encrypt +#undef key_sched +#undef cbc_encrypt +#undef cbc_cksum +#undef C_Block_print +#undef quad_cksum + +int +string_to_key(str, key) + char *str; + register des_cblock *key; +{ + return des_string_to_key(str, key); +} + + +int +read_pw_string(s, max, prompt, verify) + char *s; + int max; + char *prompt; + int verify; +{ + return des_read_pw_string (s, max, prompt, verify); +} + +random_key(key) + des_cblock *key; +{ + return des_random_key(key); +} + +pcbc_encrypt(in, out, length, key, iv, encrypt) + des_cblock *in, *out; + register long length; + des_key_schedule key; + des_cblock *iv; + int encrypt; +{ + return des_pcbc_encrypt (in, out, length, key, iv, encrypt); +} + +key_sched(k, s) + unsigned char *k; + des_key_schedule s; +{ + return des_key_sched (k, s); +} + +cbc_encrypt(in, out, length, key, iv, encrypt) + des_cblock *in, *out; + register long length; + des_key_schedule key; + des_cblock *iv; + int encrypt; +{ + return des_cbc_encrypt (in, out, length, key, iv, encrypt); +} + +cbc_cksum(in, out, length, key, iv) + des_cblock *in; /* >= length bytes of inputtext */ + des_cblock *out; /* >= length bytes of outputtext */ + register long length; /* in bytes */ + des_key_schedule key; /* precomputed key schedule */ + des_cblock *iv; /* 8 bytes of ivec */ +{ + return des_cbc_cksum(in, out, length, key, iv); +} + +C_Block_print(x) + des_cblock *x; +{ + return des_cblock_print (x); +} + +unsigned long +quad_cksum(in,out,length,out_count,c_seed) + des_cblock *c_seed; /* secret seed, 8 bytes */ + unsigned char *in; /* input block */ + unsigned long *out; /* optional longer output */ + int out_count; /* number of iterations */ + long length; /* original length in bytes */ +{ + return des_quad_cksum(in,out,length,out_count,c_seed); +} +#endif diff --git a/libdes/destest.c b/libdes/destest.c new file mode 100644 index 0000000..ad6333f --- /dev/null +++ b/libdes/destest.c @@ -0,0 +1,37 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +#ifndef lint +static char rcsid_destest_c[] = + "$Id$"; +#endif + +#include +#include +#include + +char clear[] = "eight bytes"; +char cipher[8]; +char key[8]; +Key_schedule schedule; + +main() +{ + int i; + string_to_key("good morning!", key); + i = key_sched(key, schedule); + if (i) { + printf("bad schedule (%d)\n", i); + exit(1); + } + for (i = 1; i <= 10000; i++) + des_ecb_encrypt(clear, cipher, schedule, i&1); + return 0; +} diff --git a/libdes/enc.c b/libdes/enc.c new file mode 100644 index 0000000..58e9a2d --- /dev/null +++ b/libdes/enc.c @@ -0,0 +1,127 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + */ + +#ifndef lint +static char rcsid_enc_c[] = + "$Id$"; +#endif + +#include +#include +#include +#include +#include + +#include + +des_key_schedule KEYSCHED; +des_cblock key = {0,1,2,3,4,5,6,7}; +des_cblock sum; +char inbuf[512+8]; /* leave room for cksum and len */ +char oubuf[512+8]; +int ind; +int oud; +long orig_size; + +main(argc,argv) + int argc; + char *argv[]; +{ + register int encrypt; + register long length; + register int *p; + u_int32 ivec[2]; + if (argc != 4) { + fprintf (stderr, "%s: Usage: %s infile outfile mode.\n", + argv[0], argv[0]); + exit (1); + } + if (!strcmp(argv[3], "e")) + encrypt = 1; + else if (!strcmp(argv[3], "d")) + encrypt = 0; + else { + fprintf (stderr, "%s: Mode must be e (encrypt) or d (decrypt).\n", + argv[0]); + exit (1); + } + if ((ind = open(argv[1], O_RDONLY, 0666)) < 0) { + fprintf (stderr, "%s: Cannot open %s for input.\n", + argv[0], argv[1]); + exit (1); + } + if (!strcmp(argv[2], "-")) + oud = dup(1); + else if ((oud = open(argv[2], O_CREAT|O_WRONLY, 0666)) < 0) { + fprintf (stderr, "%s: Cannot open %s for output.\n", + argv[0], argv[2]); + exit (1); + } +#ifdef notdef + (void) freopen ("/dev/tty", "r", stdin); + (void) freopen ("/dev/tty", "w", stdout); +#endif + des_read_password (key, "\n\07\07Enter Key> ", 1); + if (des_key_sched (key, KEYSCHED) < 0) { + fprintf (stderr, "%s: Key parity error\n", argv[0]); + exit (1); + } + ivec[0] = 0; + ivec[1] = 0; + memcpy(sum, key, sizeof(des_cblock)); + for (;;) { + if ((length = read (ind, inbuf, 512)) < 0) { + fprintf (stderr, "%s: Error reading from input.\n", + argv[0]); + exit (1); + } else if (length == 0) { + fprintf (stderr, "\n"); + break; + } + if (encrypt) { +#ifdef notdef + sum = des_quad_cksum(inbuf,NULL,length,1,sum); +#endif + des_quad_cksum(inbuf,sum,length,1,sum); + orig_size += length; + fprintf(stderr, + "\nlength = %d tot length = %d quad_sum = %X %X", + length, orig_size, *(unsigned long *) sum, + *((unsigned long *) sum+1)); + fflush(stderr); + } + des_pcbc_encrypt (inbuf, oubuf, (long) length, KEYSCHED, ivec, + encrypt); + if (!encrypt) { +#ifdef notdef + sum = des_quad_cksum(oubuf,NULL,length,1,sum); +#endif + des_quad_cksum(oubuf,sum,length,1,sum); + orig_size += length; + fprintf(stderr, + "\nlength = %d tot length = %d quad_sum = %X ", + length, orig_size, *(unsigned long *) sum, + *((unsigned long *) sum+1)); + } + length = (length+7)& ~07; + write (oud, oubuf, length); + if (!encrypt) + p = (int *)&oubuf[length-8]; + else + p = (int *)&inbuf[length-8]; + ivec[0] = *p++; + ivec[1] = *p; + } + + fprintf(stderr,"\ntot length = %d quad_sum = %X\n", + orig_size,sum); + /* if encrypting, now put the original length and checksum in */ + return 0; +} diff --git a/libdes/f_README b/libdes/f_README new file mode 100644 index 0000000..0d381e3 --- /dev/null +++ b/libdes/f_README @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +Sorry about the poor quality of installation instructions. Included +here are replacements for the DES portions of Eric Young's kerberos +DES library replacement. To use this you will need his distribution. +Untar the latter and: + +(1) Copy all .c and .h files into the distribution directory. This will + overwrite some files and add others. + +(2) Apply the patch included here to set_key.c in the distribution directory. + +(3) Edit the Imakefile (or the Makefile) to include the following files + on the SRCS= line: + + des_tables.c ecb_buffer.c make_sched.c + + Add the following files to the OBJS= line: + + des_tables.o ecb_buffer.o make_sched.o + + Add the following file to the CODE= line: + + des_tables.h + +Recompile and you're done. + +The salient differences between this DES and Eric Young's are as follows: + +(1) There are no dependencies on byte ordering, the ability to do + unaligned loads and stores, or any other machine dependencies + that I know of. There are no #ifdef's. The code could probably + be made faster by adding such things, but not enough to be worth + it. + +(2) Combined S and P tables are used for the inner loop of the cipher + routine and the E expansion is computed on the fly, like Eric + Young's code, but the computation is reordered from the standard + to save instructions. + +(3) The initial and final permutations are table driven, and take + about the same amount of work as a single round of the inner + loop (i.e. only about 12% of the work done for an ecb encryption + is spent in the IP and FP code). + +(4) Since NTP (for which this DES was originally implemented) uses + lots of keys to encrypt small things, the key permutation code + has been well worked over and is quite speedy (the amount of + work required to permute a key is on the order of that required + to do a single ECB encryption, more or less). + +(5) Since the code required to do an ECB encryption using the tables + is actually fairly compact, even with lots of inlining, it was + implemented as a macro and is expanded in situ where needed. + +On the one machine I ran a comparison on this code ran 80% faster than +Eric's, compiled into a slightly smaller space, and did pass destest. +I suspect this stuff is also faster, and not a lot larger, than the +library MIT doesn't export with kerberos. You mileage may vary. + +The silly copyright was a (probably ineffective) afterthought. If it +really inconveniences you give me a call. diff --git a/libdes/f_cbc.c b/libdes/f_cbc.c new file mode 100644 index 0000000..eba53be --- /dev/null +++ b/libdes/f_cbc.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode + */ +#include "des.h" +#include "f_tables.h" + +/* + * des_cbc_encrypt - {en,de}crypt a stream in CBC mode + */ +int +des_cbc_encrypt(in, out, length, schedule, ivec, encrypt) + des_cblock *in; + des_cblock *out; + long length; + des_key_schedule schedule; + des_cblock ivec; + int encrypt; +{ + register unsigned long left, right; + register unsigned long temp; + register u_int32 *kp; + register unsigned char *ip, *op; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp = (u_int32 *)schedule; + + /* + * Deal with encryption and decryption separately. + */ + if (encrypt) { + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = (unsigned char *)in; + op = (unsigned char *)out; + while (length > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length >= 8) { + left ^= ((*ip++) & 0xff) << 24; + left ^= ((*ip++) & 0xff) << 16; + left ^= ((*ip++) & 0xff) << 8; + left ^= (*ip++) & 0xff; + right ^= ((*ip++) & 0xff) << 24; + right ^= ((*ip++) & 0xff) << 16; + right ^= ((*ip++) & 0xff) << 8; + right ^= (*ip++) & 0xff; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) length; + switch(length) { + case 7: + right ^= (*(--ip) & 0xff) << 8; + case 6: + right ^= (*(--ip) & 0xff) << 16; + case 5: + right ^= (*(--ip) & 0xff) << 24; + case 4: + left ^= *(--ip) & 0xff; + case 3: + left ^= (*(--ip) & 0xff) << 8; + case 2: + left ^= (*(--ip) & 0xff) << 16; + case 1: + left ^= (*(--ip) & 0xff) << 24; + break; + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, temp, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + } + } else { + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + unsigned long ocipherl, ocipherr; + unsigned long cipherl, cipherr; + + if (length <= 0) + return 0; + + /* + * Prime the old cipher with ivec. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + ip = (unsigned char *)in; + op = (unsigned char *)out; + for (;;) { /* check done inside loop */ + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, temp, kp); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + if (length > 8) { + length -= 8; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: + *(--op) = right & 0xff; + case 7: + *(--op) = (right >> 8) & 0xff; + case 6: + *(--op) = (right >> 16) & 0xff; + case 5: + *(--op) = (right >> 24) & 0xff; + case 4: + *(--op) = left & 0xff; + case 3: + *(--op) = (left >> 8) & 0xff; + case 2: + *(--op) = (left >> 16) & 0xff; + case 1: + *(--op) = (left >> 24) & 0xff; + break; + } + break; /* we're done */ + } + } + } + + /* + * Done, return nothing. + */ + return 0; +} diff --git a/libdes/f_cksum.c b/libdes/f_cksum.c new file mode 100644 index 0000000..5fbc4f9 --- /dev/null +++ b/libdes/f_cksum.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode + */ +#include "des.h" +#include "f_tables.h" + +unsigned long +des_cbc_cksum(in, out, length, schedule, ivec) + des_cblock *in; + des_cblock *out; + long length; + des_key_schedule schedule; + des_cblock ivec; +{ + register unsigned long left, right; + register unsigned long temp; + register u_int32 *kp; + register unsigned char *ip; + register long len; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = (unsigned char *)in; + len = length; + while (len > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (len >= 8) { + left ^= ((*ip++) & 0xff) << 24; + left ^= ((*ip++) & 0xff) << 16; + left ^= ((*ip++) & 0xff) << 8; + left ^= (*ip++) & 0xff; + right ^= ((*ip++) & 0xff) << 24; + right ^= ((*ip++) & 0xff) << 16; + right ^= ((*ip++) & 0xff) << 8; + right ^= (*ip++) & 0xff; + len -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) len; + switch(len) { + case 7: + right ^= (*(--ip) & 0xff) << 8; + case 6: + right ^= (*(--ip) & 0xff) << 16; + case 5: + right ^= (*(--ip) & 0xff) << 24; + case 4: + left ^= *(--ip) & 0xff; + case 3: + left ^= (*(--ip) & 0xff) << 8; + case 2: + left ^= (*(--ip) & 0xff) << 16; + case 1: + left ^= (*(--ip) & 0xff) << 24; + break; + } + len = 0; + } + + /* + * Encrypt what we have + */ + kp = (u_int32 *)schedule; + DES_DO_ENCRYPT(left, right, temp, kp); + } + + /* + * Done. Left and right have the checksum. Put it into + * the output. + */ + ip = (unsigned char *)out; + PUT_HALF_BLOCK(left, ip); + PUT_HALF_BLOCK(right, ip); + + /* + * Return right. I'll bet the MIT code returns this + * inconsistantly (with the low order byte of the checksum + * not always in the low order byte of the long). We won't. + */ + return right; +} diff --git a/libdes/f_ecb.c b/libdes/f_ecb.c new file mode 100644 index 0000000..a4d0579 --- /dev/null +++ b/libdes/f_ecb.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_ecb_encrypt.c - do an encryption in ECB mode + */ +#include "des.h" +#include "f_tables.h" + +/* + * des_ecb_encrypt - {en,de}crypt a block in ECB mode + */ +int +des_ecb_encrypt(in, out, schedule, encrypt) + des_cblock *in; + des_cblock *out; + des_key_schedule schedule; + int encrypt; +{ + register unsigned long left, right; + register unsigned long temp; + register int i; + + { + /* + * Need a temporary for copying the data in + */ + register unsigned char *datap; + + /* + * Copy the input block into the registers + */ + datap = (unsigned char *)in; + GET_HALF_BLOCK(left, datap); + GET_HALF_BLOCK(right, datap); + } + + /* + * Do the initial permutation. + */ + DES_INITIAL_PERM(left, right, temp); + + /* + * Now the rounds. Use different code depending on whether it + * is an encryption or a decryption (gross, should keep both + * sets of keys in the key schedule instead). + */ + if (encrypt) { + register u_int32 *kp; + + kp = (u_int32 *)schedule; + for (i = 0; i < 8; i++) { + DES_SP_ENCRYPT_ROUND(left, right, temp, kp); + DES_SP_ENCRYPT_ROUND(right, left, temp, kp); + } + } else { + register u_int32 *kp; + + /* + * Point kp past end of schedule + */ + kp = ((u_int32 *)schedule) + (2 * 16);; + for (i = 0; i < 8; i++) { + DES_SP_DECRYPT_ROUND(left, right, temp, kp); + DES_SP_DECRYPT_ROUND(right, left, temp, kp); + } + } + + /* + * Do the final permutation + */ + DES_FINAL_PERM(left, right, temp); + + /* + * Finally, copy the result out a byte at a time + */ + { + register unsigned char *datap; + + datap = (unsigned char *)out; + PUT_HALF_BLOCK(left, datap); + PUT_HALF_BLOCK(right, datap); + } + + /* + * return nothing + */ + return (0); +} diff --git a/libdes/f_parity.c b/libdes/f_parity.c new file mode 100644 index 0000000..44d2307 --- /dev/null +++ b/libdes/f_parity.c @@ -0,0 +1,62 @@ +/* + * These routines check and fix parity of encryption keys for the DES + * algorithm. + * + * They are a replacement for routines in key_parity.c, that don't require + * the table building that they do. + * + * Mark Eichin -- Cygnus Support + */ + +#ifndef lint +static char rcsid_f_parity_c[] = + "$Id$"; +#endif + +#include "des.h" + +/* + * des_fixup_key_parity: Forces odd parity per byte; parity is bits + * 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order. + */ +#define smask(step) ((1<>step)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +void +des_fixup_key_parity(key) + register des_cblock key; +{ + int i; + for (i=0; i 0) { + /* + * Get block of input. If the length is + * greater than 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length > 8) { + GET_HALF_BLOCK(plainl, ip); + GET_HALF_BLOCK(plainr, ip); + left ^= plainl; + right ^= plainr; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. We know this is the + * last block, though, so we don't have + * to save the plain text. + */ + ip += (int) length; + switch(length) { + case 8: + right ^= *(--ip) & 0xff; + case 7: + right ^= (*(--ip) & 0xff) << 8; + case 6: + right ^= (*(--ip) & 0xff) << 16; + case 5: + right ^= (*(--ip) & 0xff) << 24; + case 4: + left ^= *(--ip) & 0xff; + case 3: + left ^= (*(--ip) & 0xff) << 8; + case 2: + left ^= (*(--ip) & 0xff) << 16; + case 1: + left ^= (*(--ip) & 0xff) << 24; + break; + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, temp, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Xor with the old plain text + */ + left ^= plainl; + right ^= plainr; + } + } else { + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + unsigned long ocipherl, ocipherr; + unsigned long cipherl, cipherr; + + if (length <= 0) + return 0; + + /* + * Prime the old cipher with ivec. + */ + ip = (unsigned char *)ivec; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + ip = (unsigned char *)in; + op = (unsigned char *)out; + for (;;) { /* check done inside loop */ + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, temp, kp); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + if (length > 8) { + length -= 8; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + /* + * Save current cipher block here + */ + ocipherl = cipherl ^ left; + ocipherr = cipherr ^ right; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: + *(--op) = right & 0xff; + case 7: + *(--op) = (right >> 8) & 0xff; + case 6: + *(--op) = (right >> 16) & 0xff; + case 5: + *(--op) = (right >> 24) & 0xff; + case 4: + *(--op) = left & 0xff; + case 3: + *(--op) = (left >> 8) & 0xff; + case 2: + *(--op) = (left >> 16) & 0xff; + case 1: + *(--op) = (left >> 24) & 0xff; + break; + } + break; /* we're done */ + } + } + } + + /* + * Done, return nothing. + */ + return 0; +} diff --git a/libdes/f_sched.c b/libdes/f_sched.c new file mode 100644 index 0000000..82ff800 --- /dev/null +++ b/libdes/f_sched.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_make_sched.c - permute a DES key, returning the resulting key schedule + */ +#include "des.h" +#include "f_tables.h" +/* + * Permuted choice 1 tables. These are used to extract bits + * from the left and right parts of the key to form Ci and Di. + * The code that uses these tables knows which bits from which + * part of each key are used to form Ci and Di. + */ +static unsigned long PC1_CL[8] = { + 0x00000000, 0x00000010, 0x00001000, 0x00001010, + 0x00100000, 0x00100010, 0x00101000, 0x00101010 +}; + +static unsigned long PC1_DL[16] = { + 0x00000000, 0x00100000, 0x00001000, 0x00101000, + 0x00000010, 0x00100010, 0x00001010, 0x00101010, + 0x00000001, 0x00100001, 0x00001001, 0x00101001, + 0x00000011, 0x00100011, 0x00001011, 0x00101011 +}; + +static unsigned long PC1_CR[16] = { + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static unsigned long PC1_DR[8] = { + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100 +}; + + +/* + * At the start of some iterations of the key schedule we do + * a circular left shift by one place, while for others we do a shift by + * two places. This has bits set for the iterations where we do 2 bit + * shifts, starting at the low order bit. + */ +#define TWO_BIT_SHIFTS 0x7efc + +/* + * Permuted choice 2 tables. The first actually produces the low order + * 24 bits of the subkey Ki from the 28 bit value of Ci. The second produces + * the high order 24 bits from Di. The tables are indexed by six bit + * segments of Ci and Di respectively. The code is handcrafted to compute + * the appropriate 6 bit chunks. + * + * Note that for ease of computation, the 24 bit values are produced with + * six bits going into each byte. Note also that the table has been byte + * rearranged to produce keys which match the order we will apply them + * in in the des code. + */ +static unsigned long PC2_C[4][64] = { + 0x00000000, 0x00000004, 0x00010000, 0x00010004, + 0x00000400, 0x00000404, 0x00010400, 0x00010404, + 0x00000020, 0x00000024, 0x00010020, 0x00010024, + 0x00000420, 0x00000424, 0x00010420, 0x00010424, + 0x01000000, 0x01000004, 0x01010000, 0x01010004, + 0x01000400, 0x01000404, 0x01010400, 0x01010404, + 0x01000020, 0x01000024, 0x01010020, 0x01010024, + 0x01000420, 0x01000424, 0x01010420, 0x01010424, + 0x00020000, 0x00020004, 0x00030000, 0x00030004, + 0x00020400, 0x00020404, 0x00030400, 0x00030404, + 0x00020020, 0x00020024, 0x00030020, 0x00030024, + 0x00020420, 0x00020424, 0x00030420, 0x00030424, + 0x01020000, 0x01020004, 0x01030000, 0x01030004, + 0x01020400, 0x01020404, 0x01030400, 0x01030404, + 0x01020020, 0x01020024, 0x01030020, 0x01030024, + 0x01020420, 0x01020424, 0x01030420, 0x01030424, + + 0x00000000, 0x02000000, 0x00000800, 0x02000800, + 0x00080000, 0x02080000, 0x00080800, 0x02080800, + 0x00000001, 0x02000001, 0x00000801, 0x02000801, + 0x00080001, 0x02080001, 0x00080801, 0x02080801, + 0x00000100, 0x02000100, 0x00000900, 0x02000900, + 0x00080100, 0x02080100, 0x00080900, 0x02080900, + 0x00000101, 0x02000101, 0x00000901, 0x02000901, + 0x00080101, 0x02080101, 0x00080901, 0x02080901, + 0x10000000, 0x12000000, 0x10000800, 0x12000800, + 0x10080000, 0x12080000, 0x10080800, 0x12080800, + 0x10000001, 0x12000001, 0x10000801, 0x12000801, + 0x10080001, 0x12080001, 0x10080801, 0x12080801, + 0x10000100, 0x12000100, 0x10000900, 0x12000900, + 0x10080100, 0x12080100, 0x10080900, 0x12080900, + 0x10000101, 0x12000101, 0x10000901, 0x12000901, + 0x10080101, 0x12080101, 0x10080901, 0x12080901, + + 0x00000000, 0x00040000, 0x00002000, 0x00042000, + 0x00100000, 0x00140000, 0x00102000, 0x00142000, + 0x20000000, 0x20040000, 0x20002000, 0x20042000, + 0x20100000, 0x20140000, 0x20102000, 0x20142000, + 0x00000008, 0x00040008, 0x00002008, 0x00042008, + 0x00100008, 0x00140008, 0x00102008, 0x00142008, + 0x20000008, 0x20040008, 0x20002008, 0x20042008, + 0x20100008, 0x20140008, 0x20102008, 0x20142008, + 0x00200000, 0x00240000, 0x00202000, 0x00242000, + 0x00300000, 0x00340000, 0x00302000, 0x00342000, + 0x20200000, 0x20240000, 0x20202000, 0x20242000, + 0x20300000, 0x20340000, 0x20302000, 0x20342000, + 0x00200008, 0x00240008, 0x00202008, 0x00242008, + 0x00300008, 0x00340008, 0x00302008, 0x00342008, + 0x20200008, 0x20240008, 0x20202008, 0x20242008, + 0x20300008, 0x20340008, 0x20302008, 0x20342008, + + 0x00000000, 0x00000010, 0x08000000, 0x08000010, + 0x00000200, 0x00000210, 0x08000200, 0x08000210, + 0x00000002, 0x00000012, 0x08000002, 0x08000012, + 0x00000202, 0x00000212, 0x08000202, 0x08000212, + 0x04000000, 0x04000010, 0x0c000000, 0x0c000010, + 0x04000200, 0x04000210, 0x0c000200, 0x0c000210, + 0x04000002, 0x04000012, 0x0c000002, 0x0c000012, + 0x04000202, 0x04000212, 0x0c000202, 0x0c000212, + 0x00001000, 0x00001010, 0x08001000, 0x08001010, + 0x00001200, 0x00001210, 0x08001200, 0x08001210, + 0x00001002, 0x00001012, 0x08001002, 0x08001012, + 0x00001202, 0x00001212, 0x08001202, 0x08001212, + 0x04001000, 0x04001010, 0x0c001000, 0x0c001010, + 0x04001200, 0x04001210, 0x0c001200, 0x0c001210, + 0x04001002, 0x04001012, 0x0c001002, 0x0c001012, + 0x04001202, 0x04001212, 0x0c001202, 0x0c001212 +}; + +static unsigned long PC2_D[4][64] = { + 0x00000000, 0x02000000, 0x00020000, 0x02020000, + 0x00000100, 0x02000100, 0x00020100, 0x02020100, + 0x00000008, 0x02000008, 0x00020008, 0x02020008, + 0x00000108, 0x02000108, 0x00020108, 0x02020108, + 0x00200000, 0x02200000, 0x00220000, 0x02220000, + 0x00200100, 0x02200100, 0x00220100, 0x02220100, + 0x00200008, 0x02200008, 0x00220008, 0x02220008, + 0x00200108, 0x02200108, 0x00220108, 0x02220108, + 0x00000200, 0x02000200, 0x00020200, 0x02020200, + 0x00000300, 0x02000300, 0x00020300, 0x02020300, + 0x00000208, 0x02000208, 0x00020208, 0x02020208, + 0x00000308, 0x02000308, 0x00020308, 0x02020308, + 0x00200200, 0x02200200, 0x00220200, 0x02220200, + 0x00200300, 0x02200300, 0x00220300, 0x02220300, + 0x00200208, 0x02200208, 0x00220208, 0x02220208, + 0x00200308, 0x02200308, 0x00220308, 0x02220308, + + 0x00000000, 0x00001000, 0x00000020, 0x00001020, + 0x00100000, 0x00101000, 0x00100020, 0x00101020, + 0x08000000, 0x08001000, 0x08000020, 0x08001020, + 0x08100000, 0x08101000, 0x08100020, 0x08101020, + 0x00000004, 0x00001004, 0x00000024, 0x00001024, + 0x00100004, 0x00101004, 0x00100024, 0x00101024, + 0x08000004, 0x08001004, 0x08000024, 0x08001024, + 0x08100004, 0x08101004, 0x08100024, 0x08101024, + 0x00000400, 0x00001400, 0x00000420, 0x00001420, + 0x00100400, 0x00101400, 0x00100420, 0x00101420, + 0x08000400, 0x08001400, 0x08000420, 0x08001420, + 0x08100400, 0x08101400, 0x08100420, 0x08101420, + 0x00000404, 0x00001404, 0x00000424, 0x00001424, + 0x00100404, 0x00101404, 0x00100424, 0x00101424, + 0x08000404, 0x08001404, 0x08000424, 0x08001424, + 0x08100404, 0x08101404, 0x08100424, 0x08101424, + + 0x00000000, 0x10000000, 0x00010000, 0x10010000, + 0x00000002, 0x10000002, 0x00010002, 0x10010002, + 0x00002000, 0x10002000, 0x00012000, 0x10012000, + 0x00002002, 0x10002002, 0x00012002, 0x10012002, + 0x00040000, 0x10040000, 0x00050000, 0x10050000, + 0x00040002, 0x10040002, 0x00050002, 0x10050002, + 0x00042000, 0x10042000, 0x00052000, 0x10052000, + 0x00042002, 0x10042002, 0x00052002, 0x10052002, + 0x20000000, 0x30000000, 0x20010000, 0x30010000, + 0x20000002, 0x30000002, 0x20010002, 0x30010002, + 0x20002000, 0x30002000, 0x20012000, 0x30012000, + 0x20002002, 0x30002002, 0x20012002, 0x30012002, + 0x20040000, 0x30040000, 0x20050000, 0x30050000, + 0x20040002, 0x30040002, 0x20050002, 0x30050002, + 0x20042000, 0x30042000, 0x20052000, 0x30052000, + 0x20042002, 0x30042002, 0x20052002, 0x30052002, + + 0x00000000, 0x04000000, 0x00000001, 0x04000001, + 0x01000000, 0x05000000, 0x01000001, 0x05000001, + 0x00000010, 0x04000010, 0x00000011, 0x04000011, + 0x01000010, 0x05000010, 0x01000011, 0x05000011, + 0x00080000, 0x04080000, 0x00080001, 0x04080001, + 0x01080000, 0x05080000, 0x01080001, 0x05080001, + 0x00080010, 0x04080010, 0x00080011, 0x04080011, + 0x01080010, 0x05080010, 0x01080011, 0x05080011, + 0x00000800, 0x04000800, 0x00000801, 0x04000801, + 0x01000800, 0x05000800, 0x01000801, 0x05000801, + 0x00000810, 0x04000810, 0x00000811, 0x04000811, + 0x01000810, 0x05000810, 0x01000811, 0x05000811, + 0x00080800, 0x04080800, 0x00080801, 0x04080801, + 0x01080800, 0x05080800, 0x01080801, 0x05080801, + 0x00080810, 0x04080810, 0x00080811, 0x04080811, + 0x01080810, 0x05080810, 0x01080811, 0x05080811 +}; + + + +/* + * Permute the key to give us our key schedule. + */ +int +make_key_sched(key, schedule) + des_cblock *key; + des_key_schedule schedule; +{ + register unsigned long c, d; + + { + /* + * Need a pointer for the keys and a temporary long + */ + register unsigned char *k; + register unsigned long tmp; + + /* + * Fetch the key into something we can work with + */ + k = (unsigned char *)key; + + /* + * The first permutted choice gives us the 28 bits for C0 and + * 28 for D0. C0 gets 12 bits from the left key and 16 from + * the right, while D0 gets 16 from the left and 12 from the + * right. The code knows which bits go where. + */ + tmp = ((u_int32)(*(k)++)) << 24; + tmp |= ((u_int32)(*(k)++)) << 16; + tmp |= ((u_int32)(*(k)++)) << 8; + tmp |= (u_int32)(*(k)++); /* left part of key */ + c = PC1_CL[(tmp >> 29) & 0x7] + | (PC1_CL[(tmp >> 21) & 0x7] << 1) + | (PC1_CL[(tmp >> 13) & 0x7] << 2) + | (PC1_CL[(tmp >> 5) & 0x7] << 3); + d = PC1_DL[(tmp >> 25) & 0xf] + | (PC1_DL[(tmp >> 17) & 0xf] << 1) + | (PC1_DL[(tmp >> 9) & 0xf] << 2) + | (PC1_DL[(tmp >> 1) & 0xf] << 3); + + tmp = ((u_int32)(*(k)++)) << 24; + tmp |= ((u_int32)(*(k)++)) << 16; + tmp |= ((u_int32)(*(k)++)) << 8; + tmp |= (u_int32)(*(k)++); /* right part of key */ + c |= PC1_CR[(tmp >> 28) & 0xf] + | (PC1_CR[(tmp >> 20) & 0xf] << 1) + | (PC1_CR[(tmp >> 12) & 0xf] << 2) + | (PC1_CR[(tmp >> 4) & 0xf] << 3); + d |= PC1_DR[(tmp >> 25) & 0x7] + | (PC1_DR[(tmp >> 17) & 0x7] << 1) + | (PC1_DR[(tmp >> 9) & 0x7] << 2) + | (PC1_DR[(tmp >> 1) & 0x7] << 3); + } + + { + /* + * Need several temporaries in here + */ + register unsigned long ltmp, rtmp; + register u_int32 *k; + register int two_bit_shifts; + register int i; + /* + * Now iterate to compute the key schedule. Note that we + * record the entire set of subkeys in 6 bit chunks since + * they are used that way. At 6 bits/char, we need + * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes. + * The schedule must be this big. + */ + k = (u_int32 *)schedule; + two_bit_shifts = TWO_BIT_SHIFTS; + for (i = 16; i > 0; i--) { + /* + * Do the rotation. One bit and two bit rotations + * are done separately. Note C and D are 28 bits. + */ + if (two_bit_shifts & 0x1) { + c = ((c << 2) & 0xffffffc) | (c >> 26); + d = ((d << 2) & 0xffffffc) | (d >> 26); + } else { + c = ((c << 1) & 0xffffffe) | (c >> 27); + d = ((d << 1) & 0xffffffe) | (d >> 27); + } + two_bit_shifts >>= 1; + + /* + * Apply permutted choice 2 to C to get the first + * 24 bits worth of keys. Note that bits 9, 18, 22 + * and 25 (using DES numbering) in C are unused. The + * shift-mask stuff is done to delete these bits from + * the indices, since this cuts the table size in half. + * + * The table is torqued, by the way. If the standard + * byte order for this (high to low order) is 1234, + * the table actually gives us 4132. + */ + ltmp = PC2_C[0][((c >> 22) & 0x3f)] + | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)] + | PC2_C[2][((c >> 4) & 0x3) | ((c >> 9) & 0x3c)] + | PC2_C[3][((c ) & 0x7) | ((c >> 4) & 0x38)]; + /* + * Apply permutted choice 2 to D to get the other half. + * Here, bits 7, 10, 15 and 26 go unused. The sqeezing + * actually turns out to be cheaper here. + * + * This table is similarly torqued. If the standard + * byte order is 5678, the table has the bytes permuted + * to give us 7685. + */ + rtmp = PC2_D[0][((d >> 22) & 0x3f)] + | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)] + | PC2_D[2][((d >> 7) & 0x3f)] + | PC2_D[3][((d ) & 0x3) | ((d >> 1) & 0x3c)]; + + /* + * Make up two words of the key schedule, with a + * byte order which is convenient for the DES + * inner loop. The high order (first) word will + * hold bytes 7135 (high to low order) while the + * second holds bytes 4682. + */ + *k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff); + *k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00); + } + } + return (0); +} diff --git a/libdes/f_tables.c b/libdes/f_tables.c new file mode 100644 index 0000000..396c7a8 --- /dev/null +++ b/libdes/f_tables.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_tables.c - precomputed tables used for the DES cipher function + */ + +/* + * Include the header file so something will complain if the + * declarations get out of sync + */ +#include "f_tables.h" + +/* + * These tables may be declared const if you want. Many compilers + * don't support this, though. + */ + +/* + * The DES algorithm which uses these is intended to be fairly speedy + * at the expense of some memory. All the standard hacks are used. + * The S boxes and the P permutation are precomputed into one table. + * The E box never actually appears explicitly since it is easy to apply + * this algorithmically as needed. The initial permutation and final + * (inverse initial) permutation are computed from tables designed to + * permute one byte at a time. This should run pretty fast on machines + * with 32 bit words and bit field/multiple bit shift instructions which + * are fast. + */ + +/* + * The initial permutation array. This is used to compute both the + * left and the right halves of the initial permutation using bytes + * from words made from the following operations: + * + * ((left & 0x55555555) << 1) | (right & 0x55555555) for left half + * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1) for right half + * + * The scheme is that we index into the table using each byte. The + * result from the high order byte is or'd with the result from the + * next byte shifted left once is or'd with the result from the next + * byte shifted left twice if or'd with the result from the low order + * byte shifted left by three. Clear? + */ + +unsigned long des_IP_table[256] = { + 0x00000000, 0x00000010, 0x00000001, 0x00000011, + 0x00001000, 0x00001010, 0x00001001, 0x00001011, + 0x00000100, 0x00000110, 0x00000101, 0x00000111, + 0x00001100, 0x00001110, 0x00001101, 0x00001111, + 0x00100000, 0x00100010, 0x00100001, 0x00100011, + 0x00101000, 0x00101010, 0x00101001, 0x00101011, + 0x00100100, 0x00100110, 0x00100101, 0x00100111, + 0x00101100, 0x00101110, 0x00101101, 0x00101111, + 0x00010000, 0x00010010, 0x00010001, 0x00010011, + 0x00011000, 0x00011010, 0x00011001, 0x00011011, + 0x00010100, 0x00010110, 0x00010101, 0x00010111, + 0x00011100, 0x00011110, 0x00011101, 0x00011111, + 0x00110000, 0x00110010, 0x00110001, 0x00110011, + 0x00111000, 0x00111010, 0x00111001, 0x00111011, + 0x00110100, 0x00110110, 0x00110101, 0x00110111, + 0x00111100, 0x00111110, 0x00111101, 0x00111111, + 0x10000000, 0x10000010, 0x10000001, 0x10000011, + 0x10001000, 0x10001010, 0x10001001, 0x10001011, + 0x10000100, 0x10000110, 0x10000101, 0x10000111, + 0x10001100, 0x10001110, 0x10001101, 0x10001111, + 0x10100000, 0x10100010, 0x10100001, 0x10100011, + 0x10101000, 0x10101010, 0x10101001, 0x10101011, + 0x10100100, 0x10100110, 0x10100101, 0x10100111, + 0x10101100, 0x10101110, 0x10101101, 0x10101111, + 0x10010000, 0x10010010, 0x10010001, 0x10010011, + 0x10011000, 0x10011010, 0x10011001, 0x10011011, + 0x10010100, 0x10010110, 0x10010101, 0x10010111, + 0x10011100, 0x10011110, 0x10011101, 0x10011111, + 0x10110000, 0x10110010, 0x10110001, 0x10110011, + 0x10111000, 0x10111010, 0x10111001, 0x10111011, + 0x10110100, 0x10110110, 0x10110101, 0x10110111, + 0x10111100, 0x10111110, 0x10111101, 0x10111111, + 0x01000000, 0x01000010, 0x01000001, 0x01000011, + 0x01001000, 0x01001010, 0x01001001, 0x01001011, + 0x01000100, 0x01000110, 0x01000101, 0x01000111, + 0x01001100, 0x01001110, 0x01001101, 0x01001111, + 0x01100000, 0x01100010, 0x01100001, 0x01100011, + 0x01101000, 0x01101010, 0x01101001, 0x01101011, + 0x01100100, 0x01100110, 0x01100101, 0x01100111, + 0x01101100, 0x01101110, 0x01101101, 0x01101111, + 0x01010000, 0x01010010, 0x01010001, 0x01010011, + 0x01011000, 0x01011010, 0x01011001, 0x01011011, + 0x01010100, 0x01010110, 0x01010101, 0x01010111, + 0x01011100, 0x01011110, 0x01011101, 0x01011111, + 0x01110000, 0x01110010, 0x01110001, 0x01110011, + 0x01111000, 0x01111010, 0x01111001, 0x01111011, + 0x01110100, 0x01110110, 0x01110101, 0x01110111, + 0x01111100, 0x01111110, 0x01111101, 0x01111111, + 0x11000000, 0x11000010, 0x11000001, 0x11000011, + 0x11001000, 0x11001010, 0x11001001, 0x11001011, + 0x11000100, 0x11000110, 0x11000101, 0x11000111, + 0x11001100, 0x11001110, 0x11001101, 0x11001111, + 0x11100000, 0x11100010, 0x11100001, 0x11100011, + 0x11101000, 0x11101010, 0x11101001, 0x11101011, + 0x11100100, 0x11100110, 0x11100101, 0x11100111, + 0x11101100, 0x11101110, 0x11101101, 0x11101111, + 0x11010000, 0x11010010, 0x11010001, 0x11010011, + 0x11011000, 0x11011010, 0x11011001, 0x11011011, + 0x11010100, 0x11010110, 0x11010101, 0x11010111, + 0x11011100, 0x11011110, 0x11011101, 0x11011111, + 0x11110000, 0x11110010, 0x11110001, 0x11110011, + 0x11111000, 0x11111010, 0x11111001, 0x11111011, + 0x11110100, 0x11110110, 0x11110101, 0x11110111, + 0x11111100, 0x11111110, 0x11111101, 0x11111111 +}; + +/* + * The final permutation array. Like the IP array, used + * to compute both the left and right results from the bytes + * of words computed from: + * + * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f) for left result + * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4) for right result + * + * The result from the high order byte is shifted left 6 bits and + * or'd with the result from the next byte shifted left 4 bits, which + * is or'd with the result from the next byte shifted left 2 bits, + * which is or'd with the result from the low byte. + */ +unsigned long des_FP_table[256] = { + 0x00000000, 0x02000000, 0x00020000, 0x02020000, + 0x00000200, 0x02000200, 0x00020200, 0x02020200, + 0x00000002, 0x02000002, 0x00020002, 0x02020002, + 0x00000202, 0x02000202, 0x00020202, 0x02020202, + 0x01000000, 0x03000000, 0x01020000, 0x03020000, + 0x01000200, 0x03000200, 0x01020200, 0x03020200, + 0x01000002, 0x03000002, 0x01020002, 0x03020002, + 0x01000202, 0x03000202, 0x01020202, 0x03020202, + 0x00010000, 0x02010000, 0x00030000, 0x02030000, + 0x00010200, 0x02010200, 0x00030200, 0x02030200, + 0x00010002, 0x02010002, 0x00030002, 0x02030002, + 0x00010202, 0x02010202, 0x00030202, 0x02030202, + 0x01010000, 0x03010000, 0x01030000, 0x03030000, + 0x01010200, 0x03010200, 0x01030200, 0x03030200, + 0x01010002, 0x03010002, 0x01030002, 0x03030002, + 0x01010202, 0x03010202, 0x01030202, 0x03030202, + 0x00000100, 0x02000100, 0x00020100, 0x02020100, + 0x00000300, 0x02000300, 0x00020300, 0x02020300, + 0x00000102, 0x02000102, 0x00020102, 0x02020102, + 0x00000302, 0x02000302, 0x00020302, 0x02020302, + 0x01000100, 0x03000100, 0x01020100, 0x03020100, + 0x01000300, 0x03000300, 0x01020300, 0x03020300, + 0x01000102, 0x03000102, 0x01020102, 0x03020102, + 0x01000302, 0x03000302, 0x01020302, 0x03020302, + 0x00010100, 0x02010100, 0x00030100, 0x02030100, + 0x00010300, 0x02010300, 0x00030300, 0x02030300, + 0x00010102, 0x02010102, 0x00030102, 0x02030102, + 0x00010302, 0x02010302, 0x00030302, 0x02030302, + 0x01010100, 0x03010100, 0x01030100, 0x03030100, + 0x01010300, 0x03010300, 0x01030300, 0x03030300, + 0x01010102, 0x03010102, 0x01030102, 0x03030102, + 0x01010302, 0x03010302, 0x01030302, 0x03030302, + 0x00000001, 0x02000001, 0x00020001, 0x02020001, + 0x00000201, 0x02000201, 0x00020201, 0x02020201, + 0x00000003, 0x02000003, 0x00020003, 0x02020003, + 0x00000203, 0x02000203, 0x00020203, 0x02020203, + 0x01000001, 0x03000001, 0x01020001, 0x03020001, + 0x01000201, 0x03000201, 0x01020201, 0x03020201, + 0x01000003, 0x03000003, 0x01020003, 0x03020003, + 0x01000203, 0x03000203, 0x01020203, 0x03020203, + 0x00010001, 0x02010001, 0x00030001, 0x02030001, + 0x00010201, 0x02010201, 0x00030201, 0x02030201, + 0x00010003, 0x02010003, 0x00030003, 0x02030003, + 0x00010203, 0x02010203, 0x00030203, 0x02030203, + 0x01010001, 0x03010001, 0x01030001, 0x03030001, + 0x01010201, 0x03010201, 0x01030201, 0x03030201, + 0x01010003, 0x03010003, 0x01030003, 0x03030003, + 0x01010203, 0x03010203, 0x01030203, 0x03030203, + 0x00000101, 0x02000101, 0x00020101, 0x02020101, + 0x00000301, 0x02000301, 0x00020301, 0x02020301, + 0x00000103, 0x02000103, 0x00020103, 0x02020103, + 0x00000303, 0x02000303, 0x00020303, 0x02020303, + 0x01000101, 0x03000101, 0x01020101, 0x03020101, + 0x01000301, 0x03000301, 0x01020301, 0x03020301, + 0x01000103, 0x03000103, 0x01020103, 0x03020103, + 0x01000303, 0x03000303, 0x01020303, 0x03020303, + 0x00010101, 0x02010101, 0x00030101, 0x02030101, + 0x00010301, 0x02010301, 0x00030301, 0x02030301, + 0x00010103, 0x02010103, 0x00030103, 0x02030103, + 0x00010303, 0x02010303, 0x00030303, 0x02030303, + 0x01010101, 0x03010101, 0x01030101, 0x03030101, + 0x01010301, 0x03010301, 0x01030301, 0x03030301, + 0x01010103, 0x03010103, 0x01030103, 0x03030103, + 0x01010303, 0x03010303, 0x01030303, 0x03030303 +}; + + +/* + * The SP table is actually the S boxes and the P permutation + * table combined. This table is actually reordered from the + * spec, to match the order of key application we follow. + */ +unsigned long des_SP_table[8][64] = { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, /* 7 */ + 0x00000400, 0x02000401, 0x00100401, 0x02100400, + 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, + 0x02000400, 0x00100401, 0x00100001, 0x02000400, + 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, + 0x00100400, 0x00000001, 0x02000000, 0x00100400, + 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, + 0x00100001, 0x02000000, 0x02000400, 0x00100000, + 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, + 0x00100400, 0x00000000, 0x00000001, 0x02100401, + 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001, + + 0x00808200, 0x00000000, 0x00008000, 0x00808202, /* 1 */ + 0x00808002, 0x00008202, 0x00000002, 0x00008000, + 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, + 0x00000202, 0x00800200, 0x00800200, 0x00008200, + 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, + 0x00000000, 0x00000202, 0x00008202, 0x00800000, + 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, + 0x00808002, 0x00008000, 0x00008200, 0x00800002, + 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, + 0x00800002, 0x00000202, 0x00008202, 0x00808200, + 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002, + + 0x00000104, 0x04010100, 0x00000000, 0x04010004, /* 3 */ + 0x04000100, 0x00000000, 0x00010104, 0x04000100, + 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, + 0x04000000, 0x00000004, 0x04010100, 0x00000100, + 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, + 0x00000004, 0x04010104, 0x00000100, 0x04000000, + 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, + 0x00000100, 0x00010004, 0x04010104, 0x04000100, + 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, + 0x00000004, 0x00010104, 0x00010100, 0x04000004, + 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100, + + 0x00000080, 0x01040080, 0x01040000, 0x21000080, /* 5 */ + 0x00040000, 0x00000080, 0x20000000, 0x01040000, + 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, + 0x01000000, 0x20040000, 0x20040000, 0x00000000, + 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, + 0x01040080, 0x01000000, 0x21000000, 0x00040080, + 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, + 0x01000080, 0x20000000, 0x21040000, 0x01040080, + 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, + 0x01040000, 0x00000000, 0x20040000, 0x21000000, + 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080, + + 0x80401000, 0x80001040, 0x80001040, 0x00000040, /* 4 */ + 0x00401040, 0x80400040, 0x80400000, 0x80001000, + 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, + 0x80000000, 0x00001000, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, + 0x00001000, 0x00401040, 0x80401040, 0x80000040, + 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, + 0x00001040, 0x00400040, 0x80400040, 0x80000000, + 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, + 0x80400000, 0x80001000, 0x00401040, 0x80400040, + 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040, + + 0x10000008, 0x10200000, 0x00002000, 0x10202008, /* 6 */ + 0x10200000, 0x00000008, 0x10202008, 0x00200000, + 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, + 0x00000000, 0x00200008, 0x10002008, 0x00002000, + 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, + 0x00002008, 0x00202000, 0x10202000, 0x10000000, + 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, + 0x00200000, 0x10002000, 0x10000000, 0x00002008, + 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, + 0x00000008, 0x00002000, 0x10200000, 0x00202008, + 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008, + + 0x08000820, 0x00000800, 0x00020000, 0x08020820, /* 8 */ + 0x08000000, 0x08000820, 0x00000020, 0x08000000, + 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, + 0x08020000, 0x08000020, 0x08000800, 0x00000820, + 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, + 0x08000020, 0x08000800, 0x00020820, 0x00020000, + 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, + 0x08000800, 0x00000020, 0x08000020, 0x08020000, + 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, + 0x08020000, 0x08000800, 0x08000820, 0x00000000, + 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800, + + 0x40084010, 0x40004000, 0x00004000, 0x00084010, /* 2 */ + 0x00080000, 0x00000010, 0x40080010, 0x40004010, + 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, + 0x00084000, 0x00080010, 0x40004010, 0x00000000, + 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, + 0x00004010, 0x40084000, 0x40080000, 0x00004010, + 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, + 0x40080000, 0x40004000, 0x00000010, 0x40084010, + 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, + 0x00080010, 0x40004010, 0x40000010, 0x00080010, + 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 +}; diff --git a/libdes/f_tables.h b/libdes/f_tables.h new file mode 100644 index 0000000..db9cbb9 --- /dev/null +++ b/libdes/f_tables.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1990 Dennis Ferguson. All rights reserved. + * + * Commercial use is permitted only if products which are derived from + * or include this software are made available for purchase and/or use + * in Canada. Otherwise, redistribution and use in source and binary + * forms are permitted. + */ + +/* + * des_tables.h - declarations to import the DES tables, used internally + * by some of the library routines. + */ +#ifndef __DES_TABLES_H__ +#define __DES_TABLES_H__ /* nothing */ + +/* + * These may be declared const if you wish. Be sure to change the + * declarations in des_tables.c as well. + */ +extern unsigned long des_IP_table[256]; +extern unsigned long des_FP_table[256]; +extern unsigned long des_SP_table[8][64]; + +/* + * Use standard shortforms to reference these to save typing + */ +#define IP des_IP_table +#define FP des_FP_table +#define SP des_SP_table + +/* + * Code to do a DES round using the tables. Note that the E expansion + * is easy to compute algorithmically, especially if done out-of-order. + * Take a look at its form and compare it to everything involving temp + * below. Since SP[0-7] don't have any bits in common set it is okay + * to do the successive xor's. + * + * Note too that the SP table has been reordered to match the order of + * the keys (if the original order of SP was 12345678, the reordered + * table is 71354682). This is unnecessary, but was done since some + * compilers seem to like you going through the matrix from beginning + * to end. + * + * There is a difference in the best way to do this depending on whether + * one is encrypting or decrypting. If encrypting we move forward through + * the keys and hence should move forward through the table. If decrypting + * we go back. Part of the need for this comes from trying to emulate + * existing software which generates a single key schedule and uses it + * both for encrypting and decrypting. Generating separate encryption + * and decryption key schedules would allow one to use the same code + * for both. + * + * left, right and temp should be unsigned long values. left and right + * should be the high and low order parts of the cipher block at the + * current stage of processing (this makes sense if you read the spec). + * kp should be an unsigned long pointer which points at the current + * set of subkeys in the key schedule. It is advanced to the next set + * (i.e. by 8 bytes) when this is done. + * + * This occurs in the innermost loop of the DES function. The four + * variables should really be in registers. + * + * When using this, the inner loop of the DES function might look like: + * + * for (i = 0; i < 8; i++) { + * DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp); + * DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp); + * } + * + * Note the trick above. You are supposed to do 16 rounds, swapping + * left and right at the end of each round. By doing two rounds at + * a time and swapping left and right in the code we can avoid the + * swaps altogether. + */ +#define DES_SP_ENCRYPT_ROUND(left, right, temp, kp) \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \ + (left) ^= SP[0][((temp) >> 24) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[3][((temp) ) & 0x3f]; \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++; \ + (left) ^= SP[4][((temp) >> 24) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[7][((temp) ) & 0x3f] + +#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp)); \ + (left) ^= SP[7][((temp) ) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[4][((temp) >> 24) & 0x3f]; \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp)); \ + (left) ^= SP[3][((temp) ) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[0][((temp) >> 24) & 0x3f] + +/* + * Macros to help deal with the initial permutation table. Note + * the IP table only deals with 32 bits at a time, allowing us to + * collect the bits we need to deal with each half into an unsigned + * long. By carefully selecting how the bits are ordered we also + * take advantages of symmetries in the table so that we can use a + * single table to compute the permutation of all bytes. This sounds + * complicated, but if you go through the process of designing the + * table you'll find the symmetries fall right out. + * + * The follow macros compute the set of bits used to index the + * table for produce the left and right permuted result. + */ +#define DES_IP_LEFT_BITS(left, right) \ + ((((left) & 0x55555555) << 1) | ((right) & 0x55555555)) +#define DES_IP_RIGHT_BITS(left, right) \ + (((left) & 0xaaaaaaaa) | (((right) & 0xaaaaaaaa) >> 1)) + +/* + * The following macro does an in-place initial permutation given + * the current left and right parts of the block and a single + * temporary. Use this more as a guide for rolling your own, though. + * The best way to do the IP depends on the form of the data you + * are dealing with. If you use this, though, try to make left, + * right and temp register unsigned longs. + */ +#define DES_INITIAL_PERM(left, right, temp) \ + (temp) = DES_IP_RIGHT_BITS((left), (right)); \ + (right) = DES_IP_LEFT_BITS((left), (right)); \ + (left) = IP[((right) >> 24) & 0xff] \ + | (IP[((right) >> 16) & 0xff] << 1) \ + | (IP[((right) >> 8) & 0xff] << 2) \ + | (IP[(right) & 0xff] << 3); \ + (right) = IP[((temp) >> 24) & 0xff] \ + | (IP[((temp) >> 16) & 0xff] << 1) \ + | (IP[((temp) >> 8) & 0xff] << 2) \ + | (IP[(temp) & 0xff] << 3) + + +/* + * Now the final permutation stuff. The same comments apply to + * this as to the initial permutation, except that we use different + * bits and shifts. + */ +#define DES_FP_LEFT_BITS(left, right) \ + ((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f)) +#define DES_FP_RIGHT_BITS(left, right) \ + (((left) & 0xf0f0f0f0) | (((right) & 0xf0f0f0f0) >> 4)) + + +/* + * Here is a sample final permutation. Note that there is a trick + * here. DES requires swapping the left and right parts after the + * last cipher round but before the final permutation. We do this + * swapping internally, which is why left and right are confused + * at the beginning. + */ +#define DES_FINAL_PERM(left, right, temp) \ + (temp) = DES_FP_RIGHT_BITS((right), (left)); \ + (right) = DES_FP_LEFT_BITS((right), (left)); \ + (left) = (FP[((right) >> 24) & 0xff] << 6) \ + | (FP[((right) >> 16) & 0xff] << 4) \ + | (FP[((right) >> 8) & 0xff] << 2) \ + | FP[(right) & 0xff]; \ + (right) = (FP[((temp) >> 24) & 0xff] << 6) \ + | (FP[((temp) >> 16) & 0xff] << 4) \ + | (FP[((temp) >> 8) & 0xff] << 2) \ + | FP[temp & 0xff] + + +/* + * Finally, as a sample of how all this might be held together, the + * following two macros do in-place encryptions and decryptions. left + * and right are two unsigned long variables which at the beginning + * are expected to hold the clear (encrypted) block in host byte order + * (left the high order four bytes, right the low order). At the end + * they will contain the encrypted (clear) block. temp is an unsigned long + * used as a temporary. kp is an unsigned long pointer pointing at + * the start of the key schedule. All these should be in registers. + * + * You can probably do better than these by rewriting for particular + * situations. These aren't bad, though. + */ +#define DES_DO_ENCRYPT(left, right, temp, kp) \ + do { \ + register int i; \ + DES_INITIAL_PERM((left), (right), (temp)); \ + for (i = 0; i < 8; i++) { \ + DES_SP_ENCRYPT_ROUND((left), (right), (temp), (kp)); \ + DES_SP_ENCRYPT_ROUND((right), (left), (temp), (kp)); \ + } \ + DES_FINAL_PERM((left), (right), (temp)); \ + (kp) -= (2 * 16); \ + } while (0) + +#define DES_DO_DECRYPT(left, right, temp, kp) \ + do { \ + register int i; \ + DES_INITIAL_PERM((left), (right), (temp)); \ + (kp) += (2 * 16); \ + for (i = 0; i < 8; i++) { \ + DES_SP_DECRYPT_ROUND((left), (right), (temp), (kp)); \ + DES_SP_DECRYPT_ROUND((right), (left), (temp), (kp)); \ + } \ + DES_FINAL_PERM((left), (right), (temp)); \ + } while (0) + +/* + * These are handy dandy utility thingies for straightening out bytes. + * Included here because they're used a couple of places. + */ +#define GET_HALF_BLOCK(lr, ip) \ + (lr) = ((u_int32)(*(ip)++)) << 24; \ + (lr) |= ((u_int32)(*(ip)++)) << 16; \ + (lr) |= ((u_int32)(*(ip)++)) << 8; \ + (lr) |= (u_int32)(*(ip)++) + +#define PUT_HALF_BLOCK(lr, op) \ + *(op)++ = ((lr) >> 24) & 0xff; \ + *(op)++ = ((lr) >> 16) & 0xff; \ + *(op)++ = ((lr) >> 8) & 0xff; \ + *(op)++ = (lr) & 0xff + +#endif /* __DES_TABLES_H__ */ diff --git a/libdes/key_sched.c b/libdes/key_sched.c new file mode 100644 index 0000000..04fc12b --- /dev/null +++ b/libdes/key_sched.c @@ -0,0 +1,58 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * . + * + * This routine computes the DES key schedule given a key. The + * permutations and shifts have been done at compile time, resulting + * in a direct one-step mapping from the input key to the key + * schedule. + * + * Also checks parity and weak keys. + * + * Watch out for the subscripts -- most effectively start at 1 instead + * of at zero. Maybe some bugs in that area. + * + * DON'T change the data types for arrays and such, or it will either + * break or run slower. This was optimized for Uvax2. + * + * In case the user wants to cache the computed key schedule, it is + * passed as an arg. Also implies that caller has explicit control + * over zeroing both the key schedule and the key. + * + * All registers labeled imply Vax using the Ultrix or 4.2bsd compiler. + * + * Originally written 6/85 by Steve Miller, MIT Project Athena. + */ + +#ifndef lint +static char rcsid_key_sched_c[] = + "$Id$"; +#endif + +#include +#include +#include "des.h" + +int +des_key_sched(k,schedule) + register des_cblock k; + des_key_schedule schedule; +{ + if (!des_check_key_parity(k)) /* bad parity --> return -1 */ + return(-1); + + /* check against weak keys */ + if (des_is_weak_key(k)) + return(-2); + + make_key_sched(k,schedule); + + /* if key was good, return 0 */ + return 0; +} diff --git a/libdes/new_rnd_key.c b/libdes/new_rnd_key.c new file mode 100644 index 0000000..4ee0218 --- /dev/null +++ b/libdes/new_rnd_key.c @@ -0,0 +1,207 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * New pseudo-random key generator, using DES encryption to make the + * pseudo-random cycle as hard to break as DES. + * + * Written by Mark Lillibridge, MIT Project Athena + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + */ + +#ifndef lint +static char rcsid_new_rnd_key_c[] = + "$Id"; +#endif + +#include + +#include +#include +#include +#include + +extern void des_fixup_key_parity(); +extern int des_is_weak_key(); + +void des_set_random_generator_seed(), des_set_sequence_number(); +void des_generate_random_block(); + +/* + * des_new_random_key: create a random des key + * + * Requires: des_set_random_number_generater_seed must be at called least + * once before this routine is called. + * + * Notes: the returned key has correct parity and is guarenteed not + * to be a weak des key. Des_generate_random_block is used to + * provide the random bits. + */ +int +des_new_random_key(key) + des_cblock key; +{ + do { + des_generate_random_block(key); + des_fixup_key_parity(key); + } while (des_is_weak_key(key)); + + return(0); +} + +/* + * des_init_random_number_generator: + * + * This routine takes a secret key possibly shared by a number + * of servers and uses it to generate a random number stream that is + * not shared by any of the other servers. It does this by using the current + * process id, host id, and the current time to the nearest second. The + * resulting stream seed is not useful information for cracking the secret + * key. Moreover, this routine keeps no copy of the secret key. + * This routine is used for example, by the kerberos server(s) with the + * key in question being the kerberos master key. + * + * Note: this routine calls des_set_random_generator_seed. + */ + +void des_init_random_number_generator(key) + des_cblock key; +{ + struct { /* This must be 64 bits exactly */ + long process_id; + long host_id; + } seed; + struct timeval time; /* this must also be 64 bits exactly */ + des_cblock new_key; + + /* + * use a host id and process id in generating the seed to ensure + * that different servers have different streams: + */ + seed.process_id = getpid(); +#if !defined(SOLARIS) + seed.host_id = gethostid(); +#endif + + /* + * Generate a tempory value that depends on the key, host_id, and + * process_id such that it gives no useful information about the key: + */ + des_set_random_generator_seed(key); + des_set_sequence_number((unsigned char *)&seed); + des_new_random_key(new_key); + + /* + * use it to select a random stream: + */ + des_set_random_generator_seed(new_key); + + /* + * use a time stamp to ensure that a server started later does not reuse + * an old stream: + */ + gettimeofday(&time, (struct timezone *)0); + des_set_sequence_number((unsigned char *)&time); + + /* + * use the time stamp finally to select the final seed using the + * current random number stream: + */ + des_new_random_key(new_key); + des_set_random_generator_seed(new_key); +} + + +/* + * This module implements a random number generator faculty such that the next + * number in any random number stream is very hard to predict without knowing + * the seed for that stream even given the preceeding random numbers. + */ + +/* + * The secret des key schedule for the current stream of random numbers: + */ +static des_key_schedule random_sequence_key; + +/* + * The sequence # in the current stream of random numbers: + */ +static unsigned char sequence_number[8]; + +/* + * des_set_random_generator_seed: this routine is used to select a random + * number stream. The stream that results is + * totally determined by the passed in key. + * (I.e., calling this routine again with the + * same key allows repeating a sequence of + * random numbers) + * + * Requires: key is a valid des key. I.e., has correct parity and is not a + * weak des key. + */ +void +des_set_random_generator_seed(key) + des_cblock key; +{ + register int i; + + /* select the new stream: (note errors are not possible here...) */ + des_key_sched(key, random_sequence_key); + + /* "seek" to the start of the stream: */ + for (i=0; i<8; i++) + sequence_number[i] = 0; +} + +/* + * des_set_sequence_number: this routine is used to set the sequence number + * of the current random number stream. This routine + * may be used to "seek" within the current random + * number stream. + * + * Note that des_set_random_generator_seed resets the sequence number to 0. + */ +void +des_set_sequence_number(new_sequence_number) + des_cblock new_sequence_number; +{ + memcpy((char *)sequence_number, + (char *)new_sequence_number, + sizeof(sequence_number)); +} + +/* + * des_generate_random_block: routine to return the next random number + * from the current random number stream. + * The returned number is 64 bits long. + * + * Requires: des_set_random_generator_seed must have been called at least once + * before this routine is called. + */ +void des_generate_random_block(block) + des_cblock block; +{ + int i; + + /* + * Encrypt the sequence number to get the new random block: + */ + des_ecb_encrypt(sequence_number, block, random_sequence_key, 1); + + /* + * Increment the sequence number as an 8 byte unsigned number with wrap: + * (using LSB here) + */ + for (i=0; i<8; i++) { + sequence_number[i] = (sequence_number[i] + 1) & 0xff; + if (sequence_number[i]) + break; + } +} diff --git a/libdes/quad_cksum.c b/libdes/quad_cksum.c new file mode 100644 index 0000000..651e843 --- /dev/null +++ b/libdes/quad_cksum.c @@ -0,0 +1,153 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Quadratic Congruential Manipulation Dectection Code + * + * ref: "Message Authentication" + * R.R. Jueneman, S. M. Matyas, C.H. Meyer + * IEEE Communications Magazine, + * Sept 1985 Vol 23 No 9 p 29-40 + * + * This routine, part of the Athena DES library built for the Kerberos + * authentication system, calculates a manipulation detection code for + * a message. It is a much faster alternative to the DES-checksum + * method. No guarantees are offered for its security. Refer to the + * paper noted above for more information + * + * Implementation for 4.2bsd + * by S.P. Miller Project Athena/MIT + */ + +/* + * Algorithm (per paper): + * define: + * message to be composed of n m-bit blocks X1,...,Xn + * optional secret seed S in block X1 + * MDC in block Xn+1 + * prime modulus N + * accumulator Z + * initial (secret) value of accumulator C + * N, C, and S are known at both ends + * C and , optionally, S, are hidden from the end users + * then + * (read array references as subscripts over time) + * Z[0] = c; + * for i = 1...n + * Z[i] = (Z[i+1] + X[i])**2 modulo N + * X[n+1] = Z[n] = MDC + * + * Then pick + * N = 2**31 -1 + * m = 16 + * iterate 4 times over plaintext, also use Zn + * from iteration j as seed for iteration j+1, + * total MDC is then a 128 bit array of the four + * Zn; + * + * return the last Zn and optionally, all + * four as output args. + * + * Modifications: + * To inhibit brute force searches of the seed space, this + * implementation is modified to have + * Z = 64 bit accumulator + * C = 64 bit C seed + * N = 2**63 - 1 + * S = S seed is not implemented here + * arithmetic is not quite real double integer precision, since we + * cant get at the carry or high order results from multiply, + * but nontheless is 64 bit arithmetic. + */ + +#ifndef lint +static char rcsid_quad_cksum_c[] = + "$Id$"; +#endif + +#include +#include +#include + +#include +#include "des.h" + +/* Externals */ +extern int des_debug; + +/*** Routines ***************************************************** */ + +unsigned long +des_quad_cksum(in,out,length,out_count,c_seed) + des_cblock c_seed; /* secret seed, 8 bytes */ + unsigned char *in; /* input block */ + u_int32 *out; /* optional longer output */ + int out_count; /* number of iterations */ + long length; /* original length in bytes */ +{ + + /* + * this routine both returns the low order of the final (last in + * time) 32bits of the checksum, and if "out" is not a null + * pointer, a longer version, up to entire 32 bytes of the + * checksum is written unto the address pointed to. + */ + + register u_int32 z; + register u_int32 z2; + register u_int32 x; + register u_int32 x2; + register unsigned char *p; + register long len; + register int i; + + /* use all 8 bytes of seed */ + + z = c_seed[0] + + ((u_int32)c_seed[1] << 8) + + ((u_int32)c_seed[2] << 16) + + ((u_int32)c_seed[3] << 24); + + z2 = c_seed[4] + + ((u_int32)c_seed[5] << 8) + + ((u_int32)c_seed[6] << 16) + + ((u_int32)c_seed[7] << 24); + + if (out == NULL) + out_count = 1; /* default */ + + /* This is repeated n times!! */ + for (i = 1; i <=4 && i<= out_count; i++) { + len = length; + p = in; + while (len) { + if (len > 1) { + x = (z + p[0] + (p[1]<<8)); + p += 2; + len -= 2; + } + else { + x = (z + *(unsigned char *)p++); + len = 0; + } + x2 = z2; + z = ((x * x) + (x2 * x2)) % 0x7fffffff; + z2 = (x * (x2+83653421)) % 0x7fffffff; /* modulo */ + if (des_debug & 8) + printf("%d %d\n",z,z2); + } + + if (out != NULL) { + *out++ = z; + *out++ = z2; + } + } + /* return final z value as 32 bit version of checksum */ + return z; +} diff --git a/libdes/random_key.c b/libdes/random_key.c new file mode 100644 index 0000000..8c20d85 --- /dev/null +++ b/libdes/random_key.c @@ -0,0 +1,97 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * These routines perform encryption and decryption using the DES + * private key algorithm, or else a subset of it-- fewer inner loops. + * ( AUTH_DES_ITER defaults to 16, may be less) + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * These routines form the library interface to the des facilities. + * + * spm 8/85 MIT project athena + */ + +#ifndef lint +static char rcsid_random_key_c[] = + "$Id$"; +#endif + +#include +#include +#include +#include + +#include + +#ifdef USE_RAND48 +#define random lrand48 +#define srandom srand48 +#endif + +/* random_key */ +int +des_random_key(key) + des_cblock *key; +{ + /* + * create a random des key; should force odd parity per byte; + * parity is bits 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order + */ + + register unsigned int temp; + register int odd; + register unsigned char *c = (unsigned char *) key; + unsigned long *k = (unsigned long *) key; + static long p = 0; + static long n = 0; + + int i,j; + + static struct timeval time; + + if (!p) { + p = getpid(); +#ifndef SOLARIS + p ^= gethostid(); +#endif + } + + (void) gettimeofday(&time,(struct timezone *)0); + /* randomize start */ + srandom(time.tv_usec ^ time.tv_sec ^ p ^ n++); + + *k++ = random(); + *k = random(); + + /* make each byte parity odd */ + for (i = 0; i <= 7; i++) { + odd = 0; + temp = (unsigned int) *c; + /* ignore bit 0, lsb, it will be parity (on vax) */ + /* should do this with a table lookup */ + for (j = 0; j <= 6; j++) { + temp = temp >> 1; + odd ^= temp & 01; + } + /* set odd parity in lsb */ + if (!odd) + *c |= 1; + else + *c &= ~1; + c++; + } + + return 0; +} diff --git a/libdes/read_password.c b/libdes/read_password.c new file mode 100644 index 0000000..59ce622 --- /dev/null +++ b/libdes/read_password.c @@ -0,0 +1,249 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * . + * + * This routine prints the supplied string to standard + * output as a prompt, and reads a password string without + * echoing. + */ + +#ifndef lint +static char rcsid_read_password_c[] = + "$Id$"; +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef POSIX +#include +#else +#include +#endif + +#ifdef POSIX +typedef void sigtype; +static sigjmp_buf env; +#else +typedef int sigtype; +static jmp_buf env; +#endif + +static sigtype sig_restore(); +static push_signals(), pop_signals(); +int des_read_pw_string(); + +/*** Routines ****************************************************** */ +int +des_read_password(k,prompt,verify) + des_cblock *k; + char *prompt; + int verify; +{ + int ok; + char key_string[BUFSIZ]; + +#ifdef POSIX + if (sigsetjmp(env, 1)) { + ok = -1; + goto lose; + } +#else + if (setjmp(env)) { + ok = -1; + goto lose; + } +#endif + + ok = des_read_pw_string(key_string, BUFSIZ, prompt, verify); + if (ok == 0) + des_string_to_key(key_string, k); + +lose: + memset(key_string, 0, sizeof (key_string)); + return ok; +} + +/* + * This version just returns the string, doesn't map to key. + * + * Returns 0 on success, non-zero on failure. + */ + +int +des_read_pw_string(s,max,prompt,verify) + char *s; + int max; + char *prompt; + int verify; +{ + int ok = 0; + char *ptr; + char key_string[BUFSIZ]; +#ifdef POSIX + sigjmp_buf old_env; + struct termios tty_state; +#else + jmp_buf old_env; + struct sgttyb tty_state; +#endif + + if (max > BUFSIZ) { + return -1; + } + +#ifdef POSIX + /* save terminal state */ + if (tcgetattr(0, &tty_state) == -1) + return -1; + /* Turn off echo */ + tty_state.c_lflag &= ~ECHO; + if (tcsetattr(0, TCSANOW, &tty_state) == -1) + return -1; + + memcpy((char *)env, (char *)old_env, sizeof(env)); + if (sigsetjmp(env, 1)) + goto lose; +#else + /* save terminal state*/ + if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1) + return -1; + /* Turn off echo */ + tty_state.sg_flags &= ~ECHO; + if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1) + return -1; + memcpy((char *)env, (char *)old_env, sizeof(env)); + if (setjmp(env)) + goto lose; +#endif + push_signals(); + + while (!ok) { + (void) printf(prompt); + (void) fflush(stdout); +#ifdef CROSSMSDOS + h19line(s,sizeof(s),0); + if (!strlen(s)) + continue; +#else + if (!fgets(s, max, stdin)) { + clearerr(stdin); + continue; + } + if ((ptr = strchr(s, '\n'))) + *ptr = '\0'; +#endif + if (verify) { + printf("\nVerifying, please re-enter %s",prompt); + (void) fflush(stdout); +#ifdef CROSSMSDOS + h19line(key_string,sizeof(key_string),0); + if (!strlen(key_string)) + continue; +#else + if (!fgets(key_string, sizeof(key_string), stdin)) { + clearerr(stdin); + continue; + } + if ((ptr = strchr(key_string, '\n'))) + *ptr = '\0'; +#endif + if (strcmp(s,key_string)) { + printf("\n\07\07Mismatch - try again\n"); + (void) fflush(stdout); + continue; + } + } + ok = 1; + } + +lose: + if (!ok) + memset(s, 0, max); + printf("\n"); +#ifdef POSIX + /* turn echo back on */ + tty_state.c_lflag |= ECHO; + if (tcsetattr(0, TCSANOW, &tty_state)) + ok = 0; +#else + /* turn echo back on */ + tty_state.sg_flags |= ECHO; + if (ioctl(0,TIOCSETP,(char *)&tty_state)) + ok = 0; +#endif + pop_signals(); + memcpy((char *)old_env, (char *)env, sizeof(env)); + + if (verify) + memset(key_string, 0, sizeof (key_string)); + s[max-1] = 0; /* force termination */ + return !ok; /* return nonzero if not okay */ +} + +#ifdef POSIX +/* This can be static since we should never have more than one set saved... */ +static struct sigaction osa[NSIG]; + +static push_signals() +{ + register int i; + struct sigaction nsa; + + sigemptyset(&nsa.sa_mask); + nsa.sa_flags = 0; + nsa.sa_handler = sig_restore; + + for (i=0; i. + * + * These routines perform encryption and decryption using the DES + * private key algorithm, or else a subset of it-- fewer inner loops. + * (AUTH_DES_ITER defaults to 16, may be less.) + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * These routines form the library interface to the DES facilities. + * + * spm 8/85 MIT project athena + */ + +#ifndef lint +static char rcsid_string_to_key_c[] = + "$Id$"; +#endif + +#include +#include +#include + +extern int des_debug; +extern int des_debug_print(); +extern void des_fixup_key_parity(); + +/* + * convert an arbitrary length string to a DES key + */ +int +des_string_to_key(str,key) + char *str; + register des_cblock *key; +{ + register char *in_str; + register unsigned temp,i; + register int j; + register long length; + static unsigned char *k_p; + static int forward; + register char *p_char; + static char k_char[64]; + static des_key_schedule key_sked; + extern unsigned long des_cbc_cksum(); + + in_str = str; + forward = 1; + p_char = k_char; + length = strlen(str); + + /* init key array for bits */ + memset(k_char, 0, sizeof(k_char)); + +#ifdef DEBUG + if (des_debug) + fprintf(stdout, + "\n\ninput str length = %d string = %s\nstring = 0x ", + length,str); +#endif + + /* get next 8 bytes, strip parity, xor */ + for (i = 1; i <= length; i++) { + /* get next input key byte */ + temp = (unsigned int) *str++; +#ifdef DEBUG + if (des_debug) + fprintf(stdout,"%02x ",temp & 0xff); +#endif + /* loop through bits within byte, ignore parity */ + for (j = 0; j <= 6; j++) { + if (forward) + *p_char++ ^= (int) temp & 01; + else + *--p_char ^= (int) temp & 01; + temp = temp >> 1; + } while (--j > 0); + + /* check and flip direction */ + if ((i%8) == 0) + forward = !forward; + } + + /* now stuff into the key des_cblock, and force odd parity */ + p_char = k_char; + k_p = (unsigned char *) key; + + for (i = 0; i <= 7; i++) { + temp = 0; + for (j = 0; j <= 6; j++) + temp |= *p_char++ << (1+j); + *k_p++ = (unsigned char) temp; + } + + /* fix key parity */ + des_fixup_key_parity(key); + + /* Now one-way encrypt it with the folded key */ + (void) des_key_sched(key,key_sked); + (void) des_cbc_cksum((des_cblock *)in_str,key,length,key_sked,key); + /* erase key_sked */ + memset((char *)key_sked, 0, sizeof(key_sked)); + + /* now fix up key parity again */ + des_fixup_key_parity(key); + + if (des_debug) + fprintf(stdout, + "\nResulting string_to_key = 0x%x 0x%x\n", + *((unsigned long *) key), + *((unsigned long *) key+1)); +} diff --git a/libdes/util.c b/libdes/util.c new file mode 100644 index 0000000..770ebd1 --- /dev/null +++ b/libdes/util.c @@ -0,0 +1,36 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Miscellaneous debug printing utilities + */ + +#ifndef lint +static char rcsid_util_c[] = + "$Id$"; +#endif + +#include +#include +#include + +des_cblock_print_file(x, fp) + des_cblock *x; + FILE *fp; +{ + unsigned char *y = (unsigned char *) x; + register int i = 0; + fprintf(fp," 0x { "); + + while (i++ < 8) { + fprintf(fp,"%x",*y++); + if (i < 8) + fprintf(fp,", "); + } + fprintf(fp," }"); +} diff --git a/libdes/verify.c b/libdes/verify.c new file mode 100644 index 0000000..b5e775a --- /dev/null +++ b/libdes/verify.c @@ -0,0 +1,275 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Program to test the correctness of the DES library + * implementation. + * + * exit returns 0 ==> success + * -1 ==> error + */ + +#ifndef lint +static char rcsid_verify_c[] = + "$Id$"; +#endif + +#include +#include +#include +#include + +extern char *errmsg(); +extern int errno; +extern int des_string_to_key(); +extern int des_key_sched(); +extern int des_ecb_encrypt(); +extern int des_cbc_encrypt(); +extern exit(); +char *progname; +int nflag = 2; +int vflag; +int mflag; +int zflag; +int pid; +int des_debug; +des_key_schedule KS; +unsigned char cipher_text[64]; +unsigned char clear_text[64] = "Now is the time for all " ; +unsigned char clear_text2[64] = "7654321 Now is the time for "; +unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0}; +unsigned char output[64]; +unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0}; +unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */ +unsigned char *input; + +/* 0x0123456789abcdef */ +unsigned char default_key[8] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef +}; +unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f }; +unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 }; +des_cblock s_key; +unsigned char default_ivec[8] = { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef +}; +unsigned char *ivec; +unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */ +int i,j; + +/* + * Can also add : + * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) + */ + +main(argc,argv) + int argc; + char *argv[]; +{ + /* Local Declarations */ + long in_length; + + progname=argv[0]; /* salt away invoking program */ + + /* Assume a u_int32 is four bytes */ + if (sizeof(u_int32) != 4) { + printf("\nERROR, size of long is %d",sizeof(u_int32)); + exit(-1); + } + + while (--argc > 0 && (*++argv)[0] == '-') + for (i=1; argv[0][i] != '\0'; i++) { + switch (argv[0][i]) { + + /* debug flag */ + case 'd': + des_debug=3; + continue; + + case 'z': + zflag = 1; + continue; + + case 'm': + mflag = 1; + continue; + + default: + printf("%s: illegal flag \"%c\" ", + progname,argv[0][i]); + exit(1); + } + }; + + if (argc) { + fprintf(stderr, "Usage: %s [-dmz]\n", progname); + exit(1); + } + + /* use known input and key */ + + /* ECB zero text zero key */ + if (zflag) { + input = zero_text; + des_key_sched(zero_key,KS); + printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n"); + do_decrypt(output,cipher_text); + return(0); + } + + if (mflag) { + input = msb_text; + des_key_sched(key3,KS); + printf("plaintext = 0x00 00 00 00 00 00 00 40, "); + printf("key = 0, cipher = 0x??\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n"); + do_decrypt(output,cipher_text); + return(0); + } + + /* ECB mode Davies and Price */ + { + input = zero_text; + des_key_sched(key2,KS); + printf("Examples per FIPS publication 81, keys ivs and cipher\n"); + printf("in hex. These are the correct answers, see below for\n"); + printf("the actual answers.\n\n"); + printf("Examples per Davies and Price.\n\n"); + printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n"); + printf("\tclear = 0\n"); + printf("\tcipher = 25 dd ac 3e 96 17 64 67\n"); + printf("ACTUAL ECB\n"); + printf("\tclear \"%s\"\n", input); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + do_decrypt(output,cipher_text); + } + + /* ECB mode */ + { + des_key_sched(default_key,KS); + input = clear_text; + ivec = default_ivec; + printf("EXAMPLE ECB\tkey = 0123456789abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n"); + printf("ACTUAL ECB\n\tclear \"%s\"",input); + do_encrypt(input,cipher_text); + printf("\n\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n\n"); + do_decrypt(output,cipher_text); + } + + /* CBC mode */ + printf("EXAMPLE CBC\tkey = 0123456789abcdef"); + printf("\tiv = 1234567890abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n"); + printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n"); + printf("\t\t\t68 37 88 49 9a 7c 05 f6\n"); + + printf("ACTUAL CBC\n\tclear \"%s\"\n",input); + in_length = strlen(input); + des_cbc_encrypt(input,cipher_text,(long) in_length,KS,ivec,1); + printf("\tciphertext = (low to high bytes)\n"); + for (i = 0; i <= 7; i++) { + printf("\t\t"); + for (j = 0; j <= 7; j++) { + printf("%02x ",cipher_text[i*8+j]); + } + printf("\n"); + } + des_cbc_encrypt(cipher_text,clear_text,(long) in_length,KS,ivec,0); + printf("\tdecrypted clear_text = \"%s\"\n",clear_text); + + printf("EXAMPLE CBC checksum"); + printf("\tkey = 0123456789abcdef\tiv = 1234567890abcdef\n"); + printf("\tclear =\t\t\"7654321 Now is the time for \"\n"); + printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, "); + printf("or some part thereof\n"); + input = clear_text2; + des_cbc_cksum(input,cipher_text,(long) strlen(input),KS,ivec,1); + printf("ACTUAL CBC checksum\n"); + printf("\t\tencrypted cksum = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + exit(0); +} + +flip(array) + char *array; +{ + register int old,new,i,j; + /* flips the bit order within each byte from 0 lsb to 0 msb */ + for (i = 0; i<=7; i++) { + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + if (old & 01) + new = new | 01; + if (j < 7) { + old = old >> 1; + new = new << 1; + } + } + *array = new; + array++; + } +} + +do_encrypt(in,out) + char *in; + char *out; +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(in,out,KS,1); + if (des_debug) { + printf("\nclear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +do_decrypt(in,out) + char *out; + char *in; + /* try to invert it */ +{ + for (i =1; i<=nflag; i++) { + des_ecb_encrypt(out,in,KS,0); + if (des_debug) { + printf("clear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} diff --git a/libdes/weak_key.c b/libdes/weak_key.c new file mode 100644 index 0000000..6657c1e --- /dev/null +++ b/libdes/weak_key.c @@ -0,0 +1,73 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + */ + +#ifndef lint +static char rcsid_weak_key_c[] = + "$Id$"; +#endif + +#include + +/* + * The following are the weak DES keys: + */ +static des_cblock weak[16] = { + /* weak keys */ + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}, + {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, + {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, + + /* semi-weak */ + {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe}, + {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01}, + + {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1}, + {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e}, + + {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1}, + {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01}, + + {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe}, + {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e}, + + {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e}, + {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01}, + + {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe}, + {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1} +}; + +/* + * des_is_weak_key: returns true iff key is a [semi-]weak des key. + * + * Requires: key has correct odd parity. + */ +int +des_is_weak_key(key) + des_cblock key; +{ + int i; + des_cblock *weak_p = weak; + + for (i = 0; i < (sizeof(weak)/sizeof(des_cblock)); i++) { + if (!memcmp((char *)weak_p++, (char *)key, sizeof(des_cblock))) + return 1; + } + + return 0; +} -- cgit v1.2.3