diff --git a/ChangeLog b/ChangeLog index bed5f6ff..df1a6842 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,546 +1,554 @@ +2001-08-03 Werner Koch + + * tests/: New. + * Makefile.am: Included tests directory + + * configure.in (DYNLINK_MOD_CFLAGS): Use -shared with dec-osf. + Reported by Chris Adams. Merged some cases. + 2001-05-31 Werner Koch Release 1.1.3. * configure.in: Use _gcry_ prefix when creating the cipher constructor. * acconfig.h (_GCRYPT_IN_LIBGCRYPT): Define it here. 2001-05-28 Werner Koch * acinclude.m4 (GPH_PROG_DOCBOOK): Removed. (GPH_PROG_DB2ANY): New. Taken from GPH. * configure.in: Use it here. 2000-12-19 Werner Koch Major change: Removed all GnuPG stuff and renamed this piece of software to gcrypt. The directory gcrypt has been renamed to src. 2000-11-14 Werner Koch Version 1.1.2 released. 2000-11-13 Werner Koch * acinclude.m4 (GNUPG_FIX_HDR_VERSION): VPATH build fix. 2000-10-10 Werner Koch * Makefile.am (dist-hook): Create the version file. * configure.in: Set the libtool version here, removed the need for the version file. Mon Sep 18 16:35:45 CEST 2000 Werner Koch * acinclude.m4 (GNUPG_CHECK_MLOCK): Removed that silly mkdir(). * configure.in: Changes to allow for Solaris random device. By Nils Ellmenreich. (--with-egd-socket): New. * configure.in (GNUPG_HOMEDIR): New. * configure.in: Check for fstat64 and fopen64 * acinclude.m4 (GNUPG_CHECK_FAQPROG): New. * configure.in: Test for this. * configure.in (DYNLINK_MOD_CFLAGS): Fix by David Champion. Tue Aug 22 14:31:15 CEST 2000 Werner Koch Version 1.1.1 Fri Aug 18 14:27:14 CEST 2000 Werner Koch * agent/: New. * Makefile.am, configure.in: Support for the new directory. Mon Jul 17 16:35:47 CEST 2000 Werner Koch * configure.in (mingw32): Changes to allow for mingw32msvc Fri Jul 14 19:38:23 CEST 2000 Werner Koch The big merge between this one and the stable branch 1.0. Still need to merge TNANKS, AUTHORS and such. It probaly does not compile yet. * acinclude.m4 (GNUPG_CHECK_MLOCK): Fixed syntax error in C code. * configure.in: Add check for termio.h, wait unctiosn and sigaction. * acinclude.m4, configure.in (GNUPG_CHECK_GNUMAKE): New. * acinclude.m4 (MKDIR_TAKES_ONE_ARG): Check some headers. By Gaël Quéri. * configure.in (AM_INIT_AUTOMAKE): Use this now. By Gaël. * acinclude.m4 (GNUPG_CHECK_EXPORTDYNAMIC): Replacement for GNUPG_CHECK_RDYNAMIC which should handle gcc with non GNU ld nicer. Contributed by Dave Dykstra. * configure.in (GNYPG_CHECK_RDYNAMIC): Replaced by the new check. * configure.in: Add a test for unisgned long long. * configure.in (DYNLINK_MOD_CFLAGS): Set different for NetBSD. * configure.in: Add check for clock_gettime * configure.in (ALL_LINGUAS): Add nl. * configure.in (ALL_LINGUAS): Add Esperanto. * configure.in (ALL_LINGUAS): Add sv and ja. * configure.in: Use /usr/local for CFLAGS and LDFLAGS when target is freebsd. By Rémi. * configure.in: Do not set development version when the version has a dash in it. Suggested by Dave Dykstra. * configure.in: Removed substitution for doc/gph/Makefile. Do all the gcc warning only in maintainer mode. * configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc. Suggested by Alexandre Oliva. (-Wall): Moved the settting of gcc warning options near to the end so that tests don't get confused. Suggested by Paul D. Smith. * acinclude.m4 (GNUPG_SYS_NM_PARSE): Added BSDI support. (GNUPG_CHECK_RDYNAMIC): Ditto. * acinclude.m4 (GNUPG_CHECK_MLOCK): Changed the way to test for librt. Test suggested by Jeff Long. * acinclude.m4 (GNUPG_CHECK_MLOCK): Do librt check only when we can't link a test program. This way GNU systems don't need to link against linrt. (GNUPG_CHECK_IPC): Fixed use of TRY_COMPILE macro. From Tim Mooney. * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add support for DJGPP. (GNUPG_CHECK_MLOCK): Check whether mlock sits in librt. * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Add NetBSD. By Thomas Klausner. * acconfig.h (HAVE_MLOCK): Added Mon Mar 13 19:22:46 CET 2000 Werner Koch * configure.in: Now uses the Docbook M4s from GPH. Mon Jan 31 17:46:35 CET 2000 Werner Koch * Makefile.am: Re-added tools. By Rémi. Mon Jan 31 16:37:34 CET 2000 Werner Koch * configure.in: Create a symlink for types.h in gcrypt/. Thu Jan 27 18:00:44 CET 2000 Werner Koch * configure.in (g10defs.h): Replaced by gnupg-defs.h Mon Jan 24 13:04:28 CET 2000 Werner Koch * jnlib/ : New. * configure.in: Do set development version when the version has a dash in it. Suggested by Dave Dykstra. Thu Dec 9 17:22:27 CET 1999 Werner Koch * acinclude.m4 (GNUPG_FIX_HDR_VERSION): New. * configure.in: Check and fix the version number of gcrypt/gcrypt.h so that it is always the save as VERSION. Thu Oct 28 16:17:46 CEST 1999 Werner Koch * Started with development series 1.1 on 1999-10-26 Tue Oct 26 14:10:21 CEST 1999 Werner Koch * README-alpha: New * configure.in: Fixed quoting in test for development version. * THANKS: Add entries for Michael, Brenno and J Horacio who did very nice Howto documents - I apoligize for forgetting to mention them earlier. Fri Sep 17 12:56:42 CEST 1999 Werner Koch * configure.in: Add "-lcap" when capabilities are requested. Add the conditional CROSS_COMPILING. * Makefile.am: Don't use checks when CROSS_COMPILING. Wed Sep 15 16:22:17 CEST 1999 Werner Koch * configure.in (ALL_LINGUAS): Add pt_PT. * configure.in: Some tweaks for cross compiling under MingW32 * acconfig.h (USE_STATIC_RNDW32): New. Tue Sep 7 17:08:10 CEST 1999 Werner Koch * VERSION: Set to 1.0.0. Mon Sep 6 19:59:08 CEST 1999 Werner Koch * configure.in: Create makefile in doc/gph * acinclude.m4 (GNUPG_FUNC_MKDIR_TAKES_ONE_ARG): New * configure.in: use the above. Thu Sep 2 16:40:55 CEST 1999 Werner Koch * VERSION: Set to 0.9.11. Tue Aug 31 17:20:44 CEST 1999 Werner Koch * configure.in: Minor changes to the OS/2 and Mingw32 system labels. Add a printable name for Hurd. Mon Aug 30 20:38:33 CEST 1999 Werner Koch * configure.in: Some support for DJGPP (Mark Elbrecht) Wed Aug 4 10:34:46 CEST 1999 Werner Koch * VERSION: Set to 0.9.10. Mon Jul 26 09:34:46 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): remove init of ac_cv_... * Makefile.am (DISCLEANFILES): New Fri Jul 23 13:53:03 CEST 1999 Werner Koch * VERSION: Set to 0.9.9. * configure.in: Print a notice when rndunix is used. Thu Jul 15 10:15:35 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Fixed last modification. Wed Jul 7 13:08:40 CEST 1999 Werner Koch * Makefile.am: Support for libtool. * configure.in: Ditto. Tue Jun 29 21:44:25 CEST 1999 Werner Koch * configure.in (use_local_zlib): The lost dollar is back. * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add EMX case. * configure.in: Another variant of the MX vendor string * configure.in (--with-capabilities): Some test code (Remi). Sat Jun 26 12:15:59 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Support for HPUX and IRIX. * configure.in (HAVE_DL_SHL_LOAD): New for HPUX (Dave Dykstra). * VERSION: Now 0.9.8 Wed Jun 16 20:16:21 CEST 1999 Werner Koch * configure.in: Add test for docbook-to-man Tue Jun 15 12:21:08 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_SYS_NM_PARSE): Support for {net,free}bsd, Thu Jun 10 14:18:23 CEST 1999 Werner Koch * configure.in (ZLIB,GDBM): Check both, header and lib. Sat Jun 5 15:30:33 CEST 1999 Werner Koch * pkclist.c (key_present_in_pk_list): New (Michael). Tue May 25 19:50:32 CEST 1999 Werner Koch * configure.in (IS_DEVELOPMENT_VERSION): Fixed detection. Sun May 23 14:20:22 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): assume yes when cross-compiling. Mon May 17 21:54:43 CEST 1999 Werner Koch * configure.in (socket): Fix for Unisys by Katsuhiro Kondou. Sat May 8 19:28:08 CEST 1999 Werner Koch * NEWS: Add a marker line which I forgot to do for 0.9.6. Thu May 6 14:18:17 CEST 1999 Werner Koch * README: Minor updates * VERSION: Now 0.9.6 Thu Apr 8 09:35:53 CEST 1999 Werner Koch * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Fix for amiga-openbsd (Peter Reich) (GNUPG_PROG_NM): Ditto Wed Apr 7 20:51:39 CEST 1999 Werner Koch * Makefile.am (g10defs.h): Removed. * configure.in (AC_OUTPUT_COMMANDS): Create g10defs.h Sat Mar 20 12:55:33 CET 1999 Werner Koch * VERSION: Now 0.9.5 Sun Mar 14 19:34:36 CET 1999 Werner Koch * acinclude.m4 (AM_SYS_SYMBOL_UNDERSCORE): Removed because it is now in the latest libtool. Thu Mar 11 16:39:46 CET 1999 Werner Koch * configure.in: Removed the need for libtool Mon Mar 8 20:47:17 CET 1999 Werner Koch * configure.in (DLSYM_NEEDS_UNDERSCORE): Replaced. * acinclude.in (AM_SYS_SYMBOL_UNDERSCORE): New. * VERSION: Now 0.9.4 Sun Feb 28 19:11:00 CET 1999 Werner Koch * configure.in (dld): Test disabled. Fri Feb 26 17:55:41 CET 1999 Werner Koch * encode.c (encode_simple): temporary fix. Wed Feb 24 11:07:27 CET 1999 Werner Koch * configure.in: New option --enable-static-rnd. Mon Feb 22 20:04:00 CET 1999 Werner Koch * BUGS: Now we assign bug numbers. * OBUGS: New to keep rack o fixed bugs (CVS only) Fri Feb 19 18:01:54 CET 1999 Werner Koch * VERSION: Released 0.9.3 Fri Feb 19 15:49:15 CET 1999 Werner Koch * acinclude.m4: Removed gettext macros. Tue Feb 16 14:10:02 CET 1999 Werner Koch * configure.in (socket): Check for -lsocket and -lnsl. (osf4): Disable all warnings for DEC's cc. (-Wall): Add more warning options for gcc Sat Feb 13 12:04:43 CET 1999 Werner Koch * configure.in: Changed detection of compiler flags. * intl/ : Removed directory Wed Feb 10 17:15:39 CET 1999 Werner Koch * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Fix for freebsd 2.2 * configure.in: a lot of changes to allow selection of modules. Add support for OS/2. * acinclude.m4: add some more caching * README: Spelling and grammar corrections (John A. Martin) * INSTALL: Ditto. Wed Jan 20 21:40:21 CET 1999 Werner Koch * configure.in: --enable-m-guard is now default Wed Jan 13 12:49:36 CET 1999 Werner Koch * INSTALL: Applied new information how to build rpms by Fabio Coatti * Makefile.in (gnupg.spec): Changed the names. Tue Jan 12 11:17:18 CET 1999 Werner Koch * config.links (m68k-atari-mint): New Tue Jan 12 09:17:19 CET 1999 Gaël Quéri * all: Fixed typos all over the place Sat Jan 9 16:02:23 CET 1999 Werner Koch * configure.in: Add a way to statically link rndunix Sun Jan 3 15:28:44 CET 1999 Werner Koch * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): New. * configure.in (DYNLOAD_CFLAGS): Use result from CHECK_RDYNAMIC Wed Dec 23 13:18:14 CET 1998 Werner Koch * README: Replaced the command overview with a short intro. Sat Dec 12 18:40:32 CET 1998 Werner Koch * configure.in: Add check for dlopen in libc (Greg Troxel) and a new define * acconfig.h (DLSYM_NEEDS_UNDERSCORE): New. Thu Dec 10 20:15:36 CET 1998 Werner Koch * acinclude.m (GNUPG_CHECK_PIC): New * configure.in, acinclude.m4: Renamed all WK_ to GNUPG_ Tue Dec 8 15:09:29 CET 1998 Werner Koch * VERSION: Set to 0.4.5 Wed Nov 25 12:38:29 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (USE_RNDLINUX): New. Fri Nov 20 19:34:57 1998 Werner Koch (wk@isil.d.shuttle.de) * VERSION: Released 0.4.4 * configure.in (try_asm_modules): For option --disable-asm Tue Nov 10 19:32:40 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (MPI_SFLAGS): New. Tue Nov 10 13:44:53 1998 Werner Koch (wk@isil.d.shuttle.de) * ABOUT-NLS: New * configure.in (AC_REVISION): New. Sun Nov 8 18:20:35 1998 Werner Koch (wk@isil.d.shuttle.de) * VERSION: Set to 0.4.3 Sun Oct 25 19:49:37 1998 Werner Koch (wk@isil.d.shuttle.de) * Makefile.am (g10defs.h): New macro GNUPG_DATADIR. Wed Oct 21 17:24:24 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in: Removed gettext kludge * acinclude.m4: Add patched AM_WITH_NKS macro Tue Oct 20 19:03:36 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in: Kludge to make AM_GNU_GETTEXT work, changed some macors to more modern versions. Also changeg the all makefiles to remove duplicate ../intl. * acinclude.m4: Removed the gettext stuff, as this already comes with automake now. Wed Oct 14 12:11:34 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (NAME_OF_DEV_RANDOM): New. (DYNLINK_MOD_CFLAGS): New. Thu Oct 8 10:55:15 1998 Werner Koch (wk@isil.d.shuttle.de) * Makefile.am (g10defs.h): creates include file * acconfig.h: now includes g10defs.h * configure.in: Removed G10_LOCALEDIR and GNUPG_LIB Thu Sep 17 18:49:40 1998 Werner Koch (wk@(none)) * Makefile.am (dist-hook): Now creates RPM file. * scripts/gnupg.spec: New template file for RPMs Thu Jul 30 19:17:07 1998 Werner Koch (wk@(none)) * acinclude.h (WK_CHECK_IPC): New * configure.in : Add checks for SysV IPC Thu Jun 25 11:18:49 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (--disable-dynload): New. Wed Jun 10 07:48:59 1998 Werner Koch,mobil,,, (wk@tobold) * configure.in (GNUPG_LIBDIR): New. Mon May 25 19:10:59 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-unix.c (fast_random_poll): fixed syntax bug. Mon May 11 10:21:31 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (PRINTABLE_OS_NAME): Linux is now GNU/Linux Tue Apr 14 19:08:05 1998 Werner Koch (wk@isil.d.shuttle.de) * [all files]: Applied Matthew Skala's typo and grammar fixes. Wed Mar 4 10:32:40 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (getrusage,gettimeofday): New tests. Fri Feb 27 13:14:17 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (--disable-m-guard): New. Thu Feb 26 17:09:27 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in, acinclude.m4, intl/, po/: New macros taken from GNOME, switched to automake 1.2f Thu Feb 26 09:05:46 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (doc/Makefile): New Thu Feb 26 07:40:47 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in: Changed gettext stuff Wed Feb 25 11:44:10 1998 Werner Koch (wk@isil.d.shuttle.de) * checks/*test : restructured the directory. Tue Feb 24 15:59:12 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in: Changed the name of the package to GNUPG and chnaged several other names too. Wed Feb 18 17:36:45 1998 Werner Koch (wk@isil.d.shuttle.de) * Makefile.am (checks): New. Sat Feb 14 15:37:55 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (mpi_config_done): Removed asm links caching. Sat Feb 14 14:02:20 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in (PRINTABLE_OS_NAME): New. * acconfig.h: Likewise. Fri Feb 13 19:43:41 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in : Fixed zlib stuff * Makefile.am: Likewise diff --git a/Makefile.am b/Makefile.am index 80672089..86e2813c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,23 +1,23 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = jnlib mpi cipher src doc +SUBDIRS = jnlib mpi cipher src doc tests EXTRA_DIST = README-alpha BUGS DISTCLEANFILES = gcrypt-defs.h # Add all the files listed in "distfiles" files to the distribution, # apply version number s to some files and create a VERSION file which # we need for the Prereq: patch file trick. dist-hook: @set -e; \ for file in `cd $(top_srcdir); find . -type f -name distfiles`; do \ dir=`dirname $$file` ; $(mkinstalldirs) $(distdir)/$$dir ; \ for i in distfiles `cat $(top_srcdir)/$$file` ; do \ ln $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i 2> /dev/null \ || cp -p $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \ done ; \ done @set -e; \ echo "$(VERSION)" > $(distdir)/VERSION diff --git a/NEWS b/NEWS index e815ed0d..dc41db23 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,19 @@ + * Arcfour does now work. -GnuPG has been spitted into libgcrypt and GnuPG. +Noteworthy changes in version 1.1.3 (2001-05-31) +------------------------------------------------ + + * First release of Libgcrypt which is a result of splitting GnuPG + into into libgcrypt and GnuPG. + + +Copyright 2001 Free Software Foundation, Inc. + +This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/THANKS b/THANKS index 4eeb8d98..fc47e6f7 100644 --- a/THANKS +++ b/THANKS @@ -1,110 +1,112 @@ Libgcrypt is based on the GnuPG code. Here is a list of people, who helped in GnuPG and Libgcrypt development. Please help us to keep it complete and free of errors. Allan Clark allanc@sco.com Anand Kumria wildfire@progsoc.uts.edu.au Ariel T Glenn ariel@columbia.edu Bodo Moeller Bodo_Moeller@public.uni-hamburg.de Brenno de Winter brenno@dewinter.com Brian Moore bem@cmc.net Brian Warner warner@lothar.com Bryan Fullerton bryanf@samurai.com Caskey L. Dickson caskey@technocage.com Cees van de Griend cees-list@griend.xs4all.nl Charles Levert charles@comm.polymtl.ca Christian von Roques roques@pond.sub.org Christopher Oliver oliver@fritz.traverse.net Christian Recktenwald chris@citecs.de Daniel Eisenbud eisenbud@cs.swarthmore.edu Daniel Koening dan@mail.isis.de David Ellement ellement@sdd.hp.com Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de Dirk Lattermann dlatt@t-online.de Ed Boraas ecxjo@esperanto.org Enzo Michelangeli em@MailAndNews.com Ernst Molitor ernst.molitor@uni-bonn.de Fabio Coatti cova@felix.unife.it Felix von Leitner leitner@amdiv.de Frank Heckenbach heckenb@mi.uni-erlangen.de Frank Stajano frank.stajano@cl.cam.ac.uk Gaël Quéri gqueri@mail.dotcom.fr Gerlinde Klaes gk@u64.de Greg Louis glouis@dynamicro.on.ca Greg Troxel gdt@ir.bbn.com Gregory Steuck steuck@iname.com Geoff Keating geoffk@ozemail.com.au Harald Denker harry@hal.westfalen.de Hendrik Buschkamp buschkamp@rheumanet.org Holger Schurig holger@d.om.org Hugh Daniel hugh@toad.com Ian McKellar imckellar@harvestroad.com.au Janusz A. Urbanowicz alex@bofh.torun.pl James Troup james@nocrew.org Jean-loup Gailly gzip@prep.ai.mit.edu Jens Bachem bachem@rrz.uni-koeln.de J Horacio MG homega@ciberia.es Joachim Backes backes@rhrk.uni-kl.de John A. Martin jam@jamux.com Johnny Teveßen j.tevessen@gmx.de Jörg Schilling schilling@fokus.gmd.de Jun Kuriyama kuriyama@sky.rim.or.jp Karl Fogel kfogel@guanabana.onshore.com Karsten Thygesen karthy@kom.auc.dk Katsuhiro Kondou kondou@nec.co.jp Kazu Yamamoto kazu@iijlab.net Lars Kellogg-Stedman lars@bu.edu Marco d'Itri md@linux.it Mark Adler madler@alumni.caltech.edu Mark Elbrecht snowball3@bigfoot.com Markus Friedl Markus.Friedl@informatik.uni-erlangen.de Martin Kahlert martin.kahlert@provi.de Martin Hamilton Martin Schulte schulte@thp.uni-koeln.de Matthew Skala mskala@ansuz.sooke.bc.ca Max Valianskiy maxcom@maxcom.ml.org Michael Fischer v. Mollard mfvm@gmx.de Michael Roth mroth@nessie.de Michael Sobolev mss@despair.transas.com Nicolas Graner Nicolas.Graner@cri.u-psud.fr NIIBE Yutaka gniibe@chroot.org Niklas Hernaeus Nimrod Zimerman zimerman@forfree.at N J Doye nic@niss.ac.uk Oliver Haakert haakert@hsp.de Oskari Jääskeläinen f33003a@cc.hut.fi Paul D. Smith psmith@baynetworks.com Philippe Laliberte arsphl@oeil.qc.ca Peter Gutmann pgut001@cs.auckland.ac.nz QingLong qinglong@bolizm.ihep.su Ralph Gillen gillen@theochem.uni-duesseldorf.de +Rami Lehti Rami.Lehti@finland.sun.com Rat ratinox@peorth.gweep.net Reinhard Wobst R.Wobst@ifw-dresden.de Rémi Guyomarch rguyom@mail.dotcom.fr Reuben Sumner rasumner@wisdom.weizmann.ac.il Richard Outerbridge outer@interlog.com Roddy Strachan roddy@satlink.com.au Roland Rosenfeld roland@spinnaker.rhein.de Ross Golder rossigee@bigfoot.com Serge Munhoven munhoven@mema.ucl.ac.be SL Baur steve@xemacs.org Stefan Karrmann S.Karrmann@gmx.net Stefan Keller dres@cs.tu-berlin.de Steffen Ullrich ccrlphr@xensei.com Steffen Zahn zahn@berlin.snafu.de Steven Bakker steven@icoe.att.com Susanne Schultz schultz@hsp.de Thiago Jung Bauermann jungmann@cwb.matrix.com.br Thomas Roessler roessler@guug.de Tom Spindler dogcow@home.merit.edu Tom Zerucha tzeruch@ceddec.com Tomas Fasth tomas.fasth@twinspot.net +Tommi Komulainen Tommi.Komulainen@iki.fi Thomas Mikkelsen tbm@image.dk Ulf Möller 3umoelle@informatik.uni-hamburg.de Urko Lusa ulusa@euskalnet.net Walter Koch koch@hsp.de Werner Koch werner.koch@guug.de Wim Vandeputte bunbun@reptile.rug.ac.be nbecker@hns.com diff --git a/cipher/ChangeLog b/cipher/ChangeLog index e96ce481..ee015638 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,856 +1,894 @@ +2001-08-03 Werner Koch + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + 2001-08-02 Werner Koch + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + * arcfour.c (arcfour_setkey): Check the minimim keylength against bytes and not bits. (selftest): Must reset the key before decryption. 2001-05-31 Werner Koch * sha1.c (sha1_init): Made static. Changed all g10_ prefixed function names as well as some mpi_ function names to cope with the introduced naming changes. * md.c (prepare_macpads): Made key const. 2001-05-28 Werner Koch * rndegd.c (gather_random): Removed the use of tty_printf. 2001-03-29 Werner Koch * md5.c (md5_final): Fixed calculation of hashed length. Thanks to disastry@saiknes.lv for pointing out that it was horrible wrong for more than 512MB of input. * sha1.c (sha1_final): Ditto. * rmd160.c (rmd160_final): Ditto. * tiger.c (tiger_final): Ditto. * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to avoid name clashes with an encrypt function in stdlib.h of Dynix/PIX. Thanks to Gene Carter. * elgamal.c (encrypt,do_encrypt): Ditto. * twofish.c (gnupgext_enum_func): Use only when when compiled as a module. * rijndael.c (gnupgext_enum_func): Ditto. * tiger.c (tiger_get_info): Return "TIGER192" and not just "TIGER". By Edwin Woudt. * random.c: Always include time.h - standard requirement. Thanks to James Troup. * rndw32.c: Fixes to the macros. 2001-01-11 Werner Koch * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and not 8. 2000-12-19 Werner Koch Major change: Removed all GnuPG stuff and renamed this piece of software to gcrypt. 2000-11-14 Werner Koch * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and mpi_free by gcry_mpi_release. * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. * rsa.c (test_keys,generate,rsa_verify): Ditto. * primegen.c (generate_elg_prime): Ditto. (gen_prime): Ditto and removed nlimbs. * rsa.c (generate): Allocate 2 more vars in secure memory. * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency problems. 2000-10-09 Werner Koch * arcfour.c, arcfour.h: New. * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. (setup_cipher_table): Add Arcfour. (gcry_cipher_open): Kludge to allow stream mode. Wed Oct 4 13:16:18 CEST 2000 Werner Koch * sha1.c (transform): Use rol() macro. Actually this is not needed for a newer gcc but there are still aoter compilers. * rsa.c (test_keys): Use new random function. * md.c (gcry_md_setkey): New function to overcome problems with const conflics. (gcry_md_ctl): Pass set key to the new functions. * rijndael.c: New. * cipher.c: Add Rijndael support. Mon Sep 18 16:35:45 CEST 2000 Werner Koch * rndlinux.c (open_device): Loose random device checking. By Nils Ellmenreich. * random.c (fast_random_poll): Check ENOSYS for getrusage. * rndunix.c: Add 2 sources for QNX. By Sam Roberts. * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. * rsa.c: Changed the comment about the patent. (secret): Speed up by using the CRT. For a 2k keys this is about 3 times faster. (stronger_key_check): New but unused code to check the secret key. * Makefile.am: Included rsa.[ch]. * pubkey.c: Enabled RSA support. (pubkey_get_npkey): Removed RSA workaround. Mon Jul 31 10:04:47 CEST 2000 Werner Koch * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new gcry_sexp_nth_{data,mpi} functions. Tue Jul 25 17:44:15 CEST 2000 Werner Koch * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with the new S-Exp interface. Mon Jul 17 16:35:47 CEST 2000 Werner Koch * random.c (gather_faked): Replaced make_timestamp by time(2) again. Fri Jul 14 19:38:23 CEST 2000 Werner Koch * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. * Makefile.am: Never compile mingw32 as module. * Makefile.am: Tweaked module build and removed libtool * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. * elgamal.c (sign): Removed inactive code. * rsa.c, rsa.h: New based on the old module version (only in CVS for now). * pubkey.c (setup_pubkey_table): Added commented support for RSA. * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. (my_popen): Do the FD_CLOEXEC only if it is available (start_gatherer): Cope with missing _SC_OPEN_MAX * rndunix.c: Add some more headers for QNX. By Sam Roberts. * rndegd.c (gather_random): Shortcut level 0. * rndunix.c (gather_random): Ditto. * rndw32.c (gather_random): Ditto. * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. * rndw32.c: Add some debuging code enabled by an environment variable. * random.c (read_seed_file): Binary open for DOSish system (update_random_seed_file): Ditto. * random.c [MINGW32]: Include process.h for getpid. * random.c (fast_random_poll): Add clock_gettime() as fallback for system which support this POSIX.4 fucntion. By Sam Roberts. * random.c (read_seed_file): Removed the S_ISLNK test becuase it is already covered by !S_ISREG and is not defined in Unixware. Reported by Dave Dykstra. (update_random_seed_file): Silently ignore update request when pool is not filled. * random.c (read_seed_file): New. (set_random_seed_file): New. (read_pool): Try to read the seeding file. (update_random_seed_file): New. (read_pool): Do an initial extra seeding when level 2 quality random is requested the first time. This requestes at least POOLSIZE/2 bytes of entropy. Compined with the seeding file this should make normal random bytes cheaper and increase the quality of the random bytes used for key generation. * random.c (read_pool): Print a more friendly error message in cases when too much random is requested in one call. * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; this is not the case for some ESIX and Unixware, although they have getrusage(). * primegen.c (generate_elg_prime): All primes are now generated with the lowest random quality level. Because they are public anyway we don't need stronger random and by this we do not drain the systems entropy so much. * primegen.c (register_primegen_progress): New. * dsa.c (register_pk_dsa_progress): New. * elgamal.c (register_pk_elg_progress): New. * elgamal.c (wiener_map): New. (gen_k): Use a much smaller k. (generate): Calculate the qbits using the wiener map and choose an x at a size comparable to the one choosen in gen_k * rmd160.c (rmd160_get_info): Moved casting to the left side due to a problem with UTS4.3. Suggested by Dave Dykstra. * sha1.c (sha1_get_info): Ditto. * tiger.c (tiger_get_info): Ditto. * md5.c (md5_get_info): Ditto * des.c (des_get_info): Ditto. * blowfish.c (blowfish_get_info): Ditto. * cast5.c (cast5_get_info): Ditto. * twofish.c (twofish_get_info): Ditto. Fri Mar 24 11:25:45 CET 2000 Werner Koch * md.c (md_open): Add hmac arg and allocate space for the pads. (md_finalize): Add HMAC support. (md_copy): Ditto. (md_close): Ditto. (gcry_md_reset): Ditto. (gcry_md_ctl): Ditto. (prepare_macpdas): New. Mon Mar 13 19:22:46 CET 2000 Werner Koch * md.c (gcry_md_hash_buffer): Add support for the other algorithms. Mon Jan 31 16:37:34 CET 2000 Werner Koch * genprime.c (generate_elg_prime): Fixed returned factors which never worked for non-DSA keys. Thu Jan 27 18:00:44 CET 2000 Werner Koch * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. Mon Jan 24 22:24:38 CET 2000 Werner Koch * pubkey.c (gcry_pk_decrypt): Implemented. (gcry_pk_encrypt): Implemented. (gcry_pk_testkey): New. (gcry_pk_genkey): New. (pubkey_decrypt): Made static. (pubkey_encrypt): Ditto. (pubkey_check_secret_key): Ditto. (pubkey_generate): Ditto. Mon Jan 24 13:04:28 CET 2000 Werner Koch * pubkey.c (pubkey_nbits): Removed and replaced by ... (gcry_pk_get_nbits): this new one. Wed Dec 8 21:58:32 CET 1999 Werner Koch * dsa.c: s/mpi_powm/gcry_mpi_powm/g * elgamal.c: Ditto. * primegen.c: Ditto. * : Replaced g10_opt_verbose by g10_log_verbosity(). * Makefile.am (INCLUDES): removed intl, add ../gcrypt Fri Nov 19 17:15:20 CET 1999 Werner Koch * dynload.c (cmp_filenames): New to replaced compare_filename() in module. (register_cipher_extension): Removed the tilde expansion stuff. * rndeg.c (my_make_filename): New. * : Replaced header util.h by g10lib.h * random.c (gather_faked): Replaced make_timestamp by time(2). Disabled wrning printed with tty_printf. * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; this should be replaced by a callback function. * primegen.c (gen_prime): Use gcry_mpi_randomize. (is_prime): Ditto. * elgamal.c (test_keys): Ditto. * dsa.c (test_keys): Ditto. * cipher.c (gcry_cipher_close): Die on invalid handle. Mon Nov 15 21:36:02 CET 1999 Werner Koch * elgamal.c (gen_k): Use the new random API. (generate): Ditto. * dsa.c (gen_k): Ditto. (generate): Ditto. Sat Nov 13 17:44:23 CET 1999 Werner Koch * pubkey.c (disable_pubkey_algo): Made static. (gcry_pk_ctl): New. * random.c (get_random_bits): Renamed to ... (get_random_bytes): ... this and made static. (gcry_random_bytes): New. (gcry_random_bytes_secure): New. (randomize_buffer): Renamed to ... (gcry_randomize): ...this. * md.c (gcry_md_hash_buffer): New. * pubkey.c (gcry_pk_algo_info): 4 new commands. (pubkey_get_npkey): Made static. (pubkey_get_nskey): Made static. (pubkey_get_nsig): Made static. (pubkey_get_nenc): Made static. * pubkey.c: Removed all G10ERR_xxx. * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. * blowfish.c: Ditto. * des.c: Ditto. * twofish.c: Ditto. * dsa.c: Ditto. * elgamal.c: Ditto. * g10c.c: Removed * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL if we are out of core. * dynload.c: Replaced all memory allocation functions. * md.c: Ditto. * primegen.c: Ditto. * pubkey.c: Ditto. * random.c: Ditto. * rndw32.c: Ditto. * elgamal.c: Ditto. * dsa.c: Ditto. Tue Oct 26 14:10:21 CEST 1999 Werner Koch * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). * cipher.c: Merged with gcrypt/symapi.c. * pubkey.c (string_to_pubkey_algo): Renamed function to ... (gcry_pk_map_name): ... this. (pubkey_algo_to_string): Renamed function to ... (gcry_pk_algo_name): ... this. (gcry_pk_algo_info): New. * pubkey.c: Merged with gcrypt/pkapi.c. * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for fixing this bug. * md.c: Merged with gcrypt/mdapi.c Wed Sep 15 14:39:59 CEST 1999 Michael Roth * des.c: Various speed improvements: One bit pre rotation trick after initial permutation (Richard Outerbridge). Finished test of SSLeay Tripple-DES patterns. Wed Sep 15 16:22:17 CEST 1999 Werner Koch * rndw32.c: New. Mon Sep 13 10:51:29 CEST 1999 Werner Koch * bithelp.h: New. * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h Tue Sep 7 16:23:36 CEST 1999 Werner Koch * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. Mon Sep 6 19:59:08 CEST 1999 Werner Koch * des.c (selftest): Add some testpattern Mon Aug 30 20:38:33 CEST 1999 Werner Koch * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using in place encryption. Pointed out by Frank Stajano. Mon Jul 26 09:34:46 CEST 1999 Werner Koch * md5.c (md5_final): Fix for a SCO cpp bug. Thu Jul 15 10:15:35 CEST 1999 Werner Koch * elgamal.c (elg_check_secret_key,elg_encrypt elg_decrypt,elg_sign,elg_verify): Sanity check on the args. * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. * pubkey.c (disable_pubkey_algo): New. (check_pubkey_algo2): Look at disabled algo table. * cipher.c (disable_cipher_algo): New. (check_cipher_algo): Look at disabled algo table. Wed Jul 7 13:08:40 CEST 1999 Werner Koch * Makefile.am: Support for libtool. Fri Jul 2 11:45:54 CEST 1999 Werner Koch * dsa.c (gen_k): Changed algorithm to consume less random bytes * elgamal.c (gen_k): Ditto. * random.c (random_dump_stats): New. Thu Jul 1 12:47:31 CEST 1999 Werner Koch * primegen.c, elgamal.c, dsa.c (progess): New and replaced all fputc with a call to this function. Sat Jun 26 12:15:59 CEST 1999 Werner Koch * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). * Makefile.am (install-exec-hook): Removed. Sun May 23 14:20:22 CEST 1999 Werner Koch * cipher.c (setup_cipher_table): Enable Twofish * random.c (fast_random_poll): Disable use of times() for mingw32. Mon May 17 21:54:43 CEST 1999 Werner Koch * dynload.c (register_internal_cipher_extension): Minor init fix. Tue May 4 15:47:53 CEST 1999 Werner Koch * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug that we didn't correct for step when passing the prime to the Rabin-Miller test which led to bad performance (Stefan Keller). (check_prime): Add a first Fermat test. Sun Apr 18 10:11:28 CEST 1999 Werner Koch * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. * random.c (randomize_buffer): alway use secure memory because we can't use m_is_secure() on a statically allocated buffer. * twofish.c: Replaced some macros by a loop to reduce text size. * Makefile.am (twofish): No more need for sed editing. Fri Apr 9 12:26:25 CEST 1999 Werner Koch * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. * blowfish.c: Dropped the Blowfish 160 mode. * cipher.c (cipher_open): Ditto. (setup_cipher_table): Ditto. And removed support of twofish128 Wed Apr 7 20:51:39 CEST 1999 Werner Koch * random.c (get_random_bits): Can now handle requests > POOLSIZE * cipher.c (cipher_open): Now uses standard CFB for automode if the blocksize is gt 8 (according to rfc2440). * twofish.c: Applied Matthew Skala's patches for 256 bit key. Tue Apr 6 19:58:12 CEST 1999 Werner Koch * random.c (get_random_bits): Can now handle requests > POOLSIZE * cipher.c (cipher_open): Now uses standard CFB for automode if the blocksize is gt 8 (according to rfc2440). Sat Mar 20 11:44:21 CET 1999 Werner Koch * rndlinux.c (tty_printf) [IS_MODULE]: Removed. * rndegd.c (gather_random): Some fixes. Wed Mar 17 13:09:03 CET 1999 Werner Koch * rndegd.c (do_read): New. (gather_random): Changed the implementation. Mon Mar 8 20:47:17 CET 1999 Werner Koch * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. Fri Feb 26 17:55:41 CET 1999 Werner Koch * md.c: Nearly a total rewrote. Wed Feb 24 11:07:27 CET 1999 Werner Koch * cipher.c (context): Fixed alignment * md.c: Ditto. * rndegd.c: New Mon Feb 22 20:04:00 CET 1999 Werner Koch * rndegd.c: New. Wed Feb 10 17:15:39 CET 1999 Werner Koch * Makefile.am: Modules are now figured out by configure * construct.c: New. Generated by configure. Changed all modules to work with that. * sha1.h: Removed. * md5.h: Removed. * twofish.c: Changed interface to allow Twofish/256 * rndunix.c (start_gatherer): Die on SIGPIPE. Wed Jan 20 18:59:49 CET 1999 Werner Koch * rndunix.c (gather_random): Fix to avoid infinite loop. Sun Jan 17 11:04:33 CET 1999 Werner Koch * des.c (is_weak_key): Replace system memcmp due to bugs in SunOS's memcmp. (des_get_info): Return error on failed selftest. * twofish.c (twofish_setkey): Return error on failed selftest or invalid keylength. * cast5.c (cast_setkey): Ditto. * blowfish.c (bf_setkey): Return error on failed selftest. Tue Jan 12 11:17:18 CET 1999 Werner Koch * random.c (random_is_faked): New. * tiger.c: Only compile if we have the u64 type Sat Jan 9 16:02:23 CET 1999 Werner Koch * rndunix.c (gather_random): check for setuid. * Makefile.am: Add a way to staically link random modules Thu Jan 7 18:00:58 CET 1999 Werner Koch * md.c (md_stop_debug): Do a flush first. (md_open): size of buffer now depends on the secure parameter Sun Jan 3 15:28:44 CET 1999 Werner Koch * rndunix.c (start_gatherer): Fixed stupid ==/= bug 1998-12-31 Geoff Keating * des.c (is_weak_key): Rewrite loop end condition. Tue Dec 29 14:41:47 CET 1998 Werner Koch * random.c: add unistd.h for getpid(). (RAND_MAX): Fallback value for Sun. Wed Dec 23 17:12:24 CET 1998 Werner Koch * md.c (md_copy): Reset debug. Mon Dec 14 21:18:49 CET 1998 Werner Koch * random.c (read_random_source): Changed the interface to the random gathering function. (gather_faked): Use new interface. * dynload.c (dynload_getfnc_fast_random_poll): Ditto. (dynload_getfnc_gather_random): Ditto. * rndlinux.c (gather_random): Ditto. * rndunix.c (gather_random): Ditto. Sat Dec 12 18:40:32 CET 1998 Werner Koch * dynload.c (SYMBOL_VERSION): New to cope with system which needs underscores. * rndunix.c: Rewrote large parts Thu Dec 10 20:15:36 CET 1998 Werner Koch * dynload.c (load_extension): increased needed verbosity level. * random.c (fast_random_poll): Fallback to a default fast random poll function. (read_random_source): Always use the faked entroy gatherer if no gather module is available. * rndlinux.c (fast_poll): Removed. * rndunix.c (fast_poll): Removed. Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-*.c: Removed. * rndlinux.c : New. * rndunix.c : New. * random.c : Restructured the interface to the gather modules. (intialize): Call constructor functions (read_radnom_source): Moved to here. * dynload.c (dynload_getfnc_gather_random): New. (dynload_getfnc_fast_random_poll): New. (register_internal_cipher_extension): New. (register_cipher_extension): Support of internal modules. Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-unix.c (read_random_source): Removed the assert. Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) * pubkey.c: Hack to allow us to give some info about RSA keys back. Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) * dynload.c: Support for DLD Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-unix.c: Now uses names from configure for /dev/random. 1998-10-10 SL Baur * Makefile.am: fix sed -O substitutions to catch -O6, etc. Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c (md_digest): New. (md_reset): New. Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) * des.c: Some patches from Michael. Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) * des.c : New file from Michael Roth Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) * Makefile.am: Fixes to allow a different build directory Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) * random.c (get_random_byte): Removed and changed all callers to use get_random_bits() Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) * cipher.c : Support for other blocksizes (cipher_get_blocksize): New. * twofish.c: New. * Makefile.am: Add twofish module. Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) * random.c (read_pool): Simple alloc if secure_alloc is not set. (get_random_bits): Ditto. Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) * dynload.c (load_extension): Function now nbails out if the program is run setuid. Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) * rmd160.c (rmd160_hash_buffer): New. Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c (cipher_open): algos >=100 use standard CFB Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) * Makefile.am: Support for extensions Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) * random.c (mix_pool): simpler handling for level 0 Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) * tiger.c: Removed from dist, will reappear as dynload module Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) * pubkey.c: Major changes to allow extensions. Changed the inteface of all public key ciphers and added the ability to load extensions on demand. * misc.c: Removed. Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) * dynload.c: New. * cipher.c: Major changes to allow extensions. Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c: Major internal chnages to support extensions. * blowfish.c (blowfish_get_info): New and made all internal functions static, changed heder. * cast5.c (cast5_get_info): Likewise. Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) * tiger.c (transform): Fix for big endian * cipher.c (do_cfb_decrypt): Big endian fix. Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c (md_get_oid): Add a new one for TIGER. Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c: Add support for a dummy cipher Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) * rmd160.c (transform): fixed sigbus - I should better add Christian von Roques's new implemenation of rmd160_write. Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New * random.c: Moved system specific functions to rand-****.c Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) * random.c (fast_random_poll): add call to gethrtime. Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) * elgamal.c (elg_generate): choosing x was not correct, could yield 6 bytes which are not from the random pool, tsss, tsss.. Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) * primegen.c (generate_elg_prime): Add arg mode, changed all callers and implemented mode 1. Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c (cipher_get_keylen): New. Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) * tiger.c, tiger.h: New. Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) * misc.c (check_pubkey_algo2): New. Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c: New * misc.c (check_cipher_algo): Moved to cipher.c * cast5.c: Moved many functions to cipher.c * blowfish.c: Likewise. Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) * cast5.c: Implemented and tested. Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) * elgamal.c (elg_generate): Faster generation of x in some cases. Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) * blowfish.c (blowfish_decode_cfb): changed XOR operation (blowfish_encode_cfb): Ditto. Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) * sha1.c (transform): Rewrote * blowfish.c (encrypt): Unrolled for rounds == 16 (decrypt): Ditto. Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) * rmd160.c (transform): Unrolled the loop. Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) * random.c (read_pool): Add pool_balance stuff. (get_random_bits): New. * elgamal.c (elg_generate): Now uses get_random_bits to generate x. Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c (md_digest_length): New. Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) * dsa.c (dsa_verify): Works. Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) * dsa.c, dsa.h: Removed some unused code. Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c (md_open): Add call to fast_random_poll. blowfish.c (blowfish_setkey): Ditto. Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) * rmd160.c (rmd160_mixblock): New. * random.c: Restructured to start with a new RNG implementation. * random.h: New. Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) * gost.c, gost.h: Removed because they did only conatin trash. Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) * random.c (fill_buffer): removed error message if n == -1. Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c (md_enable): No init if called twice. Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) * primegen.c (generate_elg_prime): Changed the progress printing. (gen_prime): Ditto. Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) * md5.c, md.5 : Replaced by a modified version of md5.c from GNU textutils 1.22. Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) * md.c, md.h : New debugging support Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) * misc.c (cipher_algo_to_string): New (pubkey_algo_to_string): New. (digest_algo_to_string): New. diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 0d78e93d..217aa35e 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -1,98 +1,116 @@ +# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + # Process this file with automake to produce Makefile.in INCLUDES = -I$(top_srcdir)/src noinst_LTLIBRARIES = libcipher.la OMIT_DEPENDENCIES = types.h gcrypt.h # The configure script greps the module names from the EXTRA_PROGRAMS line EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger EXTRA_rndlinux_SOURCES = rndlinux.c EXTRA_rndunix_SOURCES = rndunix.c EXTRA_rndegd_SOURCES = rndegd.c EXTRA_rndw32_SOURCES = rndw32.c EXTRA_md5_SOURCES = md5.c EXTRA_rmd160_SOURCES = rmd160.c EXTRA_sha1_SOURCES = sha1.c EXTRA_tiger_SOURCES = tiger.c if ENABLE_GNUPG_EXTENSIONS pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@ else pkglib_PROGRAMS = endif DYNLINK_MOD_CFLAGS = -DIS_MODULE @DYNLINK_MOD_CFLAGS@ libcipher_la_LDFLAGS = libcipher_la_SOURCES = cipher.c \ pubkey.c \ md.c \ dynload.c \ dynload.h \ bithelp.h \ des.c \ des.h \ rijndael.c \ twofish.c \ blowfish.c \ blowfish.h \ cast5.c \ cast5.h \ arcfour.c arcfour.h \ elgamal.c \ elgamal.h \ primegen.c \ random.h \ random.c \ rand-internal.h \ rmd.h \ dsa.h \ dsa.c \ rsa.c rsa.h \ smallprime.c \ construct.c # configure creates the constructor file BUILT_SOURCES = construct.c libcipher_la_DEPENDENCIES = @STATIC_CIPHER_OBJS@ libcipher_la_LIBADD = @STATIC_CIPHER_OBJS@ # If I remember it correct, automake 1.4 has a feature to set # fooFLAGS depending on the program. So we should check it out. tiger: $(srcdir)/tiger.c `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \ sed -e 's/-O[2-9s]*/-O/g' ` tiger.o: $(srcdir)/tiger.c `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' ` #twofish: $(srcdir)/twofish.c # `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \ # sed -e 's/-O[0-9s]*/ /g' ` twofish: $(srcdir)/twofish.c $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c #twofish.o: $(srcdir)/twofish.c # `echo $(COMPILE) -c $(srcdir)/twofish.c | sed -e 's/-O[0-9s]*/ /g' ` rndunix: $(srcdir)/rndunix.c $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndunix $(srcdir)/rndunix.c rndlinux: $(srcdir)/rndlinux.c $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndlinux $(srcdir)/rndlinux.c rndegd: $(srcdir)/rndegd.c $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndegd $(srcdir)/rndegd.c diff --git a/cipher/arcfour.c b/cipher/arcfour.c index c19d282d..e9db410b 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -1,162 +1,191 @@ /* arcfour.c - The arcfour stream cipher * Copyright (C) 2000, 2001 Free Software Foundation, Inc. * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. * ISBN 0-471-11709-9. Pages 397 ff. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "arcfour.h" static const char *selftest(void); typedef struct { int idx_i, idx_j; byte sbox[256]; } ARCFOUR_context; static void -encrypt_stream( ARCFOUR_context *ctx, +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + +static void +do_encrypt_stream( ARCFOUR_context *ctx, byte *outbuf, const byte *inbuf, unsigned int length ) { int t; int i = ctx->idx_i; int j = ctx->idx_j; byte *sbox = ctx->sbox; while ( length-- ) { i = (i+1) % 256; j = (j + sbox[i]) % 256; t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) % 256]; } ctx->idx_i = i; ctx->idx_j = j; } +static void +encrypt_stream( ARCFOUR_context *ctx, + byte *outbuf, const byte *inbuf, unsigned int length ) +{ + + do_encrypt_stream (ctx, outbuf, inbuf, length ); + burn_stack (64); +} + static int -arcfour_setkey( ARCFOUR_context *ctx, const byte *key, unsigned int keylen ) +do_arcfour_setkey( ARCFOUR_context *ctx, const byte *key, unsigned int keylen ) { static int initialized; static const char* selftest_failed; int i, j; byte karr[256]; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) fprintf(stderr,"ARCFOUR selftest failed (%s)\n", selftest_failed ); } if( selftest_failed ) return GCRYERR_SELFTEST; if( keylen < 40/8 ) /* we want at least 40 bits */ return GCRYERR_INV_KEYLEN; ctx->idx_i = ctx->idx_j = 0; for (i=0; i < 256; i++ ) ctx->sbox[i] = i; for (i=0; i < 256; i++ ) karr[i] = key[i%keylen]; for (i=j=0; i < 256; i++ ) { int t; j = (j + ctx->sbox[i] + karr[i]) % 256; t = ctx->sbox[i]; ctx->sbox[i] = ctx->sbox[j]; ctx->sbox[j] = t; } memset( karr, 0, 256 ); return 0; } +static int +arcfour_setkey ( ARCFOUR_context *ctx, const byte *key, unsigned int keylen ) +{ + int rc = do_arcfour_setkey (ctx, key, keylen ); + burn_stack (300); + return rc; +} + static const char* selftest(void) { ARCFOUR_context ctx; byte scratch[16]; /* Test vector from Cryptlib labeled there: * "from the State/Commerce Department" */ static const byte key_1[] = { 0x61, 0x8A, 0x63, 0xD2, 0xFB }; static const byte plaintext_1[] = { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C }; static const byte ciphertext_1[] = { 0xF1, 0x38, 0x29, 0xC9, 0xDE }; arcfour_setkey( &ctx, key_1, sizeof(key_1)); encrypt_stream( &ctx, scratch, plaintext_1, sizeof(plaintext_1)); if (memcmp (scratch, ciphertext_1, sizeof (ciphertext_1))) return "Arcfour encryption test 1 failed."; arcfour_setkey( &ctx, key_1, sizeof(key_1)); encrypt_stream(&ctx, scratch, scratch, sizeof(plaintext_1)); /* decrypt */ if ( memcmp (scratch, plaintext_1, sizeof (plaintext_1))) return "Arcfour decryption test 1 failed."; return NULL; } /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. * NOTE: This is a special get_info function which is different from all * others because arcfour is a stream cipher. We use this hack until * we have redesign the interface. */ const char * _gcry_arcfour_get_info( int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey)( void *c, byte *key, unsigned keylen ), void (**r_stencrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int nbytes ), void (**r_stdecrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int nbytes ) ) { *keylen = 128; /* arbitrary value */ *blocksize = 1; *contextsize = sizeof(ARCFOUR_context); *(int (**)(ARCFOUR_context*, const byte*, unsigned))r_setkey = arcfour_setkey; *(void (**)(ARCFOUR_context*, byte*, const byte*, unsigned))r_stencrypt = encrypt_stream; *(void (**)(ARCFOUR_context*, byte*, const byte*, unsigned))r_stdecrypt = encrypt_stream; if( algo == 301 ) return "ARCFOUR"; return NULL; } diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 0847de38..dc8e3feb 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -1,598 +1,632 @@ /* blowfish.c - Blowfish encryption - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. * ISBN 0-471-11709-9. Pages 336 ff. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Test values: * key "abcdefghijklmnopqrstuvwxyz"; * plain "BLOWFISH" * cipher 32 4E D0 FE F4 13 A2 03 * */ #include #include #include #include #include #include "types.h" #include "g10lib.h" #include "blowfish.h" #include "dynload.h" #define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ #define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f) #define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f) #define BLOWFISH_BLOCKSIZE 8 #define BLOWFISH_ROUNDS 16 typedef struct { u32 s0[256]; u32 s1[256]; u32 s2[256]; u32 s3[256]; u32 p[BLOWFISH_ROUNDS+2]; } BLOWFISH_context; static int bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ); static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); /* precomputed S boxes */ static const u32 ks0[256] = { 0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96, 0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16, 0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658, 0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013, 0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E, 0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60, 0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6, 0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A, 0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C, 0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193, 0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1, 0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239, 0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A, 0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3, 0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176, 0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE, 0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706, 0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B, 0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B, 0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463, 0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C, 0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3, 0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A, 0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8, 0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760, 0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB, 0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8, 0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B, 0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33, 0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4, 0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0, 0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C, 0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777, 0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299, 0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705, 0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF, 0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E, 0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA, 0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9, 0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915, 0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F, 0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664, 0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A }; static const u32 ks1[256] = { 0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D, 0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1, 0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65, 0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1, 0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9, 0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737, 0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D, 0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD, 0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC, 0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41, 0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908, 0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF, 0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124, 0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C, 0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908, 0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD, 0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B, 0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E, 0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA, 0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A, 0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D, 0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66, 0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5, 0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84, 0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96, 0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14, 0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA, 0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7, 0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77, 0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99, 0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054, 0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73, 0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA, 0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105, 0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646, 0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285, 0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA, 0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB, 0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E, 0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC, 0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD, 0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20, 0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 }; static const u32 ks2[256] = { 0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7, 0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF, 0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF, 0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504, 0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4, 0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE, 0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC, 0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B, 0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332, 0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527, 0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58, 0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C, 0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22, 0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17, 0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60, 0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115, 0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99, 0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0, 0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74, 0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D, 0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3, 0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3, 0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979, 0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C, 0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA, 0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A, 0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086, 0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC, 0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24, 0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2, 0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84, 0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C, 0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09, 0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10, 0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE, 0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027, 0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0, 0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634, 0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188, 0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC, 0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8, 0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837, 0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 }; static const u32 ks3[256] = { 0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742, 0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B, 0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79, 0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6, 0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A, 0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4, 0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1, 0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59, 0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797, 0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28, 0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6, 0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28, 0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA, 0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A, 0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5, 0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F, 0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE, 0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680, 0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD, 0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB, 0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB, 0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370, 0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC, 0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048, 0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC, 0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9, 0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A, 0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F, 0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A, 0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1, 0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B, 0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E, 0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E, 0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F, 0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623, 0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC, 0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A, 0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6, 0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3, 0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060, 0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C, 0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F, 0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 }; static const u32 ps[BLOWFISH_ROUNDS+2] = { 0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0, 0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C, 0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B }; #if BLOWFISH_ROUNDS != 16 static inline u32 function_F( BLOWFISH_context *bc, u32 x ) { u16 a, b, c, d; #ifdef BIG_ENDIAN_HOST a = ((byte*)&x)[0]; b = ((byte*)&x)[1]; c = ((byte*)&x)[2]; d = ((byte*)&x)[3]; #else a = ((byte*)&x)[3]; b = ((byte*)&x)[2]; c = ((byte*)&x)[1]; d = ((byte*)&x)[0]; #endif return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d]; } #endif #ifdef BIG_ENDIAN_HOST #define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \ ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] ) #else #define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \ ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] ) #endif #define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) +static void +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + static void do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { #if BLOWFISH_ROUNDS == 16 u32 xl, xr, *s0, *s1, *s2, *s3, *p; xl = *ret_xl; xr = *ret_xr; p = bc->p; s0 = bc->s0; s1 = bc->s1; s2 = bc->s2; s3 = bc->s3; R( xl, xr, 0); R( xr, xl, 1); R( xl, xr, 2); R( xr, xl, 3); R( xl, xr, 4); R( xr, xl, 5); R( xl, xr, 6); R( xr, xl, 7); R( xl, xr, 8); R( xr, xl, 9); R( xl, xr, 10); R( xr, xl, 11); R( xl, xr, 12); R( xr, xl, 13); R( xl, xr, 14); R( xr, xl, 15); xl ^= p[BLOWFISH_ROUNDS]; xr ^= p[BLOWFISH_ROUNDS+1]; *ret_xl = xr; *ret_xr = xl; #else u32 xl, xr, temp, *p; int i; xl = *ret_xl; xr = *ret_xr; p = bc->p; for(i=0; i < BLOWFISH_ROUNDS; i++ ) { xl ^= p[i]; xr ^= function_F(bc, xl); temp = xl; xl = xr; xr = temp; } temp = xl; xl = xr; xr = temp; xr ^= p[BLOWFISH_ROUNDS]; xl ^= p[BLOWFISH_ROUNDS+1]; *ret_xl = xl; *ret_xr = xr; #endif } static void decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { #if BLOWFISH_ROUNDS == 16 u32 xl, xr, *s0, *s1, *s2, *s3, *p; xl = *ret_xl; xr = *ret_xr; p = bc->p; s0 = bc->s0; s1 = bc->s1; s2 = bc->s2; s3 = bc->s3; R( xl, xr, 17); R( xr, xl, 16); R( xl, xr, 15); R( xr, xl, 14); R( xl, xr, 13); R( xr, xl, 12); R( xl, xr, 11); R( xr, xl, 10); R( xl, xr, 9); R( xr, xl, 8); R( xl, xr, 7); R( xr, xl, 6); R( xl, xr, 5); R( xr, xl, 4); R( xl, xr, 3); R( xr, xl, 2); xl ^= p[1]; xr ^= p[0]; *ret_xl = xr; *ret_xr = xl; #else u32 xl, xr, temp, *p; int i; xl = *ret_xl; xr = *ret_xr; p = bc->p; for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) { xl ^= p[i]; xr ^= function_F(bc, xl); temp = xl; xl = xr; xr = temp; } temp = xl; xl = xr; xr = temp; xr ^= p[1]; xl ^= p[0]; *ret_xl = xl; *ret_xr = xr; #endif } #undef F #undef R static void -encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; do_encrypt( bc, &d1, &d2 ); outbuf[0] = (d1 >> 24) & 0xff; outbuf[1] = (d1 >> 16) & 0xff; outbuf[2] = (d1 >> 8) & 0xff; outbuf[3] = d1 & 0xff; outbuf[4] = (d2 >> 24) & 0xff; outbuf[5] = (d2 >> 16) & 0xff; outbuf[6] = (d2 >> 8) & 0xff; outbuf[7] = d2 & 0xff; } +static void +encrypt_block ( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +{ + do_encrypt_block (bc, outbuf, inbuf); + burn_stack (64); +} + static void -decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; decrypt( bc, &d1, &d2 ); outbuf[0] = (d1 >> 24) & 0xff; outbuf[1] = (d1 >> 16) & 0xff; outbuf[2] = (d1 >> 8) & 0xff; outbuf[3] = d1 & 0xff; outbuf[4] = (d2 >> 24) & 0xff; outbuf[5] = (d2 >> 16) & 0xff; outbuf[6] = (d2 >> 8) & 0xff; outbuf[7] = d2 & 0xff; } +static void +decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +{ + do_decrypt_block (bc, outbuf, inbuf); + burn_stack (64); +} + static const char* selftest(void) { BLOWFISH_context c; byte plain[] = "BLOWFISH"; byte buffer[8]; byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; bf_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); encrypt_block( &c, buffer, plain ); if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) return "Blowfish selftest failed (1)."; decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) return "Blowfish selftest failed (2)."; bf_setkey( &c, key3, 8 ); encrypt_block( &c, buffer, plain3 ); if( memcmp( buffer, cipher3, 8 ) ) return "Blowfish selftest failed (3)."; decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain3, 8 ) ) return "Blowfish selftest failed (4)."; return NULL; } static int -bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) +do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) { int i, j; u32 data, datal, datar; static int initialized; static const char *selftest_failed; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) fprintf(stderr,"%s\n", selftest_failed ); } if( selftest_failed ) return GCRYERR_SELFTEST; for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; for(i=0; i < 256; i++ ) { c->s0[i] = ks0[i]; c->s1[i] = ks1[i]; c->s2[i] = ks2[i]; c->s3[i] = ks3[i]; } for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { #ifdef BIG_ENDIAN_HOST ((byte*)&data)[0] = key[j]; ((byte*)&data)[1] = key[(j+1)%keylen]; ((byte*)&data)[2] = key[(j+2)%keylen]; ((byte*)&data)[3] = key[(j+3)%keylen]; #else ((byte*)&data)[3] = key[j]; ((byte*)&data)[2] = key[(j+1)%keylen]; ((byte*)&data)[1] = key[(j+2)%keylen]; ((byte*)&data)[0] = key[(j+3)%keylen]; #endif c->p[i] ^= data; j = (j+4) % keylen; } datal = datar = 0; for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) { do_encrypt( c, &datal, &datar ); c->p[i] = datal; c->p[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s0[i] = datal; c->s0[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s1[i] = datal; c->s1[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s2[i] = datal; c->s2[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s3[i] = datal; c->s3[i+1] = datar; } /* Check for weak key. A weak key is a key in which a value in */ /* the P-array (here c) occurs more than once per table. */ for(i=0; i < 255; i++ ) { for( j=i+1; j < 256; j++) { if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) return GCRYERR_WEAK_KEY; } } return 0; } +static int +bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) +{ + int rc = do_bf_setkey (c, key, keylen); + burn_stack (64); + return rc; +} + + /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ const char * _gcry_blowfish_get_info( int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey)( void *c, byte *key, unsigned keylen ), void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) ) { *keylen = 128; *blocksize = BLOWFISH_BLOCKSIZE; *contextsize = sizeof(BLOWFISH_context); *(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey = bf_setkey; *(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt = encrypt_block; *(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt = decrypt_block; if( algo == CIPHER_ALGO_BLOWFISH ) return "BLOWFISH"; return NULL; } diff --git a/cipher/cast5.c b/cipher/cast5.c index 9811c455..e5ffaa97 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -1,625 +1,661 @@ /* cast5.c - CAST5 cipher (RFC2144) - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Test vectors: * * 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = 23 8B 4F E5 84 7E 44 B2 * * 80-bit key = 01 23 45 67 12 34 56 78 23 45 * = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00 * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = EB 6A 71 1A 2C 02 27 1B * * 40-bit key = 01 23 45 67 12 * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00 * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = 7A C8 16 D1 6E 9B 30 2E */ #include #include #include #include #include "g10lib.h" #include "types.h" #include "cast5.h" #define CIPHER_ALGO_CAST5 3 #define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f) #define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f) #define CAST5_BLOCKSIZE 8 typedef struct { u32 Km[16]; byte Kr[16]; } CAST5_context; static int cast_setkey( CAST5_context *c, byte *key, unsigned keylen ); static void encrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); static void decrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); static const u32 s1[256] = { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf }; static const u32 s2[256] = { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 }; static const u32 s3[256] = { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 }; static const u32 s4[256] = { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 }; static const u32 s5[256] = { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 }; static const u32 s6[256] = { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f }; static const u32 s7[256] = { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 }; static const u32 s8[256] = { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e }; #if defined(__GNUC__) && defined(__i386__) static inline u32 rol(int n, u32 x) { __asm__("roll %%cl,%0" :"=r" (x) :"0" (x),"c" (n)); return x; } #else #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif #define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) #define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) #define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) static void -encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + +static void +do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { u32 l, r, t; u32 I; /* used by the Fx macros */ u32 *Km; byte *Kr; Km = c->Km; Kr = c->Kr; /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) */ l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: * Li = Ri-1; * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. * Rounds 2, 5, 8, 11, and 14 use f function Type 2. * Rounds 3, 6, 9, 12, and 15 use f function Type 3. */ t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and * concatenate to form the ciphertext.) */ outbuf[0] = (r >> 24) & 0xff; outbuf[1] = (r >> 16) & 0xff; outbuf[2] = (r >> 8) & 0xff; outbuf[3] = r & 0xff; outbuf[4] = (l >> 24) & 0xff; outbuf[5] = (l >> 16) & 0xff; outbuf[6] = (l >> 8) & 0xff; outbuf[7] = l & 0xff; } static void -decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) +encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) +{ + do_encrypt_block (c, outbuf, inbuf); + burn_stack (20+4*sizeof(void*)); +} + + + +static void +do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf ) { u32 l, r, t; u32 I; u32 *Km; byte *Kr; Km = c->Km; Kr = c->Kr; l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); outbuf[0] = (r >> 24) & 0xff; outbuf[1] = (r >> 16) & 0xff; outbuf[2] = (r >> 8) & 0xff; outbuf[3] = r & 0xff; outbuf[4] = (l >> 24) & 0xff; outbuf[5] = (l >> 16) & 0xff; outbuf[6] = (l >> 8) & 0xff; outbuf[7] = l & 0xff; } - +static void +decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) +{ + do_decrypt_block (c, outbuf, inbuf); + burn_stack (20+4*sizeof(void*)); +} + static const char* selftest(void) { CAST5_context c; byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; byte buffer[8]; cast_setkey( &c, key, 16 ); encrypt_block( &c, buffer, plain ); if( memcmp( buffer, cipher, 8 ) ) return "1"; decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) return "2"; #if 0 /* full maintenance test */ { int i; byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6, 0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 }; byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71, 0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E }; for(i=0; i < 1000000; i++ ) { cast_setkey( &c, b0, 16 ); encrypt_block( &c, a0, a0 ); encrypt_block( &c, a0+8, a0+8 ); cast_setkey( &c, a0, 16 ); encrypt_block( &c, b0, b0 ); encrypt_block( &c, b0+8, b0+8 ); } if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) ) return "3"; } #endif return NULL; } + static void key_schedule( u32 *x, u32 *z, u32 *k ) { #define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) #define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)]; k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)]; k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)]; k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)]; x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)]; k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)]; k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)]; k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)]; z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)]; k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)]; k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)]; k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)]; x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)]; k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)]; k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)]; k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)]; #undef xi #undef zi } static int -cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) +do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) { static int initialized; static const char* selftest_failed; int i; u32 x[4]; u32 z[4]; u32 k[16]; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) fprintf(stderr,"CAST5 selftest failed (%s).\n", selftest_failed ); } if( selftest_failed ) return GCRYERR_SELFTEST; if( keylen != 16 ) return GCRYERR_INV_KEYLEN; x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; key_schedule( x, z, k ); for(i=0; i < 16; i++ ) c->Km[i] = k[i]; key_schedule( x, z, k ); for(i=0; i < 16; i++ ) c->Kr[i] = k[i] & 0x1f; memset(&x,0, sizeof x); memset(&z,0, sizeof z); memset(&k,0, sizeof k); #undef xi #undef zi return 0; } +static int +cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) +{ + int rc = do_cast_setkey (c, key, keylen); + burn_stack (96+7*sizeof(void*)); + return rc; +} + /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ const char * _gcry_cast5_get_info( int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey)( void *c, byte *key, unsigned keylen ), void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) ) { *keylen = 128; *blocksize = CAST5_BLOCKSIZE; *contextsize = sizeof(CAST5_context); *(int (**)(CAST5_context*, byte*, unsigned))r_setkey = cast_setkey; *(void (**)(CAST5_context*, byte*, byte*))r_encrypt = encrypt_block; *(void (**)(CAST5_context*, byte*, byte*))r_decrypt = decrypt_block; if( algo == CIPHER_ALGO_CAST5 ) return "CAST5"; return NULL; } diff --git a/cipher/cipher.c b/cipher/cipher.c index 0dfe8661..a5afdc01 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1,950 +1,977 @@ /* cipher.c - cipher dispatcher * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "des.h" #include "blowfish.h" #include "cast5.h" #include "arcfour.h" #include "dynload.h" #define MAX_BLOCKSIZE 16 #define TABLE_SIZE 14 #define CTX_MAGIC_NORMAL 0x24091964 #define CTX_MAGIC_SECURE 0x46919042 struct cipher_table_s { const char *name; int algo; size_t blocksize; size_t keylen; size_t contextsize; /* allocate this amount of context */ int (*setkey)( void *c, byte *key, unsigned keylen ); void (*encrypt)( void *c, byte *outbuf, byte *inbuf ); void (*decrypt)( void *c, byte *outbuf, byte *inbuf ); void (*stencrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int n ); void (*stdecrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int n ); }; static struct cipher_table_s cipher_table[TABLE_SIZE]; static int disabled_algos[TABLE_SIZE]; struct gcry_cipher_handle { int magic; int algo; int mode; unsigned int flags; size_t blocksize; byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */ byte lastiv[MAX_BLOCKSIZE]; int unused; /* in IV */ int (*setkey)( void *c, byte *key, unsigned keylen ); void (*encrypt)( void *c, byte *outbuf, byte *inbuf ); void (*decrypt)( void *c, byte *outbuf, byte *inbuf ); void (*stencrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int n ); void (*stdecrypt)( void *c, byte *outbuf, byte *inbuf, unsigned int n ); PROPERLY_ALIGNED_TYPE context; }; static int dummy_setkey( void *c, byte *key, unsigned keylen ) { return 0; } static void dummy_encrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); } static void dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); } static void dummy_encrypt_stream( void *c, byte *outbuf, byte *inbuf, unsigned int n ) { BUG(); } static void dummy_decrypt_stream( void *c, byte *outbuf, byte *inbuf, unsigned int n ) { BUG(); } /**************** * Put the static entries into the table. */ static void setup_cipher_table(void) { int i; for (i=0; i < TABLE_SIZE; i++ ) { cipher_table[i].encrypt = dummy_encrypt_block; cipher_table[i].decrypt = dummy_decrypt_block; cipher_table[i].stencrypt = dummy_encrypt_stream; cipher_table[i].stdecrypt = dummy_decrypt_stream; } i = 0; cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL; cipher_table[i].name = _gcry_rijndael_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL192; cipher_table[i].name = _gcry_rijndael_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL256; cipher_table[i].name = _gcry_rijndael_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_TWOFISH; cipher_table[i].name = _gcry_twofish_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_BLOWFISH; cipher_table[i].name = _gcry_blowfish_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_CAST5; cipher_table[i].name = _gcry_cast5_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_3DES; cipher_table[i].name = _gcry_des_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].encrypt, &cipher_table[i].decrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = GCRY_CIPHER_ARCFOUR; cipher_table[i].name = _gcry_arcfour_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, &cipher_table[i].contextsize, &cipher_table[i].setkey, &cipher_table[i].stencrypt, &cipher_table[i].stdecrypt ); if( !cipher_table[i].name ) BUG(); i++; cipher_table[i].algo = CIPHER_ALGO_DUMMY; cipher_table[i].name = "DUMMY"; cipher_table[i].blocksize = 8; cipher_table[i].keylen = 128; cipher_table[i].contextsize = 0; cipher_table[i].setkey = dummy_setkey; i++; for( ; i < TABLE_SIZE; i++ ) cipher_table[i].name = NULL; } /**************** * Try to load all modules and return true if new modules are available */ static int load_cipher_modules(void) { static int done = 0; static int initialized = 0; void *context = NULL; struct cipher_table_s *ct; int ct_idx; int i; const char *name; int any = 0; if( !initialized ) { _gcry_cipher_modules_constructor(); setup_cipher_table(); /* load static modules on the first call */ initialized = 1; return 1; } if( done ) return 0; done = 1; for(ct_idx=0, ct = cipher_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) { if( !ct->name ) break; } if( ct_idx >= TABLE_SIZE-1 ) BUG(); /* table already full */ /* now load all extensions */ while( (name = _gcry_enum_gnupgext_ciphers( &context, &ct->algo, &ct->keylen, &ct->blocksize, &ct->contextsize, &ct->setkey, &ct->encrypt, &ct->decrypt)) ) { if( ct->blocksize != 8 && ct->blocksize != 16 ) { log_info("skipping cipher %d: unsupported blocksize\n", ct->algo); continue; } for(i=0; cipher_table[i].name; i++ ) if( cipher_table[i].algo == ct->algo ) break; if( cipher_table[i].name ) { log_info("skipping cipher %d: already loaded\n", ct->algo ); continue; } /* put it into the table */ if( _gcry_log_verbosity( 2 ) ) log_info("loaded cipher %d (%s)\n", ct->algo, name); ct->name = name; ct_idx++; ct++; any = 1; /* check whether there are more available table slots */ if( ct_idx >= TABLE_SIZE-1 ) { log_info("cipher table full; ignoring other extensions\n"); break; } } _gcry_enum_gnupgext_ciphers( &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); return any; } /**************** * Map a string to the cipher algo. * Returns: The algo ID of the cipher for the gioven name or * 0 if the name is not known. */ int gcry_cipher_map_name( const char *string ) { int i; const char *s; do { for(i=0; (s=cipher_table[i].name); i++ ) if( !stricmp( s, string ) ) return cipher_table[i].algo; } while( load_cipher_modules() ); return 0; } /**************** * Map a cipher algo to a string */ static const char * cipher_algo_to_string( int algo ) { int i; do { for(i=0; cipher_table[i].name; i++ ) if( cipher_table[i].algo == algo ) return cipher_table[i].name; } while( load_cipher_modules() ); return NULL; } /**************** * This function simply returns the name of the algorithm or some constant * string when there is no algo. It will never return NULL. */ const char * gcry_cipher_algo_name( int algo ) { const char *s = cipher_algo_to_string( algo ); return s? s: ""; } static void disable_cipher_algo( int algo ) { int i; for(i=0; i < DIM(disabled_algos); i++ ) { if( !disabled_algos[i] || disabled_algos[i] == algo ) { disabled_algos[i] = algo; return; } } /* fixme: we should use a linked list */ log_fatal("can't disable cipher algo %d: table full\n", algo ); } /**************** * Return 0 if the cipher algo is available */ static int check_cipher_algo( int algo ) { int i; do { for(i=0; cipher_table[i].name; i++ ) if( cipher_table[i].algo == algo ) { for(i=0; i < DIM(disabled_algos); i++ ) { if( disabled_algos[i] == algo ) return GCRYERR_INV_CIPHER_ALGO; } return 0; /* okay */ } } while( load_cipher_modules() ); return GCRYERR_INV_CIPHER_ALGO; } static unsigned cipher_get_keylen( int algo ) { int i; unsigned len = 0; do { for(i=0; cipher_table[i].name; i++ ) { if( cipher_table[i].algo == algo ) { len = cipher_table[i].keylen; if( !len ) log_bug("cipher %d w/o key length\n", algo ); return len; } } } while( load_cipher_modules() ); log_bug("cipher %d not found\n", algo ); return 0; } static unsigned cipher_get_blocksize( int algo ) { int i; unsigned len = 0; do { for(i=0; cipher_table[i].name; i++ ) { if( cipher_table[i].algo == algo ) { len = cipher_table[i].blocksize; if( !len ) log_bug("cipher %d w/o blocksize\n", algo ); return len; } } } while( load_cipher_modules() ); log_bug("cipher %d not found\n", algo ); return 0; } /**************** * Open a cipher handle for use with algorithm ALGO, in mode MODE * and return the handle. Return NULL and set the internal error variable * if something goes wrong. */ GCRY_CIPHER_HD gcry_cipher_open( int algo, int mode, unsigned int flags ) { GCRY_CIPHER_HD h; int idx; int secure = (flags & GCRY_CIPHER_SECURE); fast_random_poll(); /* check whether the algo is available */ if( check_cipher_algo( algo ) ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); return NULL; } /* check flags */ if( (flags & ~(GCRY_CIPHER_SECURE|GCRY_CIPHER_ENABLE_SYNC)) ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); return NULL; } /* get the table index of the algo */ for(idx=0; cipher_table[idx].name; idx++ ) if( cipher_table[idx].algo == algo ) break; if( !cipher_table[idx].name ) BUG(); /* check_cipher_algo() should have loaded the algo */ if( algo == CIPHER_ALGO_DUMMY ) mode = GCRY_CIPHER_MODE_NONE; /* force this mode for dummy algo */ /* check that a valid mode has been requested */ switch( mode ) { case GCRY_CIPHER_MODE_ECB: case GCRY_CIPHER_MODE_CBC: case GCRY_CIPHER_MODE_CFB: if ( cipher_table[idx].encrypt == dummy_encrypt_block || cipher_table[idx].decrypt == dummy_decrypt_block ) { set_lasterr( GCRYERR_INV_CIPHER_MODE ); return NULL; } break; case GCRY_CIPHER_MODE_STREAM: if ( cipher_table[idx].stencrypt == dummy_encrypt_stream || cipher_table[idx].stdecrypt == dummy_decrypt_stream ) { set_lasterr( GCRYERR_INV_CIPHER_MODE ); return NULL; } break; case GCRY_CIPHER_MODE_NONE: /* FIXME: issue a warning when this mode is used */ break; default: set_lasterr( GCRYERR_INV_CIPHER_MODE ); return NULL; } /* ? perform selftest here and mark this with a flag in cipher_table ? */ h = secure ? gcry_calloc_secure( 1, sizeof *h + cipher_table[idx].contextsize - sizeof(PROPERLY_ALIGNED_TYPE) ) : gcry_calloc( 1, sizeof *h + cipher_table[idx].contextsize - sizeof(PROPERLY_ALIGNED_TYPE) ); if( !h ) { set_lasterr( GCRYERR_NO_MEM ); return NULL; } h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; h->algo = algo; h->mode = mode; h->flags = flags; h->blocksize = cipher_table[idx].blocksize; h->setkey = cipher_table[idx].setkey; h->encrypt = cipher_table[idx].encrypt; h->decrypt = cipher_table[idx].decrypt; h->stencrypt = cipher_table[idx].stencrypt; h->stdecrypt = cipher_table[idx].stdecrypt; return h; } void gcry_cipher_close( GCRY_CIPHER_HD h ) { if( !h ) return; if( h->magic != CTX_MAGIC_SECURE && h->magic != CTX_MAGIC_NORMAL ) _gcry_fatal_error(GCRYERR_INTERNAL, "gcry_cipher_close: already closed/invalid handle"); h->magic = 0; gcry_free(h); } static int cipher_setkey( GCRY_CIPHER_HD c, byte *key, unsigned keylen ) { return (*c->setkey)( &c->context.c, key, keylen ); } static void cipher_setiv( GCRY_CIPHER_HD c, const byte *iv, unsigned ivlen ) { memset( c->iv, 0, c->blocksize ); if( iv ) { if( ivlen != c->blocksize ) log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", ivlen, (unsigned)c->blocksize ); if( ivlen > c->blocksize ) ivlen = c->blocksize; memcpy( c->iv, iv, ivlen ); } c->unused = 0; } static void do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) { unsigned n; for(n=0; n < nblocks; n++ ) { (*c->encrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); inbuf += c->blocksize; outbuf += c->blocksize; } } static void do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) { unsigned n; for(n=0; n < nblocks; n++ ) { (*c->decrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); inbuf += c->blocksize; outbuf += c->blocksize; } } static void do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) { unsigned int n; byte *ivp; int i; size_t blocksize = c->blocksize; for(n=0; n < nblocks; n++ ) { /* fixme: the xor should works on words and not on * bytes. Maybe it is a good idea to enhance the cipher backend * API to allow for CBC handling in the backend */ for(ivp=c->iv,i=0; i < blocksize; i++ ) outbuf[i] = inbuf[i] ^ *ivp++; (*c->encrypt)( &c->context.c, outbuf, outbuf ); memcpy(c->iv, outbuf, blocksize ); inbuf += c->blocksize; outbuf += c->blocksize; } } static void do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks ) { unsigned int n; byte *ivp; int i; size_t blocksize = c->blocksize; for(n=0; n < nblocks; n++ ) { /* because outbuf and inbuf might be the same, we have * to save the original ciphertext block. We use lastiv * for this here because it is not used otherwise */ memcpy(c->lastiv, inbuf, blocksize ); (*c->decrypt)( &c->context.c, outbuf, (char*)/*argggg*/inbuf ); for(ivp=c->iv,i=0; i < blocksize; i++ ) outbuf[i] ^= *ivp++; memcpy(c->iv, c->lastiv, blocksize ); inbuf += c->blocksize; outbuf += c->blocksize; } } static void do_cfb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes ) { byte *ivp; size_t blocksize = c->blocksize; if( nbytes <= c->unused ) { /* short enough to be encoded by the remaining XOR mask */ /* XOR the input with the IV and store input into IV */ for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); return; } if( c->unused ) { /* XOR the input with the IV and store input into IV */ nbytes -= c->unused; for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } /* now we can process complete blocks */ while( nbytes >= blocksize ) { int i; /* encrypt the IV (and save the current one) */ memcpy( c->lastiv, c->iv, blocksize ); (*c->encrypt)( &c->context.c, c->iv, c->iv ); /* XOR the input with the IV and store input into IV */ for(ivp=c->iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^= *inbuf++); nbytes -= blocksize; } if( nbytes ) { /* process the remaining bytes */ /* encrypt the IV (and save the current one) */ memcpy( c->lastiv, c->iv, blocksize ); (*c->encrypt)( &c->context.c, c->iv, c->iv ); c->unused = blocksize; /* and apply the xor */ c->unused -= nbytes; for(ivp=c->iv; nbytes; nbytes-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } } static void do_cfb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes ) { byte *ivp; ulong temp; size_t blocksize = c->blocksize; if( nbytes <= c->unused ) { /* short enough to be encoded by the remaining XOR mask */ /* XOR the input with the IV and store input into IV */ for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){ temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } return; } if( c->unused ) { /* XOR the input with the IV and store input into IV */ nbytes -= c->unused; for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } } /* now we can process complete blocks */ while( nbytes >= blocksize ) { int i; /* encrypt the IV (and save the current one) */ memcpy( c->lastiv, c->iv, blocksize ); (*c->encrypt)( &c->context.c, c->iv, c->iv ); /* XOR the input with the IV and store input into IV */ for(ivp=c->iv,i=0; i < blocksize; i++ ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } nbytes -= blocksize; } if( nbytes ) { /* process the remaining bytes */ /* encrypt the IV (and save the current one) */ memcpy( c->lastiv, c->iv, blocksize ); (*c->encrypt)( &c->context.c, c->iv, c->iv ); c->unused = blocksize; /* and apply the xor */ c->unused -= nbytes; for(ivp=c->iv; nbytes; nbytes-- ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } } } /**************** * Encrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. * Depending on the mode some contraints apply to NBYTES. */ -static void +static int cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned int nbytes ) { + int rc = 0; + switch( c->mode ) { case GCRY_CIPHER_MODE_ECB: - assert(!(nbytes%c->blocksize)); - do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize)) + do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + else + rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CBC: - assert(!(nbytes%c->blocksize)); - do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize)) + do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + else + rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CFB: do_cfb_encrypt(c, outbuf, inbuf, nbytes ); break; case GCRY_CIPHER_MODE_STREAM: (*c->stencrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf, nbytes ); break; case GCRY_CIPHER_MODE_NONE: if( inbuf != outbuf ) memmove( outbuf, inbuf, nbytes ); break; - default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); + default: + log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); + rc = GCRYERR_INV_CIPHER_MODE; + break; } + return rc; } /**************** * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has * been requested, */ int gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, const byte *in, size_t inlen ) { - if( !in ) { + int rc; + + if ( !in ) { /* caller requested in-place encryption */ /* actullay cipher_encrypt() does not need to know about it, but * we may chnage this to get better performace */ - cipher_encrypt( h, out, out, outsize ); + rc = cipher_encrypt ( h, out, out, outsize ); } else { - if( outsize < inlen ) - return set_lasterr( GCRYERR_TOO_SHORT ); + if ( outsize < inlen ) + return set_lasterr ( GCRYERR_TOO_SHORT ); /* fixme: check that the inlength is a multipe of the blocksize * if a blockoriented mode is used, or modify cipher_encrypt to * return an error in this case */ - cipher_encrypt( h, out, in, inlen ); + rc = cipher_encrypt ( h, out, in, inlen ); } - return 0; + + return rc? set_lasterr (rc):0; } /**************** * Decrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. * Depending on the mode some some contraints apply to NBYTES. */ -static void +static int cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes ) { + int rc = 0; + switch( c->mode ) { case GCRY_CIPHER_MODE_ECB: - assert(!(nbytes%c->blocksize)); - do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize)) + do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + else + rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CBC: - assert(!(nbytes%c->blocksize)); - do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + if (!(nbytes%c->blocksize)) + do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); + else + rc = GCRYERR_INV_ARG; break; case GCRY_CIPHER_MODE_CFB: do_cfb_decrypt(c, outbuf, inbuf, nbytes ); break; case GCRY_CIPHER_MODE_STREAM: (*c->stdecrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf, nbytes ); break; case GCRY_CIPHER_MODE_NONE: if( inbuf != outbuf ) memmove( outbuf, inbuf, nbytes ); break; - default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode ); + default: + log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); + rc = GCRYERR_INV_CIPHER_MODE; + break; } + return rc; } int gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, const byte *in, size_t inlen ) { + int rc; + if( !in ) { /* caller requested in-place encryption */ /* actullay cipher_encrypt() does not need to know about it, but * we may chnage this to get better performace */ - cipher_decrypt( h, out, out, outsize ); + rc = cipher_decrypt( h, out, out, outsize ); } else { if( outsize < inlen ) return set_lasterr( GCRYERR_TOO_SHORT ); /* fixme: check that the inlength is a multipe of the blocksize * if a blockoriented mode is used, or modify cipher_encrypt to * return an error in this case */ - cipher_decrypt( h, out, in, inlen ); + rc = cipher_decrypt( h, out, in, inlen ); } - return 0; + return rc? set_lasterr (rc):0; } /**************** * Used for PGP's somewhat strange CFB mode. Only works if * the corresponding flag is set. */ static void cipher_sync( GCRY_CIPHER_HD c ) { if( (c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused ) { memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused ); memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused); c->unused = 0; } } int gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen) { + int rc = 0; + switch( cmd ) { case GCRYCTL_SET_KEY: - cipher_setkey( h, buffer, buflen ); + rc = cipher_setkey( h, buffer, buflen ); break; case GCRYCTL_SET_IV: cipher_setiv( h, buffer, buflen ); break; case GCRYCTL_CFB_SYNC: cipher_sync( h ); break; case GCRYCTL_DISABLE_ALGO: /* this one expects a NULL handle and buffer pointing to an * integer with the algo number. */ if( h || !buffer || buflen != sizeof(int) ) return set_lasterr( GCRYERR_INV_CIPHER_ALGO ); disable_cipher_algo( *(int*)buffer ); break; default: - return set_lasterr( GCRYERR_INV_OP ); + rc = GCRYERR_INV_OP; } - return 0; + return set_lasterr (rc); } /**************** * Return information about the cipher handle. * -1 is returned on error and gcry_errno() may be used to get more information * about the error. */ int gcry_cipher_info( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t *nbytes) { switch( cmd ) { default: set_lasterr( GCRYERR_INV_OP ); return -1; } return 0; } /**************** * Return information about the given cipher algorithm * WHAT select the kind of information returned: * GCRYCTL_GET_KEYLEN: * Return the length of the key, if the algorithm * supports multiple key length, the maximum supported value * is returnd. The length is return as number of octets. * buffer and nbytes must be zero. * The keylength is returned in _bytes_. * GCRYCTL_GET_BLKLEN: * Return the blocklength of the algorithm counted in octets. * buffer and nbytes must be zero. * GCRYCTL_TEST_ALGO: * Returns 0 when the specified algorithm is available for use. * buffer and nbytes must be zero. * * On error the value -1 is returned and the error reason may be * retrieved by gcry_errno(). * Note: Because this function is in most caes used to return an * integer value, we can make it easier for the caller to just look at * the return value. The caller will in all cases consult the value * and thereby detecting whether a error occured or not (i.e. while checking * the block size) */ int gcry_cipher_algo_info( int algo, int what, void *buffer, size_t *nbytes) { unsigned int ui; switch( what ) { case GCRYCTL_GET_KEYLEN: if( buffer || nbytes ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); break; } ui = cipher_get_keylen( algo ); if( ui > 0 && ui <= 512 ) return (int)ui/8; /* the only reason is an invalid algo or a strange blocksize */ set_lasterr( GCRYERR_INV_CIPHER_ALGO ); break; case GCRYCTL_GET_BLKLEN: if( buffer || nbytes ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); break; } ui = cipher_get_blocksize( algo ); if( ui > 0 && ui < 10000 ) return (int)ui; /* the only reason is an invalid algo or a strange blocksize */ set_lasterr( GCRYERR_INV_CIPHER_ALGO ); break; case GCRYCTL_TEST_ALGO: if( buffer || nbytes ) { set_lasterr( GCRYERR_INV_ARG ); break; } if( check_cipher_algo( algo ) ) { set_lasterr( GCRYERR_INV_CIPHER_ALGO ); break; } return 0; default: set_lasterr( GCRYERR_INV_OP ); } return -1; } diff --git a/cipher/des.c b/cipher/des.c index f421f395..7d089c58 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -1,1014 +1,1033 @@ /* des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. * * Please see below for more legal information! * * According to the definition of DES in FIPS PUB 46-2 from December 1993. * For a description of triple encryption, see: * Bruce Schneier: Applied Cryptography. Second Edition. * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * Written by Michael Roth , September 1998 */ /* * U S A G E * =========== * * For DES or Triple-DES encryption/decryption you must initialize a proper * encryption context with a key. * * A DES key is 64bit wide but only 56bits of the key are used. The remaining * bits are parity bits and they will _not_ checked in this implementation, but * simply ignored. * * For Tripple-DES you could use either two 64bit keys or three 64bit keys. * The parity bits will _not_ checked, too. * * After initializing a context with a key you could use this context to * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. * * (In the examples below the slashes at the beginning and ending of comments * are omited.) * * DES Example * ----------- * unsigned char key[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * des_ctx context; * * * Fill 'key' and 'plaintext' with some data * * .... * * * Set up the DES encryption context * * des_setkey(context, key); * * * Encrypt the plaintext * * des_ecb_encrypt(context, plaintext, ciphertext); * * * To recover the orginal plaintext from ciphertext use: * * des_ecb_decrypt(context, ciphertext, recoverd); * * * Triple-DES Example * ------------------ * unsigned char key1[8]; * unsigned char key2[8]; * unsigned char key3[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * tripledes_ctx context; * * * If you would like to use two 64bit keys, fill 'key1' and'key2' * then setup the encryption context: * * tripledes_set2keys(context, key1, key2); * * * To use three 64bit keys with Triple-DES use: * * tripledes_set3keys(context, key1, key2, key3); * * * Encrypting plaintext with Triple-DES * * tripledes_ecb_encrypt(context, plaintext, ciphertext); * * * Decrypting ciphertext to recover the plaintext with Triple-DES * * tripledes_ecb_decrypt(context, ciphertext, recoverd); * * * Selftest * -------- * char *error_msg; * * * To perform a selftest of this DES/Triple-DES implementation use the * function selftest(). It will return an error string if their are * some problems with this library. * * * if ( (error_msg = selftest()) ) * { * fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %s\n", error_msg); * abort(); * } */ #include #include #include /* memcpy, memcmp */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "des.h" #if defined(__GNUC__) && defined(__GNU_LIBRARY__) #define working_memcmp memcmp #else /* * According to the SunOS man page, memcmp returns indeterminate sign * depending on whether characters are signed or not. */ int working_memcmp( const char *a, const char *b, size_t n ) { for( ; n; n--, a++, b++ ) if( *a != *b ) return (int)(*(byte*)a) - (int)(*(byte*)b); return 0; } #endif +static void +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + /* Some defines/checks to support standalone modules */ #ifndef CIPHER_ALGO_3DES #define CIPHER_ALGO_3DES 2 #elif CIPHER_ALGO_3DES != 2 #error CIPHER_ALGO_3DES is defined to a wrong value. #endif /* Macros used by the info function. */ #define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) #define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f)) /* * Encryption/Decryption context of DES */ typedef struct _des_ctx { u32 encrypt_subkeys[32]; u32 decrypt_subkeys[32]; } des_ctx[1]; /* * Encryption/Decryption context of Triple-DES */ typedef struct _tripledes_ctx { u32 encrypt_subkeys[96]; u32 decrypt_subkeys[96]; } tripledes_ctx[1]; static const char *selftest_failed; static void des_key_schedule (const byte *, u32 *); static int des_setkey (struct _des_ctx *, const byte *); static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); static int tripledes_set2keys (struct _tripledes_ctx *, const byte *, const byte *); static int tripledes_set3keys (struct _tripledes_ctx *, const byte *, const byte *, const byte *); static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int); static int is_weak_key ( const byte *key ); static const char *selftest (void); /* * The s-box values are permuted according to the 'primitive function P' * and are rotated one bit to the left. */ static u32 sbox1[64] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static u32 sbox2[64] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static u32 sbox3[64] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static u32 sbox4[64] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static u32 sbox5[64] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static u32 sbox6[64] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static u32 sbox7[64] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static u32 sbox8[64] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /* * These two tables are part of the 'permuted choice 1' function. * In this implementation several speed improvements are done. */ u32 leftkey_swap[16] = { 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, 0x01010000, 0x01010001, 0x01010100, 0x01010101 }; u32 rightkey_swap[16] = { 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, 0x01010101, }; /* * Numbers of left shifts per round for encryption subkeys. * To calculate the decryption subkeys we just reverse the * ordering of the calculated encryption subkeys. So their * is no need for a decryption rotate tab. */ static byte encrypt_rotate_tab[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; /* * Table with weak DES keys sorted in ascending order. * In DES their are 64 known keys wich are weak. They are weak * because they produce only one, two or four different * subkeys in the subkey scheduling process. * The keys in this table have all their parity bits cleared. */ static byte weak_keys[64][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, { 0x0e, 0x0e, 0x0e, 0x0e, 0xf0, 0xf0, 0xf0, 0xf0 }, { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } }; /* * Macro to swap bits across two words. */ #define DO_PERMUTATION(a, temp, b, offset, mask) \ temp = ((a>>offset) ^ b) & mask; \ b ^= temp; \ a ^= temp<> 31); \ temp = (left ^ right) & 0xaaaaaaaa; \ right ^= temp; \ left ^= temp; \ left = (left << 1) | (left >> 31); /* * The 'inverse initial permutation'. */ #define FINAL_PERMUTATION(left, temp, right) \ left = (left << 31) | (left >> 1); \ temp = (left ^ right) & 0xaaaaaaaa; \ left ^= temp; \ right ^= temp; \ right = (right << 31) | (right >> 1); \ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) /* * A full DES round including 'expansion function', 'sbox substitution' * and 'primitive function P' but without swapping the left and right word. * Please note: The data in 'from' and 'to' is already rotated one bit to * the left, done in the initial permutation. */ #define DES_ROUND(from, to, work, subkey) \ work = from ^ *subkey++; \ to ^= sbox8[ work & 0x3f ]; \ to ^= sbox6[ (work>>8) & 0x3f ]; \ to ^= sbox4[ (work>>16) & 0x3f ]; \ to ^= sbox2[ (work>>24) & 0x3f ]; \ work = ((from << 28) | (from >> 4)) ^ *subkey++; \ to ^= sbox7[ work & 0x3f ]; \ to ^= sbox5[ (work>>8) & 0x3f ]; \ to ^= sbox3[ (work>>16) & 0x3f ]; \ to ^= sbox1[ (work>>24) & 0x3f ]; /* * Macros to convert 8 bytes from/to 32bit words. */ #define READ_64BIT_DATA(data, left, right) \ left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; #define WRITE_64BIT_DATA(data, left, right) \ data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ data[6] = (right >> 8) &0xff; data[7] = right &0xff; /* * Handy macros for encryption and decryption of data */ #define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) #define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) #define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 0) #define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 1) /* * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for * 16 encryption rounds. * To calculate subkeys for decryption the caller * have to reorder the generated subkeys. * * rawkey: 8 Bytes of key data * subkey: Array of at least 32 u32s. Will be filled * with calculated subkeys. * */ static void des_key_schedule (const byte * rawkey, u32 * subkey) { u32 left, right, work; int round; READ_64BIT_DATA (rawkey, left, right) DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) DO_PERMUTATION (right, work, left, 0, 0x10101010) left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); left &= 0x0fffffff; right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); right &= 0x0fffffff; for (round = 0; round < 16; ++round) { left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; *subkey++ = ((left << 4) & 0x24000000) | ((left << 28) & 0x10000000) | ((left << 14) & 0x08000000) | ((left << 18) & 0x02080000) | ((left << 6) & 0x01000000) | ((left << 9) & 0x00200000) | ((left >> 1) & 0x00100000) | ((left << 10) & 0x00040000) | ((left << 2) & 0x00020000) | ((left >> 10) & 0x00010000) | ((right >> 13) & 0x00002000) | ((right >> 4) & 0x00001000) | ((right << 6) & 0x00000800) | ((right >> 1) & 0x00000400) | ((right >> 14) & 0x00000200) | (right & 0x00000100) | ((right >> 5) & 0x00000020) | ((right >> 10) & 0x00000010) | ((right >> 3) & 0x00000008) | ((right >> 18) & 0x00000004) | ((right >> 26) & 0x00000002) | ((right >> 24) & 0x00000001); *subkey++ = ((left << 15) & 0x20000000) | ((left << 17) & 0x10000000) | ((left << 10) & 0x08000000) | ((left << 22) & 0x04000000) | ((left >> 2) & 0x02000000) | ((left << 1) & 0x01000000) | ((left << 16) & 0x00200000) | ((left << 11) & 0x00100000) | ((left << 3) & 0x00080000) | ((left >> 6) & 0x00040000) | ((left << 15) & 0x00020000) | ((left >> 4) & 0x00010000) | ((right >> 2) & 0x00002000) | ((right << 8) & 0x00001000) | ((right >> 14) & 0x00000808) | ((right >> 9) & 0x00000400) | ((right) & 0x00000200) | ((right << 7) & 0x00000100) | ((right >> 7) & 0x00000020) | ((right >> 3) & 0x00000011) | ((right << 2) & 0x00000004) | ((right >> 21) & 0x00000002); } } /* * Fill a DES context with subkeys calculated from a 64bit key. * Does not check parity bits, but simply ignore them. * Does not check for weak keys. */ static int des_setkey (struct _des_ctx *ctx, const byte * key) { int i; if( selftest_failed ) return GCRYERR_SELFTEST; des_key_schedule (key, ctx->encrypt_subkeys); + burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; } return 0; } /* * Electronic Codebook Mode DES encryption/decryption of data according * to 'mode'. */ static int des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } /* * Fill a Triple-DES context with subkeys calculated from two 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set2keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2) { int i; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); + burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i]; ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1]; ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i]; ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1]; } return 0; } /* * Fill a Triple-DES context with subkeys calculated from three 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set3keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2, const byte * key3) { int i; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); + burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; } return 0; } /* * Electronic Codebook Mode Triple-DES encryption/decryption of data according to 'mode'. * Sometimes this mode is named 'EDE' mode (Encryption-Decryption-Encryption). */ static int tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } /* * Check whether the 8 byte key is weak. * Dose not check the parity bits of the key but simple ignore them. */ static int is_weak_key ( const byte *key ) { byte work[8]; int i, left, right, middle, cmp_result; /* clear parity bits */ for(i=0; i<8; ++i) work[i] = key[i] & 0xfe; /* binary search in the weak key table */ left = 0; right = 63; while(left <= right) { middle = (left + right) / 2; if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) return -1; if ( cmp_result > 0 ) left = middle + 1; else right = middle - 1; } return 0; } /* * Performs a selftest of this DES/Triple-DES implementation. * Returns an string with the error text on failure. * Returns NULL if all is ok. */ static const char * selftest (void) { /* * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation * need this. */ if (sizeof (u32) != 4) return "Wrong word size for DES configured."; /* * DES Maintenance Test */ { int i; byte key[8] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; byte input[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; byte result[8] = {0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a}; byte temp1[8], temp2[8], temp3[8]; des_ctx des; for (i = 0; i < 64; ++i) { des_setkey (des, key); des_ecb_encrypt (des, input, temp1); des_ecb_encrypt (des, temp1, temp2); des_setkey (des, temp2); des_ecb_decrypt (des, temp1, temp3); memcpy (key, temp3, 8); memcpy (input, temp1, 8); } if (memcmp (temp3, result, 8)) return "DES maintenance test failed."; } /* * Self made Triple-DES test (Does somebody known an official test?) */ { int i; byte input[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; byte key1[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; byte key2[8] = {0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd}; byte result[8] = {0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3}; tripledes_ctx des3; for (i = 0; i < 16; ++i) { tripledes_set2keys (des3, key1, key2); tripledes_ecb_encrypt (des3, input, key1); tripledes_ecb_decrypt (des3, input, key2); tripledes_set3keys (des3, key1, input, key2); tripledes_ecb_encrypt (des3, input, input); } if (memcmp (input, result, 8)) return "Triple-DES test failed."; } /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. */ { struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52, }, { 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00 } }, { { 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E }, { 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A }, { 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A } }, { { 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6 }, { 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2 }, { 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x3D,0x12,0x4F,0xE2,0x19,0x8B,0xA3,0x18 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0xFB,0xAB,0xA1,0xFF,0x9D,0x05,0xE9,0xB1 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x18,0xd7,0x48,0xe5,0x63,0x62,0x05,0x72 } }, { { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe6,0xe6,0xdd,0x5b,0x7e,0x72,0x29,0x74 } }, { { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } } }; byte result[8]; int i; static char error[80]; tripledes_ctx des3; for (i=0; i, 1995. */ /* heavily modified for GnuPG by */ /* Test values: * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 */ #include #include #include #include #include #include "g10lib.h" #include "memory.h" #include "dynload.h" #include "bithelp.h" typedef struct { u32 A,B,C,D; /* chaining variables */ u32 nblocks; byte buf[64]; int count; } MD5_CONTEXT; static void md5_init( MD5_CONTEXT *ctx ) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->nblocks = 0; ctx->count = 0; } +static void +burn_stack (int bytes) +{ + char buf[128]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /**************** * transform n*64 bytes */ static void /*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/ transform( MD5_CONTEXT *ctx, byte *data ) { u32 correct_words[16]; u32 A = ctx->A; u32 B = ctx->B; u32 C = ctx->C; u32 D = ctx->D; u32 *cwp = correct_words; #ifdef BIG_ENDIAN_HOST { int i; byte *p2, *p1; for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; p2[2] = *p1++; p2[1] = *p1++; p2[0] = *p1++; } } #else memcpy( correct_words, data, 64 ); #endif #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++) + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Before we start, one word about the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Put checksum in context given as argument. */ ctx->A += A; ctx->B += B; ctx->C += C; ctx->D += D; } /* The routine updates the message-digest context to * account for the presence of each of the characters inBuf[0..inLen-1] * in the message whose digest is being computed. */ static void md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); + burn_stack (80+6*sizeof(void*)); hd->count = 0; hd->nblocks++; } if( !inbuf ) return; if( hd->count ) { for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; md5_write( hd, NULL, 0 ); if( !inlen ) return; } + burn_stack (80+6*sizeof(void*)); while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. * The handle is prepared for a new MD5 cycle. * Returns 16 bytes representing the digest. */ static void md5_final( MD5_CONTEXT *hd ) { u32 t, msb, lsb; byte *p; md5_write(hd, NULL, 0); /* flush */; t = hd->nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->count < 56 ) { /* enough room */ hd->buf[hd->count++] = 0x80; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ hd->buf[hd->count++] = 0x80; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; md5_write(hd, NULL, 0); /* flush */; memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ hd->buf[56] = lsb ; hd->buf[57] = lsb >> 8; hd->buf[58] = lsb >> 16; hd->buf[59] = lsb >> 24; hd->buf[60] = msb ; hd->buf[61] = msb >> 8; hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); + burn_stack (80+6*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *p++ = hd->##a ; *p++ = hd->##a >> 8; \ *p++ = hd->##a >> 16; *p++ = hd->##a >> 24; } while(0) #else /* little endian */ /*#define X(a) do { *(u32*)p = hd->##a ; p += 4; } while(0)*/ /* Unixware's cpp doesn't like the above construct so we do it his way: * (reported by Allan Clark) */ #define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) #endif X(A); X(B); X(C); X(D); #undef X } static byte * md5_read( MD5_CONTEXT *hd ) { return hd->buf; } /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ static const char * md5_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), void (**r_write)( void *c, byte *buf, size_t nbytes ), void (**r_final)( void *c ), byte *(**r_read)( void *c ) ) { static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; if( algo != 1 ) return NULL; *contextsize = sizeof(MD5_CONTEXT); *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 16; *(void (**)(MD5_CONTEXT *))r_init = md5_init; *(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write; *(void (**)(MD5_CONTEXT *))r_final = md5_final; *(byte *(**)(MD5_CONTEXT *))r_read = md5_read; return "MD5"; } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "MD5 ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 10, 1, 0, (void(*)(void))md5_get_info }, { 11, 1, 1 }, }; #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if( i >= DIM(func_table) || i < 0 ) return NULL; *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while( what && what != *class ); *sequence = i; return ret; } #ifndef IS_MODULE void _gcry_md5_constructor(void) { _gcry_register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif /* end of file */ diff --git a/cipher/primegen.c b/cipher/primegen.c index da8b01f5..9489f0e8 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -1,568 +1,571 @@ /* primegen.c - prime number generator * Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * *********************************************************************** * The algorithm used to generate practically save primes is due to * Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847) * page 260. */ #include #include #include #include #include #include "g10lib.h" #include "mpi.h" #include "cipher.h" static int no_of_small_prime_numbers; static MPI gen_prime( unsigned nbits, int mode, int randomlevel ); static int check_prime( MPI prime, MPI val_2 ); static int is_prime( MPI n, int steps, int *count ); static void m_out_of_n( char *array, int m, int n ); static void (*progress_cb) ( void *, int ); static void *progress_cb_data; void _gcry_register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) { progress_cb = cb; progress_cb_data = cb_data; } static void progress( int c ) { if ( progress_cb ) progress_cb ( progress_cb_data, c ); else fputc( c, stderr ); } /**************** * Generate a prime number (stored in secure memory) */ MPI _gcry_generate_secret_prime( unsigned nbits ) { MPI prime; prime = gen_prime( nbits, 1, 2 ); progress('\n'); return prime; } MPI _gcry_generate_public_prime( unsigned nbits ) { MPI prime; prime = gen_prime( nbits, 0, 2 ); progress('\n'); return prime; } /**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ MPI _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) { int n; /* number of factors */ int m; /* number of primes in pool */ unsigned fbits; /* length of prime factors */ MPI *factors; /* current factors */ MPI *pool; /* pool of primes */ MPI q; /* first prime factor (variable)*/ MPI prime; /* prime test value */ MPI q_factor; /* used for mode 1 */ byte *perms = NULL; int i, j; int count1, count2; unsigned nprime; unsigned req_qbits = qbits; /* the requested q bits size */ MPI val_2 = mpi_alloc_set_ui( 2 ); /* find number of needed prime factors */ for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) ; n--; if( !n || (mode==1 && n < 2) ) log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits ); if( mode == 1 ) { n--; fbits = (pbits - 2*req_qbits -1) / n; qbits = pbits - req_qbits - n*fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n*fbits; } if( DBG_CIPHER ) log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n ); prime = gcry_mpi_new ( pbits ); q = gen_prime( qbits, 0, 0 ); q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = gcry_xcalloc( n+2, sizeof *factors ); /* make a pool of 3n+5 primes (this is an arbitrary value) */ m = n*3+5; if( mode == 1 ) m += 5; /* need some more for DSA */ if( m < 25 ) m = 25; pool = gcry_xcalloc( m , sizeof *pool ); /* permutate over the pool of primes */ count1=count2=0; do { next_try: if( !perms ) { /* allocate new primes */ for(i=0; i < m; i++ ) { mpi_free(pool[i]); pool[i] = NULL; } /* init m_out_of_n() */ perms = gcry_xcalloc( 1, m ); for(i=0; i < n; i++ ) { perms[i] = 1; pool[i] = gen_prime( fbits, 0, 1 ); factors[i] = pool[i]; } } else { m_out_of_n( perms, n, m ); for(i=j=0; i < m && j < n ; i++ ) if( perms[i] ) { if( !pool[i] ) pool[i] = gen_prime( fbits, 0, 1 ); factors[j++] = pool[i]; } if( i == n ) { gcry_free(perms); perms = NULL; progress('!'); goto next_try; /* allocate new primes */ } } mpi_set( prime, q ); mpi_mul_ui( prime, prime, 2 ); if( mode == 1 ) mpi_mul( prime, prime, q_factor ); for(i=0; i < n; i++ ) mpi_mul( prime, prime, factors[i] ); mpi_add_ui( prime, prime, 1 ); nprime = mpi_get_nbits(prime); if( nprime < pbits ) { if( ++count1 > 20 ) { count1 = 0; qbits++; progress('>'); + mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count1 = 0; if( nprime > pbits ) { if( ++count2 > 20 ) { count2 = 0; qbits--; progress('<'); + mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count2 = 0; } while( !(nprime == pbits && check_prime( prime, val_2 )) ); if( DBG_CIPHER ) { progress('\n'); log_mpidump( "prime : ", prime ); log_mpidump( "factor q: ", q ); if( mode == 1 ) log_mpidump( "factor q0: ", q_factor ); for(i=0; i < n; i++ ) log_mpidump( "factor pi: ", factors[i] ); log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); if( mode == 1 ) fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) ); for(i=0; i < n; i++ ) fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); progress('\n'); } if( ret_factors ) { /* caller wants the factors */ *ret_factors = gcry_xcalloc( n+2 , sizeof **ret_factors); + i = 0; if( mode == 1 ) { - i = 0; (*ret_factors)[i++] = mpi_copy( q_factor ); for(; i <= n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } else { - for(i=0; i < n; i++ ) + for(; i < n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } } if( g ) { /* create a generator (start with 3)*/ MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); MPI b = mpi_alloc( mpi_get_nlimbs(prime) ); MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) ); if( mode == 1 ) BUG(); /* not yet implemented */ factors[n] = q; factors[n+1] = mpi_alloc_set_ui(2); mpi_sub_ui( pmin1, prime, 1 ); mpi_set_ui(g,2); do { mpi_add_ui(g, g, 1); if( DBG_CIPHER ) { log_debug("checking g: "); /*mpi_print( stderr, g, 1 );*/ #warning we need an internal mpi_print for debugging } else progress('^'); for(i=0; i < n+2; i++ ) { /*fputc('~', stderr);*/ mpi_fdiv_q(tmp, pmin1, factors[i] ); /* (no mpi_pow(), but it is okay to use this with mod prime) */ gcry_mpi_powm(b, g, tmp, prime ); if( !mpi_cmp_ui(b, 1) ) break; } if( DBG_CIPHER ) progress('\n'); } while( i < n+2 ); mpi_free(factors[n+1]); mpi_free(tmp); mpi_free(b); mpi_free(pmin1); } if( !DBG_CIPHER ) progress('\n'); gcry_free( factors ); /* (factors are shallow copies) */ for(i=0; i < m; i++ ) mpi_free( pool[i] ); gcry_free( pool ); gcry_free(perms); mpi_free(val_2); + mpi_free (q); return prime; } static MPI gen_prime( unsigned nbits, int secret, int randomlevel ) { MPI prime, ptest, pminus1, val_2, val_3, result; int i; unsigned x, step; unsigned count1, count2; int *mods; if( 0 && DBG_CIPHER ) log_debug("generate a prime of %u bits ", nbits ); if( !no_of_small_prime_numbers ) { for(i=0; small_prime_numbers[i]; i++ ) no_of_small_prime_numbers++; } mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); /* make nbits fit into MPI implementation */ val_2 = mpi_alloc_set_ui( 2 ); val_3 = mpi_alloc_set_ui( 3); prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits ); result = mpi_alloc_like( prime ); pminus1= mpi_alloc_like( prime ); ptest = mpi_alloc_like( prime ); count1 = count2 = 0; for(;;) { /* try forvever */ int dotcount=0; /* generate a random number */ gcry_mpi_randomize( prime, nbits, randomlevel ); /* set high order bit to 1, set low order bit to 1 */ mpi_set_highbit( prime, nbits-1 ); mpi_set_bit( prime, 0 ); /* calculate all remainders */ for(i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); /* now try some primes starting with prime */ for(step=0; step < 20000; step += 2 ) { /* check against all the small primes we have in mods */ count1++; for(i=0; (x = small_prime_numbers[i]); i++ ) { while( mods[i] + step >= x ) mods[i] -= x; if( !(mods[i] + step) ) break; } if( x ) continue; /* found a multiple of an already known prime */ mpi_add_ui( ptest, prime, step ); /* do a faster Fermat test */ count2++; mpi_sub_ui( pminus1, ptest, 1); gcry_mpi_powm( result, val_2, pminus1, ptest ); if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */ /* perform stronger tests */ if( is_prime(ptest, 5, &count2 ) ) { if( !mpi_test_bit( ptest, nbits-1 ) ) { progress('\n'); log_debug("overflow in prime generation\n"); break; /* step loop, continue with a new prime */ } mpi_free(val_2); mpi_free(val_3); mpi_free(result); mpi_free(pminus1); mpi_free(prime); gcry_free(mods); return ptest; } } if( ++dotcount == 10 ) { progress('.'); dotcount = 0; } } progress(':'); /* restart with a new random value */ } } /**************** * Returns: true if this may be a prime */ static int check_prime( MPI prime, MPI val_2 ) { int i; unsigned x; int count=0; /* check against small primes */ for(i=0; (x = small_prime_numbers[i]); i++ ) { if( mpi_divisible_ui( prime, x ) ) return 0; } /* a quick fermat test */ { MPI result = mpi_alloc_like( prime ); MPI pminus1 = mpi_alloc_like( prime ); mpi_sub_ui( pminus1, prime, 1); gcry_mpi_powm( result, val_2, pminus1, prime ); mpi_free( pminus1 ); if( mpi_cmp_ui( result, 1 ) ) { /* if composite */ mpi_free( result ); progress('.'); return 0; } mpi_free( result ); } /* perform stronger tests */ if( is_prime(prime, 5, &count ) ) return 1; /* is probably a prime */ progress('.'); return 0; } /**************** * Return true if n is probably a prime */ static int is_prime( MPI n, int steps, int *count ) { MPI x = mpi_alloc( mpi_get_nlimbs( n ) ); MPI y = mpi_alloc( mpi_get_nlimbs( n ) ); MPI z = mpi_alloc( mpi_get_nlimbs( n ) ); MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); MPI a2 = mpi_alloc_set_ui( 2 ); MPI q; unsigned i, j, k; int rc = 0; unsigned nbits = mpi_get_nbits( n ); mpi_sub_ui( nminus1, n, 1 ); /* find q and k, so that n = 1 + 2^k * q */ q = mpi_copy( nminus1 ); k = mpi_trailing_zeros( q ); mpi_tdiv_q_2exp(q, q, k); for(i=0 ; i < steps; i++ ) { ++*count; if( !i ) { mpi_set_ui( x, 2 ); } else { gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM ); /* make sure that the number is smaller than the prime * and keep the randomness of the high bit */ if( mpi_test_bit( x, nbits-2 ) ) { mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */ } else { mpi_set_highbit( x, nbits-2 ); mpi_clear_bit( x, nbits-2 ); } assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); } gcry_mpi_powm( y, x, q, n); if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { gcry_mpi_powm(y, y, a2, n); if( !mpi_cmp_ui( y, 1 ) ) goto leave; /* not a prime */ } if( mpi_cmp( y, nminus1 ) ) goto leave; /* not a prime */ } progress('+'); } rc = 1; /* may be a prime */ leave: mpi_free( x ); mpi_free( y ); mpi_free( z ); mpi_free( nminus1 ); mpi_free( q ); return rc; } static void m_out_of_n( char *array, int m, int n ) { int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0; if( !m || m >= n ) return; if( m == 1 ) { /* special case */ for(i=0; i < n; i++ ) if( array[i] ) { array[i++] = 0; if( i >= n ) i = 0; array[i] = 1; return; } BUG(); } for(j=1; j < n; j++ ) { if( array[n-1] == array[n-j-1] ) continue; j1 = j; break; } if( m & 1 ) { /* m is odd */ if( array[n-1] ) { if( j1 & 1 ) { k1 = n - j1; k2 = k1+2; if( k2 > n ) k2 = n; goto leave; } goto scan; } k2 = n - j1 - 1; if( k2 == 0 ) { k1 = i; k2 = n - j1; } else if( array[k2] && array[k2-1] ) k1 = n; else k1 = k2 + 1; } else { /* m is even */ if( !array[n-1] ) { k1 = n - j1; k2 = k1 + 1; goto leave; } if( !(j1 & 1) ) { k1 = n - j1; k2 = k1+2; if( k2 > n ) k2 = n; goto leave; } scan: jp = n - j1 - 1; for(i=1; i <= jp; i++ ) { i1 = jp + 2 - i; if( array[i1-1] ) { if( array[i1-2] ) { k1 = i1 - 1; k2 = n - j1; } else { k1 = i1 - 1; k2 = n + 1 - j1; } goto leave; } } k1 = 1; k2 = n + 1 - m; } leave: array[k1-1] = !array[k1-1]; array[k2-1] = !array[k2-1]; } diff --git a/cipher/random.c b/cipher/random.c index f6eec21b..91c80829 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -1,688 +1,703 @@ /* random.c - random number generator - * Copyright (C) 1998, 2000 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /**************** * This random number generator is modelled after the one described * in Peter Gutmann's Paper: "Software Generation of Practically * Strong Random Numbers". */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETHRTIME #include #endif #ifdef HAVE_GETTIMEOFDAY #include #endif #ifdef HAVE_GETRUSAGE #include #endif #ifdef __MINGW32__ #include #endif #include "g10lib.h" #include "rmd.h" #include "random.h" #include "rand-internal.h" #include "dynload.h" #ifndef RAND_MAX /* for SunOS */ #define RAND_MAX 32767 #endif #if SIZEOF_UNSIGNED_LONG == 8 #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 #elif SIZEOF_UNSIGNED_LONG == 4 #define ADD_VALUE 0xa5a5a5a5 #else #error weird size for an unsigned long #endif #define BLOCKLEN 64 /* hash this amount of bytes */ #define DIGESTLEN 20 /* into a digest of this length (rmd160) */ /* poolblocks is the number of digests which make up the pool * and poolsize must be a multiple of the digest length * to make the AND operations faster, the size should also be * a multiple of ulong */ #define POOLBLOCKS 30 #define POOLSIZE (POOLBLOCKS*DIGESTLEN) #if (POOLSIZE % SIZEOF_UNSIGNED_LONG) #error Please make sure that poolsize is a multiple of ulong #endif #define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) static int is_initialized; #define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ static size_t pool_readpos; static size_t pool_writepos; static int pool_filled; static int pool_balance; static int just_mixed; static int did_initial_extra_seeding; static char *seed_file_name; static int allow_seed_file_update; static int secure_alloc; static int quick_test; static int faked_rng; static byte *get_random_bytes( size_t nbytes, int level, int secure ); static void read_pool( byte *buffer, size_t length, int level ); static void add_randomness( const void *buffer, size_t length, int source ); static void random_poll(void); static void read_random_source( int requester, size_t length, int level); static int gather_faked( void (*add)(const void*, size_t, int), int requester, size_t length, int level ); static struct { ulong mixrnd; ulong mixkey; ulong slowpolls; ulong fastpolls; ulong getbytes1; ulong ngetbytes1; ulong getbytes2; ulong ngetbytes2; ulong addbytes; ulong naddbytes; } rndstats; static void initialize(void) { /* The data buffer is allocated somewhat larger, so that * we can use this extra space (which is allocated in secure memory) * as a temporary hash buffer */ rndpool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN) : gcry_xcalloc(1,POOLSIZE+BLOCKLEN); keypool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN) : gcry_xcalloc(1,POOLSIZE+BLOCKLEN); is_initialized = 1; _gcry_cipher_modules_constructor(); } +static void +burn_stack (int bytes) +{ + char buf[128]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + void _gcry_random_dump_stats() { fprintf(stderr, "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, rndstats.naddbytes, rndstats.addbytes, rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, rndstats.ngetbytes2, rndstats.getbytes2 ); } void _gcry_secure_random_alloc() { secure_alloc = 1; } int _gcry_quick_random_gen( int onoff ) { int last; read_random_source(0,0,0); /* init */ last = quick_test; if( onoff != -1 ) quick_test = onoff; return faked_rng? 1 : last; } /**************** * Fill the buffer with LENGTH bytes of cryptographically strong * random bytes. level 0 is not very strong, 1 is strong enough * for most usage, 2 is good for key generation stuff but may be very slow. */ void gcry_randomize( byte *buffer, size_t length, enum gcry_random_level level ) { char *p = get_random_bytes( length, level, 1 ); memcpy( buffer, p, length ); gcry_free(p); } int _gcry_random_is_faked() { if( !is_initialized ) initialize(); return faked_rng || quick_test; } /**************** * Return a pointer to a randomized buffer of level 0 and LENGTH bits * caller must free the buffer. * Note: The returned value is rounded up to bytes. */ static byte * get_random_bytes( size_t nbytes, int level, int secure ) { byte *buf, *p; if( quick_test && level > 1 ) level = 1; MASK_LEVEL(level); if( level == 1 ) { rndstats.getbytes1 += nbytes; rndstats.ngetbytes1++; } else if( level >= 2 ) { rndstats.getbytes2 += nbytes; rndstats.ngetbytes2++; } buf = secure && secure_alloc ? gcry_xmalloc_secure( nbytes ) : gcry_xmalloc( nbytes ); for( p = buf; nbytes > 0; ) { size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; read_pool( p, n, level ); nbytes -= n; p += n; } return buf; } void * gcry_random_bytes( size_t nbytes, enum gcry_random_level level ) { return get_random_bytes( nbytes, level, 0 ); } void * gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level ) { return get_random_bytes( nbytes, level, 1 ); } /**************** * Mix the pool */ static void mix_pool(byte *pool) { char *hashbuf = pool + POOLSIZE; char *p, *pend; int i, n; RMD160_CONTEXT md; _gcry_rmd160_init( &md ); #if DIGESTLEN != 20 #error must have a digest length of 20 for ripe-md-160 #endif /* loop over the pool */ pend = pool + POOLSIZE; memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); _gcry_rmd160_mixblock( &md, hashbuf); memcpy(pool, hashbuf, 20 ); p = pool; for( n=1; n < POOLBLOCKS; n++ ) { memcpy(hashbuf, p, DIGESTLEN ); p += DIGESTLEN; if( p+DIGESTLEN+BLOCKLEN < pend ) memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); else { char *pp = p+DIGESTLEN; for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { if( pp >= pend ) pp = pool; hashbuf[i] = *pp++; } } _gcry_rmd160_mixblock( &md, hashbuf); memcpy(p, hashbuf, 20 ); } + burn_stack (200); /* for the rmd160_mixblock() */ } void _gcry_set_random_seed_file( const char *name ) { if( seed_file_name ) BUG(); seed_file_name = gcry_xstrdup( name ); } /**************** * Read in a seed form the random_seed file * and return true if this was successful */ static int read_seed_file() { int fd; struct stat sb; unsigned char buffer[POOLSIZE]; int n; if( !seed_file_name ) return 0; #ifdef HAVE_DOSISH_SYSTEM fd = open( seed_file_name, O_RDONLY | O_BINARY ); #else fd = open( seed_file_name, O_RDONLY ); #endif if( fd == -1 && errno == ENOENT) { allow_seed_file_update = 1; return 0; } if( fd == -1 ) { log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); return 0; } if( fstat( fd, &sb ) ) { log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); close(fd); return 0; } if( !S_ISREG(sb.st_mode) ) { log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); close(fd); return 0; } if( !sb.st_size ) { log_info(_("note: random_seed file is empty\n") ); close(fd); allow_seed_file_update = 1; return 0; } if( sb.st_size != POOLSIZE ) { log_info(_("warning: invalid size of random_seed file - not used\n") ); close(fd); return 0; } do { n = read( fd, buffer, POOLSIZE ); } while( n == -1 && errno == EINTR ); if( n != POOLSIZE ) { log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); close(fd); return 0; } close(fd); add_randomness( buffer, POOLSIZE, 0 ); /* add some minor entropy to the pool now (this will also force a mixing) */ { pid_t x = getpid(); add_randomness( &x, sizeof(x), 0 ); } { time_t x = time(NULL); add_randomness( &x, sizeof(x), 0 ); } { clock_t x = clock(); add_randomness( &x, sizeof(x), 0 ); } /* And read a few bytes from our entropy source. By using * a level of 0 this will not block and might not return anything * with some entropy drivers, however the rndlinux driver will use * /dev/urandom and return some stuff - Do not read to much as we * want to be friendly to the scare system entropy resource. */ read_random_source( 0, 16, 0 ); allow_seed_file_update = 1; return 1; } void _gcry_update_random_seed_file() { ulong *sp, *dp; int fd, i; if( !seed_file_name || !is_initialized || !pool_filled ) return; if( !allow_seed_file_update ) { log_info(_("note: random_seed file not updated\n")); return; } /* copy the entropy pool to a scratch pool and mix both of them */ for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; i < POOLWORDS; i++, dp++, sp++ ) { *dp = *sp + ADD_VALUE; } mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; #ifdef HAVE_DOSISH_SYSTEM fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR ); #else fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); #endif if( fd == -1 ) { log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); return; } do { i = write( fd, keypool, POOLSIZE ); } while( i == -1 && errno == EINTR ); if( i != POOLSIZE ) { log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); } if( close(fd) ) log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); } static void read_pool( byte *buffer, size_t length, int level ) { int i; ulong *sp, *dp; if( length >= POOLSIZE ) { log_fatal(_("too many random bits requested; the limit is %d\n"), POOLSIZE*8-1 ); } if( !pool_filled ) { if( read_seed_file() ) pool_filled = 1; } /* For level 2 quality (key generation) we alwas make * sure that the pool has been seeded enough initially */ if( level == 2 && !did_initial_extra_seeding ) { size_t needed; pool_balance = 0; needed = length - pool_balance; if( needed < POOLSIZE/2 ) needed = POOLSIZE/2; else if( needed > POOLSIZE ) BUG(); read_random_source( 3, needed, 2 ); pool_balance += needed; did_initial_extra_seeding=1; } /* for level 2 make sure that there is enough random in the pool */ if( level == 2 && pool_balance < length ) { size_t needed; if( pool_balance < 0 ) pool_balance = 0; needed = length - pool_balance; if( needed > POOLSIZE ) BUG(); read_random_source( 3, needed, 2 ); pool_balance += needed; } /* make sure the pool is filled */ while( !pool_filled ) random_poll(); /* do always a fast random poll */ fast_random_poll(); if( !level ) { /* no need for cryptographic strong random */ /* create a new pool */ for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; i < POOLWORDS; i++, dp++, sp++ ) *dp = *sp + ADD_VALUE; /* must mix both pools */ mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; memcpy( buffer, keypool, length ); } else { /* mix the pool (if add_randomness() didn't it) */ if( !just_mixed ) { mix_pool(rndpool); rndstats.mixrnd++; } /* create a new pool */ for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; i < POOLWORDS; i++, dp++, sp++ ) *dp = *sp + ADD_VALUE; /* and mix both pools */ mix_pool(rndpool); rndstats.mixrnd++; mix_pool(keypool); rndstats.mixkey++; /* read the required data * we use a readpoiter to read from a different postion each * time */ while( length-- ) { *buffer++ = keypool[pool_readpos++]; if( pool_readpos >= POOLSIZE ) pool_readpos = 0; pool_balance--; } if( pool_balance < 0 ) pool_balance = 0; /* and clear the keypool */ memset( keypool, 0, POOLSIZE ); } } /**************** * Add LENGTH bytes of randomness from buffer to the pool. * source may be used to specify the randomness source. * Source is: * 0 - used ony for initialization * 1 - fast random poll function * 2 - normal poll function * 3 - used when level 2 random quality has been requested * to do an extra pool seed. */ static void add_randomness( const void *buffer, size_t length, int source ) { const byte *p = buffer; if( !is_initialized ) initialize(); rndstats.addbytes += length; rndstats.naddbytes++; while( length-- ) { rndpool[pool_writepos++] = *p++; if( pool_writepos >= POOLSIZE ) { if( source > 1 ) pool_filled = 1; pool_writepos = 0; mix_pool(rndpool); rndstats.mixrnd++; just_mixed = !length; } } } static void random_poll() { rndstats.slowpolls++; read_random_source( 2, POOLSIZE/5, 1 ); } void _gcry_fast_random_poll() { static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; static int initialized = 0; rndstats.fastpolls++; if( !initialized ) { if( !is_initialized ) initialize(); initialized = 1; fnc = _gcry_dynload_getfnc_fast_random_poll(); } if( fnc ) { (*fnc)( add_randomness, 1 ); return; } /* fall back to the generic function */ #if HAVE_GETHRTIME { hrtime_t tv; tv = gethrtime(); add_randomness( &tv, sizeof(tv), 1 ); } #elif HAVE_GETTIMEOFDAY { struct timeval tv; if( gettimeofday( &tv, NULL ) ) BUG(); add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); } #elif HAVE_CLOCK_GETTIME { struct timespec tv; if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) BUG(); add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); } #else /* use times */ #ifndef HAVE_DOSISH_SYSTEM { struct tms buf; times( &buf ); add_randomness( &buf, sizeof buf, 1 ); } #endif #endif #ifdef HAVE_GETRUSAGE #ifndef RUSAGE_SELF #ifdef __GCC__ #warning There is no RUSAGE_SELF on this system #endif #else - { struct rusage buf; + { + struct rusage buf; /* QNX/Neutrino does return ENOSYS - so we just ignore it and - * add whatever is in buf */ - if( getrusage( RUSAGE_SELF, &buf ) && errno != ENOSYS ) - BUG(); + * add whatever is in buf. In a chroot environment it might not + * work at all (i.e. because /proc/ is not accessible), so we better + * ugnore all error codes and hope for the best + */ + getrusage (RUSAGE_SELF, &buf ); add_randomness( &buf, sizeof buf, 1 ); memset( &buf, 0, sizeof buf ); } #endif #endif /* time and clock are availabe on all systems - so * we better do it just in case one of the above functions * didn't work */ { time_t x = time(NULL); add_randomness( &x, sizeof(x), 1 ); } { clock_t x = clock(); add_randomness( &x, sizeof(x), 1 ); } } static void read_random_source( int requester, size_t length, int level ) { static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int) = NULL; if( !fnc ) { if( !is_initialized ) initialize(); fnc = _gcry_dynload_getfnc_gather_random(); if( !fnc ) { faked_rng = 1; fnc = gather_faked; } if( !requester && !length && !level ) return; /* init only */ } if( (*fnc)( add_randomness, requester, length, level ) < 0 ) log_fatal("No way to gather entropy for the RNG\n"); } static int gather_faked( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) { static int initialized=0; size_t n; char *buffer, *p; if( !initialized ) { log_info(_("WARNING: using insecure random number generator!!\n")); /* we can't use tty_printf here - do we need this function at all - does it really make sense or canit be viewed as a potential security problem ? wk 17.11.99 */ #warning Extended warning disabled #if 0 tty_printf(_("The random number generator is only a kludge to let\n" "it run - it is in no way a strong RNG!\n\n" "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); #endif initialized=1; #ifdef HAVE_RAND srand( time(NULL)*getpid()); #else srandom( time(NULL)*getpid()); #endif } p = buffer = gcry_xmalloc( length ); n = length; #ifdef HAVE_RAND while( n-- ) *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); #else while( n-- ) *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); #endif add_randomness( buffer, length, requester ); gcry_free(buffer); return 0; /* okay */ } diff --git a/cipher/rijndael.c b/cipher/rijndael.c index ec110dc5..fa43adbd 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1,2193 +1,2232 @@ /* Rijndael (AES) for GnuPG * Copyright (C) 2000, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ******************************************************************* * The code here is based on the optimized implementation taken from * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, * which carries this notice: *------------------------------------------ * rijndael-alg-fst.c v2.3 April '2000 * * Optimised ANSI C code * * authors: v1.0: Antoon Bosselaers * v2.0: Vincent Rijmen * v2.3: Paulo Barreto * * This code is placed in the public domain. *------------------------------------------ */ #include #include #include #include /* for memcmp() */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "dynload.h" #define MAXKC (256/32) #define MAXROUNDS 14 static const char *selftest(void); typedef struct { int ROUNDS; /* key-length-dependent number of rounds */ int decryption_prepared; byte keySched[MAXROUNDS+1][4][4]; /* key schedule */ byte keySched2[MAXROUNDS+1][4][4]; /* key schedule */ } RIJNDAEL_context; static const byte S[256] = { 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22 }; static const byte T1[256][4] = { { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 }, { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd }, { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 }, { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 }, { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d }, { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 }, { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 }, { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c }, { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 }, { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 }, { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 }, { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 }, { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 }, { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 }, { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e }, { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d }, { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f }, { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 }, { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 }, { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a }, { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 }, { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 }, { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 }, { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe }, { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc }, { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 }, { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a }, { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 }, { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 }, { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 }, { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 }, { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 }, { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e }, { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 }, { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 }, { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 }, { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a }, { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e }, { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 }, { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 }, { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 }, { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa }, { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e }, { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 }, { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 }, { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c }, { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 }, { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 }, { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f }, { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 }, { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 }, { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 }, { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 }, { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff }, { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 }, { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 }, { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 }, { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc }, { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a } }; static const byte T2[256][4] = { { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c }, { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b }, { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 }, { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f }, { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 }, { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 }, { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 }, { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 }, { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e }, { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b }, { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef }, { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c }, { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 }, { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d }, { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 }, { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff }, { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c }, { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 }, { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 }, { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d }, { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee }, { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e }, { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 }, { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 }, { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 }, { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 }, { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 }, { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 }, { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a }, { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd }, { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd }, { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 }, { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 }, { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 }, { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 }, { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e }, { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 }, { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 }, { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 } }; static const byte T3[256][4] = { { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c }, { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b }, { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 }, { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 }, { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 }, { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f }, { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 }, { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 }, { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 }, { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 }, { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 }, { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e }, { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b }, { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 }, { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc }, { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb }, { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c }, { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef }, { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d }, { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 }, { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c }, { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 }, { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d }, { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 }, { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff }, { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 }, { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 }, { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d }, { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 }, { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a }, { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee }, { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 }, { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 }, { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 }, { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 }, { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 }, { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd }, { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd }, { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e }, { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 }, { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 }, { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 }, { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 }, { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e }, { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 }, { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 }, { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 }, { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 }, { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 }, { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 } }; static const byte T4[256][4] = { { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 }, { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 }, { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 }, { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f }, { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 }, { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 }, { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 }, { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 }, { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e }, { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 }, { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab }, { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 }, { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 }, { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 }, { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e }, { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d }, { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc }, { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 }, { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd }, { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 }, { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 }, { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d }, { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 }, { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 }, { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a }, { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 }, { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 }, { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d }, { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 }, { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 }, { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 }, { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 }, { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 }, { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 }, { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba }, { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 }, { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 }, { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 }, { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc }, { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 }, { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c }, { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd }, { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 }, { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b }, { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 }, { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 }, { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 }, { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c }, { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 }, { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a }, { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 }, { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb }, { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 }, { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c }, { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa }, { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 }, { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 }, { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 }, { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c } }; static const byte T5[256][4] = { { 0x51,0xf4,0xa7,0x50 }, { 0x7e,0x41,0x65,0x53 }, { 0x1a,0x17,0xa4,0xc3 }, { 0x3a,0x27,0x5e,0x96 }, { 0x3b,0xab,0x6b,0xcb }, { 0x1f,0x9d,0x45,0xf1 }, { 0xac,0xfa,0x58,0xab }, { 0x4b,0xe3,0x03,0x93 }, { 0x20,0x30,0xfa,0x55 }, { 0xad,0x76,0x6d,0xf6 }, { 0x88,0xcc,0x76,0x91 }, { 0xf5,0x02,0x4c,0x25 }, { 0x4f,0xe5,0xd7,0xfc }, { 0xc5,0x2a,0xcb,0xd7 }, { 0x26,0x35,0x44,0x80 }, { 0xb5,0x62,0xa3,0x8f }, { 0xde,0xb1,0x5a,0x49 }, { 0x25,0xba,0x1b,0x67 }, { 0x45,0xea,0x0e,0x98 }, { 0x5d,0xfe,0xc0,0xe1 }, { 0xc3,0x2f,0x75,0x02 }, { 0x81,0x4c,0xf0,0x12 }, { 0x8d,0x46,0x97,0xa3 }, { 0x6b,0xd3,0xf9,0xc6 }, { 0x03,0x8f,0x5f,0xe7 }, { 0x15,0x92,0x9c,0x95 }, { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, { 0xd4,0xbe,0x83,0x2d }, { 0x58,0x74,0x21,0xd3 }, { 0x49,0xe0,0x69,0x29 }, { 0x8e,0xc9,0xc8,0x44 }, { 0x75,0xc2,0x89,0x6a }, { 0xf4,0x8e,0x79,0x78 }, { 0x99,0x58,0x3e,0x6b }, { 0x27,0xb9,0x71,0xdd }, { 0xbe,0xe1,0x4f,0xb6 }, { 0xf0,0x88,0xad,0x17 }, { 0xc9,0x20,0xac,0x66 }, { 0x7d,0xce,0x3a,0xb4 }, { 0x63,0xdf,0x4a,0x18 }, { 0xe5,0x1a,0x31,0x82 }, { 0x97,0x51,0x33,0x60 }, { 0x62,0x53,0x7f,0x45 }, { 0xb1,0x64,0x77,0xe0 }, { 0xbb,0x6b,0xae,0x84 }, { 0xfe,0x81,0xa0,0x1c }, { 0xf9,0x08,0x2b,0x94 }, { 0x70,0x48,0x68,0x58 }, { 0x8f,0x45,0xfd,0x19 }, { 0x94,0xde,0x6c,0x87 }, { 0x52,0x7b,0xf8,0xb7 }, { 0xab,0x73,0xd3,0x23 }, { 0x72,0x4b,0x02,0xe2 }, { 0xe3,0x1f,0x8f,0x57 }, { 0x66,0x55,0xab,0x2a }, { 0xb2,0xeb,0x28,0x07 }, { 0x2f,0xb5,0xc2,0x03 }, { 0x86,0xc5,0x7b,0x9a }, { 0xd3,0x37,0x08,0xa5 }, { 0x30,0x28,0x87,0xf2 }, { 0x23,0xbf,0xa5,0xb2 }, { 0x02,0x03,0x6a,0xba }, { 0xed,0x16,0x82,0x5c }, { 0x8a,0xcf,0x1c,0x2b }, { 0xa7,0x79,0xb4,0x92 }, { 0xf3,0x07,0xf2,0xf0 }, { 0x4e,0x69,0xe2,0xa1 }, { 0x65,0xda,0xf4,0xcd }, { 0x06,0x05,0xbe,0xd5 }, { 0xd1,0x34,0x62,0x1f }, { 0xc4,0xa6,0xfe,0x8a }, { 0x34,0x2e,0x53,0x9d }, { 0xa2,0xf3,0x55,0xa0 }, { 0x05,0x8a,0xe1,0x32 }, { 0xa4,0xf6,0xeb,0x75 }, { 0x0b,0x83,0xec,0x39 }, { 0x40,0x60,0xef,0xaa }, { 0x5e,0x71,0x9f,0x06 }, { 0xbd,0x6e,0x10,0x51 }, { 0x3e,0x21,0x8a,0xf9 }, { 0x96,0xdd,0x06,0x3d }, { 0xdd,0x3e,0x05,0xae }, { 0x4d,0xe6,0xbd,0x46 }, { 0x91,0x54,0x8d,0xb5 }, { 0x71,0xc4,0x5d,0x05 }, { 0x04,0x06,0xd4,0x6f }, { 0x60,0x50,0x15,0xff }, { 0x19,0x98,0xfb,0x24 }, { 0xd6,0xbd,0xe9,0x97 }, { 0x89,0x40,0x43,0xcc }, { 0x67,0xd9,0x9e,0x77 }, { 0xb0,0xe8,0x42,0xbd }, { 0x07,0x89,0x8b,0x88 }, { 0xe7,0x19,0x5b,0x38 }, { 0x79,0xc8,0xee,0xdb }, { 0xa1,0x7c,0x0a,0x47 }, { 0x7c,0x42,0x0f,0xe9 }, { 0xf8,0x84,0x1e,0xc9 }, { 0x00,0x00,0x00,0x00 }, { 0x09,0x80,0x86,0x83 }, { 0x32,0x2b,0xed,0x48 }, { 0x1e,0x11,0x70,0xac }, { 0x6c,0x5a,0x72,0x4e }, { 0xfd,0x0e,0xff,0xfb }, { 0x0f,0x85,0x38,0x56 }, { 0x3d,0xae,0xd5,0x1e }, { 0x36,0x2d,0x39,0x27 }, { 0x0a,0x0f,0xd9,0x64 }, { 0x68,0x5c,0xa6,0x21 }, { 0x9b,0x5b,0x54,0xd1 }, { 0x24,0x36,0x2e,0x3a }, { 0x0c,0x0a,0x67,0xb1 }, { 0x93,0x57,0xe7,0x0f }, { 0xb4,0xee,0x96,0xd2 }, { 0x1b,0x9b,0x91,0x9e }, { 0x80,0xc0,0xc5,0x4f }, { 0x61,0xdc,0x20,0xa2 }, { 0x5a,0x77,0x4b,0x69 }, { 0x1c,0x12,0x1a,0x16 }, { 0xe2,0x93,0xba,0x0a }, { 0xc0,0xa0,0x2a,0xe5 }, { 0x3c,0x22,0xe0,0x43 }, { 0x12,0x1b,0x17,0x1d }, { 0x0e,0x09,0x0d,0x0b }, { 0xf2,0x8b,0xc7,0xad }, { 0x2d,0xb6,0xa8,0xb9 }, { 0x14,0x1e,0xa9,0xc8 }, { 0x57,0xf1,0x19,0x85 }, { 0xaf,0x75,0x07,0x4c }, { 0xee,0x99,0xdd,0xbb }, { 0xa3,0x7f,0x60,0xfd }, { 0xf7,0x01,0x26,0x9f }, { 0x5c,0x72,0xf5,0xbc }, { 0x44,0x66,0x3b,0xc5 }, { 0x5b,0xfb,0x7e,0x34 }, { 0x8b,0x43,0x29,0x76 }, { 0xcb,0x23,0xc6,0xdc }, { 0xb6,0xed,0xfc,0x68 }, { 0xb8,0xe4,0xf1,0x63 }, { 0xd7,0x31,0xdc,0xca }, { 0x42,0x63,0x85,0x10 }, { 0x13,0x97,0x22,0x40 }, { 0x84,0xc6,0x11,0x20 }, { 0x85,0x4a,0x24,0x7d }, { 0xd2,0xbb,0x3d,0xf8 }, { 0xae,0xf9,0x32,0x11 }, { 0xc7,0x29,0xa1,0x6d }, { 0x1d,0x9e,0x2f,0x4b }, { 0xdc,0xb2,0x30,0xf3 }, { 0x0d,0x86,0x52,0xec }, { 0x77,0xc1,0xe3,0xd0 }, { 0x2b,0xb3,0x16,0x6c }, { 0xa9,0x70,0xb9,0x99 }, { 0x11,0x94,0x48,0xfa }, { 0x47,0xe9,0x64,0x22 }, { 0xa8,0xfc,0x8c,0xc4 }, { 0xa0,0xf0,0x3f,0x1a }, { 0x56,0x7d,0x2c,0xd8 }, { 0x22,0x33,0x90,0xef }, { 0x87,0x49,0x4e,0xc7 }, { 0xd9,0x38,0xd1,0xc1 }, { 0x8c,0xca,0xa2,0xfe }, { 0x98,0xd4,0x0b,0x36 }, { 0xa6,0xf5,0x81,0xcf }, { 0xa5,0x7a,0xde,0x28 }, { 0xda,0xb7,0x8e,0x26 }, { 0x3f,0xad,0xbf,0xa4 }, { 0x2c,0x3a,0x9d,0xe4 }, { 0x50,0x78,0x92,0x0d }, { 0x6a,0x5f,0xcc,0x9b }, { 0x54,0x7e,0x46,0x62 }, { 0xf6,0x8d,0x13,0xc2 }, { 0x90,0xd8,0xb8,0xe8 }, { 0x2e,0x39,0xf7,0x5e }, { 0x82,0xc3,0xaf,0xf5 }, { 0x9f,0x5d,0x80,0xbe }, { 0x69,0xd0,0x93,0x7c }, { 0x6f,0xd5,0x2d,0xa9 }, { 0xcf,0x25,0x12,0xb3 }, { 0xc8,0xac,0x99,0x3b }, { 0x10,0x18,0x7d,0xa7 }, { 0xe8,0x9c,0x63,0x6e }, { 0xdb,0x3b,0xbb,0x7b }, { 0xcd,0x26,0x78,0x09 }, { 0x6e,0x59,0x18,0xf4 }, { 0xec,0x9a,0xb7,0x01 }, { 0x83,0x4f,0x9a,0xa8 }, { 0xe6,0x95,0x6e,0x65 }, { 0xaa,0xff,0xe6,0x7e }, { 0x21,0xbc,0xcf,0x08 }, { 0xef,0x15,0xe8,0xe6 }, { 0xba,0xe7,0x9b,0xd9 }, { 0x4a,0x6f,0x36,0xce }, { 0xea,0x9f,0x09,0xd4 }, { 0x29,0xb0,0x7c,0xd6 }, { 0x31,0xa4,0xb2,0xaf }, { 0x2a,0x3f,0x23,0x31 }, { 0xc6,0xa5,0x94,0x30 }, { 0x35,0xa2,0x66,0xc0 }, { 0x74,0x4e,0xbc,0x37 }, { 0xfc,0x82,0xca,0xa6 }, { 0xe0,0x90,0xd0,0xb0 }, { 0x33,0xa7,0xd8,0x15 }, { 0xf1,0x04,0x98,0x4a }, { 0x41,0xec,0xda,0xf7 }, { 0x7f,0xcd,0x50,0x0e }, { 0x17,0x91,0xf6,0x2f }, { 0x76,0x4d,0xd6,0x8d }, { 0x43,0xef,0xb0,0x4d }, { 0xcc,0xaa,0x4d,0x54 }, { 0xe4,0x96,0x04,0xdf }, { 0x9e,0xd1,0xb5,0xe3 }, { 0x4c,0x6a,0x88,0x1b }, { 0xc1,0x2c,0x1f,0xb8 }, { 0x46,0x65,0x51,0x7f }, { 0x9d,0x5e,0xea,0x04 }, { 0x01,0x8c,0x35,0x5d }, { 0xfa,0x87,0x74,0x73 }, { 0xfb,0x0b,0x41,0x2e }, { 0xb3,0x67,0x1d,0x5a }, { 0x92,0xdb,0xd2,0x52 }, { 0xe9,0x10,0x56,0x33 }, { 0x6d,0xd6,0x47,0x13 }, { 0x9a,0xd7,0x61,0x8c }, { 0x37,0xa1,0x0c,0x7a }, { 0x59,0xf8,0x14,0x8e }, { 0xeb,0x13,0x3c,0x89 }, { 0xce,0xa9,0x27,0xee }, { 0xb7,0x61,0xc9,0x35 }, { 0xe1,0x1c,0xe5,0xed }, { 0x7a,0x47,0xb1,0x3c }, { 0x9c,0xd2,0xdf,0x59 }, { 0x55,0xf2,0x73,0x3f }, { 0x18,0x14,0xce,0x79 }, { 0x73,0xc7,0x37,0xbf }, { 0x53,0xf7,0xcd,0xea }, { 0x5f,0xfd,0xaa,0x5b }, { 0xdf,0x3d,0x6f,0x14 }, { 0x78,0x44,0xdb,0x86 }, { 0xca,0xaf,0xf3,0x81 }, { 0xb9,0x68,0xc4,0x3e }, { 0x38,0x24,0x34,0x2c }, { 0xc2,0xa3,0x40,0x5f }, { 0x16,0x1d,0xc3,0x72 }, { 0xbc,0xe2,0x25,0x0c }, { 0x28,0x3c,0x49,0x8b }, { 0xff,0x0d,0x95,0x41 }, { 0x39,0xa8,0x01,0x71 }, { 0x08,0x0c,0xb3,0xde }, { 0xd8,0xb4,0xe4,0x9c }, { 0x64,0x56,0xc1,0x90 }, { 0x7b,0xcb,0x84,0x61 }, { 0xd5,0x32,0xb6,0x70 }, { 0x48,0x6c,0x5c,0x74 }, { 0xd0,0xb8,0x57,0x42 } }; static const byte T6[256][4] = { { 0x50,0x51,0xf4,0xa7 }, { 0x53,0x7e,0x41,0x65 }, { 0xc3,0x1a,0x17,0xa4 }, { 0x96,0x3a,0x27,0x5e }, { 0xcb,0x3b,0xab,0x6b }, { 0xf1,0x1f,0x9d,0x45 }, { 0xab,0xac,0xfa,0x58 }, { 0x93,0x4b,0xe3,0x03 }, { 0x55,0x20,0x30,0xfa }, { 0xf6,0xad,0x76,0x6d }, { 0x91,0x88,0xcc,0x76 }, { 0x25,0xf5,0x02,0x4c }, { 0xfc,0x4f,0xe5,0xd7 }, { 0xd7,0xc5,0x2a,0xcb }, { 0x80,0x26,0x35,0x44 }, { 0x8f,0xb5,0x62,0xa3 }, { 0x49,0xde,0xb1,0x5a }, { 0x67,0x25,0xba,0x1b }, { 0x98,0x45,0xea,0x0e }, { 0xe1,0x5d,0xfe,0xc0 }, { 0x02,0xc3,0x2f,0x75 }, { 0x12,0x81,0x4c,0xf0 }, { 0xa3,0x8d,0x46,0x97 }, { 0xc6,0x6b,0xd3,0xf9 }, { 0xe7,0x03,0x8f,0x5f }, { 0x95,0x15,0x92,0x9c }, { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, { 0x2d,0xd4,0xbe,0x83 }, { 0xd3,0x58,0x74,0x21 }, { 0x29,0x49,0xe0,0x69 }, { 0x44,0x8e,0xc9,0xc8 }, { 0x6a,0x75,0xc2,0x89 }, { 0x78,0xf4,0x8e,0x79 }, { 0x6b,0x99,0x58,0x3e }, { 0xdd,0x27,0xb9,0x71 }, { 0xb6,0xbe,0xe1,0x4f }, { 0x17,0xf0,0x88,0xad }, { 0x66,0xc9,0x20,0xac }, { 0xb4,0x7d,0xce,0x3a }, { 0x18,0x63,0xdf,0x4a }, { 0x82,0xe5,0x1a,0x31 }, { 0x60,0x97,0x51,0x33 }, { 0x45,0x62,0x53,0x7f }, { 0xe0,0xb1,0x64,0x77 }, { 0x84,0xbb,0x6b,0xae }, { 0x1c,0xfe,0x81,0xa0 }, { 0x94,0xf9,0x08,0x2b }, { 0x58,0x70,0x48,0x68 }, { 0x19,0x8f,0x45,0xfd }, { 0x87,0x94,0xde,0x6c }, { 0xb7,0x52,0x7b,0xf8 }, { 0x23,0xab,0x73,0xd3 }, { 0xe2,0x72,0x4b,0x02 }, { 0x57,0xe3,0x1f,0x8f }, { 0x2a,0x66,0x55,0xab }, { 0x07,0xb2,0xeb,0x28 }, { 0x03,0x2f,0xb5,0xc2 }, { 0x9a,0x86,0xc5,0x7b }, { 0xa5,0xd3,0x37,0x08 }, { 0xf2,0x30,0x28,0x87 }, { 0xb2,0x23,0xbf,0xa5 }, { 0xba,0x02,0x03,0x6a }, { 0x5c,0xed,0x16,0x82 }, { 0x2b,0x8a,0xcf,0x1c }, { 0x92,0xa7,0x79,0xb4 }, { 0xf0,0xf3,0x07,0xf2 }, { 0xa1,0x4e,0x69,0xe2 }, { 0xcd,0x65,0xda,0xf4 }, { 0xd5,0x06,0x05,0xbe }, { 0x1f,0xd1,0x34,0x62 }, { 0x8a,0xc4,0xa6,0xfe }, { 0x9d,0x34,0x2e,0x53 }, { 0xa0,0xa2,0xf3,0x55 }, { 0x32,0x05,0x8a,0xe1 }, { 0x75,0xa4,0xf6,0xeb }, { 0x39,0x0b,0x83,0xec }, { 0xaa,0x40,0x60,0xef }, { 0x06,0x5e,0x71,0x9f }, { 0x51,0xbd,0x6e,0x10 }, { 0xf9,0x3e,0x21,0x8a }, { 0x3d,0x96,0xdd,0x06 }, { 0xae,0xdd,0x3e,0x05 }, { 0x46,0x4d,0xe6,0xbd }, { 0xb5,0x91,0x54,0x8d }, { 0x05,0x71,0xc4,0x5d }, { 0x6f,0x04,0x06,0xd4 }, { 0xff,0x60,0x50,0x15 }, { 0x24,0x19,0x98,0xfb }, { 0x97,0xd6,0xbd,0xe9 }, { 0xcc,0x89,0x40,0x43 }, { 0x77,0x67,0xd9,0x9e }, { 0xbd,0xb0,0xe8,0x42 }, { 0x88,0x07,0x89,0x8b }, { 0x38,0xe7,0x19,0x5b }, { 0xdb,0x79,0xc8,0xee }, { 0x47,0xa1,0x7c,0x0a }, { 0xe9,0x7c,0x42,0x0f }, { 0xc9,0xf8,0x84,0x1e }, { 0x00,0x00,0x00,0x00 }, { 0x83,0x09,0x80,0x86 }, { 0x48,0x32,0x2b,0xed }, { 0xac,0x1e,0x11,0x70 }, { 0x4e,0x6c,0x5a,0x72 }, { 0xfb,0xfd,0x0e,0xff }, { 0x56,0x0f,0x85,0x38 }, { 0x1e,0x3d,0xae,0xd5 }, { 0x27,0x36,0x2d,0x39 }, { 0x64,0x0a,0x0f,0xd9 }, { 0x21,0x68,0x5c,0xa6 }, { 0xd1,0x9b,0x5b,0x54 }, { 0x3a,0x24,0x36,0x2e }, { 0xb1,0x0c,0x0a,0x67 }, { 0x0f,0x93,0x57,0xe7 }, { 0xd2,0xb4,0xee,0x96 }, { 0x9e,0x1b,0x9b,0x91 }, { 0x4f,0x80,0xc0,0xc5 }, { 0xa2,0x61,0xdc,0x20 }, { 0x69,0x5a,0x77,0x4b }, { 0x16,0x1c,0x12,0x1a }, { 0x0a,0xe2,0x93,0xba }, { 0xe5,0xc0,0xa0,0x2a }, { 0x43,0x3c,0x22,0xe0 }, { 0x1d,0x12,0x1b,0x17 }, { 0x0b,0x0e,0x09,0x0d }, { 0xad,0xf2,0x8b,0xc7 }, { 0xb9,0x2d,0xb6,0xa8 }, { 0xc8,0x14,0x1e,0xa9 }, { 0x85,0x57,0xf1,0x19 }, { 0x4c,0xaf,0x75,0x07 }, { 0xbb,0xee,0x99,0xdd }, { 0xfd,0xa3,0x7f,0x60 }, { 0x9f,0xf7,0x01,0x26 }, { 0xbc,0x5c,0x72,0xf5 }, { 0xc5,0x44,0x66,0x3b }, { 0x34,0x5b,0xfb,0x7e }, { 0x76,0x8b,0x43,0x29 }, { 0xdc,0xcb,0x23,0xc6 }, { 0x68,0xb6,0xed,0xfc }, { 0x63,0xb8,0xe4,0xf1 }, { 0xca,0xd7,0x31,0xdc }, { 0x10,0x42,0x63,0x85 }, { 0x40,0x13,0x97,0x22 }, { 0x20,0x84,0xc6,0x11 }, { 0x7d,0x85,0x4a,0x24 }, { 0xf8,0xd2,0xbb,0x3d }, { 0x11,0xae,0xf9,0x32 }, { 0x6d,0xc7,0x29,0xa1 }, { 0x4b,0x1d,0x9e,0x2f }, { 0xf3,0xdc,0xb2,0x30 }, { 0xec,0x0d,0x86,0x52 }, { 0xd0,0x77,0xc1,0xe3 }, { 0x6c,0x2b,0xb3,0x16 }, { 0x99,0xa9,0x70,0xb9 }, { 0xfa,0x11,0x94,0x48 }, { 0x22,0x47,0xe9,0x64 }, { 0xc4,0xa8,0xfc,0x8c }, { 0x1a,0xa0,0xf0,0x3f }, { 0xd8,0x56,0x7d,0x2c }, { 0xef,0x22,0x33,0x90 }, { 0xc7,0x87,0x49,0x4e }, { 0xc1,0xd9,0x38,0xd1 }, { 0xfe,0x8c,0xca,0xa2 }, { 0x36,0x98,0xd4,0x0b }, { 0xcf,0xa6,0xf5,0x81 }, { 0x28,0xa5,0x7a,0xde }, { 0x26,0xda,0xb7,0x8e }, { 0xa4,0x3f,0xad,0xbf }, { 0xe4,0x2c,0x3a,0x9d }, { 0x0d,0x50,0x78,0x92 }, { 0x9b,0x6a,0x5f,0xcc }, { 0x62,0x54,0x7e,0x46 }, { 0xc2,0xf6,0x8d,0x13 }, { 0xe8,0x90,0xd8,0xb8 }, { 0x5e,0x2e,0x39,0xf7 }, { 0xf5,0x82,0xc3,0xaf }, { 0xbe,0x9f,0x5d,0x80 }, { 0x7c,0x69,0xd0,0x93 }, { 0xa9,0x6f,0xd5,0x2d }, { 0xb3,0xcf,0x25,0x12 }, { 0x3b,0xc8,0xac,0x99 }, { 0xa7,0x10,0x18,0x7d }, { 0x6e,0xe8,0x9c,0x63 }, { 0x7b,0xdb,0x3b,0xbb }, { 0x09,0xcd,0x26,0x78 }, { 0xf4,0x6e,0x59,0x18 }, { 0x01,0xec,0x9a,0xb7 }, { 0xa8,0x83,0x4f,0x9a }, { 0x65,0xe6,0x95,0x6e }, { 0x7e,0xaa,0xff,0xe6 }, { 0x08,0x21,0xbc,0xcf }, { 0xe6,0xef,0x15,0xe8 }, { 0xd9,0xba,0xe7,0x9b }, { 0xce,0x4a,0x6f,0x36 }, { 0xd4,0xea,0x9f,0x09 }, { 0xd6,0x29,0xb0,0x7c }, { 0xaf,0x31,0xa4,0xb2 }, { 0x31,0x2a,0x3f,0x23 }, { 0x30,0xc6,0xa5,0x94 }, { 0xc0,0x35,0xa2,0x66 }, { 0x37,0x74,0x4e,0xbc }, { 0xa6,0xfc,0x82,0xca }, { 0xb0,0xe0,0x90,0xd0 }, { 0x15,0x33,0xa7,0xd8 }, { 0x4a,0xf1,0x04,0x98 }, { 0xf7,0x41,0xec,0xda }, { 0x0e,0x7f,0xcd,0x50 }, { 0x2f,0x17,0x91,0xf6 }, { 0x8d,0x76,0x4d,0xd6 }, { 0x4d,0x43,0xef,0xb0 }, { 0x54,0xcc,0xaa,0x4d }, { 0xdf,0xe4,0x96,0x04 }, { 0xe3,0x9e,0xd1,0xb5 }, { 0x1b,0x4c,0x6a,0x88 }, { 0xb8,0xc1,0x2c,0x1f }, { 0x7f,0x46,0x65,0x51 }, { 0x04,0x9d,0x5e,0xea }, { 0x5d,0x01,0x8c,0x35 }, { 0x73,0xfa,0x87,0x74 }, { 0x2e,0xfb,0x0b,0x41 }, { 0x5a,0xb3,0x67,0x1d }, { 0x52,0x92,0xdb,0xd2 }, { 0x33,0xe9,0x10,0x56 }, { 0x13,0x6d,0xd6,0x47 }, { 0x8c,0x9a,0xd7,0x61 }, { 0x7a,0x37,0xa1,0x0c }, { 0x8e,0x59,0xf8,0x14 }, { 0x89,0xeb,0x13,0x3c }, { 0xee,0xce,0xa9,0x27 }, { 0x35,0xb7,0x61,0xc9 }, { 0xed,0xe1,0x1c,0xe5 }, { 0x3c,0x7a,0x47,0xb1 }, { 0x59,0x9c,0xd2,0xdf }, { 0x3f,0x55,0xf2,0x73 }, { 0x79,0x18,0x14,0xce }, { 0xbf,0x73,0xc7,0x37 }, { 0xea,0x53,0xf7,0xcd }, { 0x5b,0x5f,0xfd,0xaa }, { 0x14,0xdf,0x3d,0x6f }, { 0x86,0x78,0x44,0xdb }, { 0x81,0xca,0xaf,0xf3 }, { 0x3e,0xb9,0x68,0xc4 }, { 0x2c,0x38,0x24,0x34 }, { 0x5f,0xc2,0xa3,0x40 }, { 0x72,0x16,0x1d,0xc3 }, { 0x0c,0xbc,0xe2,0x25 }, { 0x8b,0x28,0x3c,0x49 }, { 0x41,0xff,0x0d,0x95 }, { 0x71,0x39,0xa8,0x01 }, { 0xde,0x08,0x0c,0xb3 }, { 0x9c,0xd8,0xb4,0xe4 }, { 0x90,0x64,0x56,0xc1 }, { 0x61,0x7b,0xcb,0x84 }, { 0x70,0xd5,0x32,0xb6 }, { 0x74,0x48,0x6c,0x5c }, { 0x42,0xd0,0xb8,0x57 } }; static const byte T7[256][4] = { { 0xa7,0x50,0x51,0xf4 }, { 0x65,0x53,0x7e,0x41 }, { 0xa4,0xc3,0x1a,0x17 }, { 0x5e,0x96,0x3a,0x27 }, { 0x6b,0xcb,0x3b,0xab }, { 0x45,0xf1,0x1f,0x9d }, { 0x58,0xab,0xac,0xfa }, { 0x03,0x93,0x4b,0xe3 }, { 0xfa,0x55,0x20,0x30 }, { 0x6d,0xf6,0xad,0x76 }, { 0x76,0x91,0x88,0xcc }, { 0x4c,0x25,0xf5,0x02 }, { 0xd7,0xfc,0x4f,0xe5 }, { 0xcb,0xd7,0xc5,0x2a }, { 0x44,0x80,0x26,0x35 }, { 0xa3,0x8f,0xb5,0x62 }, { 0x5a,0x49,0xde,0xb1 }, { 0x1b,0x67,0x25,0xba }, { 0x0e,0x98,0x45,0xea }, { 0xc0,0xe1,0x5d,0xfe }, { 0x75,0x02,0xc3,0x2f }, { 0xf0,0x12,0x81,0x4c }, { 0x97,0xa3,0x8d,0x46 }, { 0xf9,0xc6,0x6b,0xd3 }, { 0x5f,0xe7,0x03,0x8f }, { 0x9c,0x95,0x15,0x92 }, { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, { 0x83,0x2d,0xd4,0xbe }, { 0x21,0xd3,0x58,0x74 }, { 0x69,0x29,0x49,0xe0 }, { 0xc8,0x44,0x8e,0xc9 }, { 0x89,0x6a,0x75,0xc2 }, { 0x79,0x78,0xf4,0x8e }, { 0x3e,0x6b,0x99,0x58 }, { 0x71,0xdd,0x27,0xb9 }, { 0x4f,0xb6,0xbe,0xe1 }, { 0xad,0x17,0xf0,0x88 }, { 0xac,0x66,0xc9,0x20 }, { 0x3a,0xb4,0x7d,0xce }, { 0x4a,0x18,0x63,0xdf }, { 0x31,0x82,0xe5,0x1a }, { 0x33,0x60,0x97,0x51 }, { 0x7f,0x45,0x62,0x53 }, { 0x77,0xe0,0xb1,0x64 }, { 0xae,0x84,0xbb,0x6b }, { 0xa0,0x1c,0xfe,0x81 }, { 0x2b,0x94,0xf9,0x08 }, { 0x68,0x58,0x70,0x48 }, { 0xfd,0x19,0x8f,0x45 }, { 0x6c,0x87,0x94,0xde }, { 0xf8,0xb7,0x52,0x7b }, { 0xd3,0x23,0xab,0x73 }, { 0x02,0xe2,0x72,0x4b }, { 0x8f,0x57,0xe3,0x1f }, { 0xab,0x2a,0x66,0x55 }, { 0x28,0x07,0xb2,0xeb }, { 0xc2,0x03,0x2f,0xb5 }, { 0x7b,0x9a,0x86,0xc5 }, { 0x08,0xa5,0xd3,0x37 }, { 0x87,0xf2,0x30,0x28 }, { 0xa5,0xb2,0x23,0xbf }, { 0x6a,0xba,0x02,0x03 }, { 0x82,0x5c,0xed,0x16 }, { 0x1c,0x2b,0x8a,0xcf }, { 0xb4,0x92,0xa7,0x79 }, { 0xf2,0xf0,0xf3,0x07 }, { 0xe2,0xa1,0x4e,0x69 }, { 0xf4,0xcd,0x65,0xda }, { 0xbe,0xd5,0x06,0x05 }, { 0x62,0x1f,0xd1,0x34 }, { 0xfe,0x8a,0xc4,0xa6 }, { 0x53,0x9d,0x34,0x2e }, { 0x55,0xa0,0xa2,0xf3 }, { 0xe1,0x32,0x05,0x8a }, { 0xeb,0x75,0xa4,0xf6 }, { 0xec,0x39,0x0b,0x83 }, { 0xef,0xaa,0x40,0x60 }, { 0x9f,0x06,0x5e,0x71 }, { 0x10,0x51,0xbd,0x6e }, { 0x8a,0xf9,0x3e,0x21 }, { 0x06,0x3d,0x96,0xdd }, { 0x05,0xae,0xdd,0x3e }, { 0xbd,0x46,0x4d,0xe6 }, { 0x8d,0xb5,0x91,0x54 }, { 0x5d,0x05,0x71,0xc4 }, { 0xd4,0x6f,0x04,0x06 }, { 0x15,0xff,0x60,0x50 }, { 0xfb,0x24,0x19,0x98 }, { 0xe9,0x97,0xd6,0xbd }, { 0x43,0xcc,0x89,0x40 }, { 0x9e,0x77,0x67,0xd9 }, { 0x42,0xbd,0xb0,0xe8 }, { 0x8b,0x88,0x07,0x89 }, { 0x5b,0x38,0xe7,0x19 }, { 0xee,0xdb,0x79,0xc8 }, { 0x0a,0x47,0xa1,0x7c }, { 0x0f,0xe9,0x7c,0x42 }, { 0x1e,0xc9,0xf8,0x84 }, { 0x00,0x00,0x00,0x00 }, { 0x86,0x83,0x09,0x80 }, { 0xed,0x48,0x32,0x2b }, { 0x70,0xac,0x1e,0x11 }, { 0x72,0x4e,0x6c,0x5a }, { 0xff,0xfb,0xfd,0x0e }, { 0x38,0x56,0x0f,0x85 }, { 0xd5,0x1e,0x3d,0xae }, { 0x39,0x27,0x36,0x2d }, { 0xd9,0x64,0x0a,0x0f }, { 0xa6,0x21,0x68,0x5c }, { 0x54,0xd1,0x9b,0x5b }, { 0x2e,0x3a,0x24,0x36 }, { 0x67,0xb1,0x0c,0x0a }, { 0xe7,0x0f,0x93,0x57 }, { 0x96,0xd2,0xb4,0xee }, { 0x91,0x9e,0x1b,0x9b }, { 0xc5,0x4f,0x80,0xc0 }, { 0x20,0xa2,0x61,0xdc }, { 0x4b,0x69,0x5a,0x77 }, { 0x1a,0x16,0x1c,0x12 }, { 0xba,0x0a,0xe2,0x93 }, { 0x2a,0xe5,0xc0,0xa0 }, { 0xe0,0x43,0x3c,0x22 }, { 0x17,0x1d,0x12,0x1b }, { 0x0d,0x0b,0x0e,0x09 }, { 0xc7,0xad,0xf2,0x8b }, { 0xa8,0xb9,0x2d,0xb6 }, { 0xa9,0xc8,0x14,0x1e }, { 0x19,0x85,0x57,0xf1 }, { 0x07,0x4c,0xaf,0x75 }, { 0xdd,0xbb,0xee,0x99 }, { 0x60,0xfd,0xa3,0x7f }, { 0x26,0x9f,0xf7,0x01 }, { 0xf5,0xbc,0x5c,0x72 }, { 0x3b,0xc5,0x44,0x66 }, { 0x7e,0x34,0x5b,0xfb }, { 0x29,0x76,0x8b,0x43 }, { 0xc6,0xdc,0xcb,0x23 }, { 0xfc,0x68,0xb6,0xed }, { 0xf1,0x63,0xb8,0xe4 }, { 0xdc,0xca,0xd7,0x31 }, { 0x85,0x10,0x42,0x63 }, { 0x22,0x40,0x13,0x97 }, { 0x11,0x20,0x84,0xc6 }, { 0x24,0x7d,0x85,0x4a }, { 0x3d,0xf8,0xd2,0xbb }, { 0x32,0x11,0xae,0xf9 }, { 0xa1,0x6d,0xc7,0x29 }, { 0x2f,0x4b,0x1d,0x9e }, { 0x30,0xf3,0xdc,0xb2 }, { 0x52,0xec,0x0d,0x86 }, { 0xe3,0xd0,0x77,0xc1 }, { 0x16,0x6c,0x2b,0xb3 }, { 0xb9,0x99,0xa9,0x70 }, { 0x48,0xfa,0x11,0x94 }, { 0x64,0x22,0x47,0xe9 }, { 0x8c,0xc4,0xa8,0xfc }, { 0x3f,0x1a,0xa0,0xf0 }, { 0x2c,0xd8,0x56,0x7d }, { 0x90,0xef,0x22,0x33 }, { 0x4e,0xc7,0x87,0x49 }, { 0xd1,0xc1,0xd9,0x38 }, { 0xa2,0xfe,0x8c,0xca }, { 0x0b,0x36,0x98,0xd4 }, { 0x81,0xcf,0xa6,0xf5 }, { 0xde,0x28,0xa5,0x7a }, { 0x8e,0x26,0xda,0xb7 }, { 0xbf,0xa4,0x3f,0xad }, { 0x9d,0xe4,0x2c,0x3a }, { 0x92,0x0d,0x50,0x78 }, { 0xcc,0x9b,0x6a,0x5f }, { 0x46,0x62,0x54,0x7e }, { 0x13,0xc2,0xf6,0x8d }, { 0xb8,0xe8,0x90,0xd8 }, { 0xf7,0x5e,0x2e,0x39 }, { 0xaf,0xf5,0x82,0xc3 }, { 0x80,0xbe,0x9f,0x5d }, { 0x93,0x7c,0x69,0xd0 }, { 0x2d,0xa9,0x6f,0xd5 }, { 0x12,0xb3,0xcf,0x25 }, { 0x99,0x3b,0xc8,0xac }, { 0x7d,0xa7,0x10,0x18 }, { 0x63,0x6e,0xe8,0x9c }, { 0xbb,0x7b,0xdb,0x3b }, { 0x78,0x09,0xcd,0x26 }, { 0x18,0xf4,0x6e,0x59 }, { 0xb7,0x01,0xec,0x9a }, { 0x9a,0xa8,0x83,0x4f }, { 0x6e,0x65,0xe6,0x95 }, { 0xe6,0x7e,0xaa,0xff }, { 0xcf,0x08,0x21,0xbc }, { 0xe8,0xe6,0xef,0x15 }, { 0x9b,0xd9,0xba,0xe7 }, { 0x36,0xce,0x4a,0x6f }, { 0x09,0xd4,0xea,0x9f }, { 0x7c,0xd6,0x29,0xb0 }, { 0xb2,0xaf,0x31,0xa4 }, { 0x23,0x31,0x2a,0x3f }, { 0x94,0x30,0xc6,0xa5 }, { 0x66,0xc0,0x35,0xa2 }, { 0xbc,0x37,0x74,0x4e }, { 0xca,0xa6,0xfc,0x82 }, { 0xd0,0xb0,0xe0,0x90 }, { 0xd8,0x15,0x33,0xa7 }, { 0x98,0x4a,0xf1,0x04 }, { 0xda,0xf7,0x41,0xec }, { 0x50,0x0e,0x7f,0xcd }, { 0xf6,0x2f,0x17,0x91 }, { 0xd6,0x8d,0x76,0x4d }, { 0xb0,0x4d,0x43,0xef }, { 0x4d,0x54,0xcc,0xaa }, { 0x04,0xdf,0xe4,0x96 }, { 0xb5,0xe3,0x9e,0xd1 }, { 0x88,0x1b,0x4c,0x6a }, { 0x1f,0xb8,0xc1,0x2c }, { 0x51,0x7f,0x46,0x65 }, { 0xea,0x04,0x9d,0x5e }, { 0x35,0x5d,0x01,0x8c }, { 0x74,0x73,0xfa,0x87 }, { 0x41,0x2e,0xfb,0x0b }, { 0x1d,0x5a,0xb3,0x67 }, { 0xd2,0x52,0x92,0xdb }, { 0x56,0x33,0xe9,0x10 }, { 0x47,0x13,0x6d,0xd6 }, { 0x61,0x8c,0x9a,0xd7 }, { 0x0c,0x7a,0x37,0xa1 }, { 0x14,0x8e,0x59,0xf8 }, { 0x3c,0x89,0xeb,0x13 }, { 0x27,0xee,0xce,0xa9 }, { 0xc9,0x35,0xb7,0x61 }, { 0xe5,0xed,0xe1,0x1c }, { 0xb1,0x3c,0x7a,0x47 }, { 0xdf,0x59,0x9c,0xd2 }, { 0x73,0x3f,0x55,0xf2 }, { 0xce,0x79,0x18,0x14 }, { 0x37,0xbf,0x73,0xc7 }, { 0xcd,0xea,0x53,0xf7 }, { 0xaa,0x5b,0x5f,0xfd }, { 0x6f,0x14,0xdf,0x3d }, { 0xdb,0x86,0x78,0x44 }, { 0xf3,0x81,0xca,0xaf }, { 0xc4,0x3e,0xb9,0x68 }, { 0x34,0x2c,0x38,0x24 }, { 0x40,0x5f,0xc2,0xa3 }, { 0xc3,0x72,0x16,0x1d }, { 0x25,0x0c,0xbc,0xe2 }, { 0x49,0x8b,0x28,0x3c }, { 0x95,0x41,0xff,0x0d }, { 0x01,0x71,0x39,0xa8 }, { 0xb3,0xde,0x08,0x0c }, { 0xe4,0x9c,0xd8,0xb4 }, { 0xc1,0x90,0x64,0x56 }, { 0x84,0x61,0x7b,0xcb }, { 0xb6,0x70,0xd5,0x32 }, { 0x5c,0x74,0x48,0x6c }, { 0x57,0x42,0xd0,0xb8 } }; static const byte T8[256][4] = { { 0xf4,0xa7,0x50,0x51 }, { 0x41,0x65,0x53,0x7e }, { 0x17,0xa4,0xc3,0x1a }, { 0x27,0x5e,0x96,0x3a }, { 0xab,0x6b,0xcb,0x3b }, { 0x9d,0x45,0xf1,0x1f }, { 0xfa,0x58,0xab,0xac }, { 0xe3,0x03,0x93,0x4b }, { 0x30,0xfa,0x55,0x20 }, { 0x76,0x6d,0xf6,0xad }, { 0xcc,0x76,0x91,0x88 }, { 0x02,0x4c,0x25,0xf5 }, { 0xe5,0xd7,0xfc,0x4f }, { 0x2a,0xcb,0xd7,0xc5 }, { 0x35,0x44,0x80,0x26 }, { 0x62,0xa3,0x8f,0xb5 }, { 0xb1,0x5a,0x49,0xde }, { 0xba,0x1b,0x67,0x25 }, { 0xea,0x0e,0x98,0x45 }, { 0xfe,0xc0,0xe1,0x5d }, { 0x2f,0x75,0x02,0xc3 }, { 0x4c,0xf0,0x12,0x81 }, { 0x46,0x97,0xa3,0x8d }, { 0xd3,0xf9,0xc6,0x6b }, { 0x8f,0x5f,0xe7,0x03 }, { 0x92,0x9c,0x95,0x15 }, { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, { 0xbe,0x83,0x2d,0xd4 }, { 0x74,0x21,0xd3,0x58 }, { 0xe0,0x69,0x29,0x49 }, { 0xc9,0xc8,0x44,0x8e }, { 0xc2,0x89,0x6a,0x75 }, { 0x8e,0x79,0x78,0xf4 }, { 0x58,0x3e,0x6b,0x99 }, { 0xb9,0x71,0xdd,0x27 }, { 0xe1,0x4f,0xb6,0xbe }, { 0x88,0xad,0x17,0xf0 }, { 0x20,0xac,0x66,0xc9 }, { 0xce,0x3a,0xb4,0x7d }, { 0xdf,0x4a,0x18,0x63 }, { 0x1a,0x31,0x82,0xe5 }, { 0x51,0x33,0x60,0x97 }, { 0x53,0x7f,0x45,0x62 }, { 0x64,0x77,0xe0,0xb1 }, { 0x6b,0xae,0x84,0xbb }, { 0x81,0xa0,0x1c,0xfe }, { 0x08,0x2b,0x94,0xf9 }, { 0x48,0x68,0x58,0x70 }, { 0x45,0xfd,0x19,0x8f }, { 0xde,0x6c,0x87,0x94 }, { 0x7b,0xf8,0xb7,0x52 }, { 0x73,0xd3,0x23,0xab }, { 0x4b,0x02,0xe2,0x72 }, { 0x1f,0x8f,0x57,0xe3 }, { 0x55,0xab,0x2a,0x66 }, { 0xeb,0x28,0x07,0xb2 }, { 0xb5,0xc2,0x03,0x2f }, { 0xc5,0x7b,0x9a,0x86 }, { 0x37,0x08,0xa5,0xd3 }, { 0x28,0x87,0xf2,0x30 }, { 0xbf,0xa5,0xb2,0x23 }, { 0x03,0x6a,0xba,0x02 }, { 0x16,0x82,0x5c,0xed }, { 0xcf,0x1c,0x2b,0x8a }, { 0x79,0xb4,0x92,0xa7 }, { 0x07,0xf2,0xf0,0xf3 }, { 0x69,0xe2,0xa1,0x4e }, { 0xda,0xf4,0xcd,0x65 }, { 0x05,0xbe,0xd5,0x06 }, { 0x34,0x62,0x1f,0xd1 }, { 0xa6,0xfe,0x8a,0xc4 }, { 0x2e,0x53,0x9d,0x34 }, { 0xf3,0x55,0xa0,0xa2 }, { 0x8a,0xe1,0x32,0x05 }, { 0xf6,0xeb,0x75,0xa4 }, { 0x83,0xec,0x39,0x0b }, { 0x60,0xef,0xaa,0x40 }, { 0x71,0x9f,0x06,0x5e }, { 0x6e,0x10,0x51,0xbd }, { 0x21,0x8a,0xf9,0x3e }, { 0xdd,0x06,0x3d,0x96 }, { 0x3e,0x05,0xae,0xdd }, { 0xe6,0xbd,0x46,0x4d }, { 0x54,0x8d,0xb5,0x91 }, { 0xc4,0x5d,0x05,0x71 }, { 0x06,0xd4,0x6f,0x04 }, { 0x50,0x15,0xff,0x60 }, { 0x98,0xfb,0x24,0x19 }, { 0xbd,0xe9,0x97,0xd6 }, { 0x40,0x43,0xcc,0x89 }, { 0xd9,0x9e,0x77,0x67 }, { 0xe8,0x42,0xbd,0xb0 }, { 0x89,0x8b,0x88,0x07 }, { 0x19,0x5b,0x38,0xe7 }, { 0xc8,0xee,0xdb,0x79 }, { 0x7c,0x0a,0x47,0xa1 }, { 0x42,0x0f,0xe9,0x7c }, { 0x84,0x1e,0xc9,0xf8 }, { 0x00,0x00,0x00,0x00 }, { 0x80,0x86,0x83,0x09 }, { 0x2b,0xed,0x48,0x32 }, { 0x11,0x70,0xac,0x1e }, { 0x5a,0x72,0x4e,0x6c }, { 0x0e,0xff,0xfb,0xfd }, { 0x85,0x38,0x56,0x0f }, { 0xae,0xd5,0x1e,0x3d }, { 0x2d,0x39,0x27,0x36 }, { 0x0f,0xd9,0x64,0x0a }, { 0x5c,0xa6,0x21,0x68 }, { 0x5b,0x54,0xd1,0x9b }, { 0x36,0x2e,0x3a,0x24 }, { 0x0a,0x67,0xb1,0x0c }, { 0x57,0xe7,0x0f,0x93 }, { 0xee,0x96,0xd2,0xb4 }, { 0x9b,0x91,0x9e,0x1b }, { 0xc0,0xc5,0x4f,0x80 }, { 0xdc,0x20,0xa2,0x61 }, { 0x77,0x4b,0x69,0x5a }, { 0x12,0x1a,0x16,0x1c }, { 0x93,0xba,0x0a,0xe2 }, { 0xa0,0x2a,0xe5,0xc0 }, { 0x22,0xe0,0x43,0x3c }, { 0x1b,0x17,0x1d,0x12 }, { 0x09,0x0d,0x0b,0x0e }, { 0x8b,0xc7,0xad,0xf2 }, { 0xb6,0xa8,0xb9,0x2d }, { 0x1e,0xa9,0xc8,0x14 }, { 0xf1,0x19,0x85,0x57 }, { 0x75,0x07,0x4c,0xaf }, { 0x99,0xdd,0xbb,0xee }, { 0x7f,0x60,0xfd,0xa3 }, { 0x01,0x26,0x9f,0xf7 }, { 0x72,0xf5,0xbc,0x5c }, { 0x66,0x3b,0xc5,0x44 }, { 0xfb,0x7e,0x34,0x5b }, { 0x43,0x29,0x76,0x8b }, { 0x23,0xc6,0xdc,0xcb }, { 0xed,0xfc,0x68,0xb6 }, { 0xe4,0xf1,0x63,0xb8 }, { 0x31,0xdc,0xca,0xd7 }, { 0x63,0x85,0x10,0x42 }, { 0x97,0x22,0x40,0x13 }, { 0xc6,0x11,0x20,0x84 }, { 0x4a,0x24,0x7d,0x85 }, { 0xbb,0x3d,0xf8,0xd2 }, { 0xf9,0x32,0x11,0xae }, { 0x29,0xa1,0x6d,0xc7 }, { 0x9e,0x2f,0x4b,0x1d }, { 0xb2,0x30,0xf3,0xdc }, { 0x86,0x52,0xec,0x0d }, { 0xc1,0xe3,0xd0,0x77 }, { 0xb3,0x16,0x6c,0x2b }, { 0x70,0xb9,0x99,0xa9 }, { 0x94,0x48,0xfa,0x11 }, { 0xe9,0x64,0x22,0x47 }, { 0xfc,0x8c,0xc4,0xa8 }, { 0xf0,0x3f,0x1a,0xa0 }, { 0x7d,0x2c,0xd8,0x56 }, { 0x33,0x90,0xef,0x22 }, { 0x49,0x4e,0xc7,0x87 }, { 0x38,0xd1,0xc1,0xd9 }, { 0xca,0xa2,0xfe,0x8c }, { 0xd4,0x0b,0x36,0x98 }, { 0xf5,0x81,0xcf,0xa6 }, { 0x7a,0xde,0x28,0xa5 }, { 0xb7,0x8e,0x26,0xda }, { 0xad,0xbf,0xa4,0x3f }, { 0x3a,0x9d,0xe4,0x2c }, { 0x78,0x92,0x0d,0x50 }, { 0x5f,0xcc,0x9b,0x6a }, { 0x7e,0x46,0x62,0x54 }, { 0x8d,0x13,0xc2,0xf6 }, { 0xd8,0xb8,0xe8,0x90 }, { 0x39,0xf7,0x5e,0x2e }, { 0xc3,0xaf,0xf5,0x82 }, { 0x5d,0x80,0xbe,0x9f }, { 0xd0,0x93,0x7c,0x69 }, { 0xd5,0x2d,0xa9,0x6f }, { 0x25,0x12,0xb3,0xcf }, { 0xac,0x99,0x3b,0xc8 }, { 0x18,0x7d,0xa7,0x10 }, { 0x9c,0x63,0x6e,0xe8 }, { 0x3b,0xbb,0x7b,0xdb }, { 0x26,0x78,0x09,0xcd }, { 0x59,0x18,0xf4,0x6e }, { 0x9a,0xb7,0x01,0xec }, { 0x4f,0x9a,0xa8,0x83 }, { 0x95,0x6e,0x65,0xe6 }, { 0xff,0xe6,0x7e,0xaa }, { 0xbc,0xcf,0x08,0x21 }, { 0x15,0xe8,0xe6,0xef }, { 0xe7,0x9b,0xd9,0xba }, { 0x6f,0x36,0xce,0x4a }, { 0x9f,0x09,0xd4,0xea }, { 0xb0,0x7c,0xd6,0x29 }, { 0xa4,0xb2,0xaf,0x31 }, { 0x3f,0x23,0x31,0x2a }, { 0xa5,0x94,0x30,0xc6 }, { 0xa2,0x66,0xc0,0x35 }, { 0x4e,0xbc,0x37,0x74 }, { 0x82,0xca,0xa6,0xfc }, { 0x90,0xd0,0xb0,0xe0 }, { 0xa7,0xd8,0x15,0x33 }, { 0x04,0x98,0x4a,0xf1 }, { 0xec,0xda,0xf7,0x41 }, { 0xcd,0x50,0x0e,0x7f }, { 0x91,0xf6,0x2f,0x17 }, { 0x4d,0xd6,0x8d,0x76 }, { 0xef,0xb0,0x4d,0x43 }, { 0xaa,0x4d,0x54,0xcc }, { 0x96,0x04,0xdf,0xe4 }, { 0xd1,0xb5,0xe3,0x9e }, { 0x6a,0x88,0x1b,0x4c }, { 0x2c,0x1f,0xb8,0xc1 }, { 0x65,0x51,0x7f,0x46 }, { 0x5e,0xea,0x04,0x9d }, { 0x8c,0x35,0x5d,0x01 }, { 0x87,0x74,0x73,0xfa }, { 0x0b,0x41,0x2e,0xfb }, { 0x67,0x1d,0x5a,0xb3 }, { 0xdb,0xd2,0x52,0x92 }, { 0x10,0x56,0x33,0xe9 }, { 0xd6,0x47,0x13,0x6d }, { 0xd7,0x61,0x8c,0x9a }, { 0xa1,0x0c,0x7a,0x37 }, { 0xf8,0x14,0x8e,0x59 }, { 0x13,0x3c,0x89,0xeb }, { 0xa9,0x27,0xee,0xce }, { 0x61,0xc9,0x35,0xb7 }, { 0x1c,0xe5,0xed,0xe1 }, { 0x47,0xb1,0x3c,0x7a }, { 0xd2,0xdf,0x59,0x9c }, { 0xf2,0x73,0x3f,0x55 }, { 0x14,0xce,0x79,0x18 }, { 0xc7,0x37,0xbf,0x73 }, { 0xf7,0xcd,0xea,0x53 }, { 0xfd,0xaa,0x5b,0x5f }, { 0x3d,0x6f,0x14,0xdf }, { 0x44,0xdb,0x86,0x78 }, { 0xaf,0xf3,0x81,0xca }, { 0x68,0xc4,0x3e,0xb9 }, { 0x24,0x34,0x2c,0x38 }, { 0xa3,0x40,0x5f,0xc2 }, { 0x1d,0xc3,0x72,0x16 }, { 0xe2,0x25,0x0c,0xbc }, { 0x3c,0x49,0x8b,0x28 }, { 0x0d,0x95,0x41,0xff }, { 0xa8,0x01,0x71,0x39 }, { 0x0c,0xb3,0xde,0x08 }, { 0xb4,0xe4,0x9c,0xd8 }, { 0x56,0xc1,0x90,0x64 }, { 0xcb,0x84,0x61,0x7b }, { 0x32,0xb6,0x70,0xd5 }, { 0x6c,0x5c,0x74,0x48 }, { 0xb8,0x57,0x42,0xd0 } }; static const byte S5[256] = { 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d }; static const byte U1[256][4] = { { 0x00,0x00,0x00,0x00 }, { 0x0e,0x09,0x0d,0x0b }, { 0x1c,0x12,0x1a,0x16 }, { 0x12,0x1b,0x17,0x1d }, { 0x38,0x24,0x34,0x2c }, { 0x36,0x2d,0x39,0x27 }, { 0x24,0x36,0x2e,0x3a }, { 0x2a,0x3f,0x23,0x31 }, { 0x70,0x48,0x68,0x58 }, { 0x7e,0x41,0x65,0x53 }, { 0x6c,0x5a,0x72,0x4e }, { 0x62,0x53,0x7f,0x45 }, { 0x48,0x6c,0x5c,0x74 }, { 0x46,0x65,0x51,0x7f }, { 0x54,0x7e,0x46,0x62 }, { 0x5a,0x77,0x4b,0x69 }, { 0xe0,0x90,0xd0,0xb0 }, { 0xee,0x99,0xdd,0xbb }, { 0xfc,0x82,0xca,0xa6 }, { 0xf2,0x8b,0xc7,0xad }, { 0xd8,0xb4,0xe4,0x9c }, { 0xd6,0xbd,0xe9,0x97 }, { 0xc4,0xa6,0xfe,0x8a }, { 0xca,0xaf,0xf3,0x81 }, { 0x90,0xd8,0xb8,0xe8 }, { 0x9e,0xd1,0xb5,0xe3 }, { 0x8c,0xca,0xa2,0xfe }, { 0x82,0xc3,0xaf,0xf5 }, { 0xa8,0xfc,0x8c,0xc4 }, { 0xa6,0xf5,0x81,0xcf }, { 0xb4,0xee,0x96,0xd2 }, { 0xba,0xe7,0x9b,0xd9 }, { 0xdb,0x3b,0xbb,0x7b }, { 0xd5,0x32,0xb6,0x70 }, { 0xc7,0x29,0xa1,0x6d }, { 0xc9,0x20,0xac,0x66 }, { 0xe3,0x1f,0x8f,0x57 }, { 0xed,0x16,0x82,0x5c }, { 0xff,0x0d,0x95,0x41 }, { 0xf1,0x04,0x98,0x4a }, { 0xab,0x73,0xd3,0x23 }, { 0xa5,0x7a,0xde,0x28 }, { 0xb7,0x61,0xc9,0x35 }, { 0xb9,0x68,0xc4,0x3e }, { 0x93,0x57,0xe7,0x0f }, { 0x9d,0x5e,0xea,0x04 }, { 0x8f,0x45,0xfd,0x19 }, { 0x81,0x4c,0xf0,0x12 }, { 0x3b,0xab,0x6b,0xcb }, { 0x35,0xa2,0x66,0xc0 }, { 0x27,0xb9,0x71,0xdd }, { 0x29,0xb0,0x7c,0xd6 }, { 0x03,0x8f,0x5f,0xe7 }, { 0x0d,0x86,0x52,0xec }, { 0x1f,0x9d,0x45,0xf1 }, { 0x11,0x94,0x48,0xfa }, { 0x4b,0xe3,0x03,0x93 }, { 0x45,0xea,0x0e,0x98 }, { 0x57,0xf1,0x19,0x85 }, { 0x59,0xf8,0x14,0x8e }, { 0x73,0xc7,0x37,0xbf }, { 0x7d,0xce,0x3a,0xb4 }, { 0x6f,0xd5,0x2d,0xa9 }, { 0x61,0xdc,0x20,0xa2 }, { 0xad,0x76,0x6d,0xf6 }, { 0xa3,0x7f,0x60,0xfd }, { 0xb1,0x64,0x77,0xe0 }, { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, { 0x9b,0x5b,0x54,0xd1 }, { 0x89,0x40,0x43,0xcc }, { 0x87,0x49,0x4e,0xc7 }, { 0xdd,0x3e,0x05,0xae }, { 0xd3,0x37,0x08,0xa5 }, { 0xc1,0x2c,0x1f,0xb8 }, { 0xcf,0x25,0x12,0xb3 }, { 0xe5,0x1a,0x31,0x82 }, { 0xeb,0x13,0x3c,0x89 }, { 0xf9,0x08,0x2b,0x94 }, { 0xf7,0x01,0x26,0x9f }, { 0x4d,0xe6,0xbd,0x46 }, { 0x43,0xef,0xb0,0x4d }, { 0x51,0xf4,0xa7,0x50 }, { 0x5f,0xfd,0xaa,0x5b }, { 0x75,0xc2,0x89,0x6a }, { 0x7b,0xcb,0x84,0x61 }, { 0x69,0xd0,0x93,0x7c }, { 0x67,0xd9,0x9e,0x77 }, { 0x3d,0xae,0xd5,0x1e }, { 0x33,0xa7,0xd8,0x15 }, { 0x21,0xbc,0xcf,0x08 }, { 0x2f,0xb5,0xc2,0x03 }, { 0x05,0x8a,0xe1,0x32 }, { 0x0b,0x83,0xec,0x39 }, { 0x19,0x98,0xfb,0x24 }, { 0x17,0x91,0xf6,0x2f }, { 0x76,0x4d,0xd6,0x8d }, { 0x78,0x44,0xdb,0x86 }, { 0x6a,0x5f,0xcc,0x9b }, { 0x64,0x56,0xc1,0x90 }, { 0x4e,0x69,0xe2,0xa1 }, { 0x40,0x60,0xef,0xaa }, { 0x52,0x7b,0xf8,0xb7 }, { 0x5c,0x72,0xf5,0xbc }, { 0x06,0x05,0xbe,0xd5 }, { 0x08,0x0c,0xb3,0xde }, { 0x1a,0x17,0xa4,0xc3 }, { 0x14,0x1e,0xa9,0xc8 }, { 0x3e,0x21,0x8a,0xf9 }, { 0x30,0x28,0x87,0xf2 }, { 0x22,0x33,0x90,0xef }, { 0x2c,0x3a,0x9d,0xe4 }, { 0x96,0xdd,0x06,0x3d }, { 0x98,0xd4,0x0b,0x36 }, { 0x8a,0xcf,0x1c,0x2b }, { 0x84,0xc6,0x11,0x20 }, { 0xae,0xf9,0x32,0x11 }, { 0xa0,0xf0,0x3f,0x1a }, { 0xb2,0xeb,0x28,0x07 }, { 0xbc,0xe2,0x25,0x0c }, { 0xe6,0x95,0x6e,0x65 }, { 0xe8,0x9c,0x63,0x6e }, { 0xfa,0x87,0x74,0x73 }, { 0xf4,0x8e,0x79,0x78 }, { 0xde,0xb1,0x5a,0x49 }, { 0xd0,0xb8,0x57,0x42 }, { 0xc2,0xa3,0x40,0x5f }, { 0xcc,0xaa,0x4d,0x54 }, { 0x41,0xec,0xda,0xf7 }, { 0x4f,0xe5,0xd7,0xfc }, { 0x5d,0xfe,0xc0,0xe1 }, { 0x53,0xf7,0xcd,0xea }, { 0x79,0xc8,0xee,0xdb }, { 0x77,0xc1,0xe3,0xd0 }, { 0x65,0xda,0xf4,0xcd }, { 0x6b,0xd3,0xf9,0xc6 }, { 0x31,0xa4,0xb2,0xaf }, { 0x3f,0xad,0xbf,0xa4 }, { 0x2d,0xb6,0xa8,0xb9 }, { 0x23,0xbf,0xa5,0xb2 }, { 0x09,0x80,0x86,0x83 }, { 0x07,0x89,0x8b,0x88 }, { 0x15,0x92,0x9c,0x95 }, { 0x1b,0x9b,0x91,0x9e }, { 0xa1,0x7c,0x0a,0x47 }, { 0xaf,0x75,0x07,0x4c }, { 0xbd,0x6e,0x10,0x51 }, { 0xb3,0x67,0x1d,0x5a }, { 0x99,0x58,0x3e,0x6b }, { 0x97,0x51,0x33,0x60 }, { 0x85,0x4a,0x24,0x7d }, { 0x8b,0x43,0x29,0x76 }, { 0xd1,0x34,0x62,0x1f }, { 0xdf,0x3d,0x6f,0x14 }, { 0xcd,0x26,0x78,0x09 }, { 0xc3,0x2f,0x75,0x02 }, { 0xe9,0x10,0x56,0x33 }, { 0xe7,0x19,0x5b,0x38 }, { 0xf5,0x02,0x4c,0x25 }, { 0xfb,0x0b,0x41,0x2e }, { 0x9a,0xd7,0x61,0x8c }, { 0x94,0xde,0x6c,0x87 }, { 0x86,0xc5,0x7b,0x9a }, { 0x88,0xcc,0x76,0x91 }, { 0xa2,0xf3,0x55,0xa0 }, { 0xac,0xfa,0x58,0xab }, { 0xbe,0xe1,0x4f,0xb6 }, { 0xb0,0xe8,0x42,0xbd }, { 0xea,0x9f,0x09,0xd4 }, { 0xe4,0x96,0x04,0xdf }, { 0xf6,0x8d,0x13,0xc2 }, { 0xf8,0x84,0x1e,0xc9 }, { 0xd2,0xbb,0x3d,0xf8 }, { 0xdc,0xb2,0x30,0xf3 }, { 0xce,0xa9,0x27,0xee }, { 0xc0,0xa0,0x2a,0xe5 }, { 0x7a,0x47,0xb1,0x3c }, { 0x74,0x4e,0xbc,0x37 }, { 0x66,0x55,0xab,0x2a }, { 0x68,0x5c,0xa6,0x21 }, { 0x42,0x63,0x85,0x10 }, { 0x4c,0x6a,0x88,0x1b }, { 0x5e,0x71,0x9f,0x06 }, { 0x50,0x78,0x92,0x0d }, { 0x0a,0x0f,0xd9,0x64 }, { 0x04,0x06,0xd4,0x6f }, { 0x16,0x1d,0xc3,0x72 }, { 0x18,0x14,0xce,0x79 }, { 0x32,0x2b,0xed,0x48 }, { 0x3c,0x22,0xe0,0x43 }, { 0x2e,0x39,0xf7,0x5e }, { 0x20,0x30,0xfa,0x55 }, { 0xec,0x9a,0xb7,0x01 }, { 0xe2,0x93,0xba,0x0a }, { 0xf0,0x88,0xad,0x17 }, { 0xfe,0x81,0xa0,0x1c }, { 0xd4,0xbe,0x83,0x2d }, { 0xda,0xb7,0x8e,0x26 }, { 0xc8,0xac,0x99,0x3b }, { 0xc6,0xa5,0x94,0x30 }, { 0x9c,0xd2,0xdf,0x59 }, { 0x92,0xdb,0xd2,0x52 }, { 0x80,0xc0,0xc5,0x4f }, { 0x8e,0xc9,0xc8,0x44 }, { 0xa4,0xf6,0xeb,0x75 }, { 0xaa,0xff,0xe6,0x7e }, { 0xb8,0xe4,0xf1,0x63 }, { 0xb6,0xed,0xfc,0x68 }, { 0x0c,0x0a,0x67,0xb1 }, { 0x02,0x03,0x6a,0xba }, { 0x10,0x18,0x7d,0xa7 }, { 0x1e,0x11,0x70,0xac }, { 0x34,0x2e,0x53,0x9d }, { 0x3a,0x27,0x5e,0x96 }, { 0x28,0x3c,0x49,0x8b }, { 0x26,0x35,0x44,0x80 }, { 0x7c,0x42,0x0f,0xe9 }, { 0x72,0x4b,0x02,0xe2 }, { 0x60,0x50,0x15,0xff }, { 0x6e,0x59,0x18,0xf4 }, { 0x44,0x66,0x3b,0xc5 }, { 0x4a,0x6f,0x36,0xce }, { 0x58,0x74,0x21,0xd3 }, { 0x56,0x7d,0x2c,0xd8 }, { 0x37,0xa1,0x0c,0x7a }, { 0x39,0xa8,0x01,0x71 }, { 0x2b,0xb3,0x16,0x6c }, { 0x25,0xba,0x1b,0x67 }, { 0x0f,0x85,0x38,0x56 }, { 0x01,0x8c,0x35,0x5d }, { 0x13,0x97,0x22,0x40 }, { 0x1d,0x9e,0x2f,0x4b }, { 0x47,0xe9,0x64,0x22 }, { 0x49,0xe0,0x69,0x29 }, { 0x5b,0xfb,0x7e,0x34 }, { 0x55,0xf2,0x73,0x3f }, { 0x7f,0xcd,0x50,0x0e }, { 0x71,0xc4,0x5d,0x05 }, { 0x63,0xdf,0x4a,0x18 }, { 0x6d,0xd6,0x47,0x13 }, { 0xd7,0x31,0xdc,0xca }, { 0xd9,0x38,0xd1,0xc1 }, { 0xcb,0x23,0xc6,0xdc }, { 0xc5,0x2a,0xcb,0xd7 }, { 0xef,0x15,0xe8,0xe6 }, { 0xe1,0x1c,0xe5,0xed }, { 0xf3,0x07,0xf2,0xf0 }, { 0xfd,0x0e,0xff,0xfb }, { 0xa7,0x79,0xb4,0x92 }, { 0xa9,0x70,0xb9,0x99 }, { 0xbb,0x6b,0xae,0x84 }, { 0xb5,0x62,0xa3,0x8f }, { 0x9f,0x5d,0x80,0xbe }, { 0x91,0x54,0x8d,0xb5 }, { 0x83,0x4f,0x9a,0xa8 }, { 0x8d,0x46,0x97,0xa3 } }; static const byte U2[256][4] = { { 0x00,0x00,0x00,0x00 }, { 0x0b,0x0e,0x09,0x0d }, { 0x16,0x1c,0x12,0x1a }, { 0x1d,0x12,0x1b,0x17 }, { 0x2c,0x38,0x24,0x34 }, { 0x27,0x36,0x2d,0x39 }, { 0x3a,0x24,0x36,0x2e }, { 0x31,0x2a,0x3f,0x23 }, { 0x58,0x70,0x48,0x68 }, { 0x53,0x7e,0x41,0x65 }, { 0x4e,0x6c,0x5a,0x72 }, { 0x45,0x62,0x53,0x7f }, { 0x74,0x48,0x6c,0x5c }, { 0x7f,0x46,0x65,0x51 }, { 0x62,0x54,0x7e,0x46 }, { 0x69,0x5a,0x77,0x4b }, { 0xb0,0xe0,0x90,0xd0 }, { 0xbb,0xee,0x99,0xdd }, { 0xa6,0xfc,0x82,0xca }, { 0xad,0xf2,0x8b,0xc7 }, { 0x9c,0xd8,0xb4,0xe4 }, { 0x97,0xd6,0xbd,0xe9 }, { 0x8a,0xc4,0xa6,0xfe }, { 0x81,0xca,0xaf,0xf3 }, { 0xe8,0x90,0xd8,0xb8 }, { 0xe3,0x9e,0xd1,0xb5 }, { 0xfe,0x8c,0xca,0xa2 }, { 0xf5,0x82,0xc3,0xaf }, { 0xc4,0xa8,0xfc,0x8c }, { 0xcf,0xa6,0xf5,0x81 }, { 0xd2,0xb4,0xee,0x96 }, { 0xd9,0xba,0xe7,0x9b }, { 0x7b,0xdb,0x3b,0xbb }, { 0x70,0xd5,0x32,0xb6 }, { 0x6d,0xc7,0x29,0xa1 }, { 0x66,0xc9,0x20,0xac }, { 0x57,0xe3,0x1f,0x8f }, { 0x5c,0xed,0x16,0x82 }, { 0x41,0xff,0x0d,0x95 }, { 0x4a,0xf1,0x04,0x98 }, { 0x23,0xab,0x73,0xd3 }, { 0x28,0xa5,0x7a,0xde }, { 0x35,0xb7,0x61,0xc9 }, { 0x3e,0xb9,0x68,0xc4 }, { 0x0f,0x93,0x57,0xe7 }, { 0x04,0x9d,0x5e,0xea }, { 0x19,0x8f,0x45,0xfd }, { 0x12,0x81,0x4c,0xf0 }, { 0xcb,0x3b,0xab,0x6b }, { 0xc0,0x35,0xa2,0x66 }, { 0xdd,0x27,0xb9,0x71 }, { 0xd6,0x29,0xb0,0x7c }, { 0xe7,0x03,0x8f,0x5f }, { 0xec,0x0d,0x86,0x52 }, { 0xf1,0x1f,0x9d,0x45 }, { 0xfa,0x11,0x94,0x48 }, { 0x93,0x4b,0xe3,0x03 }, { 0x98,0x45,0xea,0x0e }, { 0x85,0x57,0xf1,0x19 }, { 0x8e,0x59,0xf8,0x14 }, { 0xbf,0x73,0xc7,0x37 }, { 0xb4,0x7d,0xce,0x3a }, { 0xa9,0x6f,0xd5,0x2d }, { 0xa2,0x61,0xdc,0x20 }, { 0xf6,0xad,0x76,0x6d }, { 0xfd,0xa3,0x7f,0x60 }, { 0xe0,0xb1,0x64,0x77 }, { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, { 0xd1,0x9b,0x5b,0x54 }, { 0xcc,0x89,0x40,0x43 }, { 0xc7,0x87,0x49,0x4e }, { 0xae,0xdd,0x3e,0x05 }, { 0xa5,0xd3,0x37,0x08 }, { 0xb8,0xc1,0x2c,0x1f }, { 0xb3,0xcf,0x25,0x12 }, { 0x82,0xe5,0x1a,0x31 }, { 0x89,0xeb,0x13,0x3c }, { 0x94,0xf9,0x08,0x2b }, { 0x9f,0xf7,0x01,0x26 }, { 0x46,0x4d,0xe6,0xbd }, { 0x4d,0x43,0xef,0xb0 }, { 0x50,0x51,0xf4,0xa7 }, { 0x5b,0x5f,0xfd,0xaa }, { 0x6a,0x75,0xc2,0x89 }, { 0x61,0x7b,0xcb,0x84 }, { 0x7c,0x69,0xd0,0x93 }, { 0x77,0x67,0xd9,0x9e }, { 0x1e,0x3d,0xae,0xd5 }, { 0x15,0x33,0xa7,0xd8 }, { 0x08,0x21,0xbc,0xcf }, { 0x03,0x2f,0xb5,0xc2 }, { 0x32,0x05,0x8a,0xe1 }, { 0x39,0x0b,0x83,0xec }, { 0x24,0x19,0x98,0xfb }, { 0x2f,0x17,0x91,0xf6 }, { 0x8d,0x76,0x4d,0xd6 }, { 0x86,0x78,0x44,0xdb }, { 0x9b,0x6a,0x5f,0xcc }, { 0x90,0x64,0x56,0xc1 }, { 0xa1,0x4e,0x69,0xe2 }, { 0xaa,0x40,0x60,0xef }, { 0xb7,0x52,0x7b,0xf8 }, { 0xbc,0x5c,0x72,0xf5 }, { 0xd5,0x06,0x05,0xbe }, { 0xde,0x08,0x0c,0xb3 }, { 0xc3,0x1a,0x17,0xa4 }, { 0xc8,0x14,0x1e,0xa9 }, { 0xf9,0x3e,0x21,0x8a }, { 0xf2,0x30,0x28,0x87 }, { 0xef,0x22,0x33,0x90 }, { 0xe4,0x2c,0x3a,0x9d }, { 0x3d,0x96,0xdd,0x06 }, { 0x36,0x98,0xd4,0x0b }, { 0x2b,0x8a,0xcf,0x1c }, { 0x20,0x84,0xc6,0x11 }, { 0x11,0xae,0xf9,0x32 }, { 0x1a,0xa0,0xf0,0x3f }, { 0x07,0xb2,0xeb,0x28 }, { 0x0c,0xbc,0xe2,0x25 }, { 0x65,0xe6,0x95,0x6e }, { 0x6e,0xe8,0x9c,0x63 }, { 0x73,0xfa,0x87,0x74 }, { 0x78,0xf4,0x8e,0x79 }, { 0x49,0xde,0xb1,0x5a }, { 0x42,0xd0,0xb8,0x57 }, { 0x5f,0xc2,0xa3,0x40 }, { 0x54,0xcc,0xaa,0x4d }, { 0xf7,0x41,0xec,0xda }, { 0xfc,0x4f,0xe5,0xd7 }, { 0xe1,0x5d,0xfe,0xc0 }, { 0xea,0x53,0xf7,0xcd }, { 0xdb,0x79,0xc8,0xee }, { 0xd0,0x77,0xc1,0xe3 }, { 0xcd,0x65,0xda,0xf4 }, { 0xc6,0x6b,0xd3,0xf9 }, { 0xaf,0x31,0xa4,0xb2 }, { 0xa4,0x3f,0xad,0xbf }, { 0xb9,0x2d,0xb6,0xa8 }, { 0xb2,0x23,0xbf,0xa5 }, { 0x83,0x09,0x80,0x86 }, { 0x88,0x07,0x89,0x8b }, { 0x95,0x15,0x92,0x9c }, { 0x9e,0x1b,0x9b,0x91 }, { 0x47,0xa1,0x7c,0x0a }, { 0x4c,0xaf,0x75,0x07 }, { 0x51,0xbd,0x6e,0x10 }, { 0x5a,0xb3,0x67,0x1d }, { 0x6b,0x99,0x58,0x3e }, { 0x60,0x97,0x51,0x33 }, { 0x7d,0x85,0x4a,0x24 }, { 0x76,0x8b,0x43,0x29 }, { 0x1f,0xd1,0x34,0x62 }, { 0x14,0xdf,0x3d,0x6f }, { 0x09,0xcd,0x26,0x78 }, { 0x02,0xc3,0x2f,0x75 }, { 0x33,0xe9,0x10,0x56 }, { 0x38,0xe7,0x19,0x5b }, { 0x25,0xf5,0x02,0x4c }, { 0x2e,0xfb,0x0b,0x41 }, { 0x8c,0x9a,0xd7,0x61 }, { 0x87,0x94,0xde,0x6c }, { 0x9a,0x86,0xc5,0x7b }, { 0x91,0x88,0xcc,0x76 }, { 0xa0,0xa2,0xf3,0x55 }, { 0xab,0xac,0xfa,0x58 }, { 0xb6,0xbe,0xe1,0x4f }, { 0xbd,0xb0,0xe8,0x42 }, { 0xd4,0xea,0x9f,0x09 }, { 0xdf,0xe4,0x96,0x04 }, { 0xc2,0xf6,0x8d,0x13 }, { 0xc9,0xf8,0x84,0x1e }, { 0xf8,0xd2,0xbb,0x3d }, { 0xf3,0xdc,0xb2,0x30 }, { 0xee,0xce,0xa9,0x27 }, { 0xe5,0xc0,0xa0,0x2a }, { 0x3c,0x7a,0x47,0xb1 }, { 0x37,0x74,0x4e,0xbc }, { 0x2a,0x66,0x55,0xab }, { 0x21,0x68,0x5c,0xa6 }, { 0x10,0x42,0x63,0x85 }, { 0x1b,0x4c,0x6a,0x88 }, { 0x06,0x5e,0x71,0x9f }, { 0x0d,0x50,0x78,0x92 }, { 0x64,0x0a,0x0f,0xd9 }, { 0x6f,0x04,0x06,0xd4 }, { 0x72,0x16,0x1d,0xc3 }, { 0x79,0x18,0x14,0xce }, { 0x48,0x32,0x2b,0xed }, { 0x43,0x3c,0x22,0xe0 }, { 0x5e,0x2e,0x39,0xf7 }, { 0x55,0x20,0x30,0xfa }, { 0x01,0xec,0x9a,0xb7 }, { 0x0a,0xe2,0x93,0xba }, { 0x17,0xf0,0x88,0xad }, { 0x1c,0xfe,0x81,0xa0 }, { 0x2d,0xd4,0xbe,0x83 }, { 0x26,0xda,0xb7,0x8e }, { 0x3b,0xc8,0xac,0x99 }, { 0x30,0xc6,0xa5,0x94 }, { 0x59,0x9c,0xd2,0xdf }, { 0x52,0x92,0xdb,0xd2 }, { 0x4f,0x80,0xc0,0xc5 }, { 0x44,0x8e,0xc9,0xc8 }, { 0x75,0xa4,0xf6,0xeb }, { 0x7e,0xaa,0xff,0xe6 }, { 0x63,0xb8,0xe4,0xf1 }, { 0x68,0xb6,0xed,0xfc }, { 0xb1,0x0c,0x0a,0x67 }, { 0xba,0x02,0x03,0x6a }, { 0xa7,0x10,0x18,0x7d }, { 0xac,0x1e,0x11,0x70 }, { 0x9d,0x34,0x2e,0x53 }, { 0x96,0x3a,0x27,0x5e }, { 0x8b,0x28,0x3c,0x49 }, { 0x80,0x26,0x35,0x44 }, { 0xe9,0x7c,0x42,0x0f }, { 0xe2,0x72,0x4b,0x02 }, { 0xff,0x60,0x50,0x15 }, { 0xf4,0x6e,0x59,0x18 }, { 0xc5,0x44,0x66,0x3b }, { 0xce,0x4a,0x6f,0x36 }, { 0xd3,0x58,0x74,0x21 }, { 0xd8,0x56,0x7d,0x2c }, { 0x7a,0x37,0xa1,0x0c }, { 0x71,0x39,0xa8,0x01 }, { 0x6c,0x2b,0xb3,0x16 }, { 0x67,0x25,0xba,0x1b }, { 0x56,0x0f,0x85,0x38 }, { 0x5d,0x01,0x8c,0x35 }, { 0x40,0x13,0x97,0x22 }, { 0x4b,0x1d,0x9e,0x2f }, { 0x22,0x47,0xe9,0x64 }, { 0x29,0x49,0xe0,0x69 }, { 0x34,0x5b,0xfb,0x7e }, { 0x3f,0x55,0xf2,0x73 }, { 0x0e,0x7f,0xcd,0x50 }, { 0x05,0x71,0xc4,0x5d }, { 0x18,0x63,0xdf,0x4a }, { 0x13,0x6d,0xd6,0x47 }, { 0xca,0xd7,0x31,0xdc }, { 0xc1,0xd9,0x38,0xd1 }, { 0xdc,0xcb,0x23,0xc6 }, { 0xd7,0xc5,0x2a,0xcb }, { 0xe6,0xef,0x15,0xe8 }, { 0xed,0xe1,0x1c,0xe5 }, { 0xf0,0xf3,0x07,0xf2 }, { 0xfb,0xfd,0x0e,0xff }, { 0x92,0xa7,0x79,0xb4 }, { 0x99,0xa9,0x70,0xb9 }, { 0x84,0xbb,0x6b,0xae }, { 0x8f,0xb5,0x62,0xa3 }, { 0xbe,0x9f,0x5d,0x80 }, { 0xb5,0x91,0x54,0x8d }, { 0xa8,0x83,0x4f,0x9a }, { 0xa3,0x8d,0x46,0x97 } }; static const byte U3[256][4] = { { 0x00,0x00,0x00,0x00 }, { 0x0d,0x0b,0x0e,0x09 }, { 0x1a,0x16,0x1c,0x12 }, { 0x17,0x1d,0x12,0x1b }, { 0x34,0x2c,0x38,0x24 }, { 0x39,0x27,0x36,0x2d }, { 0x2e,0x3a,0x24,0x36 }, { 0x23,0x31,0x2a,0x3f }, { 0x68,0x58,0x70,0x48 }, { 0x65,0x53,0x7e,0x41 }, { 0x72,0x4e,0x6c,0x5a }, { 0x7f,0x45,0x62,0x53 }, { 0x5c,0x74,0x48,0x6c }, { 0x51,0x7f,0x46,0x65 }, { 0x46,0x62,0x54,0x7e }, { 0x4b,0x69,0x5a,0x77 }, { 0xd0,0xb0,0xe0,0x90 }, { 0xdd,0xbb,0xee,0x99 }, { 0xca,0xa6,0xfc,0x82 }, { 0xc7,0xad,0xf2,0x8b }, { 0xe4,0x9c,0xd8,0xb4 }, { 0xe9,0x97,0xd6,0xbd }, { 0xfe,0x8a,0xc4,0xa6 }, { 0xf3,0x81,0xca,0xaf }, { 0xb8,0xe8,0x90,0xd8 }, { 0xb5,0xe3,0x9e,0xd1 }, { 0xa2,0xfe,0x8c,0xca }, { 0xaf,0xf5,0x82,0xc3 }, { 0x8c,0xc4,0xa8,0xfc }, { 0x81,0xcf,0xa6,0xf5 }, { 0x96,0xd2,0xb4,0xee }, { 0x9b,0xd9,0xba,0xe7 }, { 0xbb,0x7b,0xdb,0x3b }, { 0xb6,0x70,0xd5,0x32 }, { 0xa1,0x6d,0xc7,0x29 }, { 0xac,0x66,0xc9,0x20 }, { 0x8f,0x57,0xe3,0x1f }, { 0x82,0x5c,0xed,0x16 }, { 0x95,0x41,0xff,0x0d }, { 0x98,0x4a,0xf1,0x04 }, { 0xd3,0x23,0xab,0x73 }, { 0xde,0x28,0xa5,0x7a }, { 0xc9,0x35,0xb7,0x61 }, { 0xc4,0x3e,0xb9,0x68 }, { 0xe7,0x0f,0x93,0x57 }, { 0xea,0x04,0x9d,0x5e }, { 0xfd,0x19,0x8f,0x45 }, { 0xf0,0x12,0x81,0x4c }, { 0x6b,0xcb,0x3b,0xab }, { 0x66,0xc0,0x35,0xa2 }, { 0x71,0xdd,0x27,0xb9 }, { 0x7c,0xd6,0x29,0xb0 }, { 0x5f,0xe7,0x03,0x8f }, { 0x52,0xec,0x0d,0x86 }, { 0x45,0xf1,0x1f,0x9d }, { 0x48,0xfa,0x11,0x94 }, { 0x03,0x93,0x4b,0xe3 }, { 0x0e,0x98,0x45,0xea }, { 0x19,0x85,0x57,0xf1 }, { 0x14,0x8e,0x59,0xf8 }, { 0x37,0xbf,0x73,0xc7 }, { 0x3a,0xb4,0x7d,0xce }, { 0x2d,0xa9,0x6f,0xd5 }, { 0x20,0xa2,0x61,0xdc }, { 0x6d,0xf6,0xad,0x76 }, { 0x60,0xfd,0xa3,0x7f }, { 0x77,0xe0,0xb1,0x64 }, { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, { 0x54,0xd1,0x9b,0x5b }, { 0x43,0xcc,0x89,0x40 }, { 0x4e,0xc7,0x87,0x49 }, { 0x05,0xae,0xdd,0x3e }, { 0x08,0xa5,0xd3,0x37 }, { 0x1f,0xb8,0xc1,0x2c }, { 0x12,0xb3,0xcf,0x25 }, { 0x31,0x82,0xe5,0x1a }, { 0x3c,0x89,0xeb,0x13 }, { 0x2b,0x94,0xf9,0x08 }, { 0x26,0x9f,0xf7,0x01 }, { 0xbd,0x46,0x4d,0xe6 }, { 0xb0,0x4d,0x43,0xef }, { 0xa7,0x50,0x51,0xf4 }, { 0xaa,0x5b,0x5f,0xfd }, { 0x89,0x6a,0x75,0xc2 }, { 0x84,0x61,0x7b,0xcb }, { 0x93,0x7c,0x69,0xd0 }, { 0x9e,0x77,0x67,0xd9 }, { 0xd5,0x1e,0x3d,0xae }, { 0xd8,0x15,0x33,0xa7 }, { 0xcf,0x08,0x21,0xbc }, { 0xc2,0x03,0x2f,0xb5 }, { 0xe1,0x32,0x05,0x8a }, { 0xec,0x39,0x0b,0x83 }, { 0xfb,0x24,0x19,0x98 }, { 0xf6,0x2f,0x17,0x91 }, { 0xd6,0x8d,0x76,0x4d }, { 0xdb,0x86,0x78,0x44 }, { 0xcc,0x9b,0x6a,0x5f }, { 0xc1,0x90,0x64,0x56 }, { 0xe2,0xa1,0x4e,0x69 }, { 0xef,0xaa,0x40,0x60 }, { 0xf8,0xb7,0x52,0x7b }, { 0xf5,0xbc,0x5c,0x72 }, { 0xbe,0xd5,0x06,0x05 }, { 0xb3,0xde,0x08,0x0c }, { 0xa4,0xc3,0x1a,0x17 }, { 0xa9,0xc8,0x14,0x1e }, { 0x8a,0xf9,0x3e,0x21 }, { 0x87,0xf2,0x30,0x28 }, { 0x90,0xef,0x22,0x33 }, { 0x9d,0xe4,0x2c,0x3a }, { 0x06,0x3d,0x96,0xdd }, { 0x0b,0x36,0x98,0xd4 }, { 0x1c,0x2b,0x8a,0xcf }, { 0x11,0x20,0x84,0xc6 }, { 0x32,0x11,0xae,0xf9 }, { 0x3f,0x1a,0xa0,0xf0 }, { 0x28,0x07,0xb2,0xeb }, { 0x25,0x0c,0xbc,0xe2 }, { 0x6e,0x65,0xe6,0x95 }, { 0x63,0x6e,0xe8,0x9c }, { 0x74,0x73,0xfa,0x87 }, { 0x79,0x78,0xf4,0x8e }, { 0x5a,0x49,0xde,0xb1 }, { 0x57,0x42,0xd0,0xb8 }, { 0x40,0x5f,0xc2,0xa3 }, { 0x4d,0x54,0xcc,0xaa }, { 0xda,0xf7,0x41,0xec }, { 0xd7,0xfc,0x4f,0xe5 }, { 0xc0,0xe1,0x5d,0xfe }, { 0xcd,0xea,0x53,0xf7 }, { 0xee,0xdb,0x79,0xc8 }, { 0xe3,0xd0,0x77,0xc1 }, { 0xf4,0xcd,0x65,0xda }, { 0xf9,0xc6,0x6b,0xd3 }, { 0xb2,0xaf,0x31,0xa4 }, { 0xbf,0xa4,0x3f,0xad }, { 0xa8,0xb9,0x2d,0xb6 }, { 0xa5,0xb2,0x23,0xbf }, { 0x86,0x83,0x09,0x80 }, { 0x8b,0x88,0x07,0x89 }, { 0x9c,0x95,0x15,0x92 }, { 0x91,0x9e,0x1b,0x9b }, { 0x0a,0x47,0xa1,0x7c }, { 0x07,0x4c,0xaf,0x75 }, { 0x10,0x51,0xbd,0x6e }, { 0x1d,0x5a,0xb3,0x67 }, { 0x3e,0x6b,0x99,0x58 }, { 0x33,0x60,0x97,0x51 }, { 0x24,0x7d,0x85,0x4a }, { 0x29,0x76,0x8b,0x43 }, { 0x62,0x1f,0xd1,0x34 }, { 0x6f,0x14,0xdf,0x3d }, { 0x78,0x09,0xcd,0x26 }, { 0x75,0x02,0xc3,0x2f }, { 0x56,0x33,0xe9,0x10 }, { 0x5b,0x38,0xe7,0x19 }, { 0x4c,0x25,0xf5,0x02 }, { 0x41,0x2e,0xfb,0x0b }, { 0x61,0x8c,0x9a,0xd7 }, { 0x6c,0x87,0x94,0xde }, { 0x7b,0x9a,0x86,0xc5 }, { 0x76,0x91,0x88,0xcc }, { 0x55,0xa0,0xa2,0xf3 }, { 0x58,0xab,0xac,0xfa }, { 0x4f,0xb6,0xbe,0xe1 }, { 0x42,0xbd,0xb0,0xe8 }, { 0x09,0xd4,0xea,0x9f }, { 0x04,0xdf,0xe4,0x96 }, { 0x13,0xc2,0xf6,0x8d }, { 0x1e,0xc9,0xf8,0x84 }, { 0x3d,0xf8,0xd2,0xbb }, { 0x30,0xf3,0xdc,0xb2 }, { 0x27,0xee,0xce,0xa9 }, { 0x2a,0xe5,0xc0,0xa0 }, { 0xb1,0x3c,0x7a,0x47 }, { 0xbc,0x37,0x74,0x4e }, { 0xab,0x2a,0x66,0x55 }, { 0xa6,0x21,0x68,0x5c }, { 0x85,0x10,0x42,0x63 }, { 0x88,0x1b,0x4c,0x6a }, { 0x9f,0x06,0x5e,0x71 }, { 0x92,0x0d,0x50,0x78 }, { 0xd9,0x64,0x0a,0x0f }, { 0xd4,0x6f,0x04,0x06 }, { 0xc3,0x72,0x16,0x1d }, { 0xce,0x79,0x18,0x14 }, { 0xed,0x48,0x32,0x2b }, { 0xe0,0x43,0x3c,0x22 }, { 0xf7,0x5e,0x2e,0x39 }, { 0xfa,0x55,0x20,0x30 }, { 0xb7,0x01,0xec,0x9a }, { 0xba,0x0a,0xe2,0x93 }, { 0xad,0x17,0xf0,0x88 }, { 0xa0,0x1c,0xfe,0x81 }, { 0x83,0x2d,0xd4,0xbe }, { 0x8e,0x26,0xda,0xb7 }, { 0x99,0x3b,0xc8,0xac }, { 0x94,0x30,0xc6,0xa5 }, { 0xdf,0x59,0x9c,0xd2 }, { 0xd2,0x52,0x92,0xdb }, { 0xc5,0x4f,0x80,0xc0 }, { 0xc8,0x44,0x8e,0xc9 }, { 0xeb,0x75,0xa4,0xf6 }, { 0xe6,0x7e,0xaa,0xff }, { 0xf1,0x63,0xb8,0xe4 }, { 0xfc,0x68,0xb6,0xed }, { 0x67,0xb1,0x0c,0x0a }, { 0x6a,0xba,0x02,0x03 }, { 0x7d,0xa7,0x10,0x18 }, { 0x70,0xac,0x1e,0x11 }, { 0x53,0x9d,0x34,0x2e }, { 0x5e,0x96,0x3a,0x27 }, { 0x49,0x8b,0x28,0x3c }, { 0x44,0x80,0x26,0x35 }, { 0x0f,0xe9,0x7c,0x42 }, { 0x02,0xe2,0x72,0x4b }, { 0x15,0xff,0x60,0x50 }, { 0x18,0xf4,0x6e,0x59 }, { 0x3b,0xc5,0x44,0x66 }, { 0x36,0xce,0x4a,0x6f }, { 0x21,0xd3,0x58,0x74 }, { 0x2c,0xd8,0x56,0x7d }, { 0x0c,0x7a,0x37,0xa1 }, { 0x01,0x71,0x39,0xa8 }, { 0x16,0x6c,0x2b,0xb3 }, { 0x1b,0x67,0x25,0xba }, { 0x38,0x56,0x0f,0x85 }, { 0x35,0x5d,0x01,0x8c }, { 0x22,0x40,0x13,0x97 }, { 0x2f,0x4b,0x1d,0x9e }, { 0x64,0x22,0x47,0xe9 }, { 0x69,0x29,0x49,0xe0 }, { 0x7e,0x34,0x5b,0xfb }, { 0x73,0x3f,0x55,0xf2 }, { 0x50,0x0e,0x7f,0xcd }, { 0x5d,0x05,0x71,0xc4 }, { 0x4a,0x18,0x63,0xdf }, { 0x47,0x13,0x6d,0xd6 }, { 0xdc,0xca,0xd7,0x31 }, { 0xd1,0xc1,0xd9,0x38 }, { 0xc6,0xdc,0xcb,0x23 }, { 0xcb,0xd7,0xc5,0x2a }, { 0xe8,0xe6,0xef,0x15 }, { 0xe5,0xed,0xe1,0x1c }, { 0xf2,0xf0,0xf3,0x07 }, { 0xff,0xfb,0xfd,0x0e }, { 0xb4,0x92,0xa7,0x79 }, { 0xb9,0x99,0xa9,0x70 }, { 0xae,0x84,0xbb,0x6b }, { 0xa3,0x8f,0xb5,0x62 }, { 0x80,0xbe,0x9f,0x5d }, { 0x8d,0xb5,0x91,0x54 }, { 0x9a,0xa8,0x83,0x4f }, { 0x97,0xa3,0x8d,0x46 } }; static const byte U4[256][4] = { { 0x00,0x00,0x00,0x00 }, { 0x09,0x0d,0x0b,0x0e }, { 0x12,0x1a,0x16,0x1c }, { 0x1b,0x17,0x1d,0x12 }, { 0x24,0x34,0x2c,0x38 }, { 0x2d,0x39,0x27,0x36 }, { 0x36,0x2e,0x3a,0x24 }, { 0x3f,0x23,0x31,0x2a }, { 0x48,0x68,0x58,0x70 }, { 0x41,0x65,0x53,0x7e }, { 0x5a,0x72,0x4e,0x6c }, { 0x53,0x7f,0x45,0x62 }, { 0x6c,0x5c,0x74,0x48 }, { 0x65,0x51,0x7f,0x46 }, { 0x7e,0x46,0x62,0x54 }, { 0x77,0x4b,0x69,0x5a }, { 0x90,0xd0,0xb0,0xe0 }, { 0x99,0xdd,0xbb,0xee }, { 0x82,0xca,0xa6,0xfc }, { 0x8b,0xc7,0xad,0xf2 }, { 0xb4,0xe4,0x9c,0xd8 }, { 0xbd,0xe9,0x97,0xd6 }, { 0xa6,0xfe,0x8a,0xc4 }, { 0xaf,0xf3,0x81,0xca }, { 0xd8,0xb8,0xe8,0x90 }, { 0xd1,0xb5,0xe3,0x9e }, { 0xca,0xa2,0xfe,0x8c }, { 0xc3,0xaf,0xf5,0x82 }, { 0xfc,0x8c,0xc4,0xa8 }, { 0xf5,0x81,0xcf,0xa6 }, { 0xee,0x96,0xd2,0xb4 }, { 0xe7,0x9b,0xd9,0xba }, { 0x3b,0xbb,0x7b,0xdb }, { 0x32,0xb6,0x70,0xd5 }, { 0x29,0xa1,0x6d,0xc7 }, { 0x20,0xac,0x66,0xc9 }, { 0x1f,0x8f,0x57,0xe3 }, { 0x16,0x82,0x5c,0xed }, { 0x0d,0x95,0x41,0xff }, { 0x04,0x98,0x4a,0xf1 }, { 0x73,0xd3,0x23,0xab }, { 0x7a,0xde,0x28,0xa5 }, { 0x61,0xc9,0x35,0xb7 }, { 0x68,0xc4,0x3e,0xb9 }, { 0x57,0xe7,0x0f,0x93 }, { 0x5e,0xea,0x04,0x9d }, { 0x45,0xfd,0x19,0x8f }, { 0x4c,0xf0,0x12,0x81 }, { 0xab,0x6b,0xcb,0x3b }, { 0xa2,0x66,0xc0,0x35 }, { 0xb9,0x71,0xdd,0x27 }, { 0xb0,0x7c,0xd6,0x29 }, { 0x8f,0x5f,0xe7,0x03 }, { 0x86,0x52,0xec,0x0d }, { 0x9d,0x45,0xf1,0x1f }, { 0x94,0x48,0xfa,0x11 }, { 0xe3,0x03,0x93,0x4b }, { 0xea,0x0e,0x98,0x45 }, { 0xf1,0x19,0x85,0x57 }, { 0xf8,0x14,0x8e,0x59 }, { 0xc7,0x37,0xbf,0x73 }, { 0xce,0x3a,0xb4,0x7d }, { 0xd5,0x2d,0xa9,0x6f }, { 0xdc,0x20,0xa2,0x61 }, { 0x76,0x6d,0xf6,0xad }, { 0x7f,0x60,0xfd,0xa3 }, { 0x64,0x77,0xe0,0xb1 }, { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, { 0x5b,0x54,0xd1,0x9b }, { 0x40,0x43,0xcc,0x89 }, { 0x49,0x4e,0xc7,0x87 }, { 0x3e,0x05,0xae,0xdd }, { 0x37,0x08,0xa5,0xd3 }, { 0x2c,0x1f,0xb8,0xc1 }, { 0x25,0x12,0xb3,0xcf }, { 0x1a,0x31,0x82,0xe5 }, { 0x13,0x3c,0x89,0xeb }, { 0x08,0x2b,0x94,0xf9 }, { 0x01,0x26,0x9f,0xf7 }, { 0xe6,0xbd,0x46,0x4d }, { 0xef,0xb0,0x4d,0x43 }, { 0xf4,0xa7,0x50,0x51 }, { 0xfd,0xaa,0x5b,0x5f }, { 0xc2,0x89,0x6a,0x75 }, { 0xcb,0x84,0x61,0x7b }, { 0xd0,0x93,0x7c,0x69 }, { 0xd9,0x9e,0x77,0x67 }, { 0xae,0xd5,0x1e,0x3d }, { 0xa7,0xd8,0x15,0x33 }, { 0xbc,0xcf,0x08,0x21 }, { 0xb5,0xc2,0x03,0x2f }, { 0x8a,0xe1,0x32,0x05 }, { 0x83,0xec,0x39,0x0b }, { 0x98,0xfb,0x24,0x19 }, { 0x91,0xf6,0x2f,0x17 }, { 0x4d,0xd6,0x8d,0x76 }, { 0x44,0xdb,0x86,0x78 }, { 0x5f,0xcc,0x9b,0x6a }, { 0x56,0xc1,0x90,0x64 }, { 0x69,0xe2,0xa1,0x4e }, { 0x60,0xef,0xaa,0x40 }, { 0x7b,0xf8,0xb7,0x52 }, { 0x72,0xf5,0xbc,0x5c }, { 0x05,0xbe,0xd5,0x06 }, { 0x0c,0xb3,0xde,0x08 }, { 0x17,0xa4,0xc3,0x1a }, { 0x1e,0xa9,0xc8,0x14 }, { 0x21,0x8a,0xf9,0x3e }, { 0x28,0x87,0xf2,0x30 }, { 0x33,0x90,0xef,0x22 }, { 0x3a,0x9d,0xe4,0x2c }, { 0xdd,0x06,0x3d,0x96 }, { 0xd4,0x0b,0x36,0x98 }, { 0xcf,0x1c,0x2b,0x8a }, { 0xc6,0x11,0x20,0x84 }, { 0xf9,0x32,0x11,0xae }, { 0xf0,0x3f,0x1a,0xa0 }, { 0xeb,0x28,0x07,0xb2 }, { 0xe2,0x25,0x0c,0xbc }, { 0x95,0x6e,0x65,0xe6 }, { 0x9c,0x63,0x6e,0xe8 }, { 0x87,0x74,0x73,0xfa }, { 0x8e,0x79,0x78,0xf4 }, { 0xb1,0x5a,0x49,0xde }, { 0xb8,0x57,0x42,0xd0 }, { 0xa3,0x40,0x5f,0xc2 }, { 0xaa,0x4d,0x54,0xcc }, { 0xec,0xda,0xf7,0x41 }, { 0xe5,0xd7,0xfc,0x4f }, { 0xfe,0xc0,0xe1,0x5d }, { 0xf7,0xcd,0xea,0x53 }, { 0xc8,0xee,0xdb,0x79 }, { 0xc1,0xe3,0xd0,0x77 }, { 0xda,0xf4,0xcd,0x65 }, { 0xd3,0xf9,0xc6,0x6b }, { 0xa4,0xb2,0xaf,0x31 }, { 0xad,0xbf,0xa4,0x3f }, { 0xb6,0xa8,0xb9,0x2d }, { 0xbf,0xa5,0xb2,0x23 }, { 0x80,0x86,0x83,0x09 }, { 0x89,0x8b,0x88,0x07 }, { 0x92,0x9c,0x95,0x15 }, { 0x9b,0x91,0x9e,0x1b }, { 0x7c,0x0a,0x47,0xa1 }, { 0x75,0x07,0x4c,0xaf }, { 0x6e,0x10,0x51,0xbd }, { 0x67,0x1d,0x5a,0xb3 }, { 0x58,0x3e,0x6b,0x99 }, { 0x51,0x33,0x60,0x97 }, { 0x4a,0x24,0x7d,0x85 }, { 0x43,0x29,0x76,0x8b }, { 0x34,0x62,0x1f,0xd1 }, { 0x3d,0x6f,0x14,0xdf }, { 0x26,0x78,0x09,0xcd }, { 0x2f,0x75,0x02,0xc3 }, { 0x10,0x56,0x33,0xe9 }, { 0x19,0x5b,0x38,0xe7 }, { 0x02,0x4c,0x25,0xf5 }, { 0x0b,0x41,0x2e,0xfb }, { 0xd7,0x61,0x8c,0x9a }, { 0xde,0x6c,0x87,0x94 }, { 0xc5,0x7b,0x9a,0x86 }, { 0xcc,0x76,0x91,0x88 }, { 0xf3,0x55,0xa0,0xa2 }, { 0xfa,0x58,0xab,0xac }, { 0xe1,0x4f,0xb6,0xbe }, { 0xe8,0x42,0xbd,0xb0 }, { 0x9f,0x09,0xd4,0xea }, { 0x96,0x04,0xdf,0xe4 }, { 0x8d,0x13,0xc2,0xf6 }, { 0x84,0x1e,0xc9,0xf8 }, { 0xbb,0x3d,0xf8,0xd2 }, { 0xb2,0x30,0xf3,0xdc }, { 0xa9,0x27,0xee,0xce }, { 0xa0,0x2a,0xe5,0xc0 }, { 0x47,0xb1,0x3c,0x7a }, { 0x4e,0xbc,0x37,0x74 }, { 0x55,0xab,0x2a,0x66 }, { 0x5c,0xa6,0x21,0x68 }, { 0x63,0x85,0x10,0x42 }, { 0x6a,0x88,0x1b,0x4c }, { 0x71,0x9f,0x06,0x5e }, { 0x78,0x92,0x0d,0x50 }, { 0x0f,0xd9,0x64,0x0a }, { 0x06,0xd4,0x6f,0x04 }, { 0x1d,0xc3,0x72,0x16 }, { 0x14,0xce,0x79,0x18 }, { 0x2b,0xed,0x48,0x32 }, { 0x22,0xe0,0x43,0x3c }, { 0x39,0xf7,0x5e,0x2e }, { 0x30,0xfa,0x55,0x20 }, { 0x9a,0xb7,0x01,0xec }, { 0x93,0xba,0x0a,0xe2 }, { 0x88,0xad,0x17,0xf0 }, { 0x81,0xa0,0x1c,0xfe }, { 0xbe,0x83,0x2d,0xd4 }, { 0xb7,0x8e,0x26,0xda }, { 0xac,0x99,0x3b,0xc8 }, { 0xa5,0x94,0x30,0xc6 }, { 0xd2,0xdf,0x59,0x9c }, { 0xdb,0xd2,0x52,0x92 }, { 0xc0,0xc5,0x4f,0x80 }, { 0xc9,0xc8,0x44,0x8e }, { 0xf6,0xeb,0x75,0xa4 }, { 0xff,0xe6,0x7e,0xaa }, { 0xe4,0xf1,0x63,0xb8 }, { 0xed,0xfc,0x68,0xb6 }, { 0x0a,0x67,0xb1,0x0c }, { 0x03,0x6a,0xba,0x02 }, { 0x18,0x7d,0xa7,0x10 }, { 0x11,0x70,0xac,0x1e }, { 0x2e,0x53,0x9d,0x34 }, { 0x27,0x5e,0x96,0x3a }, { 0x3c,0x49,0x8b,0x28 }, { 0x35,0x44,0x80,0x26 }, { 0x42,0x0f,0xe9,0x7c }, { 0x4b,0x02,0xe2,0x72 }, { 0x50,0x15,0xff,0x60 }, { 0x59,0x18,0xf4,0x6e }, { 0x66,0x3b,0xc5,0x44 }, { 0x6f,0x36,0xce,0x4a }, { 0x74,0x21,0xd3,0x58 }, { 0x7d,0x2c,0xd8,0x56 }, { 0xa1,0x0c,0x7a,0x37 }, { 0xa8,0x01,0x71,0x39 }, { 0xb3,0x16,0x6c,0x2b }, { 0xba,0x1b,0x67,0x25 }, { 0x85,0x38,0x56,0x0f }, { 0x8c,0x35,0x5d,0x01 }, { 0x97,0x22,0x40,0x13 }, { 0x9e,0x2f,0x4b,0x1d }, { 0xe9,0x64,0x22,0x47 }, { 0xe0,0x69,0x29,0x49 }, { 0xfb,0x7e,0x34,0x5b }, { 0xf2,0x73,0x3f,0x55 }, { 0xcd,0x50,0x0e,0x7f }, { 0xc4,0x5d,0x05,0x71 }, { 0xdf,0x4a,0x18,0x63 }, { 0xd6,0x47,0x13,0x6d }, { 0x31,0xdc,0xca,0xd7 }, { 0x38,0xd1,0xc1,0xd9 }, { 0x23,0xc6,0xdc,0xcb }, { 0x2a,0xcb,0xd7,0xc5 }, { 0x15,0xe8,0xe6,0xef }, { 0x1c,0xe5,0xed,0xe1 }, { 0x07,0xf2,0xf0,0xf3 }, { 0x0e,0xff,0xfb,0xfd }, { 0x79,0xb4,0x92,0xa7 }, { 0x70,0xb9,0x99,0xa9 }, { 0x6b,0xae,0x84,0xbb }, { 0x62,0xa3,0x8f,0xb5 }, { 0x5d,0x80,0xbe,0x9f }, { 0x54,0x8d,0xb5,0x91 }, { 0x4f,0x9a,0xa8,0x83 }, { 0x46,0x97,0xa3,0x8d } }; static const u32 rcon[30] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 }; + +static void +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + /* Perform the key setup. */ static int -rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) +do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) { static int initialized = 0; static const char *selftest_failed=0; int ROUNDS; byte k[MAXKC][4]; int i,j, r, t, rconpointer = 0; byte tk[MAXKC][4]; int KC; if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) fprintf(stderr, "%s\n", selftest_failed ); } if( selftest_failed ) return GCRYERR_SELFTEST; if( keylen == 128/8 ) { ROUNDS = 10; KC = 4; } else if ( keylen == 192/8 ) { ROUNDS = 12; KC = 6; } else if ( keylen == 256/8 ) { ROUNDS = 14; KC = 8; } else return GCRYERR_INV_KEYLEN; ctx->ROUNDS = ROUNDS; ctx->decryption_prepared = 0; for (i = 0; i < keylen; i++) { k[i >> 2][i & 3] = key[i]; } #define W (ctx->keySched) for (j = KC-1; j >= 0; j--) { *((u32*)tk[j]) = *((u32*)k[j]); } r = 0; t = 0; /* copy values into round key array */ for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { for (; (j < KC) && (t < 4); j++, t++) { *((u32*)W[r][t]) = *((u32*)tk[j]); } if (t == 4) { r++; t = 0; } } while (r < ROUNDS + 1) { /* while not enough round key material calculated */ /* calculate new values */ tk[0][0] ^= S[tk[KC-1][1]]; tk[0][1] ^= S[tk[KC-1][2]]; tk[0][2] ^= S[tk[KC-1][3]]; tk[0][3] ^= S[tk[KC-1][0]]; tk[0][0] ^= rcon[rconpointer++]; if (KC != 8) { for (j = 1; j < KC; j++) { *((u32*)tk[j]) ^= *((u32*)tk[j-1]); } } else { for (j = 1; j < KC/2; j++) { *((u32*)tk[j]) ^= *((u32*)tk[j-1]); } tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; for (j = KC/2 + 1; j < KC; j++) { *((u32*)tk[j]) ^= *((u32*)tk[j-1]); } } /* copy values into round key array */ for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { for (; (j < KC) && (t < 4); j++, t++) { *((u32*)W[r][t]) = *((u32*)tk[j]); } if (t == 4) { r++; t = 0; } } } #undef W return 0; } +static int +rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) +{ + int rc = do_setkey (ctx, key, keylen); + burn_stack ( 100 + 16*sizeof(int)); + return rc; +} + + /* make a decryption key from an encryption key */ static void prepare_decryption( RIJNDAEL_context *ctx ) { int r; byte *w; for (r=0; r < MAXROUNDS+1; r++ ) { *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]); *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]); *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]); *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]); } #define W (ctx->keySched2) for (r = 1; r < ctx->ROUNDS; r++) { w = W[r][0]; *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); w = W[r][1]; *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); w = W[r][2]; *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); w = W[r][3]; *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); } #undef W } /* Encrypt one block. A and B may be the same. */ static void -rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) +do_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) { int r; byte temp[4][4]; int ROUNDS = ctx->ROUNDS; #define rk (ctx->keySched) *((u32*)temp[0]) = *((u32*)(a )) ^ *((u32*)rk[0][0]); *((u32*)temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[0][1]); *((u32*)temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[0][2]); *((u32*)temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[0][3]); *((u32*)(b )) = *((u32*)T1[temp[0][0]]) ^ *((u32*)T2[temp[1][1]]) ^ *((u32*)T3[temp[2][2]]) ^ *((u32*)T4[temp[3][3]]); *((u32*)(b + 4)) = *((u32*)T1[temp[1][0]]) ^ *((u32*)T2[temp[2][1]]) ^ *((u32*)T3[temp[3][2]]) ^ *((u32*)T4[temp[0][3]]); *((u32*)(b + 8)) = *((u32*)T1[temp[2][0]]) ^ *((u32*)T2[temp[3][1]]) ^ *((u32*)T3[temp[0][2]]) ^ *((u32*)T4[temp[1][3]]); *((u32*)(b +12)) = *((u32*)T1[temp[3][0]]) ^ *((u32*)T2[temp[0][1]]) ^ *((u32*)T3[temp[1][2]]) ^ *((u32*)T4[temp[2][3]]); for (r = 1; r < ROUNDS-1; r++) { *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]); *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]); *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]); *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]); *((u32*)(b )) = *((u32*)T1[temp[0][0]]) ^ *((u32*)T2[temp[1][1]]) ^ *((u32*)T3[temp[2][2]]) ^ *((u32*)T4[temp[3][3]]); *((u32*)(b + 4)) = *((u32*)T1[temp[1][0]]) ^ *((u32*)T2[temp[2][1]]) ^ *((u32*)T3[temp[3][2]]) ^ *((u32*)T4[temp[0][3]]); *((u32*)(b + 8)) = *((u32*)T1[temp[2][0]]) ^ *((u32*)T2[temp[3][1]]) ^ *((u32*)T3[temp[0][2]]) ^ *((u32*)T4[temp[1][3]]); *((u32*)(b +12)) = *((u32*)T1[temp[3][0]]) ^ *((u32*)T2[temp[0][1]]) ^ *((u32*)T3[temp[1][2]]) ^ *((u32*)T4[temp[2][3]]); } /* last round is special */ *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[ROUNDS-1][0]); *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[ROUNDS-1][1]); *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[ROUNDS-1][2]); *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[ROUNDS-1][3]); b[ 0] = T1[temp[0][0]][1]; b[ 1] = T1[temp[1][1]][1]; b[ 2] = T1[temp[2][2]][1]; b[ 3] = T1[temp[3][3]][1]; b[ 4] = T1[temp[1][0]][1]; b[ 5] = T1[temp[2][1]][1]; b[ 6] = T1[temp[3][2]][1]; b[ 7] = T1[temp[0][3]][1]; b[ 8] = T1[temp[2][0]][1]; b[ 9] = T1[temp[3][1]][1]; b[10] = T1[temp[0][2]][1]; b[11] = T1[temp[1][3]][1]; b[12] = T1[temp[3][0]][1]; b[13] = T1[temp[0][1]][1]; b[14] = T1[temp[1][2]][1]; b[15] = T1[temp[2][3]][1]; *((u32*)(b )) ^= *((u32*)rk[ROUNDS][0]); *((u32*)(b+ 4)) ^= *((u32*)rk[ROUNDS][1]); *((u32*)(b+ 8)) ^= *((u32*)rk[ROUNDS][2]); *((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]); #undef rk } + +static void +rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) +{ + do_encrypt (ctx, b, a); + burn_stack (16 + 2*sizeof(int)); +} + + /* Decrypt one block. a and b may be the same. */ static void -rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) +do_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) { #define rk (ctx->keySched2) int ROUNDS = ctx->ROUNDS; int r; byte temp[4][4]; if ( !ctx->decryption_prepared ) { prepare_decryption ( ctx ); + burn_stack (64); ctx->decryption_prepared = 1; } *((u32*)temp[0]) = *((u32*)(a )) ^ *((u32*)rk[ROUNDS][0]); *((u32*)temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[ROUNDS][1]); *((u32*)temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[ROUNDS][2]); *((u32*)temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[ROUNDS][3]); *((u32*)(b )) = *((u32*)T5[temp[0][0]]) ^ *((u32*)T6[temp[3][1]]) ^ *((u32*)T7[temp[2][2]]) ^ *((u32*)T8[temp[1][3]]); *((u32*)(b+ 4)) = *((u32*)T5[temp[1][0]]) ^ *((u32*)T6[temp[0][1]]) ^ *((u32*)T7[temp[3][2]]) ^ *((u32*)T8[temp[2][3]]); *((u32*)(b+ 8)) = *((u32*)T5[temp[2][0]]) ^ *((u32*)T6[temp[1][1]]) ^ *((u32*)T7[temp[0][2]]) ^ *((u32*)T8[temp[3][3]]); *((u32*)(b+12)) = *((u32*)T5[temp[3][0]]) ^ *((u32*)T6[temp[2][1]]) ^ *((u32*)T7[temp[1][2]]) ^ *((u32*)T8[temp[0][3]]); for (r = ROUNDS-1; r > 1; r--) { *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]); *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]); *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]); *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]); *((u32*)(b )) = *((u32*)T5[temp[0][0]]) ^ *((u32*)T6[temp[3][1]]) ^ *((u32*)T7[temp[2][2]]) ^ *((u32*)T8[temp[1][3]]); *((u32*)(b+ 4)) = *((u32*)T5[temp[1][0]]) ^ *((u32*)T6[temp[0][1]]) ^ *((u32*)T7[temp[3][2]]) ^ *((u32*)T8[temp[2][3]]); *((u32*)(b+ 8)) = *((u32*)T5[temp[2][0]]) ^ *((u32*)T6[temp[1][1]]) ^ *((u32*)T7[temp[0][2]]) ^ *((u32*)T8[temp[3][3]]); *((u32*)(b+12)) = *((u32*)T5[temp[3][0]]) ^ *((u32*)T6[temp[2][1]]) ^ *((u32*)T7[temp[1][2]]) ^ *((u32*)T8[temp[0][3]]); } /* last round is special */ *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[1][0]); *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[1][1]); *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[1][2]); *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[1][3]); b[ 0] = S5[temp[0][0]]; b[ 1] = S5[temp[3][1]]; b[ 2] = S5[temp[2][2]]; b[ 3] = S5[temp[1][3]]; b[ 4] = S5[temp[1][0]]; b[ 5] = S5[temp[0][1]]; b[ 6] = S5[temp[3][2]]; b[ 7] = S5[temp[2][3]]; b[ 8] = S5[temp[2][0]]; b[ 9] = S5[temp[1][1]]; b[10] = S5[temp[0][2]]; b[11] = S5[temp[3][3]]; b[12] = S5[temp[3][0]]; b[13] = S5[temp[2][1]]; b[14] = S5[temp[1][2]]; b[15] = S5[temp[0][3]]; *((u32*)(b )) ^= *((u32*)rk[0][0]); *((u32*)(b+ 4)) ^= *((u32*)rk[0][1]); *((u32*)(b+ 8)) ^= *((u32*)rk[0][2]); *((u32*)(b+12)) ^= *((u32*)rk[0][3]); #undef rk } + +static void +rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) +{ + do_decrypt (ctx, b, a); + burn_stack (16+2*sizeof(int)); +} /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { RIJNDAEL_context ctx; byte scratch[16]; /* The test vectors are from the AES supplied ones; more or less * randomly taken from ecb_tbl.txt (I=42,81,14) */ static const byte plaintext[16] = { 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33, 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A }; static const byte key[16] = { 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0, 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA }; static const byte ciphertext[16] = { 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2, 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD }; static const byte plaintext_192[16] = { 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4, 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72 }; static const byte key_192[24] = { 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C, 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16, 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20 }; static const byte ciphertext_192[16] = { 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC, 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA }; static const byte plaintext_256[16] = { 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 }; static const byte key_256[32] = { 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10, 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24, 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E }; static const byte ciphertext_256[16] = { 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71, 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3 }; rijndael_setkey (&ctx, key, sizeof(key)); rijndael_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "Rijndael-128 test encryption failed."; rijndael_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "Rijndael-128 test decryption failed."; rijndael_setkey (&ctx, key_192, sizeof(key_192)); rijndael_encrypt (&ctx, scratch, plaintext_192); if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192))) return "Rijndael-192 test encryption failed."; rijndael_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_192, sizeof (plaintext_192))) return "Rijndael-192 test decryption failed."; rijndael_setkey (&ctx, key_256, sizeof(key_256)); rijndael_encrypt (&ctx, scratch, plaintext_256); if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) return "Rijndael-256 test encryption failed."; rijndael_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) return "Rijndael-256 test decryption failed."; return NULL; } #ifdef IS_MODULE static #endif const char * _gcry_rijndael_get_info (int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey) (void *c, byte *key, unsigned keylen), void (**r_encrypt) (void *c, byte *outbuf, byte *inbuf), void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf) ) { *keylen = algo==7? 128 : algo==8? 192 : 256; *blocksize = 16; *contextsize = sizeof (RIJNDAEL_context); *(int (**)(RIJNDAEL_context*, const byte*, const unsigned))r_setkey = rijndael_setkey; *(void (**)(const RIJNDAEL_context*, byte*, const byte*))r_encrypt = rijndael_encrypt; *(void (**)(RIJNDAEL_context*, byte*, const byte*))r_decrypt = rijndael_decrypt; if( algo == 7 ) return "RIJNDAEL"; if (algo == 8) return "RIJNDAEL192"; if (algo == 9) return "RIJNDAEL256"; return NULL; } #ifdef IS_MODULE const char * const gnupgext_version = "RIJNDAEL ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 20, 1, 0, (void(*)(void))_gcry_rijndael_get_info }, { 21, 1, 7 }, { 21, 1, 8 }, { 21, 1, 9 }, }; /**************** * Enumerate the names of the functions together with information about * this function. Set sequence to an integer with a initial value of 0 and * do not change it. * If what is 0 all kind of functions are returned. * Return values: class := class of function: * 10 = message digest algorithm info function * 11 = integer with available md algorithms * 20 = cipher algorithm info function * 21 = integer with available cipher algorithms * 30 = public key algorithm info function * 31 = integer with available pubkey algorithms * version = interface version of the function/pointer * (currently this is 1 for all functions) */ void * gnupgext_enum_func ( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if ( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while ( what && what != *class ); *sequence = i; return ret; } #endif diff --git a/cipher/rmd160.c b/cipher/rmd160.c index cce9d3c5..d3f00f2e 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -1,633 +1,648 @@ /* rmd160.c - RIPE-MD160 * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include "g10lib.h" #include "memory.h" #include "rmd.h" #include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ #include "dynload.h" #include "bithelp.h" /********************************* * RIPEMD-160 is not patented, see (as of 25.10.97) * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html * Note that the code uses Little Endian byteorder, which is good for * 386 etc, but we must add some conversion when used on a big endian box. * * * Pseudo-code for RIPEMD-160 * * RIPEMD-160 is an iterative hash function that operates on 32-bit words. * The round function takes as input a 5-word chaining variable and a 16-word * message block and maps this to a new chaining variable. All operations are * defined on 32-bit words. Padding is identical to that of MD4. * * * RIPEMD-160: definitions * * * nonlinear functions at bit level: exor, mux, -, mux, - * * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) * * * added constants (hexadecimal) * * K(j) = 0x00000000 (0 <= j <= 15) * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) * K'(j) = 0x00000000 (64 <= j <= 79) * * * selection of message word * * r(j) = j (0 <= j <= 15) * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 * * * amount for rotate left (rol) * * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 * * * initial value (hexadecimal) * * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; * h4 = 0xC3D2E1F0; * * * RIPEMD-160: pseudo-code * * It is assumed that the message after padding consists of t 16-word blocks * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left * shift (rotate) over s positions. * * * for i := 0 to t-1 { * A := h0; B := h1; C := h2; D = h3; E = h4; * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; * for j := 0 to 79 { * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; * A := E; E := D; D := rol_10(C); C := B; B := T; * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] [+] K'(j)) [+] E'; * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; * } * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; * } */ /* Some examples: * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ +static void +burn_stack (int bytes) +{ + char buf[150]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + void _gcry_rmd160_init( RMD160_CONTEXT *hd ) { hd->h0 = 0x67452301; hd->h1 = 0xEFCDAB89; hd->h2 = 0x98BADCFE; hd->h3 = 0x10325476; hd->h4 = 0xC3D2E1F0; hd->nblocks = 0; hd->count = 0; } /**************** * Transform the message X which consists of 16 32-bit-words */ static void transform( RMD160_CONTEXT *hd, byte *data ) { u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; #ifdef BIG_ENDIAN_HOST u32 x[16]; { int i; byte *p2, *p1; for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; p2[2] = *p1++; p2[1] = *p1++; p2[0] = *p1++; } } #else #if 0 u32 *x =(u32*)data; #else /* this version is better because it is always aligned; * The performance penalty on a 586-100 is about 6% which * is acceptable - because the data is more local it might * also be possible that this is faster on some machines. * This function (when compiled with -02 on gcc 2.7.2) * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; * [measured with a 4MB data and "gpgm --print-md rmd160"] */ u32 x[16]; memcpy( x, data, 64 ); #endif #endif #define K0 0x00000000 #define K1 0x5A827999 #define K2 0x6ED9EBA1 #define K3 0x8F1BBCDC #define K4 0xA953FD4E #define KK0 0x50A28BE6 #define KK1 0x5C4DD124 #define KK2 0x6D703EF3 #define KK3 0x7A6D76E9 #define KK4 0x00000000 #define F0(x,y,z) ( (x) ^ (y) ^ (z) ) #define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) #define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) #define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) #define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) #define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ a = rol(t,s) + e; \ c = rol(c,10); \ } while(0) /* left lane */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; R( a, b, c, d, e, F0, K0, 0, 11 ); R( e, a, b, c, d, F0, K0, 1, 14 ); R( d, e, a, b, c, F0, K0, 2, 15 ); R( c, d, e, a, b, F0, K0, 3, 12 ); R( b, c, d, e, a, F0, K0, 4, 5 ); R( a, b, c, d, e, F0, K0, 5, 8 ); R( e, a, b, c, d, F0, K0, 6, 7 ); R( d, e, a, b, c, F0, K0, 7, 9 ); R( c, d, e, a, b, F0, K0, 8, 11 ); R( b, c, d, e, a, F0, K0, 9, 13 ); R( a, b, c, d, e, F0, K0, 10, 14 ); R( e, a, b, c, d, F0, K0, 11, 15 ); R( d, e, a, b, c, F0, K0, 12, 6 ); R( c, d, e, a, b, F0, K0, 13, 7 ); R( b, c, d, e, a, F0, K0, 14, 9 ); R( a, b, c, d, e, F0, K0, 15, 8 ); R( e, a, b, c, d, F1, K1, 7, 7 ); R( d, e, a, b, c, F1, K1, 4, 6 ); R( c, d, e, a, b, F1, K1, 13, 8 ); R( b, c, d, e, a, F1, K1, 1, 13 ); R( a, b, c, d, e, F1, K1, 10, 11 ); R( e, a, b, c, d, F1, K1, 6, 9 ); R( d, e, a, b, c, F1, K1, 15, 7 ); R( c, d, e, a, b, F1, K1, 3, 15 ); R( b, c, d, e, a, F1, K1, 12, 7 ); R( a, b, c, d, e, F1, K1, 0, 12 ); R( e, a, b, c, d, F1, K1, 9, 15 ); R( d, e, a, b, c, F1, K1, 5, 9 ); R( c, d, e, a, b, F1, K1, 2, 11 ); R( b, c, d, e, a, F1, K1, 14, 7 ); R( a, b, c, d, e, F1, K1, 11, 13 ); R( e, a, b, c, d, F1, K1, 8, 12 ); R( d, e, a, b, c, F2, K2, 3, 11 ); R( c, d, e, a, b, F2, K2, 10, 13 ); R( b, c, d, e, a, F2, K2, 14, 6 ); R( a, b, c, d, e, F2, K2, 4, 7 ); R( e, a, b, c, d, F2, K2, 9, 14 ); R( d, e, a, b, c, F2, K2, 15, 9 ); R( c, d, e, a, b, F2, K2, 8, 13 ); R( b, c, d, e, a, F2, K2, 1, 15 ); R( a, b, c, d, e, F2, K2, 2, 14 ); R( e, a, b, c, d, F2, K2, 7, 8 ); R( d, e, a, b, c, F2, K2, 0, 13 ); R( c, d, e, a, b, F2, K2, 6, 6 ); R( b, c, d, e, a, F2, K2, 13, 5 ); R( a, b, c, d, e, F2, K2, 11, 12 ); R( e, a, b, c, d, F2, K2, 5, 7 ); R( d, e, a, b, c, F2, K2, 12, 5 ); R( c, d, e, a, b, F3, K3, 1, 11 ); R( b, c, d, e, a, F3, K3, 9, 12 ); R( a, b, c, d, e, F3, K3, 11, 14 ); R( e, a, b, c, d, F3, K3, 10, 15 ); R( d, e, a, b, c, F3, K3, 0, 14 ); R( c, d, e, a, b, F3, K3, 8, 15 ); R( b, c, d, e, a, F3, K3, 12, 9 ); R( a, b, c, d, e, F3, K3, 4, 8 ); R( e, a, b, c, d, F3, K3, 13, 9 ); R( d, e, a, b, c, F3, K3, 3, 14 ); R( c, d, e, a, b, F3, K3, 7, 5 ); R( b, c, d, e, a, F3, K3, 15, 6 ); R( a, b, c, d, e, F3, K3, 14, 8 ); R( e, a, b, c, d, F3, K3, 5, 6 ); R( d, e, a, b, c, F3, K3, 6, 5 ); R( c, d, e, a, b, F3, K3, 2, 12 ); R( b, c, d, e, a, F4, K4, 4, 9 ); R( a, b, c, d, e, F4, K4, 0, 15 ); R( e, a, b, c, d, F4, K4, 5, 5 ); R( d, e, a, b, c, F4, K4, 9, 11 ); R( c, d, e, a, b, F4, K4, 7, 6 ); R( b, c, d, e, a, F4, K4, 12, 8 ); R( a, b, c, d, e, F4, K4, 2, 13 ); R( e, a, b, c, d, F4, K4, 10, 12 ); R( d, e, a, b, c, F4, K4, 14, 5 ); R( c, d, e, a, b, F4, K4, 1, 12 ); R( b, c, d, e, a, F4, K4, 3, 13 ); R( a, b, c, d, e, F4, K4, 8, 14 ); R( e, a, b, c, d, F4, K4, 11, 11 ); R( d, e, a, b, c, F4, K4, 6, 8 ); R( c, d, e, a, b, F4, K4, 15, 5 ); R( b, c, d, e, a, F4, K4, 13, 6 ); aa = a; bb = b; cc = c; dd = d; ee = e; /* right lane */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; R( a, b, c, d, e, F4, KK0, 5, 8); R( e, a, b, c, d, F4, KK0, 14, 9); R( d, e, a, b, c, F4, KK0, 7, 9); R( c, d, e, a, b, F4, KK0, 0, 11); R( b, c, d, e, a, F4, KK0, 9, 13); R( a, b, c, d, e, F4, KK0, 2, 15); R( e, a, b, c, d, F4, KK0, 11, 15); R( d, e, a, b, c, F4, KK0, 4, 5); R( c, d, e, a, b, F4, KK0, 13, 7); R( b, c, d, e, a, F4, KK0, 6, 7); R( a, b, c, d, e, F4, KK0, 15, 8); R( e, a, b, c, d, F4, KK0, 8, 11); R( d, e, a, b, c, F4, KK0, 1, 14); R( c, d, e, a, b, F4, KK0, 10, 14); R( b, c, d, e, a, F4, KK0, 3, 12); R( a, b, c, d, e, F4, KK0, 12, 6); R( e, a, b, c, d, F3, KK1, 6, 9); R( d, e, a, b, c, F3, KK1, 11, 13); R( c, d, e, a, b, F3, KK1, 3, 15); R( b, c, d, e, a, F3, KK1, 7, 7); R( a, b, c, d, e, F3, KK1, 0, 12); R( e, a, b, c, d, F3, KK1, 13, 8); R( d, e, a, b, c, F3, KK1, 5, 9); R( c, d, e, a, b, F3, KK1, 10, 11); R( b, c, d, e, a, F3, KK1, 14, 7); R( a, b, c, d, e, F3, KK1, 15, 7); R( e, a, b, c, d, F3, KK1, 8, 12); R( d, e, a, b, c, F3, KK1, 12, 7); R( c, d, e, a, b, F3, KK1, 4, 6); R( b, c, d, e, a, F3, KK1, 9, 15); R( a, b, c, d, e, F3, KK1, 1, 13); R( e, a, b, c, d, F3, KK1, 2, 11); R( d, e, a, b, c, F2, KK2, 15, 9); R( c, d, e, a, b, F2, KK2, 5, 7); R( b, c, d, e, a, F2, KK2, 1, 15); R( a, b, c, d, e, F2, KK2, 3, 11); R( e, a, b, c, d, F2, KK2, 7, 8); R( d, e, a, b, c, F2, KK2, 14, 6); R( c, d, e, a, b, F2, KK2, 6, 6); R( b, c, d, e, a, F2, KK2, 9, 14); R( a, b, c, d, e, F2, KK2, 11, 12); R( e, a, b, c, d, F2, KK2, 8, 13); R( d, e, a, b, c, F2, KK2, 12, 5); R( c, d, e, a, b, F2, KK2, 2, 14); R( b, c, d, e, a, F2, KK2, 10, 13); R( a, b, c, d, e, F2, KK2, 0, 13); R( e, a, b, c, d, F2, KK2, 4, 7); R( d, e, a, b, c, F2, KK2, 13, 5); R( c, d, e, a, b, F1, KK3, 8, 15); R( b, c, d, e, a, F1, KK3, 6, 5); R( a, b, c, d, e, F1, KK3, 4, 8); R( e, a, b, c, d, F1, KK3, 1, 11); R( d, e, a, b, c, F1, KK3, 3, 14); R( c, d, e, a, b, F1, KK3, 11, 14); R( b, c, d, e, a, F1, KK3, 15, 6); R( a, b, c, d, e, F1, KK3, 0, 14); R( e, a, b, c, d, F1, KK3, 5, 6); R( d, e, a, b, c, F1, KK3, 12, 9); R( c, d, e, a, b, F1, KK3, 2, 12); R( b, c, d, e, a, F1, KK3, 13, 9); R( a, b, c, d, e, F1, KK3, 9, 12); R( e, a, b, c, d, F1, KK3, 7, 5); R( d, e, a, b, c, F1, KK3, 10, 15); R( c, d, e, a, b, F1, KK3, 14, 8); R( b, c, d, e, a, F0, KK4, 12, 8); R( a, b, c, d, e, F0, KK4, 15, 5); R( e, a, b, c, d, F0, KK4, 10, 12); R( d, e, a, b, c, F0, KK4, 4, 9); R( c, d, e, a, b, F0, KK4, 1, 12); R( b, c, d, e, a, F0, KK4, 5, 5); R( a, b, c, d, e, F0, KK4, 8, 14); R( e, a, b, c, d, F0, KK4, 7, 6); R( d, e, a, b, c, F0, KK4, 6, 8); R( c, d, e, a, b, F0, KK4, 2, 13); R( b, c, d, e, a, F0, KK4, 13, 6); R( a, b, c, d, e, F0, KK4, 14, 5); R( e, a, b, c, d, F0, KK4, 0, 15); R( d, e, a, b, c, F0, KK4, 3, 13); R( c, d, e, a, b, F0, KK4, 9, 11); R( b, c, d, e, a, F0, KK4, 11, 11); t = hd->h1 + d + cc; hd->h1 = hd->h2 + e + dd; hd->h2 = hd->h3 + a + ee; hd->h3 = hd->h4 + b + aa; hd->h4 = hd->h0 + c + bb; hd->h0 = t; } /* Update the message digest with the contents * of INBUF with length INLEN. */ static void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); hd->count = 0; hd->nblocks++; } if( !inbuf ) return; if( hd->count ) { for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; rmd160_write( hd, NULL, 0 ); if( !inlen ) return; } while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } + burn_stack (108+5*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } /**************** * Apply the rmd160 transform function on the buffer which must have * a length 64 bytes. Do not use this function together with the * other functions, use rmd160_init to initialize internal variables. * Returns: 16 bytes in buffer with the mixed contentes of buffer. */ void _gcry_rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) { char *p = buffer; transform( hd, buffer ); #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X } /* The routine terminates the computation */ static void rmd160_final( RMD160_CONTEXT *hd ) { u32 t, msb, lsb; byte *p; rmd160_write(hd, NULL, 0); /* flush */; t = hd->nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->count < 56 ) { /* enough room */ hd->buf[hd->count++] = 0x80; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ hd->buf[hd->count++] = 0x80; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; rmd160_write(hd, NULL, 0); /* flush */; memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ hd->buf[56] = lsb ; hd->buf[57] = lsb >> 8; hd->buf[58] = lsb >> 16; hd->buf[59] = lsb >> 24; hd->buf[60] = msb ; hd->buf[61] = msb >> 8; hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) #else /* little endian */ #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) #endif X(0); X(1); X(2); X(3); X(4); #undef X } static byte * rmd160_read( RMD160_CONTEXT *hd ) { return hd->buf; } /**************** * Shortcut functions which puts the hash value of the supplied buffer * into outbuf which must have a size of 20 bytes. */ void _gcry_rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) { RMD160_CONTEXT hd; _gcry_rmd160_init( &hd ); rmd160_write( &hd, (byte*)buffer, length ); rmd160_final( &hd ); memcpy( outbuf, hd.buf, 20 ); } /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ static const char * rmd160_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), void (**r_write)( void *c, byte *buf, size_t nbytes ), void (**r_final)( void *c ), byte *(**r_read)( void *c ) ) { static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; if( algo != 3 ) return NULL; *contextsize = sizeof(RMD160_CONTEXT); *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 20; *(void (**)(RMD160_CONTEXT *))r_init = _gcry_rmd160_init; *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; return "RIPEMD160"; } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "RMD160 ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 10, 1, 0, (void(*)(void))rmd160_get_info }, { 11, 1, 3 }, }; #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while( what && what != *class ); *sequence = i; return ret; } #ifndef IS_MODULE void _gcry_rmd160_constructor(void) { _gcry_register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif diff --git a/cipher/rndlinux.c b/cipher/rndlinux.c index cf3df66b..e0442407 100644 --- a/cipher/rndlinux.c +++ b/cipher/rndlinux.c @@ -1,221 +1,222 @@ /* rndlinux.c - raw random number for OSes with /dev/random * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include #ifdef HAVE_GETTIMEOFDAY #include #endif #include #include #include #if 0 #ifdef HAVE_LINUX_RANDOM_H #include #include #include #endif #endif #include "types.h" #include "g10lib.h" #include "dynload.h" static int open_device( const char *name, int minor ); static int gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ); #if 0 #ifdef HAVE_DEV_RANDOM_IOCTL static ulong get_entropy_count( int fd ) { ulong count; if( ioctl( fd, RNDGETENTCNT, &count ) == -1 ) log_fatal("ioctl(RNDGETENTCNT) failed: %s\n", strerror(errno) ); return count; } #endif #endif /**************** * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists), ...) */ static int open_device( const char *name, int minor ) { int fd; struct stat sb; fd = open( name, O_RDONLY ); if( fd == -1 ) log_fatal("can't open %s: %s\n", name, strerror(errno) ); if( fstat( fd, &sb ) ) log_fatal("stat() off %s failed: %s\n", name, strerror(errno) ); /* Don't check device type for better portability */ /* if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) ) log_fatal("invalid random device!\n" ); */ return fd; } static int gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) { static int fd_urandom = -1; static int fd_random = -1; int fd; int n; int warn=0; byte buffer[768]; if( level >= 2 ) { if( fd_random == -1 ) fd_random = open_device( NAME_OF_DEV_RANDOM, 8 ); fd = fd_random; } else { if( fd_urandom == -1 ) fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 ); fd = fd_urandom; } #if 0 #ifdef HAVE_DEV_RANDOM_IOCTL log_info("entropy count of %d is %lu\n", fd, get_entropy_count(fd) ); #endif #endif while( length ) { fd_set rfds; struct timeval tv; int rc; FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = 3; tv.tv_usec = 0; if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { #warning FIXME: Replace fprintf by a callback if( !warn ) fprintf(stderr, _("\n" "Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n"), length ); +"the OS a chance to collect more entropy! (Need %d more bytes)\n"), + (int)length ); warn = 1; continue; } else if( rc == -1 ) { fprintf(stderr, "select() error: %s\n", strerror(errno)); continue; } do { int nbytes = length < sizeof(buffer)? length : sizeof(buffer); n = read(fd, buffer, nbytes ); if( n >= 0 && n > nbytes ) { log_error("bogus read from random device (n=%d)\n", n ); n = nbytes; } } while( n == -1 && errno == EINTR ); if( n == -1 ) log_fatal("read error on random device: %s\n", strerror(errno)); (*add)( buffer, n, requester ); length -= n; } memset(buffer, 0, sizeof(buffer) ); return 0; /* success */ } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "RNDLINUX ($Revision$)"; static struct { int class; int version; void *func; } func_table[] = { { 40, 1, gather_random }, }; /**************** * Enumerate the names of the functions together with informations about * this function. Set sequence to an integer with a initial value of 0 and * do not change it. * If what is 0 all kind of functions are returned. * Return values: class := class of function: * 10 = message digest algorithm info function * 11 = integer with available md algorithms * 20 = cipher algorithm info function * 21 = integer with available cipher algorithms * 30 = public key algorithm info function * 31 = integer with available pubkey algorithms * 40 = get gather_random function * 41 = get fast_random_poll function * version = interface version of the function/pointer * (currently this is 1 for all functions) */ #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if ( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; ret = func_table[i].func; i++; } while ( what && what != *class ); *sequence = i; return ret; } #ifndef IS_MODULE void _gcry_rndlinux_constructor(void) { _gcry_register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif diff --git a/cipher/rndunix.c b/cipher/rndunix.c index 8ef1caed..bcb1f3fd 100644 --- a/cipher/rndunix.c +++ b/cipher/rndunix.c @@ -1,916 +1,917 @@ /**************************************************************************** * * * * * Unix Randomness-Gathering Code * * * * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. * * Heavily modified for GnuPG by Werner Koch * * * * * ****************************************************************************/ /* This module is part of the cryptlib continuously seeded pseudorandom number generator. For usage conditions, see lib_rand.c [Here is the notice from lib_rand.c:] This module and the misc/rnd*.c modules represent the cryptlib continuously seeded pseudorandom number generator (CSPRNG) as described in my 1998 Usenix Security Symposium paper "The generation of random numbers for cryptographic purposes". The CSPRNG code is copyright Peter Gutmann (and various others) 1996, 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG modules and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice and this permission notice in its entirety. 2. Redistributions in binary form must reproduce the copyright notice in the documentation and/or other materials provided with the distribution. 3. A copy of any bugfixes or enhancements made must be provided to the author, to allow them to be added to the baseline version of the code. ALTERNATIVELY, the code may be distributed under the terms of the GNU General Public License, version 2 or any later version published by the Free Software Foundation, in which case the provisions of the GNU GPL are required INSTEAD OF the above restrictions. Although not required under the terms of the GPL, it would still be nice if you could make any changes available to the author to allow a consistent code base to be maintained */ /* Fixme: We use plain mallocs here beucase it may be used as a module * should be changed. */ /* General includes */ #include #include #include #include #include /* OS-specific includes */ #ifdef __osf__ /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in * via the following includes are various endianness defines, so we * undefine the cryptlib ones, which aren't really needed for this module * anyway */ #undef BIG_ENDIAN #undef LITTLE_ENDIAN #endif /* __osf__ */ #include #include #include #ifndef __QNX__ #include #include #endif /* __QNX__ */ #include /* SCO and SunOS need this before resource.h */ #ifndef __QNX__ #include #endif /* __QNX__ */ #if defined( _AIX ) || defined( __QNX__ ) #include #endif /* _AIX */ #ifndef __QNX__ #include +#include #include #endif /* __QNX__ */ #include #include /* Verschiedene komische Typen */ #if defined( __hpux ) && ( OS_VERSION == 9 ) #include #endif /* __hpux 9.x, after that it's in unistd.h */ #include /* #include */ #ifdef __QNX__ #include #include #endif /* __QNX__ */ #include #include "types.h" /* for byte and u32 typedefs */ #ifndef IS_MODULE #include "dynload.h" #endif #include "g10lib.h" #ifndef EAGAIN #define EAGAIN EWOULDBLOCK #endif #ifndef STDIN_FILENO #define STDIN_FILENO 0 #endif #ifndef STDOUT_FILENO #define STDOUT_FILENO 1 #endif #define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */ /* The structure containing information on random-data sources. Each * record contains the source and a relative estimate of its usefulness * (weighting) which is used to scale the number of kB of output from the * source (total = data_bytes / usefulness). Usually the weighting is in the * range 1-3 (or 0 for especially useless sources), resulting in a usefulness * rating of 1...3 for each kB of source output (or 0 for the useless * sources). * * If the source is constantly changing (certain types of network statistics * have this characteristic) but the amount of output is small, the weighting * is given as a negative value to indicate that the output should be treated * as if a minimum of 1K of output had been obtained. If the source produces * a lot of output then the scale factor is fractional, resulting in a * usefulness rating of < 1 for each kB of source output. * * In order to provide enough randomness to satisfy the requirements for a * slow poll, we need to accumulate at least 20 points of usefulness (a * typical system should get about 30 points). * * Some potential options are missed out because of special considerations. * pstat -i and pstat -f can produce amazing amounts of output (the record * is 600K on an Oracle server) which floods the buffer and doesn't yield * anything useful (apart from perhaps increasing the entropy of the vmstat * output a bit), so we don't bother with this. pstat in general produces * quite a bit of output, but it doesn't change much over time, so it gets * very low weightings. netstat -s produces constantly-changing output but * also produces quite a bit of it, so it only gets a weighting of 2 rather * than 3. The same holds for netstat -in, which gets 1 rather than 2. * * Some binaries are stored in different locations on different systems so * alternative paths are given for them. The code sorts out which one to * run by itself, once it finds an exectable somewhere it moves on to the * next source. The sources are arranged roughly in their order of * usefulness, occasionally sources which provide a tiny amount of * relatively useless data are placed ahead of ones which provide a large * amount of possibly useful data because another 100 bytes can't hurt, and * it means the buffer won't be swamped by one or two high-output sources. * All the high-output sources are clustered towards the end of the list * for this reason. Some binaries are checked for in a certain order, for * example under Slowaris /usr/ucb/ps understands aux as an arg, but the * others don't. Some systems have conditional defines enabling alternatives * to commands which don't understand the usual options but will provide * enough output (in the form of error messages) to look like they're the * real thing, causing alternative options to be skipped (we can't check the * return either because some commands return peculiar, non-zero status even * when they're working correctly). * * In order to maximise use of the buffer, the code performs a form of run- * length compression on its input where a repeated sequence of bytes is * replaced by the occurrence count mod 256. Some commands output an awful * lot of whitespace, this measure greatly increases the amount of data we * can fit in the buffer. * * When we scale the weighting using the SC() macro, some preprocessors may * give a division by zero warning for the most obvious expression * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero * trap), so we define a value SC_0 which evaluates to zero when fed to * '1024 / SC_0' */ #define SC( weight ) ( 1024 / weight ) /* Scale factor */ #define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */ static struct RI { const char *path; /* Path to check for existence of source */ const char *arg; /* Args for source */ const int usefulness; /* Usefulness of source */ FILE *pipe; /* Pipe to source as FILE * */ int pipeFD; /* Pipe to source as FD */ pid_t pid; /* pid of child for waitpid() */ int length; /* Quantity of output produced */ const int hasAlternative; /* Whether source has alt.location */ } dataSources[] = { { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 }, { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0}, { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 }, { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0}, { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0}, { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 }, { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0}, { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1}, { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0}, { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0}, { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 }, { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1}, { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0}, { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0", SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0", SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0", SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0", SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0", SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0", SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 }, { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 }, { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 }, { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 }, { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 }, { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 }, { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 }, #if defined( __sgi ) || defined( __hpux ) { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 }, #endif /* __sgi || __hpux */ { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 }, { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/ { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 }, { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 }, /* Unreliable source, depends on system usage */ { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 }, { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 }, { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 }, { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 }, { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 }, { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 }, { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 }, { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 }, { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, /* pstat is your friend */ { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 }, #ifdef __sgi { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, #endif /* __sgi */ #ifdef __hpux { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, #endif /* __hpux */ { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 }, { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0", SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0", SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 }, { "/usr/sbin/ripquery", "-nw 1 127.0.0.1", SC(0.1), NULL, 0, 0, 0, 0 }, { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 }, /* This is very environment-dependant. If network traffic is low, it'll * probably time out before delivering 5 packets, which is OK because * it'll probably be fixed stuff like ARP anyway */ { "/usr/sbin/advfsstat", "-b usr_domain", SC(SC_0), NULL, 0, 0, 0, 0}, { "/usr/sbin/advfsstat", "-l 2 usr_domain", SC(0.5), NULL, 0, 0, 0, 0}, { "/usr/sbin/advfsstat", "-p usr_domain", SC(SC_0), NULL, 0, 0, 0, 0}, /* This is a complex and screwball program. Some systems have things * like rX_dmn, x = integer, for RAID systems, but the statistics are * pretty dodgy */ #ifdef __QNXNTO__ { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3), NULL, 0, 0, 0, 0 }, #endif #if 0 /* The following aren't enabled since they're somewhat slow and not very * unpredictable, however they give an indication of the sort of sources * you can use (for example the finger might be more useful on a * firewalled internal network) */ { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 }, { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html", SC(0.9), NULL, 0, 0, 0, 0 }, { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 }, #endif /* 0 */ { NULL, NULL, 0, NULL, 0, 0, 0, 0 } }; static byte *gather_buffer; /* buffer for gathering random noise */ static int gather_buffer_size; /* size of the memory buffer */ static uid_t gatherer_uid; /* The message structure used to communicate with the parent */ typedef struct { int usefulness; /* usefulness of data */ int ndata; /* valid bytes in data */ char data[500]; /* gathered data */ } GATHER_MSG; #ifndef HAVE_WAITPID pid_t waitpid(pid_t pid, int *statptr, int options) { #ifdef HAVE_WAIT4 return wait4(pid, statptr, options, NULL); #else /* If wait4 is also not available, try wait3 for SVR3 variants */ /* Less ideal because can't actually request a specific pid */ /* For that reason, first check to see if pid is for an */ /* existing process. */ int tmp_pid, dummystat;; if (kill(pid, 0) == -1) { errno = ECHILD; return -1; } if (statptr == NULL) statptr = &dummystat; while (((tmp_pid = wait3(statptr, options, 0)) != pid) && (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) ; return tmp_pid; #endif } #endif /* Under SunOS popen() doesn't record the pid of the child process. When * pclose() is called, instead of calling waitpid() for the correct child, it * calls wait() repeatedly until the right child is reaped. The problem is * that this reaps any other children that happen to have died at that * moment, and when their pclose() comes along, the process hangs forever. * The fix is to use a wrapper for popen()/pclose() which saves the pid in * the dataSources structure (code adapted from GNU-libc's popen() call). * * Aut viam inveniam aut faciam */ static FILE * my_popen(struct RI *entry) { int pipedes[2]; FILE *stream; /* Create the pipe */ if (pipe(pipedes) < 0) return (NULL); /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to * do it, but most just end up faking it" - Chris Wedgwood). If your OS * supports it, you should try to use vfork() here because it's somewhat * more efficient */ #if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \ defined(__hpux) entry->pid = vfork(); #else /* */ entry->pid = fork(); #endif /* Unixen which have vfork() */ if (entry->pid == (pid_t) - 1) { /* The fork failed */ close(pipedes[0]); close(pipedes[1]); return (NULL); } if (entry->pid == (pid_t) 0) { struct passwd *passwd; /* We are the child. Make the read side of the pipe be stdout */ if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) exit(127); /* Now that everything is set up, give up our permissions to make * sure we don't read anything sensitive. If the getpwnam() fails, * we default to -1, which is usually nobody */ if (gatherer_uid == (uid_t)-1 && \ (passwd = getpwnam("nobody")) != NULL) gatherer_uid = passwd->pw_uid; setuid(gatherer_uid); /* Close the pipe descriptors */ close(pipedes[STDIN_FILENO]); close(pipedes[STDOUT_FILENO]); /* Try and exec the program */ execl(entry->path, entry->path, entry->arg, NULL); /* Die if the exec failed */ exit(127); } /* We are the parent. Close the irrelevant side of the pipe and open * the relevant side as a new stream. Mark our side of the pipe to * close on exec, so new children won't see it */ close(pipedes[STDOUT_FILENO]); #ifdef FD_CLOEXEC fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); #endif stream = fdopen(pipedes[STDIN_FILENO], "r"); if (stream == NULL) { int savedErrno = errno; /* The stream couldn't be opened or the child structure couldn't be * allocated. Kill the child and close the other side of the pipe */ kill(entry->pid, SIGKILL); if (stream == NULL) close(pipedes[STDOUT_FILENO]); else fclose(stream); waitpid(entry->pid, NULL, 0); entry->pid = 0; errno = savedErrno; return (NULL); } return (stream); } static int my_pclose(struct RI *entry) { int status = 0; if (fclose(entry->pipe)) return (-1); /* We ignore the return value from the process because some programs * return funny values which would result in the input being discarded * even if they executed successfully. This isn't a problem because the * result data size threshold will filter out any programs which exit * with a usage message without producing useful output */ if (waitpid(entry->pid, NULL, 0) != entry->pid) status = -1; entry->pipe = NULL; entry->pid = 0; return (status); } /* Unix slow poll (without special support for Linux) * * If a few of the randomness sources create a large amount of output then * the slowPoll() stops once the buffer has been filled (but before all the * randomness sources have been sucked dry) so that the 'usefulness' factor * remains below the threshold. For this reason the gatherer buffer has to * be fairly sizeable on moderately loaded systems. This is something of a * bug since the usefulness should be influenced by the amount of output as * well as the source type */ static int slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) { int moreSources; struct timeval tv; fd_set fds; #if defined( __hpux ) size_t maxFD = 0; #else int maxFD = 0; #endif /* OS-specific brokenness */ int bufPos, i, usefulness = 0; /* Fire up each randomness source */ FD_ZERO(&fds); for (i = 0; dataSources[i].path != NULL; i++) { /* Since popen() is a fairly heavy function, we check to see whether * the executable exists before we try to run it */ if (access(dataSources[i].path, X_OK)) { if( dbgfp && dbgall ) fprintf(dbgfp, "%s not present%s\n", dataSources[i].path, dataSources[i].hasAlternative ? ", has alternatives" : ""); dataSources[i].pipe = NULL; } else dataSources[i].pipe = my_popen(&dataSources[i]); if (dataSources[i].pipe != NULL) { dataSources[i].pipeFD = fileno(dataSources[i].pipe); if (dataSources[i].pipeFD > maxFD) maxFD = dataSources[i].pipeFD; #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */ fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK); #else #warning O_NONBLOCK is missing #endif FD_SET(dataSources[i].pipeFD, &fds); dataSources[i].length = 0; /* If there are alternatives for this command, don't try and * execute them */ while (dataSources[i].hasAlternative) { if( dbgfp && dbgall ) fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path); i++; } } } /* Suck all the data we can get from each of the sources */ bufPos = 0; moreSources = 1; while (moreSources && bufPos <= gather_buffer_size) { /* Wait for data to become available from any of the sources, with a * timeout of 10 seconds. This adds even more randomness since data * becomes available in a nondeterministic fashion. Kudos to HP's QA * department for managing to ship a select() which breaks its own * prototype */ tv.tv_sec = 10; tv.tv_usec = 0; #if defined( __hpux ) && ( OS_VERSION == 9 ) if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) #else /* */ if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) #endif /* __hpux */ break; /* One of the sources has data available, read it into the buffer */ for (i = 0; dataSources[i].path != NULL; i++) { if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { size_t noBytes; if ((noBytes = fread(gather_buffer + bufPos, 1, gather_buffer_size - bufPos, dataSources[i].pipe)) == 0) { if (my_pclose(&dataSources[i]) == 0) { int total = 0; /* Try and estimate how much entropy we're getting * from a data source */ if (dataSources[i].usefulness) { if (dataSources[i].usefulness < 0) total = (dataSources[i].length + 999) / -dataSources[i].usefulness; else total = dataSources[i].length / dataSources[i].usefulness; } if( dbgfp ) fprintf(dbgfp, "%s %s contributed %d bytes, " "usefulness = %d\n", dataSources[i].path, (dataSources[i].arg != NULL) ? dataSources[i].arg : "", dataSources[i].length, total); if( dataSources[i].length ) usefulness += total; } dataSources[i].pipe = NULL; } else { int currPos = bufPos; int endPos = bufPos + noBytes; /* Run-length compress the input byte sequence */ while (currPos < endPos) { int ch = gather_buffer[currPos]; /* If it's a single byte, just copy it over */ if (ch != gather_buffer[currPos + 1]) { gather_buffer[bufPos++] = ch; currPos++; } else { int count = 0; /* It's a run of repeated bytes, replace them * with the byte count mod 256 */ while ((ch == gather_buffer[currPos]) && currPos < endPos) { count++; currPos++; } gather_buffer[bufPos++] = count; noBytes -= count - 1; } } /* Remember the number of (compressed) bytes of input we * obtained */ dataSources[i].length += noBytes; } } } /* Check if there is more input available on any of the sources */ moreSources = 0; FD_ZERO(&fds); for (i = 0; dataSources[i].path != NULL; i++) { if (dataSources[i].pipe != NULL) { FD_SET(dataSources[i].pipeFD, &fds); moreSources = 1; } } } if( dbgfp ) { fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); fflush(dbgfp); } *nbytes = bufPos; return usefulness; } /**************** * Start the gatherer process which writes messages of * type GATHERER_MSG to pipedes */ static void start_gatherer( int pipefd ) { FILE *dbgfp = NULL; int dbgall; { const char *s = getenv("GNUPG_RNDUNIX_DBG"); if( s ) { dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a"); if( !dbgfp ) log_info("can't open debug file `%s': %s\n", s, strerror(errno) ); else fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid()); } dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL"); } /* close all files but the ones we need */ { int nmax, n1, n2, i; #ifdef _SC_OPEN_MAX if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) { #ifdef _POSIX_OPEN_MAX nmax = _POSIX_OPEN_MAX; #else nmax = 20; /* assume a reasonable value */ #endif } #else nmax = 20; /* assume a reasonable value */ #endif n1 = fileno( stderr ); n2 = dbgfp? fileno( dbgfp ) : -1; for(i=0; i < nmax; i++ ) { if( i != n1 && i != n2 && i != pipefd ) close(i); } errno = 0; } /* Set up the buffer */ gather_buffer_size = GATHER_BUFSIZE; gather_buffer = malloc( gather_buffer_size ); if( !gather_buffer ) { log_error("out of core while allocating the gatherer buffer\n"); exit(2); } /* Reset the SIGC(H)LD handler to the system default. This is necessary * because if the program which cryptlib is a part of installs its own * SIGC(H)LD handler, it will end up reaping the cryptlib children before * cryptlib can. As a result, my_pclose() will call waitpid() on a * process which has already been reaped by the installed handler and * return an error, so the read data won't be added to the randomness * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and * the BSD/Posix SIGCHLD, so we need to handle either possibility */ #ifdef SIGCLD signal(SIGCLD, SIG_DFL); #else signal(SIGCHLD, SIG_DFL); #endif fclose(stderr); /* Arrghh!! It's Stuart code!! */ for(;;) { GATHER_MSG msg; size_t nbytes; const char *p; msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes ); p = gather_buffer; while( nbytes ) { msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes; memcpy( msg.data, p, msg.ndata ); nbytes -= msg.ndata; p += msg.ndata; while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) { if( errno == EINTR ) continue; if( errno == EAGAIN ) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 50000; select(0, NULL, NULL, NULL, &tv); continue; } if( errno == EPIPE ) /* parent has exited, so give up */ exit(0); /* we can't do very much here because stderr is closed */ if( dbgfp ) fprintf(dbgfp, "gatherer can't write to pipe: %s\n", strerror(errno) ); /* we start a new poll to give the system some time */ nbytes = 0; break; } } } /* we are killed when the parent dies */ } static int read_a_msg( int fd, GATHER_MSG *msg ) { char *buffer = (char*)msg; size_t length = sizeof( *msg ); int n; do { do { n = read(fd, buffer, length ); } while( n == -1 && errno == EINTR ); if( n == -1 ) return -1; buffer += n; length -= n; } while( length ); return 0; } /**************** * Using a level of 0 should never block and better add nothing * to the pool. So this is just a dummy for this gatherer. */ static int gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) { static pid_t gatherer_pid = 0; static int pipedes[2]; GATHER_MSG msg; size_t n; if( !level ) return 0; if( !gatherer_pid ) { /* make sure we are not setuid */ if( getuid() != geteuid() ) BUG(); /* time to start the gatherer process */ if( pipe( pipedes ) ) { log_error("pipe() failed: %s\n", strerror(errno)); return -1; } gatherer_pid = fork(); if( gatherer_pid == -1 ) { log_error("can't for gatherer process: %s\n", strerror(errno)); return -1; } if( !gatherer_pid ) { start_gatherer( pipedes[1] ); /* oops, can't happen */ return -1; } } /* now read from the gatherer */ while( length ) { int goodness; ulong subtract; if( read_a_msg( pipedes[0], &msg ) ) { log_error("reading from gatherer pipe failed: %s\n", strerror(errno)); return -1; } if( level > 1 ) { if( msg.usefulness > 30 ) goodness = 100; else if ( msg.usefulness ) goodness = msg.usefulness * 100 / 30; else goodness = 0; } else if( level ) { if( msg.usefulness > 15 ) goodness = 100; else if ( msg.usefulness ) goodness = msg.usefulness * 100 / 15; else goodness = 0; } else goodness = 100; /* goodness of level 0 is always 100 % */ n = msg.ndata; if( n > length ) n = length; (*add)( msg.data, n, requester ); /* this is the trick how e cope with the goodness */ subtract = (ulong)n * goodness / 100; /* subtract at least 1 byte to avoid infinite loops */ length -= subtract ? subtract : 1; } return 0; } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "RNDUNIX ($Revision$)"; static struct { int class; int version; void *func; } func_table[] = { { 40, 1, gather_random }, }; /**************** * Enumerate the names of the functions together with informations about * this function. Set sequence to an integer with a initial value of 0 and * do not change it. * If what is 0 all kind of functions are returned. * Return values: class := class of function: * 10 = message digest algorithm info function * 11 = integer with available md algorithms * 20 = cipher algorithm info function * 21 = integer with available cipher algorithms * 30 = public key algorithm info function * 31 = integer with available pubkey algorithms * 40 = get read_random_source() function * 41 = get fast_random_poll function * version = interface version of the function/pointer * (currently this is 1 for all functions) */ #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if ( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; ret = func_table[i].func; i++; } while ( what && what != *class ); *sequence = i; return ret; } #ifndef IS_MODULE void rndunix_constructor(void) { register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif diff --git a/cipher/sha1.c b/cipher/sha1.c index 39583208..8f0cfc19 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -1,409 +1,422 @@ /* sha1.c - SHA1 hash function * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * Please see below for more legal information! * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Test vectors: * * "abc" * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D * * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 */ #include #include #include #include #include #include "g10lib.h" #include "memory.h" #include "dynload.h" #include "bithelp.h" typedef struct { u32 h0,h1,h2,h3,h4; u32 nblocks; byte buf[64]; int count; } SHA1_CONTEXT; +static void +burn_stack (int bytes) +{ + char buf[128]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} static void sha1_init( SHA1_CONTEXT *hd ) { hd->h0 = 0x67452301; hd->h1 = 0xefcdab89; hd->h2 = 0x98badcfe; hd->h3 = 0x10325476; hd->h4 = 0xc3d2e1f0; hd->nblocks = 0; hd->count = 0; } /**************** * Transform the message X which consists of 16 32-bit-words */ static void transform( SHA1_CONTEXT *hd, byte *data ) { u32 a,b,c,d,e,tm; u32 x[16]; /* get values from the chaining vars */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; #ifdef BIG_ENDIAN_HOST memcpy( x, data, 64 ); #else { int i; byte *p2; for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) { p2[3] = *data++; p2[2] = *data++; p2[1] = *data++; p2[0] = *data++; } } #endif #define K1 0x5A827999L #define K2 0x6ED9EBA1L #define K3 0x8F1BBCDCL #define K4 0xCA62C1D6L #define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) #define F2(x,y,z) ( x ^ y ^ z ) #define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) #define F4(x,y,z) ( x ^ y ^ z ) #define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ , (x[i&0x0f] = rol(tm, 1)) ) #define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + f( b, c, d ) \ + k \ + m; \ b = rol( b, 30 ); \ } while(0) R( a, b, c, d, e, F1, K1, x[ 0] ); R( e, a, b, c, d, F1, K1, x[ 1] ); R( d, e, a, b, c, F1, K1, x[ 2] ); R( c, d, e, a, b, F1, K1, x[ 3] ); R( b, c, d, e, a, F1, K1, x[ 4] ); R( a, b, c, d, e, F1, K1, x[ 5] ); R( e, a, b, c, d, F1, K1, x[ 6] ); R( d, e, a, b, c, F1, K1, x[ 7] ); R( c, d, e, a, b, F1, K1, x[ 8] ); R( b, c, d, e, a, F1, K1, x[ 9] ); R( a, b, c, d, e, F1, K1, x[10] ); R( e, a, b, c, d, F1, K1, x[11] ); R( d, e, a, b, c, F1, K1, x[12] ); R( c, d, e, a, b, F1, K1, x[13] ); R( b, c, d, e, a, F1, K1, x[14] ); R( a, b, c, d, e, F1, K1, x[15] ); R( e, a, b, c, d, F1, K1, M(16) ); R( d, e, a, b, c, F1, K1, M(17) ); R( c, d, e, a, b, F1, K1, M(18) ); R( b, c, d, e, a, F1, K1, M(19) ); R( a, b, c, d, e, F2, K2, M(20) ); R( e, a, b, c, d, F2, K2, M(21) ); R( d, e, a, b, c, F2, K2, M(22) ); R( c, d, e, a, b, F2, K2, M(23) ); R( b, c, d, e, a, F2, K2, M(24) ); R( a, b, c, d, e, F2, K2, M(25) ); R( e, a, b, c, d, F2, K2, M(26) ); R( d, e, a, b, c, F2, K2, M(27) ); R( c, d, e, a, b, F2, K2, M(28) ); R( b, c, d, e, a, F2, K2, M(29) ); R( a, b, c, d, e, F2, K2, M(30) ); R( e, a, b, c, d, F2, K2, M(31) ); R( d, e, a, b, c, F2, K2, M(32) ); R( c, d, e, a, b, F2, K2, M(33) ); R( b, c, d, e, a, F2, K2, M(34) ); R( a, b, c, d, e, F2, K2, M(35) ); R( e, a, b, c, d, F2, K2, M(36) ); R( d, e, a, b, c, F2, K2, M(37) ); R( c, d, e, a, b, F2, K2, M(38) ); R( b, c, d, e, a, F2, K2, M(39) ); R( a, b, c, d, e, F3, K3, M(40) ); R( e, a, b, c, d, F3, K3, M(41) ); R( d, e, a, b, c, F3, K3, M(42) ); R( c, d, e, a, b, F3, K3, M(43) ); R( b, c, d, e, a, F3, K3, M(44) ); R( a, b, c, d, e, F3, K3, M(45) ); R( e, a, b, c, d, F3, K3, M(46) ); R( d, e, a, b, c, F3, K3, M(47) ); R( c, d, e, a, b, F3, K3, M(48) ); R( b, c, d, e, a, F3, K3, M(49) ); R( a, b, c, d, e, F3, K3, M(50) ); R( e, a, b, c, d, F3, K3, M(51) ); R( d, e, a, b, c, F3, K3, M(52) ); R( c, d, e, a, b, F3, K3, M(53) ); R( b, c, d, e, a, F3, K3, M(54) ); R( a, b, c, d, e, F3, K3, M(55) ); R( e, a, b, c, d, F3, K3, M(56) ); R( d, e, a, b, c, F3, K3, M(57) ); R( c, d, e, a, b, F3, K3, M(58) ); R( b, c, d, e, a, F3, K3, M(59) ); R( a, b, c, d, e, F4, K4, M(60) ); R( e, a, b, c, d, F4, K4, M(61) ); R( d, e, a, b, c, F4, K4, M(62) ); R( c, d, e, a, b, F4, K4, M(63) ); R( b, c, d, e, a, F4, K4, M(64) ); R( a, b, c, d, e, F4, K4, M(65) ); R( e, a, b, c, d, F4, K4, M(66) ); R( d, e, a, b, c, F4, K4, M(67) ); R( c, d, e, a, b, F4, K4, M(68) ); R( b, c, d, e, a, F4, K4, M(69) ); R( a, b, c, d, e, F4, K4, M(70) ); R( e, a, b, c, d, F4, K4, M(71) ); R( d, e, a, b, c, F4, K4, M(72) ); R( c, d, e, a, b, F4, K4, M(73) ); R( b, c, d, e, a, F4, K4, M(74) ); R( a, b, c, d, e, F4, K4, M(75) ); R( e, a, b, c, d, F4, K4, M(76) ); R( d, e, a, b, c, F4, K4, M(77) ); R( c, d, e, a, b, F4, K4, M(78) ); R( b, c, d, e, a, F4, K4, M(79) ); /* update chainig vars */ hd->h0 += a; hd->h1 += b; hd->h2 += c; hd->h3 += d; hd->h4 += e; } /* Update the message digest with the contents * of INBUF with length INLEN. */ static void sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); + burn_stack (88+4*sizeof(void*)); hd->count = 0; hd->nblocks++; } if( !inbuf ) return; if( hd->count ) { for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; sha1_write( hd, NULL, 0 ); if( !inlen ) return; } while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } + burn_stack (88+4*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 20 bytes representing the digest. */ static void sha1_final(SHA1_CONTEXT *hd) { u32 t, msb, lsb; byte *p; sha1_write(hd, NULL, 0); /* flush */; t = hd->nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->count < 56 ) { /* enough room */ hd->buf[hd->count++] = 0x80; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ hd->buf[hd->count++] = 0x80; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; sha1_write(hd, NULL, 0); /* flush */; memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ hd->buf[56] = msb >> 24; hd->buf[57] = msb >> 16; hd->buf[58] = msb >> 8; hd->buf[59] = msb ; hd->buf[60] = lsb >> 24; hd->buf[61] = lsb >> 16; hd->buf[62] = lsb >> 8; hd->buf[63] = lsb ; transform( hd, hd->buf ); + burn_stack (88+4*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) #else /* little endian */ #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) #endif X(0); X(1); X(2); X(3); X(4); #undef X } static byte * sha1_read( SHA1_CONTEXT *hd ) { return hd->buf; } /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ static const char * sha1_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), void (**r_write)( void *c, byte *buf, size_t nbytes ), void (**r_final)( void *c ), byte *(**r_read)( void *c ) ) { static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; if( algo != 2 ) return NULL; *contextsize = sizeof(SHA1_CONTEXT); *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 20; *(void (**)(SHA1_CONTEXT *))r_init = sha1_init; *(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write; *(void (**)(SHA1_CONTEXT *))r_final = sha1_final; *(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read; return "SHA1"; } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "SHA1 ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 10, 1, 0, (void(*)(void))sha1_get_info }, { 11, 1, 2 }, }; #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while( what && what != *class ); *sequence = i; return ret; } #ifndef IS_MODULE void _gcry_sha1_constructor(void) { _gcry_register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif diff --git a/cipher/tiger.c b/cipher/tiger.c index 7152492e..c4b107da 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -1,992 +1,961 @@ /* tiger.c - The TIGER hash function - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include "g10lib.h" #include "memory.h" #ifdef HAVE_U64_TYPEDEF /* we really need it here, but as this is only experiment we * can live without Tiger */ typedef struct { u64 a, b, c; byte buf[64]; int count; u32 nblocks; } TIGER_CONTEXT; /********************************* * Okay, okay, this is not the fastest code - improvements are welcome. * */ /* Some test vectors: * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge." * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge, 1996." * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 */ static u64 sbox1[256] = { 0x02aab17cf7e90c5eLL /* 0 */, 0xac424b03e243a8ecLL /* 1 */, 0x72cd5be30dd5fcd3LL /* 2 */, 0x6d019b93f6f97f3aLL /* 3 */, 0xcd9978ffd21f9193LL /* 4 */, 0x7573a1c9708029e2LL /* 5 */, 0xb164326b922a83c3LL /* 6 */, 0x46883eee04915870LL /* 7 */, 0xeaace3057103ece6LL /* 8 */, 0xc54169b808a3535cLL /* 9 */, 0x4ce754918ddec47cLL /* 10 */, 0x0aa2f4dfdc0df40cLL /* 11 */, 0x10b76f18a74dbefaLL /* 12 */, 0xc6ccb6235ad1ab6aLL /* 13 */, 0x13726121572fe2ffLL /* 14 */, 0x1a488c6f199d921eLL /* 15 */, 0x4bc9f9f4da0007caLL /* 16 */, 0x26f5e6f6e85241c7LL /* 17 */, 0x859079dbea5947b6LL /* 18 */, 0x4f1885c5c99e8c92LL /* 19 */, 0xd78e761ea96f864bLL /* 20 */, 0x8e36428c52b5c17dLL /* 21 */, 0x69cf6827373063c1LL /* 22 */, 0xb607c93d9bb4c56eLL /* 23 */, 0x7d820e760e76b5eaLL /* 24 */, 0x645c9cc6f07fdc42LL /* 25 */, 0xbf38a078243342e0LL /* 26 */, 0x5f6b343c9d2e7d04LL /* 27 */, 0xf2c28aeb600b0ec6LL /* 28 */, 0x6c0ed85f7254bcacLL /* 29 */, 0x71592281a4db4fe5LL /* 30 */, 0x1967fa69ce0fed9fLL /* 31 */, 0xfd5293f8b96545dbLL /* 32 */, 0xc879e9d7f2a7600bLL /* 33 */, 0x860248920193194eLL /* 34 */, 0xa4f9533b2d9cc0b3LL /* 35 */, 0x9053836c15957613LL /* 36 */, 0xdb6dcf8afc357bf1LL /* 37 */, 0x18beea7a7a370f57LL /* 38 */, 0x037117ca50b99066LL /* 39 */, 0x6ab30a9774424a35LL /* 40 */, 0xf4e92f02e325249bLL /* 41 */, 0x7739db07061ccae1LL /* 42 */, 0xd8f3b49ceca42a05LL /* 43 */, 0xbd56be3f51382f73LL /* 44 */, 0x45faed5843b0bb28LL /* 45 */, 0x1c813d5c11bf1f83LL /* 46 */, 0x8af0e4b6d75fa169LL /* 47 */, 0x33ee18a487ad9999LL /* 48 */, 0x3c26e8eab1c94410LL /* 49 */, 0xb510102bc0a822f9LL /* 50 */, 0x141eef310ce6123bLL /* 51 */, 0xfc65b90059ddb154LL /* 52 */, 0xe0158640c5e0e607LL /* 53 */, 0x884e079826c3a3cfLL /* 54 */, 0x930d0d9523c535fdLL /* 55 */, 0x35638d754e9a2b00LL /* 56 */, 0x4085fccf40469dd5LL /* 57 */, 0xc4b17ad28be23a4cLL /* 58 */, 0xcab2f0fc6a3e6a2eLL /* 59 */, 0x2860971a6b943fcdLL /* 60 */, 0x3dde6ee212e30446LL /* 61 */, 0x6222f32ae01765aeLL /* 62 */, 0x5d550bb5478308feLL /* 63 */, 0xa9efa98da0eda22aLL /* 64 */, 0xc351a71686c40da7LL /* 65 */, 0x1105586d9c867c84LL /* 66 */, 0xdcffee85fda22853LL /* 67 */, 0xccfbd0262c5eef76LL /* 68 */, 0xbaf294cb8990d201LL /* 69 */, 0xe69464f52afad975LL /* 70 */, 0x94b013afdf133e14LL /* 71 */, 0x06a7d1a32823c958LL /* 72 */, 0x6f95fe5130f61119LL /* 73 */, 0xd92ab34e462c06c0LL /* 74 */, 0xed7bde33887c71d2LL /* 75 */, 0x79746d6e6518393eLL /* 76 */, 0x5ba419385d713329LL /* 77 */, 0x7c1ba6b948a97564LL /* 78 */, 0x31987c197bfdac67LL /* 79 */, 0xde6c23c44b053d02LL /* 80 */, 0x581c49fed002d64dLL /* 81 */, 0xdd474d6338261571LL /* 82 */, 0xaa4546c3e473d062LL /* 83 */, 0x928fce349455f860LL /* 84 */, 0x48161bbacaab94d9LL /* 85 */, 0x63912430770e6f68LL /* 86 */, 0x6ec8a5e602c6641cLL /* 87 */, 0x87282515337ddd2bLL /* 88 */, 0x2cda6b42034b701bLL /* 89 */, 0xb03d37c181cb096dLL /* 90 */, 0xe108438266c71c6fLL /* 91 */, 0x2b3180c7eb51b255LL /* 92 */, 0xdf92b82f96c08bbcLL /* 93 */, 0x5c68c8c0a632f3baLL /* 94 */, 0x5504cc861c3d0556LL /* 95 */, 0xabbfa4e55fb26b8fLL /* 96 */, 0x41848b0ab3baceb4LL /* 97 */, 0xb334a273aa445d32LL /* 98 */, 0xbca696f0a85ad881LL /* 99 */, 0x24f6ec65b528d56cLL /* 100 */, 0x0ce1512e90f4524aLL /* 101 */, 0x4e9dd79d5506d35aLL /* 102 */, 0x258905fac6ce9779LL /* 103 */, 0x2019295b3e109b33LL /* 104 */, 0xf8a9478b73a054ccLL /* 105 */, 0x2924f2f934417eb0LL /* 106 */, 0x3993357d536d1bc4LL /* 107 */, 0x38a81ac21db6ff8bLL /* 108 */, 0x47c4fbf17d6016bfLL /* 109 */, 0x1e0faadd7667e3f5LL /* 110 */, 0x7abcff62938beb96LL /* 111 */, 0xa78dad948fc179c9LL /* 112 */, 0x8f1f98b72911e50dLL /* 113 */, 0x61e48eae27121a91LL /* 114 */, 0x4d62f7ad31859808LL /* 115 */, 0xeceba345ef5ceaebLL /* 116 */, 0xf5ceb25ebc9684ceLL /* 117 */, 0xf633e20cb7f76221LL /* 118 */, 0xa32cdf06ab8293e4LL /* 119 */, 0x985a202ca5ee2ca4LL /* 120 */, 0xcf0b8447cc8a8fb1LL /* 121 */, 0x9f765244979859a3LL /* 122 */, 0xa8d516b1a1240017LL /* 123 */, 0x0bd7ba3ebb5dc726LL /* 124 */, 0xe54bca55b86adb39LL /* 125 */, 0x1d7a3afd6c478063LL /* 126 */, 0x519ec608e7669eddLL /* 127 */, 0x0e5715a2d149aa23LL /* 128 */, 0x177d4571848ff194LL /* 129 */, 0xeeb55f3241014c22LL /* 130 */, 0x0f5e5ca13a6e2ec2LL /* 131 */, 0x8029927b75f5c361LL /* 132 */, 0xad139fabc3d6e436LL /* 133 */, 0x0d5df1a94ccf402fLL /* 134 */, 0x3e8bd948bea5dfc8LL /* 135 */, 0xa5a0d357bd3ff77eLL /* 136 */, 0xa2d12e251f74f645LL /* 137 */, 0x66fd9e525e81a082LL /* 138 */, 0x2e0c90ce7f687a49LL /* 139 */, 0xc2e8bcbeba973bc5LL /* 140 */, 0x000001bce509745fLL /* 141 */, 0x423777bbe6dab3d6LL /* 142 */, 0xd1661c7eaef06eb5LL /* 143 */, 0xa1781f354daacfd8LL /* 144 */, 0x2d11284a2b16affcLL /* 145 */, 0xf1fc4f67fa891d1fLL /* 146 */, 0x73ecc25dcb920adaLL /* 147 */, 0xae610c22c2a12651LL /* 148 */, 0x96e0a810d356b78aLL /* 149 */, 0x5a9a381f2fe7870fLL /* 150 */, 0xd5ad62ede94e5530LL /* 151 */, 0xd225e5e8368d1427LL /* 152 */, 0x65977b70c7af4631LL /* 153 */, 0x99f889b2de39d74fLL /* 154 */, 0x233f30bf54e1d143LL /* 155 */, 0x9a9675d3d9a63c97LL /* 156 */, 0x5470554ff334f9a8LL /* 157 */, 0x166acb744a4f5688LL /* 158 */, 0x70c74caab2e4aeadLL /* 159 */, 0xf0d091646f294d12LL /* 160 */, 0x57b82a89684031d1LL /* 161 */, 0xefd95a5a61be0b6bLL /* 162 */, 0x2fbd12e969f2f29aLL /* 163 */, 0x9bd37013feff9fe8LL /* 164 */, 0x3f9b0404d6085a06LL /* 165 */, 0x4940c1f3166cfe15LL /* 166 */, 0x09542c4dcdf3defbLL /* 167 */, 0xb4c5218385cd5ce3LL /* 168 */, 0xc935b7dc4462a641LL /* 169 */, 0x3417f8a68ed3b63fLL /* 170 */, 0xb80959295b215b40LL /* 171 */, 0xf99cdaef3b8c8572LL /* 172 */, 0x018c0614f8fcb95dLL /* 173 */, 0x1b14accd1a3acdf3LL /* 174 */, 0x84d471f200bb732dLL /* 175 */, 0xc1a3110e95e8da16LL /* 176 */, 0x430a7220bf1a82b8LL /* 177 */, 0xb77e090d39df210eLL /* 178 */, 0x5ef4bd9f3cd05e9dLL /* 179 */, 0x9d4ff6da7e57a444LL /* 180 */, 0xda1d60e183d4a5f8LL /* 181 */, 0xb287c38417998e47LL /* 182 */, 0xfe3edc121bb31886LL /* 183 */, 0xc7fe3ccc980ccbefLL /* 184 */, 0xe46fb590189bfd03LL /* 185 */, 0x3732fd469a4c57dcLL /* 186 */, 0x7ef700a07cf1ad65LL /* 187 */, 0x59c64468a31d8859LL /* 188 */, 0x762fb0b4d45b61f6LL /* 189 */, 0x155baed099047718LL /* 190 */, 0x68755e4c3d50baa6LL /* 191 */, 0xe9214e7f22d8b4dfLL /* 192 */, 0x2addbf532eac95f4LL /* 193 */, 0x32ae3909b4bd0109LL /* 194 */, 0x834df537b08e3450LL /* 195 */, 0xfa209da84220728dLL /* 196 */, 0x9e691d9b9efe23f7LL /* 197 */, 0x0446d288c4ae8d7fLL /* 198 */, 0x7b4cc524e169785bLL /* 199 */, 0x21d87f0135ca1385LL /* 200 */, 0xcebb400f137b8aa5LL /* 201 */, 0x272e2b66580796beLL /* 202 */, 0x3612264125c2b0deLL /* 203 */, 0x057702bdad1efbb2LL /* 204 */, 0xd4babb8eacf84be9LL /* 205 */, 0x91583139641bc67bLL /* 206 */, 0x8bdc2de08036e024LL /* 207 */, 0x603c8156f49f68edLL /* 208 */, 0xf7d236f7dbef5111LL /* 209 */, 0x9727c4598ad21e80LL /* 210 */, 0xa08a0896670a5fd7LL /* 211 */, 0xcb4a8f4309eba9cbLL /* 212 */, 0x81af564b0f7036a1LL /* 213 */, 0xc0b99aa778199abdLL /* 214 */, 0x959f1ec83fc8e952LL /* 215 */, 0x8c505077794a81b9LL /* 216 */, 0x3acaaf8f056338f0LL /* 217 */, 0x07b43f50627a6778LL /* 218 */, 0x4a44ab49f5eccc77LL /* 219 */, 0x3bc3d6e4b679ee98LL /* 220 */, 0x9cc0d4d1cf14108cLL /* 221 */, 0x4406c00b206bc8a0LL /* 222 */, 0x82a18854c8d72d89LL /* 223 */, 0x67e366b35c3c432cLL /* 224 */, 0xb923dd61102b37f2LL /* 225 */, 0x56ab2779d884271dLL /* 226 */, 0xbe83e1b0ff1525afLL /* 227 */, 0xfb7c65d4217e49a9LL /* 228 */, 0x6bdbe0e76d48e7d4LL /* 229 */, 0x08df828745d9179eLL /* 230 */, 0x22ea6a9add53bd34LL /* 231 */, 0xe36e141c5622200aLL /* 232 */, 0x7f805d1b8cb750eeLL /* 233 */, 0xafe5c7a59f58e837LL /* 234 */, 0xe27f996a4fb1c23cLL /* 235 */, 0xd3867dfb0775f0d0LL /* 236 */, 0xd0e673de6e88891aLL /* 237 */, 0x123aeb9eafb86c25LL /* 238 */, 0x30f1d5d5c145b895LL /* 239 */, 0xbb434a2dee7269e7LL /* 240 */, 0x78cb67ecf931fa38LL /* 241 */, 0xf33b0372323bbf9cLL /* 242 */, 0x52d66336fb279c74LL /* 243 */, 0x505f33ac0afb4eaaLL /* 244 */, 0xe8a5cd99a2cce187LL /* 245 */, 0x534974801e2d30bbLL /* 246 */, 0x8d2d5711d5876d90LL /* 247 */, 0x1f1a412891bc038eLL /* 248 */, 0xd6e2e71d82e56648LL /* 249 */, 0x74036c3a497732b7LL /* 250 */, 0x89b67ed96361f5abLL /* 251 */, 0xffed95d8f1ea02a2LL /* 252 */, 0xe72b3bd61464d43dLL /* 253 */, 0xa6300f170bdc4820LL /* 254 */, 0xebc18760ed78a77aLL /* 255 */ }; static u64 sbox2[256] = { 0xe6a6be5a05a12138LL /* 256 */, 0xb5a122a5b4f87c98LL /* 257 */, 0x563c6089140b6990LL /* 258 */, 0x4c46cb2e391f5dd5LL /* 259 */, 0xd932addbc9b79434LL /* 260 */, 0x08ea70e42015aff5LL /* 261 */, 0xd765a6673e478cf1LL /* 262 */, 0xc4fb757eab278d99LL /* 263 */, 0xdf11c6862d6e0692LL /* 264 */, 0xddeb84f10d7f3b16LL /* 265 */, 0x6f2ef604a665ea04LL /* 266 */, 0x4a8e0f0ff0e0dfb3LL /* 267 */, 0xa5edeef83dbcba51LL /* 268 */, 0xfc4f0a2a0ea4371eLL /* 269 */, 0xe83e1da85cb38429LL /* 270 */, 0xdc8ff882ba1b1ce2LL /* 271 */, 0xcd45505e8353e80dLL /* 272 */, 0x18d19a00d4db0717LL /* 273 */, 0x34a0cfeda5f38101LL /* 274 */, 0x0be77e518887caf2LL /* 275 */, 0x1e341438b3c45136LL /* 276 */, 0xe05797f49089ccf9LL /* 277 */, 0xffd23f9df2591d14LL /* 278 */, 0x543dda228595c5cdLL /* 279 */, 0x661f81fd99052a33LL /* 280 */, 0x8736e641db0f7b76LL /* 281 */, 0x15227725418e5307LL /* 282 */, 0xe25f7f46162eb2faLL /* 283 */, 0x48a8b2126c13d9feLL /* 284 */, 0xafdc541792e76eeaLL /* 285 */, 0x03d912bfc6d1898fLL /* 286 */, 0x31b1aafa1b83f51bLL /* 287 */, 0xf1ac2796e42ab7d9LL /* 288 */, 0x40a3a7d7fcd2ebacLL /* 289 */, 0x1056136d0afbbcc5LL /* 290 */, 0x7889e1dd9a6d0c85LL /* 291 */, 0xd33525782a7974aaLL /* 292 */, 0xa7e25d09078ac09bLL /* 293 */, 0xbd4138b3eac6edd0LL /* 294 */, 0x920abfbe71eb9e70LL /* 295 */, 0xa2a5d0f54fc2625cLL /* 296 */, 0xc054e36b0b1290a3LL /* 297 */, 0xf6dd59ff62fe932bLL /* 298 */, 0x3537354511a8ac7dLL /* 299 */, 0xca845e9172fadcd4LL /* 300 */, 0x84f82b60329d20dcLL /* 301 */, 0x79c62ce1cd672f18LL /* 302 */, 0x8b09a2add124642cLL /* 303 */, 0xd0c1e96a19d9e726LL /* 304 */, 0x5a786a9b4ba9500cLL /* 305 */, 0x0e020336634c43f3LL /* 306 */, 0xc17b474aeb66d822LL /* 307 */, 0x6a731ae3ec9baac2LL /* 308 */, 0x8226667ae0840258LL /* 309 */, 0x67d4567691caeca5LL /* 310 */, 0x1d94155c4875adb5LL /* 311 */, 0x6d00fd985b813fdfLL /* 312 */, 0x51286efcb774cd06LL /* 313 */, 0x5e8834471fa744afLL /* 314 */, 0xf72ca0aee761ae2eLL /* 315 */, 0xbe40e4cdaee8e09aLL /* 316 */, 0xe9970bbb5118f665LL /* 317 */, 0x726e4beb33df1964LL /* 318 */, 0x703b000729199762LL /* 319 */, 0x4631d816f5ef30a7LL /* 320 */, 0xb880b5b51504a6beLL /* 321 */, 0x641793c37ed84b6cLL /* 322 */, 0x7b21ed77f6e97d96LL /* 323 */, 0x776306312ef96b73LL /* 324 */, 0xae528948e86ff3f4LL /* 325 */, 0x53dbd7f286a3f8f8LL /* 326 */, 0x16cadce74cfc1063LL /* 327 */, 0x005c19bdfa52c6ddLL /* 328 */, 0x68868f5d64d46ad3LL /* 329 */, 0x3a9d512ccf1e186aLL /* 330 */, 0x367e62c2385660aeLL /* 331 */, 0xe359e7ea77dcb1d7LL /* 332 */, 0x526c0773749abe6eLL /* 333 */, 0x735ae5f9d09f734bLL /* 334 */, 0x493fc7cc8a558ba8LL /* 335 */, 0xb0b9c1533041ab45LL /* 336 */, 0x321958ba470a59bdLL /* 337 */, 0x852db00b5f46c393LL /* 338 */, 0x91209b2bd336b0e5LL /* 339 */, 0x6e604f7d659ef19fLL /* 340 */, 0xb99a8ae2782ccb24LL /* 341 */, 0xccf52ab6c814c4c7LL /* 342 */, 0x4727d9afbe11727bLL /* 343 */, 0x7e950d0c0121b34dLL /* 344 */, 0x756f435670ad471fLL /* 345 */, 0xf5add442615a6849LL /* 346 */, 0x4e87e09980b9957aLL /* 347 */, 0x2acfa1df50aee355LL /* 348 */, 0xd898263afd2fd556LL /* 349 */, 0xc8f4924dd80c8fd6LL /* 350 */, 0xcf99ca3d754a173aLL /* 351 */, 0xfe477bacaf91bf3cLL /* 352 */, 0xed5371f6d690c12dLL /* 353 */, 0x831a5c285e687094LL /* 354 */, 0xc5d3c90a3708a0a4LL /* 355 */, 0x0f7f903717d06580LL /* 356 */, 0x19f9bb13b8fdf27fLL /* 357 */, 0xb1bd6f1b4d502843LL /* 358 */, 0x1c761ba38fff4012LL /* 359 */, 0x0d1530c4e2e21f3bLL /* 360 */, 0x8943ce69a7372c8aLL /* 361 */, 0xe5184e11feb5ce66LL /* 362 */, 0x618bdb80bd736621LL /* 363 */, 0x7d29bad68b574d0bLL /* 364 */, 0x81bb613e25e6fe5bLL /* 365 */, 0x071c9c10bc07913fLL /* 366 */, 0xc7beeb7909ac2d97LL /* 367 */, 0xc3e58d353bc5d757LL /* 368 */, 0xeb017892f38f61e8LL /* 369 */, 0xd4effb9c9b1cc21aLL /* 370 */, 0x99727d26f494f7abLL /* 371 */, 0xa3e063a2956b3e03LL /* 372 */, 0x9d4a8b9a4aa09c30LL /* 373 */, 0x3f6ab7d500090fb4LL /* 374 */, 0x9cc0f2a057268ac0LL /* 375 */, 0x3dee9d2dedbf42d1LL /* 376 */, 0x330f49c87960a972LL /* 377 */, 0xc6b2720287421b41LL /* 378 */, 0x0ac59ec07c00369cLL /* 379 */, 0xef4eac49cb353425LL /* 380 */, 0xf450244eef0129d8LL /* 381 */, 0x8acc46e5caf4deb6LL /* 382 */, 0x2ffeab63989263f7LL /* 383 */, 0x8f7cb9fe5d7a4578LL /* 384 */, 0x5bd8f7644e634635LL /* 385 */, 0x427a7315bf2dc900LL /* 386 */, 0x17d0c4aa2125261cLL /* 387 */, 0x3992486c93518e50LL /* 388 */, 0xb4cbfee0a2d7d4c3LL /* 389 */, 0x7c75d6202c5ddd8dLL /* 390 */, 0xdbc295d8e35b6c61LL /* 391 */, 0x60b369d302032b19LL /* 392 */, 0xce42685fdce44132LL /* 393 */, 0x06f3ddb9ddf65610LL /* 394 */, 0x8ea4d21db5e148f0LL /* 395 */, 0x20b0fce62fcd496fLL /* 396 */, 0x2c1b912358b0ee31LL /* 397 */, 0xb28317b818f5a308LL /* 398 */, 0xa89c1e189ca6d2cfLL /* 399 */, 0x0c6b18576aaadbc8LL /* 400 */, 0xb65deaa91299fae3LL /* 401 */, 0xfb2b794b7f1027e7LL /* 402 */, 0x04e4317f443b5bebLL /* 403 */, 0x4b852d325939d0a6LL /* 404 */, 0xd5ae6beefb207ffcLL /* 405 */, 0x309682b281c7d374LL /* 406 */, 0xbae309a194c3b475LL /* 407 */, 0x8cc3f97b13b49f05LL /* 408 */, 0x98a9422ff8293967LL /* 409 */, 0x244b16b01076ff7cLL /* 410 */, 0xf8bf571c663d67eeLL /* 411 */, 0x1f0d6758eee30da1LL /* 412 */, 0xc9b611d97adeb9b7LL /* 413 */, 0xb7afd5887b6c57a2LL /* 414 */, 0x6290ae846b984fe1LL /* 415 */, 0x94df4cdeacc1a5fdLL /* 416 */, 0x058a5bd1c5483affLL /* 417 */, 0x63166cc142ba3c37LL /* 418 */, 0x8db8526eb2f76f40LL /* 419 */, 0xe10880036f0d6d4eLL /* 420 */, 0x9e0523c9971d311dLL /* 421 */, 0x45ec2824cc7cd691LL /* 422 */, 0x575b8359e62382c9LL /* 423 */, 0xfa9e400dc4889995LL /* 424 */, 0xd1823ecb45721568LL /* 425 */, 0xdafd983b8206082fLL /* 426 */, 0xaa7d29082386a8cbLL /* 427 */, 0x269fcd4403b87588LL /* 428 */, 0x1b91f5f728bdd1e0LL /* 429 */, 0xe4669f39040201f6LL /* 430 */, 0x7a1d7c218cf04adeLL /* 431 */, 0x65623c29d79ce5ceLL /* 432 */, 0x2368449096c00bb1LL /* 433 */, 0xab9bf1879da503baLL /* 434 */, 0xbc23ecb1a458058eLL /* 435 */, 0x9a58df01bb401eccLL /* 436 */, 0xa070e868a85f143dLL /* 437 */, 0x4ff188307df2239eLL /* 438 */, 0x14d565b41a641183LL /* 439 */, 0xee13337452701602LL /* 440 */, 0x950e3dcf3f285e09LL /* 441 */, 0x59930254b9c80953LL /* 442 */, 0x3bf299408930da6dLL /* 443 */, 0xa955943f53691387LL /* 444 */, 0xa15edecaa9cb8784LL /* 445 */, 0x29142127352be9a0LL /* 446 */, 0x76f0371fff4e7afbLL /* 447 */, 0x0239f450274f2228LL /* 448 */, 0xbb073af01d5e868bLL /* 449 */, 0xbfc80571c10e96c1LL /* 450 */, 0xd267088568222e23LL /* 451 */, 0x9671a3d48e80b5b0LL /* 452 */, 0x55b5d38ae193bb81LL /* 453 */, 0x693ae2d0a18b04b8LL /* 454 */, 0x5c48b4ecadd5335fLL /* 455 */, 0xfd743b194916a1caLL /* 456 */, 0x2577018134be98c4LL /* 457 */, 0xe77987e83c54a4adLL /* 458 */, 0x28e11014da33e1b9LL /* 459 */, 0x270cc59e226aa213LL /* 460 */, 0x71495f756d1a5f60LL /* 461 */, 0x9be853fb60afef77LL /* 462 */, 0xadc786a7f7443dbfLL /* 463 */, 0x0904456173b29a82LL /* 464 */, 0x58bc7a66c232bd5eLL /* 465 */, 0xf306558c673ac8b2LL /* 466 */, 0x41f639c6b6c9772aLL /* 467 */, 0x216defe99fda35daLL /* 468 */, 0x11640cc71c7be615LL /* 469 */, 0x93c43694565c5527LL /* 470 */, 0xea038e6246777839LL /* 471 */, 0xf9abf3ce5a3e2469LL /* 472 */, 0x741e768d0fd312d2LL /* 473 */, 0x0144b883ced652c6LL /* 474 */, 0xc20b5a5ba33f8552LL /* 475 */, 0x1ae69633c3435a9dLL /* 476 */, 0x97a28ca4088cfdecLL /* 477 */, 0x8824a43c1e96f420LL /* 478 */, 0x37612fa66eeea746LL /* 479 */, 0x6b4cb165f9cf0e5aLL /* 480 */, 0x43aa1c06a0abfb4aLL /* 481 */, 0x7f4dc26ff162796bLL /* 482 */, 0x6cbacc8e54ed9b0fLL /* 483 */, 0xa6b7ffefd2bb253eLL /* 484 */, 0x2e25bc95b0a29d4fLL /* 485 */, 0x86d6a58bdef1388cLL /* 486 */, 0xded74ac576b6f054LL /* 487 */, 0x8030bdbc2b45805dLL /* 488 */, 0x3c81af70e94d9289LL /* 489 */, 0x3eff6dda9e3100dbLL /* 490 */, 0xb38dc39fdfcc8847LL /* 491 */, 0x123885528d17b87eLL /* 492 */, 0xf2da0ed240b1b642LL /* 493 */, 0x44cefadcd54bf9a9LL /* 494 */, 0x1312200e433c7ee6LL /* 495 */, 0x9ffcc84f3a78c748LL /* 496 */, 0xf0cd1f72248576bbLL /* 497 */, 0xec6974053638cfe4LL /* 498 */, 0x2ba7b67c0cec4e4cLL /* 499 */, 0xac2f4df3e5ce32edLL /* 500 */, 0xcb33d14326ea4c11LL /* 501 */, 0xa4e9044cc77e58bcLL /* 502 */, 0x5f513293d934fcefLL /* 503 */, 0x5dc9645506e55444LL /* 504 */, 0x50de418f317de40aLL /* 505 */, 0x388cb31a69dde259LL /* 506 */, 0x2db4a83455820a86LL /* 507 */, 0x9010a91e84711ae9LL /* 508 */, 0x4df7f0b7b1498371LL /* 509 */, 0xd62a2eabc0977179LL /* 510 */, 0x22fac097aa8d5c0eLL /* 511 */ }; static u64 sbox3[256] = { 0xf49fcc2ff1daf39bLL /* 512 */, 0x487fd5c66ff29281LL /* 513 */, 0xe8a30667fcdca83fLL /* 514 */, 0x2c9b4be3d2fcce63LL /* 515 */, 0xda3ff74b93fbbbc2LL /* 516 */, 0x2fa165d2fe70ba66LL /* 517 */, 0xa103e279970e93d4LL /* 518 */, 0xbecdec77b0e45e71LL /* 519 */, 0xcfb41e723985e497LL /* 520 */, 0xb70aaa025ef75017LL /* 521 */, 0xd42309f03840b8e0LL /* 522 */, 0x8efc1ad035898579LL /* 523 */, 0x96c6920be2b2abc5LL /* 524 */, 0x66af4163375a9172LL /* 525 */, 0x2174abdcca7127fbLL /* 526 */, 0xb33ccea64a72ff41LL /* 527 */, 0xf04a4933083066a5LL /* 528 */, 0x8d970acdd7289af5LL /* 529 */, 0x8f96e8e031c8c25eLL /* 530 */, 0xf3fec02276875d47LL /* 531 */, 0xec7bf310056190ddLL /* 532 */, 0xf5adb0aebb0f1491LL /* 533 */, 0x9b50f8850fd58892LL /* 534 */, 0x4975488358b74de8LL /* 535 */, 0xa3354ff691531c61LL /* 536 */, 0x0702bbe481d2c6eeLL /* 537 */, 0x89fb24057deded98LL /* 538 */, 0xac3075138596e902LL /* 539 */, 0x1d2d3580172772edLL /* 540 */, 0xeb738fc28e6bc30dLL /* 541 */, 0x5854ef8f63044326LL /* 542 */, 0x9e5c52325add3bbeLL /* 543 */, 0x90aa53cf325c4623LL /* 544 */, 0xc1d24d51349dd067LL /* 545 */, 0x2051cfeea69ea624LL /* 546 */, 0x13220f0a862e7e4fLL /* 547 */, 0xce39399404e04864LL /* 548 */, 0xd9c42ca47086fcb7LL /* 549 */, 0x685ad2238a03e7ccLL /* 550 */, 0x066484b2ab2ff1dbLL /* 551 */, 0xfe9d5d70efbf79ecLL /* 552 */, 0x5b13b9dd9c481854LL /* 553 */, 0x15f0d475ed1509adLL /* 554 */, 0x0bebcd060ec79851LL /* 555 */, 0xd58c6791183ab7f8LL /* 556 */, 0xd1187c5052f3eee4LL /* 557 */, 0xc95d1192e54e82ffLL /* 558 */, 0x86eea14cb9ac6ca2LL /* 559 */, 0x3485beb153677d5dLL /* 560 */, 0xdd191d781f8c492aLL /* 561 */, 0xf60866baa784ebf9LL /* 562 */, 0x518f643ba2d08c74LL /* 563 */, 0x8852e956e1087c22LL /* 564 */, 0xa768cb8dc410ae8dLL /* 565 */, 0x38047726bfec8e1aLL /* 566 */, 0xa67738b4cd3b45aaLL /* 567 */, 0xad16691cec0dde19LL /* 568 */, 0xc6d4319380462e07LL /* 569 */, 0xc5a5876d0ba61938LL /* 570 */, 0x16b9fa1fa58fd840LL /* 571 */, 0x188ab1173ca74f18LL /* 572 */, 0xabda2f98c99c021fLL /* 573 */, 0x3e0580ab134ae816LL /* 574 */, 0x5f3b05b773645abbLL /* 575 */, 0x2501a2be5575f2f6LL /* 576 */, 0x1b2f74004e7e8ba9LL /* 577 */, 0x1cd7580371e8d953LL /* 578 */, 0x7f6ed89562764e30LL /* 579 */, 0xb15926ff596f003dLL /* 580 */, 0x9f65293da8c5d6b9LL /* 581 */, 0x6ecef04dd690f84cLL /* 582 */, 0x4782275fff33af88LL /* 583 */, 0xe41433083f820801LL /* 584 */, 0xfd0dfe409a1af9b5LL /* 585 */, 0x4325a3342cdb396bLL /* 586 */, 0x8ae77e62b301b252LL /* 587 */, 0xc36f9e9f6655615aLL /* 588 */, 0x85455a2d92d32c09LL /* 589 */, 0xf2c7dea949477485LL /* 590 */, 0x63cfb4c133a39ebaLL /* 591 */, 0x83b040cc6ebc5462LL /* 592 */, 0x3b9454c8fdb326b0LL /* 593 */, 0x56f56a9e87ffd78cLL /* 594 */, 0x2dc2940d99f42bc6LL /* 595 */, 0x98f7df096b096e2dLL /* 596 */, 0x19a6e01e3ad852bfLL /* 597 */, 0x42a99ccbdbd4b40bLL /* 598 */, 0xa59998af45e9c559LL /* 599 */, 0x366295e807d93186LL /* 600 */, 0x6b48181bfaa1f773LL /* 601 */, 0x1fec57e2157a0a1dLL /* 602 */, 0x4667446af6201ad5LL /* 603 */, 0xe615ebcacfb0f075LL /* 604 */, 0xb8f31f4f68290778LL /* 605 */, 0x22713ed6ce22d11eLL /* 606 */, 0x3057c1a72ec3c93bLL /* 607 */, 0xcb46acc37c3f1f2fLL /* 608 */, 0xdbb893fd02aaf50eLL /* 609 */, 0x331fd92e600b9fcfLL /* 610 */, 0xa498f96148ea3ad6LL /* 611 */, 0xa8d8426e8b6a83eaLL /* 612 */, 0xa089b274b7735cdcLL /* 613 */, 0x87f6b3731e524a11LL /* 614 */, 0x118808e5cbc96749LL /* 615 */, 0x9906e4c7b19bd394LL /* 616 */, 0xafed7f7e9b24a20cLL /* 617 */, 0x6509eadeeb3644a7LL /* 618 */, 0x6c1ef1d3e8ef0edeLL /* 619 */, 0xb9c97d43e9798fb4LL /* 620 */, 0xa2f2d784740c28a3LL /* 621 */, 0x7b8496476197566fLL /* 622 */, 0x7a5be3e6b65f069dLL /* 623 */, 0xf96330ed78be6f10LL /* 624 */, 0xeee60de77a076a15LL /* 625 */, 0x2b4bee4aa08b9bd0LL /* 626 */, 0x6a56a63ec7b8894eLL /* 627 */, 0x02121359ba34fef4LL /* 628 */, 0x4cbf99f8283703fcLL /* 629 */, 0x398071350caf30c8LL /* 630 */, 0xd0a77a89f017687aLL /* 631 */, 0xf1c1a9eb9e423569LL /* 632 */, 0x8c7976282dee8199LL /* 633 */, 0x5d1737a5dd1f7abdLL /* 634 */, 0x4f53433c09a9fa80LL /* 635 */, 0xfa8b0c53df7ca1d9LL /* 636 */, 0x3fd9dcbc886ccb77LL /* 637 */, 0xc040917ca91b4720LL /* 638 */, 0x7dd00142f9d1dcdfLL /* 639 */, 0x8476fc1d4f387b58LL /* 640 */, 0x23f8e7c5f3316503LL /* 641 */, 0x032a2244e7e37339LL /* 642 */, 0x5c87a5d750f5a74bLL /* 643 */, 0x082b4cc43698992eLL /* 644 */, 0xdf917becb858f63cLL /* 645 */, 0x3270b8fc5bf86ddaLL /* 646 */, 0x10ae72bb29b5dd76LL /* 647 */, 0x576ac94e7700362bLL /* 648 */, 0x1ad112dac61efb8fLL /* 649 */, 0x691bc30ec5faa427LL /* 650 */, 0xff246311cc327143LL /* 651 */, 0x3142368e30e53206LL /* 652 */, 0x71380e31e02ca396LL /* 653 */, 0x958d5c960aad76f1LL /* 654 */, 0xf8d6f430c16da536LL /* 655 */, 0xc8ffd13f1be7e1d2LL /* 656 */, 0x7578ae66004ddbe1LL /* 657 */, 0x05833f01067be646LL /* 658 */, 0xbb34b5ad3bfe586dLL /* 659 */, 0x095f34c9a12b97f0LL /* 660 */, 0x247ab64525d60ca8LL /* 661 */, 0xdcdbc6f3017477d1LL /* 662 */, 0x4a2e14d4decad24dLL /* 663 */, 0xbdb5e6d9be0a1eebLL /* 664 */, 0x2a7e70f7794301abLL /* 665 */, 0xdef42d8a270540fdLL /* 666 */, 0x01078ec0a34c22c1LL /* 667 */, 0xe5de511af4c16387LL /* 668 */, 0x7ebb3a52bd9a330aLL /* 669 */, 0x77697857aa7d6435LL /* 670 */, 0x004e831603ae4c32LL /* 671 */, 0xe7a21020ad78e312LL /* 672 */, 0x9d41a70c6ab420f2LL /* 673 */, 0x28e06c18ea1141e6LL /* 674 */, 0xd2b28cbd984f6b28LL /* 675 */, 0x26b75f6c446e9d83LL /* 676 */, 0xba47568c4d418d7fLL /* 677 */, 0xd80badbfe6183d8eLL /* 678 */, 0x0e206d7f5f166044LL /* 679 */, 0xe258a43911cbca3eLL /* 680 */, 0x723a1746b21dc0bcLL /* 681 */, 0xc7caa854f5d7cdd3LL /* 682 */, 0x7cac32883d261d9cLL /* 683 */, 0x7690c26423ba942cLL /* 684 */, 0x17e55524478042b8LL /* 685 */, 0xe0be477656a2389fLL /* 686 */, 0x4d289b5e67ab2da0LL /* 687 */, 0x44862b9c8fbbfd31LL /* 688 */, 0xb47cc8049d141365LL /* 689 */, 0x822c1b362b91c793LL /* 690 */, 0x4eb14655fb13dfd8LL /* 691 */, 0x1ecbba0714e2a97bLL /* 692 */, 0x6143459d5cde5f14LL /* 693 */, 0x53a8fbf1d5f0ac89LL /* 694 */, 0x97ea04d81c5e5b00LL /* 695 */, 0x622181a8d4fdb3f3LL /* 696 */, 0xe9bcd341572a1208LL /* 697 */, 0x1411258643cce58aLL /* 698 */, 0x9144c5fea4c6e0a4LL /* 699 */, 0x0d33d06565cf620fLL /* 700 */, 0x54a48d489f219ca1LL /* 701 */, 0xc43e5eac6d63c821LL /* 702 */, 0xa9728b3a72770dafLL /* 703 */, 0xd7934e7b20df87efLL /* 704 */, 0xe35503b61a3e86e5LL /* 705 */, 0xcae321fbc819d504LL /* 706 */, 0x129a50b3ac60bfa6LL /* 707 */, 0xcd5e68ea7e9fb6c3LL /* 708 */, 0xb01c90199483b1c7LL /* 709 */, 0x3de93cd5c295376cLL /* 710 */, 0xaed52edf2ab9ad13LL /* 711 */, 0x2e60f512c0a07884LL /* 712 */, 0xbc3d86a3e36210c9LL /* 713 */, 0x35269d9b163951ceLL /* 714 */, 0x0c7d6e2ad0cdb5faLL /* 715 */, 0x59e86297d87f5733LL /* 716 */, 0x298ef221898db0e7LL /* 717 */, 0x55000029d1a5aa7eLL /* 718 */, 0x8bc08ae1b5061b45LL /* 719 */, 0xc2c31c2b6c92703aLL /* 720 */, 0x94cc596baf25ef42LL /* 721 */, 0x0a1d73db22540456LL /* 722 */, 0x04b6a0f9d9c4179aLL /* 723 */, 0xeffdafa2ae3d3c60LL /* 724 */, 0xf7c8075bb49496c4LL /* 725 */, 0x9cc5c7141d1cd4e3LL /* 726 */, 0x78bd1638218e5534LL /* 727 */, 0xb2f11568f850246aLL /* 728 */, 0xedfabcfa9502bc29LL /* 729 */, 0x796ce5f2da23051bLL /* 730 */, 0xaae128b0dc93537cLL /* 731 */, 0x3a493da0ee4b29aeLL /* 732 */, 0xb5df6b2c416895d7LL /* 733 */, 0xfcabbd25122d7f37LL /* 734 */, 0x70810b58105dc4b1LL /* 735 */, 0xe10fdd37f7882a90LL /* 736 */, 0x524dcab5518a3f5cLL /* 737 */, 0x3c9e85878451255bLL /* 738 */, 0x4029828119bd34e2LL /* 739 */, 0x74a05b6f5d3ceccbLL /* 740 */, 0xb610021542e13ecaLL /* 741 */, 0x0ff979d12f59e2acLL /* 742 */, 0x6037da27e4f9cc50LL /* 743 */, 0x5e92975a0df1847dLL /* 744 */, 0xd66de190d3e623feLL /* 745 */, 0x5032d6b87b568048LL /* 746 */, 0x9a36b7ce8235216eLL /* 747 */, 0x80272a7a24f64b4aLL /* 748 */, 0x93efed8b8c6916f7LL /* 749 */, 0x37ddbff44cce1555LL /* 750 */, 0x4b95db5d4b99bd25LL /* 751 */, 0x92d3fda169812fc0LL /* 752 */, 0xfb1a4a9a90660bb6LL /* 753 */, 0x730c196946a4b9b2LL /* 754 */, 0x81e289aa7f49da68LL /* 755 */, 0x64669a0f83b1a05fLL /* 756 */, 0x27b3ff7d9644f48bLL /* 757 */, 0xcc6b615c8db675b3LL /* 758 */, 0x674f20b9bcebbe95LL /* 759 */, 0x6f31238275655982LL /* 760 */, 0x5ae488713e45cf05LL /* 761 */, 0xbf619f9954c21157LL /* 762 */, 0xeabac46040a8eae9LL /* 763 */, 0x454c6fe9f2c0c1cdLL /* 764 */, 0x419cf6496412691cLL /* 765 */, 0xd3dc3bef265b0f70LL /* 766 */, 0x6d0e60f5c3578a9eLL /* 767 */ }; static u64 sbox4[256] = { 0x5b0e608526323c55LL /* 768 */, 0x1a46c1a9fa1b59f5LL /* 769 */, 0xa9e245a17c4c8ffaLL /* 770 */, 0x65ca5159db2955d7LL /* 771 */, 0x05db0a76ce35afc2LL /* 772 */, 0x81eac77ea9113d45LL /* 773 */, 0x528ef88ab6ac0a0dLL /* 774 */, 0xa09ea253597be3ffLL /* 775 */, 0x430ddfb3ac48cd56LL /* 776 */, 0xc4b3a67af45ce46fLL /* 777 */, 0x4ececfd8fbe2d05eLL /* 778 */, 0x3ef56f10b39935f0LL /* 779 */, 0x0b22d6829cd619c6LL /* 780 */, 0x17fd460a74df2069LL /* 781 */, 0x6cf8cc8e8510ed40LL /* 782 */, 0xd6c824bf3a6ecaa7LL /* 783 */, 0x61243d581a817049LL /* 784 */, 0x048bacb6bbc163a2LL /* 785 */, 0xd9a38ac27d44cc32LL /* 786 */, 0x7fddff5baaf410abLL /* 787 */, 0xad6d495aa804824bLL /* 788 */, 0xe1a6a74f2d8c9f94LL /* 789 */, 0xd4f7851235dee8e3LL /* 790 */, 0xfd4b7f886540d893LL /* 791 */, 0x247c20042aa4bfdaLL /* 792 */, 0x096ea1c517d1327cLL /* 793 */, 0xd56966b4361a6685LL /* 794 */, 0x277da5c31221057dLL /* 795 */, 0x94d59893a43acff7LL /* 796 */, 0x64f0c51ccdc02281LL /* 797 */, 0x3d33bcc4ff6189dbLL /* 798 */, 0xe005cb184ce66af1LL /* 799 */, 0xff5ccd1d1db99beaLL /* 800 */, 0xb0b854a7fe42980fLL /* 801 */, 0x7bd46a6a718d4b9fLL /* 802 */, 0xd10fa8cc22a5fd8cLL /* 803 */, 0xd31484952be4bd31LL /* 804 */, 0xc7fa975fcb243847LL /* 805 */, 0x4886ed1e5846c407LL /* 806 */, 0x28cddb791eb70b04LL /* 807 */, 0xc2b00be2f573417fLL /* 808 */, 0x5c9590452180f877LL /* 809 */, 0x7a6bddfff370eb00LL /* 810 */, 0xce509e38d6d9d6a4LL /* 811 */, 0xebeb0f00647fa702LL /* 812 */, 0x1dcc06cf76606f06LL /* 813 */, 0xe4d9f28ba286ff0aLL /* 814 */, 0xd85a305dc918c262LL /* 815 */, 0x475b1d8732225f54LL /* 816 */, 0x2d4fb51668ccb5feLL /* 817 */, 0xa679b9d9d72bba20LL /* 818 */, 0x53841c0d912d43a5LL /* 819 */, 0x3b7eaa48bf12a4e8LL /* 820 */, 0x781e0e47f22f1ddfLL /* 821 */, 0xeff20ce60ab50973LL /* 822 */, 0x20d261d19dffb742LL /* 823 */, 0x16a12b03062a2e39LL /* 824 */, 0x1960eb2239650495LL /* 825 */, 0x251c16fed50eb8b8LL /* 826 */, 0x9ac0c330f826016eLL /* 827 */, 0xed152665953e7671LL /* 828 */, 0x02d63194a6369570LL /* 829 */, 0x5074f08394b1c987LL /* 830 */, 0x70ba598c90b25ce1LL /* 831 */, 0x794a15810b9742f6LL /* 832 */, 0x0d5925e9fcaf8c6cLL /* 833 */, 0x3067716cd868744eLL /* 834 */, 0x910ab077e8d7731bLL /* 835 */, 0x6a61bbdb5ac42f61LL /* 836 */, 0x93513efbf0851567LL /* 837 */, 0xf494724b9e83e9d5LL /* 838 */, 0xe887e1985c09648dLL /* 839 */, 0x34b1d3c675370cfdLL /* 840 */, 0xdc35e433bc0d255dLL /* 841 */, 0xd0aab84234131be0LL /* 842 */, 0x08042a50b48b7eafLL /* 843 */, 0x9997c4ee44a3ab35LL /* 844 */, 0x829a7b49201799d0LL /* 845 */, 0x263b8307b7c54441LL /* 846 */, 0x752f95f4fd6a6ca6LL /* 847 */, 0x927217402c08c6e5LL /* 848 */, 0x2a8ab754a795d9eeLL /* 849 */, 0xa442f7552f72943dLL /* 850 */, 0x2c31334e19781208LL /* 851 */, 0x4fa98d7ceaee6291LL /* 852 */, 0x55c3862f665db309LL /* 853 */, 0xbd0610175d53b1f3LL /* 854 */, 0x46fe6cb840413f27LL /* 855 */, 0x3fe03792df0cfa59LL /* 856 */, 0xcfe700372eb85e8fLL /* 857 */, 0xa7be29e7adbce118LL /* 858 */, 0xe544ee5cde8431ddLL /* 859 */, 0x8a781b1b41f1873eLL /* 860 */, 0xa5c94c78a0d2f0e7LL /* 861 */, 0x39412e2877b60728LL /* 862 */, 0xa1265ef3afc9a62cLL /* 863 */, 0xbcc2770c6a2506c5LL /* 864 */, 0x3ab66dd5dce1ce12LL /* 865 */, 0xe65499d04a675b37LL /* 866 */, 0x7d8f523481bfd216LL /* 867 */, 0x0f6f64fcec15f389LL /* 868 */, 0x74efbe618b5b13c8LL /* 869 */, 0xacdc82b714273e1dLL /* 870 */, 0xdd40bfe003199d17LL /* 871 */, 0x37e99257e7e061f8LL /* 872 */, 0xfa52626904775aaaLL /* 873 */, 0x8bbbf63a463d56f9LL /* 874 */, 0xf0013f1543a26e64LL /* 875 */, 0xa8307e9f879ec898LL /* 876 */, 0xcc4c27a4150177ccLL /* 877 */, 0x1b432f2cca1d3348LL /* 878 */, 0xde1d1f8f9f6fa013LL /* 879 */, 0x606602a047a7ddd6LL /* 880 */, 0xd237ab64cc1cb2c7LL /* 881 */, 0x9b938e7225fcd1d3LL /* 882 */, 0xec4e03708e0ff476LL /* 883 */, 0xfeb2fbda3d03c12dLL /* 884 */, 0xae0bced2ee43889aLL /* 885 */, 0x22cb8923ebfb4f43LL /* 886 */, 0x69360d013cf7396dLL /* 887 */, 0x855e3602d2d4e022LL /* 888 */, 0x073805bad01f784cLL /* 889 */, 0x33e17a133852f546LL /* 890 */, 0xdf4874058ac7b638LL /* 891 */, 0xba92b29c678aa14aLL /* 892 */, 0x0ce89fc76cfaadcdLL /* 893 */, 0x5f9d4e0908339e34LL /* 894 */, 0xf1afe9291f5923b9LL /* 895 */, 0x6e3480f60f4a265fLL /* 896 */, 0xeebf3a2ab29b841cLL /* 897 */, 0xe21938a88f91b4adLL /* 898 */, 0x57dfeff845c6d3c3LL /* 899 */, 0x2f006b0bf62caaf2LL /* 900 */, 0x62f479ef6f75ee78LL /* 901 */, 0x11a55ad41c8916a9LL /* 902 */, 0xf229d29084fed453LL /* 903 */, 0x42f1c27b16b000e6LL /* 904 */, 0x2b1f76749823c074LL /* 905 */, 0x4b76eca3c2745360LL /* 906 */, 0x8c98f463b91691bdLL /* 907 */, 0x14bcc93cf1ade66aLL /* 908 */, 0x8885213e6d458397LL /* 909 */, 0x8e177df0274d4711LL /* 910 */, 0xb49b73b5503f2951LL /* 911 */, 0x10168168c3f96b6bLL /* 912 */, 0x0e3d963b63cab0aeLL /* 913 */, 0x8dfc4b5655a1db14LL /* 914 */, 0xf789f1356e14de5cLL /* 915 */, 0x683e68af4e51dac1LL /* 916 */, 0xc9a84f9d8d4b0fd9LL /* 917 */, 0x3691e03f52a0f9d1LL /* 918 */, 0x5ed86e46e1878e80LL /* 919 */, 0x3c711a0e99d07150LL /* 920 */, 0x5a0865b20c4e9310LL /* 921 */, 0x56fbfc1fe4f0682eLL /* 922 */, 0xea8d5de3105edf9bLL /* 923 */, 0x71abfdb12379187aLL /* 924 */, 0x2eb99de1bee77b9cLL /* 925 */, 0x21ecc0ea33cf4523LL /* 926 */, 0x59a4d7521805c7a1LL /* 927 */, 0x3896f5eb56ae7c72LL /* 928 */, 0xaa638f3db18f75dcLL /* 929 */, 0x9f39358dabe9808eLL /* 930 */, 0xb7defa91c00b72acLL /* 931 */, 0x6b5541fd62492d92LL /* 932 */, 0x6dc6dee8f92e4d5bLL /* 933 */, 0x353f57abc4beea7eLL /* 934 */, 0x735769d6da5690ceLL /* 935 */, 0x0a234aa642391484LL /* 936 */, 0xf6f9508028f80d9dLL /* 937 */, 0xb8e319a27ab3f215LL /* 938 */, 0x31ad9c1151341a4dLL /* 939 */, 0x773c22a57bef5805LL /* 940 */, 0x45c7561a07968633LL /* 941 */, 0xf913da9e249dbe36LL /* 942 */, 0xda652d9b78a64c68LL /* 943 */, 0x4c27a97f3bc334efLL /* 944 */, 0x76621220e66b17f4LL /* 945 */, 0x967743899acd7d0bLL /* 946 */, 0xf3ee5bcae0ed6782LL /* 947 */, 0x409f753600c879fcLL /* 948 */, 0x06d09a39b5926db6LL /* 949 */, 0x6f83aeb0317ac588LL /* 950 */, 0x01e6ca4a86381f21LL /* 951 */, 0x66ff3462d19f3025LL /* 952 */, 0x72207c24ddfd3bfbLL /* 953 */, 0x4af6b6d3e2ece2ebLL /* 954 */, 0x9c994dbec7ea08deLL /* 955 */, 0x49ace597b09a8bc4LL /* 956 */, 0xb38c4766cf0797baLL /* 957 */, 0x131b9373c57c2a75LL /* 958 */, 0xb1822cce61931e58LL /* 959 */, 0x9d7555b909ba1c0cLL /* 960 */, 0x127fafdd937d11d2LL /* 961 */, 0x29da3badc66d92e4LL /* 962 */, 0xa2c1d57154c2ecbcLL /* 963 */, 0x58c5134d82f6fe24LL /* 964 */, 0x1c3ae3515b62274fLL /* 965 */, 0xe907c82e01cb8126LL /* 966 */, 0xf8ed091913e37fcbLL /* 967 */, 0x3249d8f9c80046c9LL /* 968 */, 0x80cf9bede388fb63LL /* 969 */, 0x1881539a116cf19eLL /* 970 */, 0x5103f3f76bd52457LL /* 971 */, 0x15b7e6f5ae47f7a8LL /* 972 */, 0xdbd7c6ded47e9ccfLL /* 973 */, 0x44e55c410228bb1aLL /* 974 */, 0xb647d4255edb4e99LL /* 975 */, 0x5d11882bb8aafc30LL /* 976 */, 0xf5098bbb29d3212aLL /* 977 */, 0x8fb5ea14e90296b3LL /* 978 */, 0x677b942157dd025aLL /* 979 */, 0xfb58e7c0a390acb5LL /* 980 */, 0x89d3674c83bd4a01LL /* 981 */, 0x9e2da4df4bf3b93bLL /* 982 */, 0xfcc41e328cab4829LL /* 983 */, 0x03f38c96ba582c52LL /* 984 */, 0xcad1bdbd7fd85db2LL /* 985 */, 0xbbb442c16082ae83LL /* 986 */, 0xb95fe86ba5da9ab0LL /* 987 */, 0xb22e04673771a93fLL /* 988 */, 0x845358c9493152d8LL /* 989 */, 0xbe2a488697b4541eLL /* 990 */, 0x95a2dc2dd38e6966LL /* 991 */, 0xc02c11ac923c852bLL /* 992 */, 0x2388b1990df2a87bLL /* 993 */, 0x7c8008fa1b4f37beLL /* 994 */, 0x1f70d0c84d54e503LL /* 995 */, 0x5490adec7ece57d4LL /* 996 */, 0x002b3c27d9063a3aLL /* 997 */, 0x7eaea3848030a2bfLL /* 998 */, 0xc602326ded2003c0LL /* 999 */, 0x83a7287d69a94086LL /* 1000 */, 0xc57a5fcb30f57a8aLL /* 1001 */, 0xb56844e479ebe779LL /* 1002 */, 0xa373b40f05dcbce9LL /* 1003 */, 0xd71a786e88570ee2LL /* 1004 */, 0x879cbacdbde8f6a0LL /* 1005 */, 0x976ad1bcc164a32fLL /* 1006 */, 0xab21e25e9666d78bLL /* 1007 */, 0x901063aae5e5c33cLL /* 1008 */, 0x9818b34448698d90LL /* 1009 */, 0xe36487ae3e1e8abbLL /* 1010 */, 0xafbdf931893bdcb4LL /* 1011 */, 0x6345a0dc5fbbd519LL /* 1012 */, 0x8628fe269b9465caLL /* 1013 */, 0x1e5d01603f9c51ecLL /* 1014 */, 0x4de44006a15049b7LL /* 1015 */, 0xbf6c70e5f776cbb1LL /* 1016 */, 0x411218f2ef552bedLL /* 1017 */, 0xcb0c0708705a36a3LL /* 1018 */, 0xe74d14754f986044LL /* 1019 */, 0xcd56d9430ea8280eLL /* 1020 */, 0xc12591d7535f5065LL /* 1021 */, 0xc83223f1720aef96LL /* 1022 */, 0xc3a0396f7363a51fLL /* 1023 */ }; static void -print_abc( const char *text, u64 a, u64 b, u64 c ) +burn_stack (int bytes) { -/*printf("%s: %08X%08X %08X%08X %08X%08X\n", - text, - (u32)(a>>32), - (u32)(a), - (u32)(b>>32), - (u32)(b), - (u32)(c>>32), - (u32)(c) );*/ + char buf[256]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); } -static void -print_data( const char *text, u64 a, u64 b, u64 c, - u64 d, u64 e, u64 f, - u64 g, u64 h ) -{ -/*printf("%s: %08X%08X %08X%08X %08X%08X %08X%08X\n" - "%s %08X%08X %08X%08X %08X%08X %08X%08X\n", - text, - (u32)(a>>32), - (u32)(a), - (u32)(b>>32), - (u32)(b), - (u32)(c>>32), - (u32)(c), - (u32)(d>>32), - (u32)(d), - text, - (u32)(e>>32), - (u32)(e), - (u32)(f>>32), - (u32)(f), - (u32)(g>>32), - (u32)(g), - (u32)(h>>32), - (u32)(h) );*/ -} static void tiger_init( TIGER_CONTEXT *hd ) { hd->a = 0x0123456789abcdefLL; hd->b = 0xfedcba9876543210LL; hd->c = 0xf096a5b4c3b2e187LL; hd->nblocks = 0; hd->count = 0; } static void round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul ) { u64 a = *ra; u64 b = *rb; u64 c = *rc; c ^= x; a -= sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ] ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]; b += sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ] ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]; b *= mul; *ra = a; *rb = b; *rc = c; } static void pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul ) { u64 a = *ra; u64 b = *rb; u64 c = *rc; round( &a, &b, &c, x[0], mul ); round( &b, &c, &a, x[1], mul ); round( &c, &a, &b, x[2], mul ); round( &a, &b, &c, x[3], mul ); round( &b, &c, &a, x[4], mul ); round( &c, &a, &b, x[5], mul ); round( &a, &b, &c, x[6], mul ); round( &b, &c, &a, x[7], mul ); *ra = a; *rb = b; *rc = c; } static void key_schedule( u64 *x ) { x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; x[1] ^= x[0]; x[2] += x[1]; x[3] -= x[2] ^ ((~x[1]) << 19 ); x[4] ^= x[3]; x[5] += x[4]; x[6] -= x[5] ^ ((~x[4]) >> 23 ); x[7] ^= x[6]; x[0] += x[7]; x[1] -= x[0] ^ ((~x[7]) << 19 ); x[2] ^= x[1]; x[3] += x[2]; x[4] -= x[3] ^ ((~x[2]) >> 23 ); x[5] ^= x[4]; x[6] += x[5]; x[7] -= x[6] ^ 0x0123456789abcdefLL; } /**************** * Transform the message DATA which consists of 512 bytes (8 words) */ static void transform( TIGER_CONTEXT *hd, byte *data ) { u64 a,b,c,aa,bb,cc; u64 x[8]; #ifdef BIG_ENDIAN_HOST #define MKWORD(d,n) \ ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) x[0] = MKWORD(data, 0); x[1] = MKWORD(data, 1); x[2] = MKWORD(data, 2); x[3] = MKWORD(data, 3); x[4] = MKWORD(data, 4); x[5] = MKWORD(data, 5); x[6] = MKWORD(data, 6); x[7] = MKWORD(data, 7); #undef MKWORD #else memcpy( &x[0], data, 64 ); #endif /* save */ a = aa = hd->a; b = bb = hd->b; c = cc = hd->c; - print_data(" key0", x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] ); - print_abc(" init", a, b, c ); pass( &a, &b, &c, x, 5); - print_abc("pass1", a, b, c ); key_schedule( x ); pass( &c, &a, &b, x, 7); - print_abc("pass2", a, b, c ); key_schedule( x ); pass( &b, &c, &a, x, 9); - print_abc("pass3", a, b, c ); - /* feedforward */ a ^= aa; b -= bb; c += cc; /* store */ hd->a = a; hd->b = b; hd->c = c; } /* Update the message digest with the contents * of INBUF with length INLEN. */ static void tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) { if( hd->count == 64 ) { /* flush the buffer */ transform( hd, hd->buf ); + burn_stack (21*8+11*sizeof(void*)); hd->count = 0; hd->nblocks++; } if( !inbuf ) return; if( hd->count ) { for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; tiger_write( hd, NULL, 0 ); if( !inlen ) return; } while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; hd->nblocks++; inlen -= 64; inbuf += 64; } + burn_stack (21*8+11*sizeof(void*)); for( ; inlen && hd->count < 64; inlen-- ) hd->buf[hd->count++] = *inbuf++; } /* The routine terminates the computation */ static void tiger_final( TIGER_CONTEXT *hd ) { u32 t, msb, lsb; byte *p; tiger_write(hd, NULL, 0); /* flush */; t = hd->nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->count < 56 ) { /* enough room */ hd->buf[hd->count++] = 0x01; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } else { /* need one extra block */ hd->buf[hd->count++] = 0x01; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; tiger_write(hd, NULL, 0); /* flush */; memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ hd->buf[56] = lsb ; hd->buf[57] = lsb >> 8; hd->buf[58] = lsb >> 16; hd->buf[59] = lsb >> 24; hd->buf[60] = msb ; hd->buf[61] = msb >> 8; hd->buf[62] = msb >> 16; hd->buf[63] = msb >> 24; transform( hd, hd->buf ); + burn_stack (21*8+11*sizeof(void*)); p = hd->buf; #ifdef BIG_ENDIAN_HOST #define X(a) do { *(u64*)p = hd->##a ; p += 8; } while(0) #else /* little endian */ #define X(a) do { *p++ = hd->##a >> 56; *p++ = hd->##a >> 48; \ *p++ = hd->##a >> 40; *p++ = hd->##a >> 32; \ *p++ = hd->##a >> 24; *p++ = hd->##a >> 16; \ *p++ = hd->##a >> 8; *p++ = hd->##a; } while(0) #endif X(a); X(b); X(c); #undef X } static byte * tiger_read( TIGER_CONTEXT *hd ) { return hd->buf; } /**************** * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if * the ALGO is invalid. */ static const char * tiger_get_info( int algo, size_t *contextsize, byte **r_asnoid, int *r_asnlen, int *r_mdlen, void (**r_init)( void *c ), void (**r_write)( void *c, byte *buf, size_t nbytes ), void (**r_final)( void *c ), byte *(**r_read)( void *c ) ) { /* 40: SEQUENCE { * 12: SEQUENCE { * 8: OCTET STRING :54 49 47 45 52 31 39 32 * 0: NULL * : } * 24: OCTET STRING * : } * * By replacing the 5th byte (0x04) with 0x16 we would have; * 8: IA5String 'TIGER192' */ static byte asn[18] = { 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47, 0x45, 0x52, 0x31, 0x39, 0x32, 0x05, 0x00, 0x04, 0x18 }; if( algo != 6 ) return NULL; *contextsize = sizeof(TIGER_CONTEXT); *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 24; *(void (**)(TIGER_CONTEXT *))r_init = tiger_init; *(void (**)(TIGER_CONTEXT *, byte*, size_t))r_write = tiger_write; *(void (**)(TIGER_CONTEXT *))r_final = tiger_final; *(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read; return "TIGER192"; } #ifndef IS_MODULE static #endif const char * const gnupgext_version = "TIGER ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 10, 1, 0, (void(*)(void))tiger_get_info }, { 11, 1, 6 }, }; /**************** * Enumerate the names of the functions together with informations about * this function. Set sequence to an integer with a initial value of 0 and * do not change it. * If what is 0 all kind of functions are returned. * Return values: class := class of function: * 10 = message digest algorithm info function * 11 = integer with available md algorithms * 20 = cipher algorithm info function * 21 = integer with available cipher algorithms * 30 = public key algorithm info function * 31 = integer with available pubkey algorithms * version = interface version of the function/pointer * (currently this is 1 for all functions) */ #ifndef IS_MODULE static #endif void * gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if( i >= DIM(func_table) || i < 0 ) { /*fprintf(stderr, "failed\n");*/ return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while( what && what != *class ); *sequence = i; /*fprintf(stderr, "success\n");*/ return ret; } #ifndef IS_MODULE void tiger_constructor(void) { register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); } #endif #endif /* HAVE_U64_TYPEDEF */ diff --git a/cipher/twofish.c b/cipher/twofish.c index a7cbb309..eb41d872 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -1,1064 +1,1103 @@ /* Twofish for GPG * By Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 * * The original author has disclaimed all copyright interest in this * code and thus putting it in the public domain. * * This code is a "clean room" implementation, written from the paper * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available * through http://www.counterpane.com/twofish.html * * For background information on multiplication in finite fields, used for * the matrix operations in the key schedule, see the book _Contemporary * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the * Third Edition. * * Only the 128- and 256-bit key sizes are supported. This code is intended * for GNU C on a 32-bit system, but it should work almost anywhere. Loops * are unrolled, precomputation tables are used, etc., for maximum speed at * some cost in memory consumption. */ #include #include #include #include /* for memcmp() */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "dynload.h" /* Prototype for the self-test function. */ static const char *selftest(void); /* Structure for an expanded Twofish key. s contains the key-dependent * S-boxes composed with the MDS matrix; w contains the eight "whitening" * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ typedef struct { u32 s[4][256], w[8], k[32]; } TWOFISH_context; /* These two tables are the q0 and q1 permutations, exactly as described in * the Twofish paper. */ static const byte q0[256] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 }; static const byte q1[256] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; /* These MDS tables are actually tables of MDS composed with q0 and q1, * because it is only ever used that way and we can save some time by * precomputing. Of course the main saving comes from precomputing the * GF(2^8) multiplication involved in the MDS matrix multiply; by looking * things up in these tables we reduce the matrix multiply to four lookups * and three XORs. Semi-formally, the definition of these tables is: * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T * where ^T means "transpose", the matrix multiply is performed in GF(2^8) * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described * by Schneier et al, and I'm casually glossing over the byte/word * conversion issues. */ static const u32 mds[4][256] = { {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} }; /* The exp_to_poly and poly_to_exp tables are used to perform efficient * operations in GF(2^8) represented as GF(2)[x]/w(x) where * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the * definition of the RS matrix in the key schedule. Elements of that field * are polynomials of degree not greater than 7 and all coefficients 0 or 1, * which can be represented naturally by bytes (just substitute x=2). In that * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) * multiplication is inefficient without hardware support. To multiply * faster, I make use of the fact x is a generator for the nonzero elements, * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for * some n in 0..254. Note that that caret is exponentiation in GF(2^8), * *not* polynomial notation. So if I want to compute pq where p and q are * in GF(2^8), I can just say: * 1. if p=0 or q=0 then pq=0 * 2. otherwise, find m and n such that p=x^m and q=x^n * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq * The translations in steps 2 and 3 are looked up in the tables * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this * in action, look at the CALC_S macro. As additional wrinkles, note that * one of my operands is always a constant, so the poly_to_exp lookup on it * is done in advance; I included the original values in the comments so * readers can have some chance of recognizing that this *is* the RS matrix * from the Twofish paper. I've only included the table entries I actually * need; I never do a lookup on a variable input of zero and the biggest * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll * never sum to more than 491. I'm repeating part of the exp_to_poly table * so that I don't have to do mod-255 reduction in the exponent arithmetic. * Since I know my constant operands are never zero, I only have to worry * about zero values in the variable operand, and I do it with a simple * conditional branch. I know conditionals are expensive, but I couldn't * see a non-horrible way of avoiding them, and I did manage to group the * statements so that each if covers four group multiplications. */ static const byte poly_to_exp[255] = { 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, 0x85, 0xC8, 0xA1 }; static const byte exp_to_poly[492] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB }; /* The table constants are indices of * S-box entries, preprocessed through q0 and q1. */ static byte calc_sb_tbl[512] = { 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 }; /* Macro to perform one column of the RS matrix multiplication. The * parameters a, b, c, and d are the four bytes of output; i is the index * of the key bytes, and w, x, y, and z, are the column of constants from * the RS matrix, preprocessed through the poly_to_exp table. */ #define CALC_S(a, b, c, d, i, w, x, y, z) \ if (key[i]) { \ tmp = poly_to_exp[key[i] - 1]; \ (a) ^= exp_to_poly[tmp + (w)]; \ (b) ^= exp_to_poly[tmp + (x)]; \ (c) ^= exp_to_poly[tmp + (y)]; \ (d) ^= exp_to_poly[tmp + (z)]; \ } /* Macros to calculate the key-dependent S-boxes for a 128-bit key using * the S vector from CALC_S. CALC_SB_2 computes a single entry in all * four S-boxes, where i is the index of the entry to compute, and a and b * are the index numbers preprocessed through the q0 and q1 tables * respectively. CALC_SB is simply a convenience to make the code shorter; * it calls CALC_SB_2 four times with consecutive indices from i to i+3, * using the remaining parameters two by two. */ #define CALC_SB_2(i, a, b) \ ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] #define CALC_SB(i, a, b, c, d, e, f, g, h) \ CALC_SB_2 (i, a, b); CALC_SB_2 ((i)+1, c, d); \ CALC_SB_2 ((i)+2, e, f); CALC_SB_2 ((i)+3, g, h) /* Macros exactly like CALC_SB and CALC_SB_2, but for 256-bit keys. */ #define CALC_SB256_2(i, a, b) \ ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; #define CALC_SB256(i, a, b, c, d, e, f, g, h) \ CALC_SB256_2 (i, a, b); CALC_SB256_2 ((i)+1, c, d); \ CALC_SB256_2 ((i)+2, e, f); CALC_SB256_2 ((i)+3, g, h) /* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the * last two stages of the h() function for a given index (either 2i or 2i+1). * a, b, c, and d are the four bytes going into the last two stages. For * 128-bit keys, this is the entire h() function and a and c are the index * preprocessed through q0 and q1 respectively; for longer keys they are the * output of previous stages. j is the index of the first key byte to use. * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 * twice, doing the Psuedo-Hadamard Transform, and doing the necessary * rotations. Its parameters are: a, the array to write the results into, * j, the index of the first output entry, k and l, the preprocessed indices * for index 2i, and m and n, the preprocessed indices for index 2i+1. * CALC_K256_2 expands CALC_K_2 to handle 256-bit keys, by doing two * additional lookup-and-XOR stages. The parameters a and b are the index * preprocessed through q0 and q1 respectively; j is the index of the first * key byte to use. CALC_K256 is identical to CALC_K but for using the * CALC_K256_2 macro instead of CALC_K_2. */ #define CALC_K_2(a, b, c, d, j) \ mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] #define CALC_K(a, j, k, l, m, n) \ x = CALC_K_2 (k, l, k, l, 0); \ y = CALC_K_2 (m, n, m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) #define CALC_K256_2(a, b, j) \ CALC_K_2 (q0[q1[b ^ key[(j) + 24]] ^ key[(j) + 16]], \ q1[q1[a ^ key[(j) + 25]] ^ key[(j) + 17]], \ q0[q0[a ^ key[(j) + 26]] ^ key[(j) + 18]], \ q1[q0[b ^ key[(j) + 27]] ^ key[(j) + 19]], j) #define CALC_K256(a, j, k, l, m, n) \ x = CALC_K256_2 (k, l, 0); \ y = CALC_K256_2 (m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +static void +burn_stack (int bytes) +{ + char buf[64]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + /* Perform the key setup. Note that this works only with 128- and 256-bit * keys, despite the API that looks like it might support other sizes. */ static int -twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen) +do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen) { int i, j, k; /* Temporaries for CALC_K. */ u32 x, y; /* The S vector used to key the S-boxes, split up into individual bytes. * 128-bit keys use only sa through sh; 256-bit use all of them. */ byte sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; byte si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; /* Temporary for CALC_S. */ byte tmp; /* Flags for self-test. */ static int initialized = 0; static const char *selftest_failed=0; /* Check key length. */ if( ( ( keylen - 16 ) | 16 ) != 16 ) return GCRYERR_INV_KEYLEN; /* Do self-test if necessary. */ if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) fprintf(stderr, "%s\n", selftest_failed ); } if( selftest_failed ) return GCRYERR_SELFTEST; /* Compute the first two words of the S vector. The magic numbers are * the entries of the RS matrix, preprocessed through poly_to_exp. The * numbers in the comments are the original (polynomial form) matrix * entries. */ CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ if (keylen == 32) { /* 256-bit key */ /* Calculate the remaining two words of the S vector */ CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ /* Compute the S-boxes. */ for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); } /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); } else { /* Compute the S-boxes. */ for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); } /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); } return 0; } + +static int +twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen) +{ + int rc = do_twofish_setkey (ctx, key, keylen); + burn_stack (23+6*sizeof(void*)); + return rc; +} + + /* Macros to compute the g() function in the encryption and decryption * rounds. G1 is the straight g() function; G2 includes the 8-bit * rotation for the high 32-bit word. */ #define G1(a) \ (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) #define G2(b) \ (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) /* Encryption and decryption Feistel rounds. Each one calls the two g() * macros, does the PHT, and performs the XOR and the appropriate bit * rotations. The parameters are the round number (used to select subkeys), * and the four 32-bit chunks of the text. */ #define ENCROUND(n, a, b, c, d) \ x = G1 (a); y = G2 (b); \ x += y; y += x + ctx->k[2 * (n) + 1]; \ (c) ^= x + ctx->k[2 * (n)]; \ (c) = ((c) >> 1) + ((c) << 31); \ (d) = (((d) << 1)+((d) >> 31)) ^ y #define DECROUND(n, a, b, c, d) \ x = G1 (a); y = G2 (b); \ x += y; y += x; \ (d) ^= y + ctx->k[2 * (n) + 1]; \ (d) = ((d) >> 1) + ((d) << 31); \ (c) = (((c) << 1)+((c) >> 31)); \ (c) ^= (x + ctx->k[2 * (n)]) /* Encryption and decryption cycles; each one is simply two Feistel rounds * with the 32-bit chunks re-ordered to simulate the "swap" */ #define ENCCYCLE(n) \ ENCROUND (2 * (n), a, b, c, d); \ ENCROUND (2 * (n) + 1, c, d, a, b) #define DECCYCLE(n) \ DECROUND (2 * (n) + 1, c, d, a, b); \ DECROUND (2 * (n), a, b, c, d) /* Macros to convert the input and output bytes into 32-bit words, * and simultaneously perform the whitening step. INPACK packs word * number n into the variable named by x, using whitening subkey number m. * OUTUNPACK unpacks word number n from the variable named by x, using * whitening subkey number m. */ #define INPACK(n, x, m) \ x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 /* Encrypt one block. in and out may be the same. */ static void -twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK (0, a, 0); INPACK (1, b, 1); INPACK (2, c, 2); INPACK (3, d, 3); /* Encryption Feistel cycles. */ ENCCYCLE (0); ENCCYCLE (1); ENCCYCLE (2); ENCCYCLE (3); ENCCYCLE (4); ENCCYCLE (5); ENCCYCLE (6); ENCCYCLE (7); /* Output whitening and unpacking. */ OUTUNPACK (0, c, 4); OUTUNPACK (1, d, 5); OUTUNPACK (2, a, 6); OUTUNPACK (3, b, 7); } + +static void +twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + do_twofish_encrypt (ctx, out, in); + burn_stack (24+3*sizeof (void*)); +} + /* Decrypt one block. in and out may be the same. */ static void -twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK (0, c, 4); INPACK (1, d, 5); INPACK (2, a, 6); INPACK (3, b, 7); /* Encryption Feistel cycles. */ DECCYCLE (7); DECCYCLE (6); DECCYCLE (5); DECCYCLE (4); DECCYCLE (3); DECCYCLE (2); DECCYCLE (1); DECCYCLE (0); /* Output whitening and unpacking. */ OUTUNPACK (0, a, 0); OUTUNPACK (1, b, 1); OUTUNPACK (2, c, 2); OUTUNPACK (3, d, 3); } + +static void +twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + do_twofish_decrypt (ctx, out, in); + burn_stack (24+3*sizeof (void*)); +} + /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { TWOFISH_context ctx; /* Expanded key. */ byte scratch[16]; /* Encryption/decryption result buffer. */ /* Test vectors for single encryption/decryption. Note that I am using * the vectors from the Twofish paper's "known answer test", I=3 for * 128-bit and I=4 for 256-bit, instead of the all-0 vectors from the * "intermediate value test", because an all-0 key would trigger all the * special cases in the RS matrix multiply, leaving the math untested. */ static const byte plaintext[16] = { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }; static const byte key[16] = { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }; static const byte ciphertext[16] = { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 }; static const byte plaintext_256[16] = { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }; static const byte key_256[32] = { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }; static const byte ciphertext_256[16] = { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA }; twofish_setkey (&ctx, key, sizeof(key)); twofish_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "Twofish-128 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "Twofish-128 test decryption failed."; twofish_setkey (&ctx, key_256, sizeof(key_256)); twofish_encrypt (&ctx, scratch, plaintext_256); if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) return "Twofish-256 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) return "Twofish-256 test decryption failed."; return NULL; } /* More complete test program. This does 1000 encryptions and decryptions * with each of 250 128-bit keys and 2000 encryptions and decryptions with * each of 125 256-bit keys, using a feedback scheme similar to a Feistel * cipher, so as to be sure of testing all the table entries pretty * thoroughly. We keep changing the keys so as to get a more meaningful * performance number, since the key setup is non-trivial for Twofish. */ #ifdef TEST #include #include #include int main() { TWOFISH_context ctx; /* Expanded key. */ int i, j; /* Loop counters. */ const char *encrypt_msg; /* Message to print regarding encryption test; * the printf is done outside the loop to avoid * stuffing up the timing. */ clock_t timer; /* For computing elapsed time. */ /* Test buffer. */ byte buffer[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Expected outputs for the million-operation test */ static const byte test_encrypt[4][16] = { {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} }; static const byte test_decrypt[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Start the timer ticking. */ timer = clock (); /* Encryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[2], buffer[2]); twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_encrypt (&ctx, buffer[0], buffer[0]); twofish_encrypt (&ctx, buffer[1], buffer[1]); } } encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? "encryption failure!\n" : "encryption OK!\n"; /* Decryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_decrypt (&ctx, buffer[0], buffer[0]); twofish_decrypt (&ctx, buffer[1], buffer[1]); } twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[2], buffer[2]); } /* Stop the timer, and print results. */ timer = clock () - timer; printf (encrypt_msg); printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? "decryption failure!\n" : "decryption OK!\n"); printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); return 0; } #endif /* TEST */ #ifdef IS_MODULE static #endif const char * _gcry_twofish_get_info (int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey) (void *c, byte *key, unsigned keylen), void (**r_encrypt) (void *c, byte *outbuf, byte *inbuf), void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf) ) { *keylen = algo==10? 256 : 128; *blocksize = 16; *contextsize = sizeof (TWOFISH_context); *(int (**)(TWOFISH_context*, const byte*, const unsigned))r_setkey = twofish_setkey; *(void (**)(const TWOFISH_context*, byte*, const byte*))r_encrypt = twofish_encrypt; *(void (**)(const TWOFISH_context*, byte*, const byte*))r_decrypt = twofish_decrypt; if( algo == 10 ) return "TWOFISH"; if (algo == 102) /* This algorithm number is assigned for * experiments, so we can use it */ return "TWOFISH128"; return NULL; } #ifdef IS_MODULE const char * const gnupgext_version = "TWOFISH ($Revision$)"; static struct { int class; int version; int value; void (*func)(void); } func_table[] = { { 20, 1, 0, (void(*)(void))_gcry_twofish_get_info }, { 21, 1, 10 }, { 21, 1, 102 }, }; /**************** * Enumerate the names of the functions together with information about * this function. Set sequence to an integer with a initial value of 0 and * do not change it. * If what is 0 all kind of functions are returned. * Return values: class := class of function: * 10 = message digest algorithm info function * 11 = integer with available md algorithms * 20 = cipher algorithm info function * 21 = integer with available cipher algorithms * 30 = public key algorithm info function * 31 = integer with available pubkey algorithms * version = interface version of the function/pointer * (currently this is 1 for all functions) */ void * gnupgext_enum_func ( int what, int *sequence, int *class, int *vers ) { void *ret; int i = *sequence; do { if ( i >= DIM(func_table) || i < 0 ) { return NULL; } *class = func_table[i].class; *vers = func_table[i].version; switch( *class ) { case 11: case 21: case 31: ret = &func_table[i].value; break; default: ret = func_table[i].func; break; } i++; } while ( what && what != *class ); *sequence = i; return ret; } #endif /*IS_MODULE*/ diff --git a/configure.in b/configure.in index a1ff1da9..c4526d18 100644 --- a/configure.in +++ b/configure.in @@ -1,729 +1,723 @@ dnl dnl Configure template for GNUPG dnl dnl (Process this file with autoconf to produce a configure script.) AC_REVISION($Revision$)dnl dnl Must reset CDPATH so that bash's cd does not print to stdout CDPATH= AC_PREREQ(2.13) AC_INIT(src/gcrypt.h) AC_CONFIG_AUX_DIR(scripts) AM_CONFIG_HEADER(config.h) AC_CANONICAL_SYSTEM ############################################# # Version numbers (Rember to change them just before a release) # 1. No interfaces changed, only implementations (good): Increment REVISION. # 2. Interfaces added, none removed (good): Increment CURRENT, increment # AGE, set REVISION to 0. # 3. Interfaces removed (BAD, breaks upward compatibility): Increment # CURRENT, set AGE and REVISION to 0. AM_INIT_AUTOMAKE(libgcrypt,1.1.3) LIBGCRYPT_LT_CURRENT=2 LIBGCRYPT_LT_AGE=1 LIBGCRYPT_LT_REVISION=0 ############################################## AC_SUBST(LIBGCRYPT_LT_CURRENT) AC_SUBST(LIBGCRYPT_LT_AGE) AC_SUBST(LIBGCRYPT_LT_REVISION) # ALL_LINGUAS="da de eo es_ES fr id it ja nl pl pt_BR pt_PT ru sv" static_modules="sha1 md5 rmd160" static_random_module="" AC_PROG_AWK MODULES_IN_CIPHER=`$AWK '/^EXTRA_PROGRAMS/ { for(i=3;i<=NF;i++) print $i}' \ $srcdir/cipher/Makefile.am` dnl dnl Check for random module options dnl dnl Fixme: get the list of available modules from MODULES_IN_CIPHER dnl and check against this list AC_MSG_CHECKING([which static random module to use]) AC_ARG_ENABLE(static-rnd, [ --enable-static-rnd=[egd|unix|linux|none] ], [use_static_rnd=$enableval], [use_static_rnd=default] ) if test "$use_static_rnd" = no; then use_static_rnd=default fi case "$use_static_rnd" in egd | linux | unix | none | default ) AC_MSG_RESULT($use_static_rnd) ;; * ) AC_MSG_RESULT(invalid argument) AC_MSG_ERROR(there is no random module rnd$use_static_rnd) ;; esac AC_ARG_WITH(egd-socket, [ --with-egd-socket=NAME Use NAME for the EGD socket)], egd_socket_name="$withval", egd_socket_name="" ) AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name") dnl dnl See whether the user wants to disable checking for /dev/random AC_MSG_CHECKING([whether use of /dev/random is requested]) AC_ARG_ENABLE(dev-random, [ --disable-dev-random disable the use of dev random], try_dev_random=$enableval, try_dev_random=yes) AC_MSG_RESULT($try_dev_random) dnl dnl Check other options dnl AC_MSG_CHECKING([whether use of extensions is requested]) AC_ARG_ENABLE(dynload, [ --disable-dynload disable use of extensions], try_dynload=$enableval, try_dynload=yes) AC_MSG_RESULT($try_dynload) AC_MSG_CHECKING([whether assembler modules are requested]) AC_ARG_ENABLE(asm, [ --disable-asm do not use assembler modules], try_asm_modules=$enableval, try_asm_modules=yes) AC_MSG_RESULT($try_asm_modules) AC_MSG_CHECKING([whether memory debugging is requested]) AC_ARG_ENABLE(m-debug, [ --enable-m-debug enable debugging of memory allocation], use_m_debug=$enableval, use_m_debug=no) AC_MSG_RESULT($use_m_debug) if test "$use_m_debug" = yes; then AC_DEFINE(M_DEBUG) use_m_guard=yes else AC_MSG_CHECKING([whether memory guard is requested]) AC_ARG_ENABLE(m-guard, [ --enable-m-guard enable memory guard facility], use_m_guard=$enableval, use_m_guard=no) AC_MSG_RESULT($use_m_guard) fi if test "$use_m_guard" = yes ; then AC_DEFINE(M_GUARD) fi dnl dnl Check whether we want to use Linux capabilities dnl AC_MSG_CHECKING([whether use of capabilities is requested]) AC_ARG_WITH(capabilities, [ --with-capabilities use linux capabilities [default=no]], [use_capabilities="$withval"],[use_capabilities=no]) AC_MSG_RESULT($use_capabilities) AM_MAINTAINER_MODE dnl Checks for programs. dnl dnl Setup some stuff depending on host/target. dnl case "${target}" in *-*-mingw32*) # special stuff for Windoze NT # Do we need to set cross_compiling here or is it sufficient # to rely on AC_PROG_CC which is called later? cross_compiling=yes CC="${target}-gcc" CPP="${target}-gcc -E" RANLIB="${target}-ranlib" disallowed_modules="rndunix rndlinux rndegd" ;; *) disallowed_modules="rndw32" ;; esac AC_ARG_PROGRAM AC_PROG_MAKE_SET AM_SANITY_CHECK missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) dnl AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_PROG_CC AC_PROG_CPP AC_ISC_POSIX AC_PROG_INSTALL AC_PROG_AWK GPH_PROG_DB2ANY AM_DISABLE_STATIC AM_PROG_LIBTOOL MPI_OPT_FLAGS="" try_gettext=no case "${target}" in *-*-mingw32*) # special stuff for Windoze NT ac_cv_have_dev_random=no AC_DEFINE(USE_ONLY_8DOT3) AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DOSISH_SYSTEM) try_gettext="no" ;; i?86-emx-os2 | i?86-*-os2*emx ) # OS/2 with the EMX environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DOSISH_SYSTEM) try_gettext="no" ;; i?86-*-msdosdjgpp*) # DOS with the DJGPP environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DOSISH_SYSTEM) try_gettext="no" ;; *-*-freebsd*) # FreeBSD CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" ;; *-*-hpux*) if test -z "$GCC" ; then CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" fi ;; *-dec-osf4*) if test -z "$GCC" ; then # Suppress all warnings # to get rid of the unsigned/signed char mismatch warnings. CFLAGS="$CFLAGS -w" fi ;; m68k-atari-mint) ;; *) ;; esac AC_SUBST(MPI_OPT_FLAGS) GNUPG_SYS_SYMBOL_UNDERSCORE GNUPG_CHECK_PIC GNUPG_CHECK_EXPORTDYNAMIC if test "$NO_PIC" = yes; then try_dynload=no fi case "${target}" in *-*-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; i?86-emx-os2 | i?86-*-os2*emx ) PRINTABLE_OS_NAME="OS/2" ;; i?86-*-msdosdjgpp*) PRINTABLE_OS_NAME="MSDOS/DJGPP" try_dynload=no ;; *-linux*) PRINTABLE_OS_NAME="GNU/Linux" ;; dnl let that after linux to avoid gnu-linux problems *-gnu*) PRINTABLE_OS_NAME="GNU/Hurd" ;; *) PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` ;; esac AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME") dnl Fixme: Are these the best flags for OpenBSD???? -dnl (I have removed the -lc from * ...CFLAGS for test purposes.) case "${target}" in - *-openbsd*) + *-openbsd* | *-netbsd*) NAME_OF_DEV_RANDOM="/dev/srandom" NAME_OF_DEV_URANDOM="/dev/urandom" DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x" ;; - *-netbsd*) - NAME_OF_DEV_RANDOM="/dev/random" - NAME_OF_DEV_URANDOM="/dev/urandom" - DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x" - ;; - - *-solaris*) + *-solaris* | *-irix* | *-dec-osf* ) NAME_OF_DEV_RANDOM="/dev/random" NAME_OF_DEV_URANDOM="/dev/random" DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" ;; *) NAME_OF_DEV_RANDOM="/dev/random" NAME_OF_DEV_URANDOM="/dev/urandom" # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. if test -n "$GCC" ; then DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" else DYNLINK_MOD_CFLAGS="$CFLAGS_PIC" fi ;; esac AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM") AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM") AC_SUBST(MPI_OPT_FLAGS) dnl Checks for libraries. USE_NLS=no USE_INCLUDED_LIBINTL=no AC_SUBST(USE_NLS) AC_SUBST(USE_INCLUDED_LIBINTL) dnl Solaris needs -lsocket and -lnsl. Unisys system includes dnl gethostbyname in libsocket but needs libnsl for socket. AC_CHECK_LIB(nsl, gethostbyname) AC_CHECK_LIB(socket, socket, ac_need_libsocket=1, ac_try_nsl=1) if test x$ac_need_libsocket = x1; then LIBS="$LIBS -lsocket" fi if test x$ac_try_nsl = x1; then AC_CHECK_LIB(nsl, gethostbyname, ac_need_libnsl=1) if test x$ac_need_libnsl = x1 then LIBS="$LIBS -lnsl" fi fi if test "$try_dynload" = yes ; then AC_CHECK_LIB(dl,dlopen) if test "$ac_cv_lib_dl_dlopen" = "yes"; then AC_DEFINE(USE_DYNAMIC_LINKING) AC_DEFINE(HAVE_DL_DLOPEN) DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" use_gnupg_extensions=yes else AC_CHECK_FUNCS(dlopen) if test "$ac_cv_func_dlopen" = "yes"; then AC_DEFINE(USE_DYNAMIC_LINKING) AC_DEFINE(HAVE_DL_DLOPEN) DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" use_gnupg_extensions=yes else AC_CHECK_LIB(dld,shl_load) if test "$ac_cv_lib_dld_shl_load" = "yes"; then AC_DEFINE(USE_DYNAMIC_LINKING) AC_DEFINE(HAVE_DL_SHL_LOAD) DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" use_gnupg_extensions=yes dnl ----------------- dnl DLD is not ready for use. So I better disable this test dnl dnl AC_CHECK_LIB(dld,dld_link) dnl if test "$ac_cv_lib_dld_dld_link" = "yes"; then dnl AC_DEFINE(USE_DYNAMIC_LINKING) dnl AC_DEFINE(HAVE_DLD_DLD_LINK) dnl DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" dnl use_gnupg_extensions=yes dnl --------------- fi fi fi else AC_MSG_CHECKING(for dynamic loading) DYNLINK_LDFLAGS= DYNLINK_MOD_CFLAGS= use_gnupg_extensions=no AC_MSG_RESULT(has been disabled) fi AM_CONDITIONAL(ENABLE_GNUPG_EXTENSIONS, test "$use_gnupg_extensions" = yes ) AC_SUBST(DYNLINK_LDFLAGS) AC_SUBST(DYNLINK_MOD_CFLAGS) dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h langinfo.h termio.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_SIGNAL AC_DECL_SYS_SIGLIST GNUPG_CHECK_ENDIAN GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) AC_CHECK_SIZEOF(unsigned short, 2) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(unsigned long long, 0) if test "$ac_cv_sizeof_unsigned_short" = "0" \ || test "$ac_cv_sizeof_unsigned_int" = "0" \ || test "$ac_cv_sizeof_unsigned_long" = "0"; then AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); fi dnl Checks for library functions. AC_FUNC_VPRINTF AC_CHECK_FUNCS(strerror stpcpy strlwr stricmp tcgetattr rand strtoul mmap) AC_CHECK_FUNCS(memmove gettimeofday getrusage gethrtime setrlimit clock_gettime) AC_CHECK_FUNCS(memicmp atexit raise getpagesize strftime nl_langinfo) AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask fopen64 fstat64) GNUPG_CHECK_MLOCK GNUPG_FUNC_MKDIR_TAKES_ONE_ARG dnl dnl Check whether we can use Linux capabilities as requested dnl if test "$use_capabilities" = "yes" ; then use_capabilities=no AC_CHECK_HEADERS(sys/capability.h) if test "$ac_cv_header_sys_capability_h" = "yes" ; then AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1) if test "$ac_cv_lib_cap_cap_init" = "yes"; then AC_DEFINE(USE_CAPABILITIES) LIBS="$LIBS -lcap" use_capabilities=yes fi fi if test "$use_capabilities" = "no" ; then AC_MSG_WARN([[ *** *** The use of capabilities on this system is not possible. *** You need a recent Linux kernel and some patches: *** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9) *** fcap-module-990613.tar.gz (kernel module) *** libcap-1.92.tar.gz (user mode library and utilities) *** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN *** set (filesystems menu). Be warned: This code is *really* ALPHA. ***]]) fi fi GNUPG_CHECK_IPC if test "$ac_cv_header_sys_shm_h" = "yes"; then AC_DEFINE(USE_SHM_COPROCESSING) fi dnl dnl check whether we have a random device dnl if test "$try_dev_random" = yes ; then AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, [if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) if test "$ac_cv_have_dev_random" = yes; then AC_DEFINE(HAVE_DEV_RANDOM) fi else AC_MSG_CHECKING(for random device) ac_cv_have_dev_random=no AC_MSG_RESULT(has been disabled) fi dnl dnl and whether this device supports ioctl dnl (Note, that we should do a real test here) dnl if test "$ac_cv_have_dev_random" = yes ; then AC_CHECK_HEADERS(linux/random.h) AC_CACHE_CHECK(for random device ioctl, ac_cv_have_dev_random_ioctl, [ if test "$ac_cv_header_linux_random_h" = yes ; then ac_cv_have_dev_random_ioctl=yes; else ac_cv_have_dev_random_ioctl=no; fi ]) if test "$ac_cv_have_dev_random_ioctl" = yes; then AC_DEFINE(HAVE_DEV_RANDOM_IOCTL) fi fi dnl dnl Figure out the default linkage mode for cipher modules dnl print_egd_notice=no if test "$use_static_rnd" = default; then if test "$ac_cv_have_dev_random" = yes; then static_random_module="rndlinux" else case "${target}" in *-*-mingw32*) static_random_module="rndw32" AC_DEFINE(USE_STATIC_RNDW32) ;; i?86-emx-os2|i?86-*-os2*emx) static_random_module="rndos2" ;; m68k-atari-mint) static_random_module="rndatari" ;; i?86-*-msdosdjgpp*) : ;; *) static_random_module="rndunix" print_egd_notice=yes ;; esac fi else if test "$use_static_rnd" = none; then : else static_random_module="rnd$use_static_rnd" if test "$use_static_rnd" = "unix"; then print_egd_notice=yes fi fi fi if test "$print_egd_notice" = "yes"; then AC_MSG_WARN([[ *** *** The performance of the UNIX random gatherer module is not very good *** and it does not keep the entropy pool over multiple invocations of *** GnuPG. The suggested way to overcome this problem is to use the *** *** Entropy Gathering Daemon (EGD) *** *** which provides a entropy source for the whole system. It is written *** in Perl and available at the GnuPG FTP servers. For more information *** consult the GnuPG webpages: *** *** http://www.gnupg.org/download.html#egd *** *** You may want to run ./configure with --enable-static-rnd=none to be *** able to load the EGD client code dynamically; this way you can choose *** between RNDUNIX and RNDEGD without recompilation. ***]]) fi dnl dnl Parse the modules list and build the list dnl of static and dymically linked modules dnl dnl (We always need a static rmd160) static_modules="$static_modules rmd160 $static_random_module" STATIC_CIPHER_NAMES="" STATIC_CIPHER_OBJS="" DYNAMIC_CIPHER_MODS="" GNUPG_MSG_PRINT([dynamically linked cipher modules:]) for name in $MODULES_IN_CIPHER; do x="yes" for i in $disallowed_modules; do if test "$name" = "$i" ; then x="no" ; fi done; if test $x = yes; then x="no" for i in $static_modules; do if test "$name" = "$i" ; then x="yes" fi done; if test $x = yes; then STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name" STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.lo" else DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name" GNUPG_MSG_PRINT([$name]) fi fi done AC_MSG_RESULT() AC_SUBST(STATIC_CIPHER_OBJS) AC_SUBST(STATIC_CIPHER_NAMES) AC_SUBST(DYNAMIC_CIPHER_MODS) dnl dnl And build the constructor file dnl test -d cipher || mkdir cipher cat <cipher/construct.c /* automatically generated by configure - do not edit */ G10EOF GNUPG_MSG_PRINT([statically linked cipher modules:]) for name in $STATIC_CIPHER_NAMES; do echo "void _gcry_${name}_constructor(void);" >>cipher/construct.c GNUPG_MSG_PRINT([$name]) done AC_MSG_RESULT() cat <>cipher/construct.c void _gcry_cipher_modules_constructor(void) { static int done = 0; if( done ) return; done = 1; G10EOF for name in $STATIC_CIPHER_NAMES; do echo " _gcry_${name}_constructor();" >>cipher/construct.c done echo '}' >>cipher/construct.c dnl dnl Figure how to link the cipher modules dnl AC_SUBST(STATIC_CIPHER_OBJS) AC_SUBST(DYNAMIC_CIPHER_MODS) dnl setup assembler stuff AC_MSG_CHECKING(for mpi assembler functions) if test -f $srcdir/mpi/config.links ; then . $srcdir/mpi/config.links GNUPG_LINK_FILES($mpi_ln_src, $mpi_ln_dst) ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" ac_cv_mpi_sflags="$mpi_sflags" ac_cv_mpi_config_done="yes" AC_MSG_RESULT(done) else AC_MSG_RESULT(failed) AC_MSG_ERROR([mpi/config.links missing!]) fi MPI_EXTRA_ASM_OBJS="" if test "$ac_cv_mpi_extra_asm_modules" != ""; then GNUPG_MSG_PRINT([mpi extra asm functions:]) for i in $ac_cv_mpi_extra_asm_modules; do GNUPG_MSG_PRINT([$i]) MPI_EXTRA_ASM_OBJS="$MPI_EXTRA_ASM_OBJS $i.lo" done AC_MSG_RESULT() fi AC_SUBST(MPI_EXTRA_ASM_OBJS) MPI_SFLAGS="$ac_cv_mpi_sflags" AC_SUBST(MPI_SFLAGS) # Allow users to append something to the version string without # flagging it as development version. The user version part is # considered everything after a dash. changequote(,)dnl tmp_pat='[a-zA-Z]' changequote([,])dnl if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then AC_DEFINE(IS_DEVELOPMENT_VERSION) fi AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) GNUPG_DO_LINK_FILES GNUPG_CHECK_GNUMAKE if test "$GCC" = yes; then if test "$MAINTAINER_MODE" = "yes"; then CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" else CFLAGS="$CFLAGS -Wall" fi fi dnl dnl Make the version number in src/gcrypt.h the same as the one here. dnl (this is easier than to have a *.in file just for one substitution) dnl GNUPG_FIX_HDR_VERSION(src/gcrypt.h, GCRYPT_VERSION) LIBGCRYPT_LIBS="-L${libdir} -lgcrypt" LIBGCRYPT_CFLAGS="" AC_SUBST(LIBGCRYPT_LIBS) AC_SUBST(LIBGCRYPT_CFLAGS) AC_OUTPUT_COMMANDS([ chmod +x scripts/db2any chmod +x src/libgcrypt-config cat >gcrypt-defs.tmp </dev/null; then echo "gcrypt-defs.h is unchanged" rm -f gcrypt-defs.tmp else rm -f gcrypt-defs.h mv gcrypt-defs.tmp gcrypt-defs.h echo "gcrypt-defs.h created" fi ],[ prefix=$prefix exec_prefix=$exec_prefix libdir=$libdir datadir=$datadir DATADIRNAME=$DATADIRNAME ]) AC_OUTPUT([ Makefile jnlib/Makefile mpi/Makefile cipher/Makefile doc/Makefile doc/version.sgml src/Makefile src/libgcrypt-config +tests/Makefile ]) diff --git a/libgcrypt.txt b/libgcrypt.txt new file mode 100644 index 00000000..1367761b --- /dev/null +++ b/libgcrypt.txt @@ -0,0 +1,93 @@ +%%comments: +Copyright (C) 2001 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the file COPYING. + +%%name: Libgcrypt + +%%short-description: Cryptographic library + +%%full-description: This is a general purpose cryptographic library +based on the code from GnuPG. It provides functions for all +cryptograhic building blocks: symmetric ciphers +(AES,DES,Blowfish,CAST5,Twofish,Arcfour), hash algorithms (MD5, +RIPE-MD160, SHA-1, TIGER-192), MACs (HMAC for all hash algorithms), +public key algorithms (RSA, ElGamal, DSA), large integer functions, +random numbers and a lot of supporting functions. + +%%category: security, libraries + +%%license: GPL +%%license verified by: +%%license verified on: + +%%maintainer: g10 Code GmbH + +%%updated: 2001-06-01 + +%%keywords: encryption, public key, digital signature, hash + +%%interface: + +%%programs: + +%%GNU: (I am not sure - it is a spring-off from GnuPG) + +%%web-page: http://www.gnupg.org + +%%support: paid extension/consulting from http://www.g10code.com + +%%doc: English programmer reference in Texinfo, Postscript, HTML included + +%%developers: Matthew Skala, Michael Roth, Niklas Hernaeus, Remi +Guyomarch, Werner Koch . + +%%contributors: + +%%sponsors: + +%%source: ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/ + +%%debian: + +%%redhat: + +%%repository: See http://www.gnupg.org/cvs-access.html + +%%related: + +%%source-language: C + +%%supported-languages: C, C++ + +%%use-requirements: + +%%build-prerequisites: + +%%weak-prerequisites: + +%%source-prerequisites: + +%%version: 1.1.3 alpha released on 2001-05-31 + +%%announce-list: announce@gnupg.org announce-request@gnupg.org + +%%announce-news: + +%%help-list: + +%%help-news: + +%%dev-list: gcrypt-devel@gnupg.org gcrypt-devel-request@gnupg.org + +%%dev-news: + +%%bug-list: + +%%bug-database: + +%%entry written by: Werner Koch \ No newline at end of file diff --git a/src/ChangeLog b/src/ChangeLog index 2ba366d9..fbc03f4b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,176 +1,184 @@ +2001-08-03 Werner Koch + + * global.c (gcry_strerror): Updated list of error codes. + +2001-07-23 Werner Koch + + * gcrypt.h: Replaced the last ulong. Noted by Rami Lehti. + 2001-05-31 Werner Koch * gcrypt.h, mpi.h: Made some mpi functions public. * wrapper.c: Removed. * global.c: Renamed all g10_ prefixed functions which had wrappers to gcry_xxx. So we now use the exported memory functions inernally. Renamed all g10_ prefixed functions to _gcry_ prefixed ones. * g10lib.h (_GCRYPT_IN_LIBGCRYPT): Replace defintion by a test on it. 2001-05-28 Werner Koch * libgcrypt.m4: Check GCRYPT_VERSION macro and not LIBGCRYPT_VERSION. * mpi.h: Removed mpi_fromstr prototype. 2001-01-11 Werner Koch * Makefile.am (libgcrypt_la_SOURCES): Add mpi.h 2000-12-19 Werner Koch * types.h: Moved from ../include to here. Major change: Removed all GnuPG stuff and renamed this piece of software to gcrypt. 2000-11-14 Werner Koch * mpi.h: Moved to ../mpi. * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency problems. 2000-10-11 Werner Koch * mpi.h: Changed the way mpi_limb_t is defined. 2000-10-10 Werner Koch * Makefile.am: Take version-info from configure. 2000-10-09 Werner Koch * gcrypt.h: New cipher mode, new algo Arcfour and new error code GCRYERR_INV_CIPHER_MODE. * global.c (gcry_strerror): New errorcode. Wed Oct 4 13:16:18 CEST 2000 Werner Koch * gcrypt.h (gcry_md_setkey): Replaced macro by function prototype. Mon Sep 18 16:35:45 CEST 2000 Werner Koch * gcrypt.h (GCRYCTL_GET_ALGO_USAGE): New. * secmem.c (secmem_realloc): check for failed secmem_malloc. By Matt Kraai. Mon Jul 31 10:04:47 CEST 2000 Werner Koch * sexp.c: Removed the datalen fields from list tags. (gcry_sexp_car_data,gcry_sexp_cdr_data,gcry_sexp_car_mpi, gcry_sexp_cdr_mpi): Removed. (gcry_sexp_nth,gcry_sexp_nth_data,gcry_sexp_nth_mpi): New. Fri Jul 28 18:19:11 CEST 2000 Werner Koch * sexp.c (sexp_sscan): Fixed reallocation to secure memory. (new_empty_list): Removed (gcry_sexp_length): New. (gcry_sexp_enum): Removed. (normalize): New. Reworked the whole thing to use NULL for an empty list. (make_space): New instead of the macro. Tue Jul 25 17:44:15 CEST 2000 Werner Koch * sexp.c: Major rewrite. (gcry_sexp_sscan): Reordered arguments. Moved functionality to .. (sexp_sscan): .. this. (gcry_sexp_build): New. (gcry_sexp_new_name_mpi, gcry_sexp_new_name_data, gcry_sexp_new_data, gcry_sexp_new_mpi): Removed. Fri Jul 14 19:38:23 CEST 2000 Werner Koch * gcrypt.h (gcry_md_start_debug, gcry_md_stop_debug): New. (gcry_ctl_cmds): New control values * sexp.c (gcry_sexp_sscan): Add hex format parsing. * secmem.c (lock_pool): Check for ENOSYS return my mlock() on old SCOs. (pool_is_mmapped): Made volatile. (lock_pool): No more warning for QNX. By Sam Roberts. (lock_pool,secmem_init): Additional check for dropped privs. 2000-03-21 09:18:48 Werner Koch (wk@habibti.gnupg.de) * gcrypt.h (gcry_md_setkey): New. (GCRY_MD_FLAG_HMAC): New. Mon Jan 31 16:37:34 CET 2000 Werner Koch * Makefile.am: Add g10lib.h Thu Jan 27 18:00:44 CET 2000 Werner Koch * sexp.c (gcry_sexp_sscan): Allow NULL for erroff. Mon Jan 24 22:24:38 CET 2000 Werner Koch * sexp.c (gcry_sexp_alist): New. Mon Jan 24 13:04:28 CET 2000 Werner Koch * secmem.c: Moved from ../util to here. * secmem.h: New. * stdmem.c: New. Based on the old ../util/memory.c. * stdmem.h: New. Wed Dec 8 21:58:32 CET 1999 Werner Koch * gcrypt.m4: New. * gcrypt-config: New. * mpi.h (mpi_get_nbit_info): Removed (mpi_set_nbit_info): Removed. (struct gcry_mpi): Removed the nbits field. * misc.c (g10_log_verbosity): New. * global.c (g10_xstrdup): New. * mpiapi.c: Removed. * mpi.h: Moved from ../include to here. Removed some obsolete prototypes and the iobuf.h header. * cipher.h: Moved from ../include to here. Removed the mpi.h header. * g10lib.h: Moved from ../include to here. Fri Nov 19 17:15:20 CET 1999 Werner Koch * sexp.c (dump_string): New. Taken from gnupg/util/miscutil.c. (do_dump_list): s/print_string/dump_string/. * testapi.c: New. * mpiapi.c (gcry_mpi_randomize): Use new random API. Sat Nov 13 17:44:23 CET 1999 Werner Koch * gloabl.c (gcry_control): Add cases for dumping random and secmem stats. Tue Oct 26 14:10:21 CEST 1999 Werner Koch * pkapi.c: Removed. * symapi.c: Removed. * g10lib.h: Moved to ../include. * mdapi.c: Removed. Wed Jul 7 13:08:40 CEST 1999 Werner Koch * sexp.c: New. Tue Dec 8 13:15:16 CET 1998 Werner Koch * gcrypt.h: New * mpiapi.c: New diff --git a/src/gcrypt.h b/src/gcrypt.h index 63f121d3..b13e3875 100644 --- a/src/gcrypt.h +++ b/src/gcrypt.h @@ -1,534 +1,534 @@ /* gcrypt.h - GNU digital encryption library interface - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef _GCRYPT_H #define _GCRYPT_H #include #ifdef __cplusplus extern "C" { #endif /* * The version of this header should match the one of the library * It should not be used by a program because gcry_check_version() * should reurn the same version. The purpose of this macro is to * let autoconf (using the AM_PATH_GCRYPT macro) check that this * header matches the installed library. * Note: Do not edit the next line as configure may fix the string here. */ #define GCRYPT_VERSION "1.1.3" #ifndef HAVE_BYTE_TYPEDEF # undef byte /* maybe there is a macro with this name */ typedef unsigned char byte; # define HAVE_BYTE_TYPEDEF #endif #ifdef _GCRYPT_IN_LIBGCRYPT # ifndef GCRYPT_NO_MPI_MACROS # define GCRYPT_NO_MPI_MACROS 1 # endif #endif struct gcry_mpi; typedef struct gcry_mpi *GCRY_MPI; /******************************************* * * * error handling etc. * * * *******************************************/ /* FIXME: We should use the same values as they were used in GnuPG 1.0. * gpg --status-fd may print some of these values */ enum { GCRYERR_SUCCESS = 0, /* "no error" */ GCRYERR_GENERAL = 1, /* catch all the other errors code */ GCRYERR_INV_PK_ALGO = 4, /* invalid public key algorithm */ GCRYERR_INV_MD_ALGO = 5, /* invalid message digest algorithm */ GCRYERR_BAD_PUBLIC_KEY = 6, /* Bad public key */ GCRYERR_BAD_SECRET_KEY = 7, /* Bad secret key */ GCRYERR_BAD_SIGNATURE = 8, /* Bad signature */ GCRYERR_INV_CIPHER_ALGO = 12, /* invalid cipher algorithm */ GCRYERR_BAD_MPI = 30, GCRYERR_WRONG_PK_ALGO = 41, /* wrong public key algorithm */ GCRYERR_WEAK_KEY = 43, /* weak encryption key */ GCRYERR_INV_KEYLEN = 44, /* invalid length of a key*/ GCRYERR_INV_ARG = 45, /* invalid argument */ GCRYERR_SELFTEST = 50, /* selftest failed */ /* error codes not used in GnuPG 1.0 */ GCRYERR_INV_OP = 61, /* invalid operation code or ctl command */ GCRYERR_NO_MEM = 62, /* out of core */ GCRYERR_INTERNAL = 63, /* internal error */ GCRYERR_EOF = 64, /* (-1) is remapped to this value */ GCRYERR_INV_OBJ = 65, /* an object is not valid */ GCRYERR_TOO_SHORT = 66, /* provided buffer too short */ GCRYERR_TOO_LARGE = 67, /* object is too large */ GCRYERR_NO_OBJ = 68, /* Missing item in an object */ GCRYERR_NOT_IMPL = 69, /* Not implemented */ GCRYERR_CONFLICT = 70, GCRYERR_INV_CIPHER_MODE = 71, }; const char *gcry_check_version( const char *req_version ); int gcry_errno(void); const char *gcry_strerror( int ec ); enum gcry_ctl_cmds { GCRYCTL_SET_KEY = 1, GCRYCTL_SET_IV = 2, GCRYCTL_CFB_SYNC = 3, GCRYCTL_RESET = 4, /* e.g. for MDs */ GCRYCTL_FINALIZE = 5, GCRYCTL_GET_KEYLEN = 6, GCRYCTL_GET_BLKLEN = 7, GCRYCTL_TEST_ALGO = 8, GCRYCTL_IS_SECURE = 9, GCRYCTL_GET_ASNOID = 10, GCRYCTL_ENABLE_ALGO = 11, GCRYCTL_DISABLE_ALGO = 12, GCRYCTL_DUMP_RANDOM_STATS = 13, GCRYCTL_DUMP_SECMEM_STATS = 14, GCRYCTL_GET_ALGO_NPKEY = 15, GCRYCTL_GET_ALGO_NSKEY = 16, GCRYCTL_GET_ALGO_NSIGN = 17, GCRYCTL_GET_ALGO_NENCR = 18, GCRYCTL_SET_VERBOSITY = 19, GCRYCTL_SET_DEBUG_FLAGS = 20, GCRYCTL_CLEAR_DEBUG_FLAGS = 21, GCRYCTL_USE_SECURE_RNDPOOL= 22, GCRYCTL_DUMP_MEMORY_STATS = 23, GCRYCTL_INIT_SECMEM = 24, GCRYCTL_TERM_SECMEM = 25, GCRYCTL_DISABLE_SECMEM_WARN = 27, GCRYCTL_SUSPEND_SECMEM_WARN = 28, GCRYCTL_RESUME_SECMEM_WARN = 29, GCRYCTL_DROP_PRIVS = 30, GCRYCTL_ENABLE_M_GUARD = 31, GCRYCTL_START_DUMP = 32, GCRYCTL_STOP_DUMP = 33, GCRYCTL_GET_ALGO_USAGE = 34 }; int gcry_control( enum gcry_ctl_cmds, ... ); enum gcry_random_level { GCRY_WEAK_RANDOM = 0, GCRY_STRONG_RANDOM = 1, GCRY_VERY_STRONG_RANDOM = 2 }; struct gcry_sexp; typedef struct gcry_sexp *GCRY_SEXP; enum gcry_sexp_format { GCRYSEXP_FMT_DEFAULT = 0, GCRYSEXP_FMT_CANON = 1, GCRYSEXP_FMT_BASE64 = 2, GCRYSEXP_FMT_ADVANCED = 3, }; void gcry_sexp_release( GCRY_SEXP sexp ); void gcry_sexp_dump( const GCRY_SEXP a ); GCRY_SEXP gcry_sexp_cons( const GCRY_SEXP a, const GCRY_SEXP b ); GCRY_SEXP gcry_sexp_alist( const GCRY_SEXP *array ); GCRY_SEXP gcry_sexp_vlist( const GCRY_SEXP a, ... ); GCRY_SEXP gcry_sexp_append( const GCRY_SEXP a, const GCRY_SEXP n ); GCRY_SEXP gcry_sexp_prepend( const GCRY_SEXP a, const GCRY_SEXP n ); int gcry_sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff, const char *buffer, size_t length ); int gcry_sexp_build( GCRY_SEXP *retsexp, size_t *erroff, const char *format, ... ); size_t gcry_sexp_sprint( GCRY_SEXP sexp, int mode, char *buffer, size_t maxlength ); GCRY_SEXP gcry_sexp_find_token( GCRY_SEXP list, const char *tok, size_t toklen ); int gcry_sexp_length( const GCRY_SEXP list ); GCRY_SEXP gcry_sexp_nth( const GCRY_SEXP list, int number ); GCRY_SEXP gcry_sexp_car( const GCRY_SEXP list ); GCRY_SEXP gcry_sexp_cdr( const GCRY_SEXP list ); GCRY_SEXP gcry_sexp_cadr( const GCRY_SEXP list ); const char *gcry_sexp_nth_data( const GCRY_SEXP list, int number, size_t *datalen ); GCRY_MPI gcry_sexp_nth_mpi( GCRY_SEXP list, int number, int mpifmt ); /******************************************* * * * multi precision integer functions * * * *******************************************/ enum gcry_mpi_format { GCRYMPI_FMT_NONE= 0, GCRYMPI_FMT_STD = 1, /* twos complement stored without length */ GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP */ GCRYMPI_FMT_SSH = 3, /* As used by SSH (same as 1 but with length)*/ GCRYMPI_FMT_HEX = 4, /* hex format */ GCRYMPI_FMT_USG = 5, /* like STD but this is an unsigned one */ }; enum gcry_mpi_flag { GCRYMPI_FLAG_SECURE = 1, GCRYMPI_FLAG_OPAQUE = 2, }; GCRY_MPI gcry_mpi_new( unsigned int nbits ); GCRY_MPI gcry_mpi_snew( unsigned int nbits ); void gcry_mpi_release( GCRY_MPI a ); GCRY_MPI gcry_mpi_copy( const GCRY_MPI a ); GCRY_MPI gcry_mpi_set( GCRY_MPI w, const GCRY_MPI u ); GCRY_MPI gcry_mpi_set_ui( GCRY_MPI w, unsigned long u ); int gcry_mpi_cmp( const GCRY_MPI u, const GCRY_MPI v ); int gcry_mpi_cmp_ui( const GCRY_MPI u, unsigned long v ); void gcry_mpi_randomize( GCRY_MPI w, unsigned int nbits, enum gcry_random_level level); int gcry_mpi_scan( GCRY_MPI *ret_mpi, enum gcry_mpi_format format, const char *buffer, size_t *nbytes ); int gcry_mpi_print( enum gcry_mpi_format format, char *buffer, size_t *nbytes, const GCRY_MPI a ); int gcry_mpi_aprint( enum gcry_mpi_format format, void **buffer, size_t *nbytes, const GCRY_MPI a ); void gcry_mpi_add(GCRY_MPI w, GCRY_MPI u, GCRY_MPI v); void gcry_mpi_add_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v ); void gcry_mpi_addm(GCRY_MPI w, GCRY_MPI u, GCRY_MPI v, GCRY_MPI m); void gcry_mpi_sub( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v); -void gcry_mpi_sub_ui(GCRY_MPI w, GCRY_MPI u, ulong v ); +void gcry_mpi_sub_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v ); void gcry_mpi_subm( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v, GCRY_MPI m); void gcry_mpi_mul_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v ); void gcry_mpi_mul_2exp( GCRY_MPI w, GCRY_MPI u, unsigned long cnt); void gcry_mpi_mul( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v); void gcry_mpi_mulm( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v, GCRY_MPI m); void gcry_mpi_powm( GCRY_MPI w, const GCRY_MPI b, const GCRY_MPI e, const GCRY_MPI m ); int gcry_mpi_gcd( GCRY_MPI g, GCRY_MPI a, GCRY_MPI b ); unsigned int gcry_mpi_get_nbits( GCRY_MPI a ); int gcry_mpi_test_bit( GCRY_MPI a, unsigned int n ); void gcry_mpi_set_bit( GCRY_MPI a, unsigned int n ); void gcry_mpi_clear_bit( GCRY_MPI a, unsigned int n ); void gcry_mpi_set_highbit( GCRY_MPI a, unsigned int n ); void gcry_mpi_clear_highbit( GCRY_MPI a, unsigned int n ); void gcry_mpi_rshift( GCRY_MPI x, GCRY_MPI a, unsigned int n ); GCRY_MPI gcry_mpi_set_opaque( GCRY_MPI a, void *p, unsigned int nbits ); void * gcry_mpi_get_opaque( GCRY_MPI a, unsigned int *nbits ); void gcry_mpi_set_flag( GCRY_MPI a, enum gcry_mpi_flag flag ); void gcry_mpi_clear_flag( GCRY_MPI a, enum gcry_mpi_flag flag ); int gcry_mpi_get_flag( GCRY_MPI a, enum gcry_mpi_flag flag ); #ifndef GCRYPT_NO_MPI_MACROS #define mpi_new(n) gcry_mpi_new( (n) ) #define mpi_secure_new( n ) gcry_mpi_snew( (n) ) #define mpi_release( a ) do { gcry_mpi_release( (a) ); \ (a) = NULL; } while(0) #define mpi_copy( a ) gcry_mpi_copy( (a) ) #define mpi_set( w, u) gcry_mpi_set( (w), (u) ) #define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) ) #define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) ) #define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) ) #define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) #define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) #define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m)) #define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v)) #define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v)) #define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m)) #define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v)) #define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v)) #define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v)) #define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m)) #define mpi_powm(w,b,e,m) gcry_mpi_powm( (w), (b), (e), (m) ) #define mpi_gcd(g,a,b) gcry_mpi_gcd( (g), (a), (b) ) #define mpi_get_nbits(a) gcry_mpi_get_nbits ((a)) #define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b)) #define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b)) #define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b)) #define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b)) #define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b)) #define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c)) #define mpi_set_opaque(a,b,c) gcry_mpi_set_opaque( (a), (b), (c) ) #define mpi_get_opaque(a,b) gcry_mpi_get_opaque( (a), (b) ) #endif /* GCRYPT_NO_MPI_MACROS */ /******************************************** ******* symmetric cipher functions ******* ********************************************/ struct gcry_cipher_handle; typedef struct gcry_cipher_handle *GCRY_CIPHER_HD; enum gcry_cipher_algos { GCRY_CIPHER_NONE = 0, GCRY_CIPHER_IDEA = 1, GCRY_CIPHER_3DES = 2, GCRY_CIPHER_CAST5 = 3, GCRY_CIPHER_BLOWFISH = 4, GCRY_CIPHER_SAFER_SK128 = 5, GCRY_CIPHER_DES_SK = 6, GCRY_CIPHER_RIJNDAEL = 7, GCRY_CIPHER_RIJNDAEL192 = 8, GCRY_CIPHER_RIJNDAEL256 = 9, GCRY_CIPHER_TWOFISH = 10, /* other cipher numbers are above 300 for OpenPGP reasons. */ GCRY_CIPHER_ARCFOUR = 301 }; #define GCRY_CIPHER_AES GCRY_CIPHER_RIJNDAEL #define GCRY_CIPHER_AES128 GCRY_CIPHER_RIJNDAEL128 #define GCRY_CIPHER_AES192 GCRY_CIPHER_RIJNDAEL192 #define GCRY_CIPHER_AES256 GCRY_CIPHER_RIJNDAEL256 enum gcry_cipher_modes { GCRY_CIPHER_MODE_NONE = 0, GCRY_CIPHER_MODE_ECB = 1, GCRY_CIPHER_MODE_CFB = 2, GCRY_CIPHER_MODE_CBC = 3, GCRY_CIPHER_MODE_STREAM = 4 /* native stream mode of some the algorithms */ }; enum gcry_cipher_flags { GCRY_CIPHER_SECURE = 1, /* allocate in secure memory */ GCRY_CIPHER_ENABLE_SYNC = 2, /* enable CFB sync mode */ }; GCRY_CIPHER_HD gcry_cipher_open( int algo, int mode, unsigned flags); void gcry_cipher_close( GCRY_CIPHER_HD h ); int gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen); int gcry_cipher_info( GCRY_CIPHER_HD h, int what, void *buffer, size_t *nbytes); int gcry_cipher_algo_info( int algo, int what, void *buffer, size_t *nbytes); const char *gcry_cipher_algo_name( int algo ); int gcry_cipher_map_name( const char* name ); int gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, const byte *in, size_t inlen ); int gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize, const byte *in, size_t inlen ); /* some handy macros */ /* We have to cast a way a const char* here - this catch-all ctl function * was probably not the best choice */ #define gcry_cipher_setkey(h,k,l) gcry_cipher_ctl( (h), GCRYCTL_SET_KEY, \ (char*)(k), (l) ) #define gcry_cipher_setiv(h,k,l) gcry_cipher_ctl( (h), GCRYCTL_SET_IV, \ (char*)(k), (l) ) #define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, \ NULL, 0 ) #define gcry_cipher_get_algo_keylen(a) \ gcry_cipher_algo_info( (a), GCRYCTL_GET_KEYLEN, NULL, NULL ) #define gcry_cipher_get_algo_blklen(a) \ gcry_cipher_algo_info( (a), GCRYCTL_GET_BLKLEN, NULL, NULL ) #define gcry_cipher_test_algo(a) \ gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) /********************************************* ******* asymmetric cipher functions ******* *********************************************/ enum gcry_pk_algos { GCRY_PK_RSA = 1, GCRY_PK_RSA_E = 2, /* use only for OpenPGP */ GCRY_PK_RSA_S = 3, /* use only for OpenPGP */ GCRY_PK_ELG_E = 16, /* use only for OpenPGP */ GCRY_PK_DSA = 17, GCRY_PK_ELG = 20, }; /* Flags describing usage capabilites/request of a PK algorithm */ #define GCRY_PK_USAGE_SIGN 1 #define GCRY_PK_USAGE_ENCR 2 int gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey ); int gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey ); int gcry_pk_sign( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey ); int gcry_pk_verify( GCRY_SEXP sigval, GCRY_SEXP data, GCRY_SEXP pkey ); int gcry_pk_testkey( GCRY_SEXP key ); int gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms ); int gcry_pk_ctl( int cmd, void *buffer, size_t buflen); int gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes); const char *gcry_pk_algo_name( int algo ); int gcry_pk_map_name( const char* name ); unsigned int gcry_pk_get_nbits( GCRY_SEXP key ); #define gcry_pk_test_algo(a) \ gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) /********************************************* ******* cryptograhic hash functions ******* *********************************************/ enum gcry_md_algos { GCRY_MD_NONE = 0, GCRY_MD_MD5 = 1, GCRY_MD_SHA1 = 2, GCRY_MD_RMD160 = 3, GCRY_MD_TIGER = 6 }; enum gcry_md_flags { GCRY_MD_FLAG_SECURE = 1, GCRY_MD_FLAG_HMAC = 2 }; struct gcry_md_context; struct gcry_md_handle { struct gcry_md_context *ctx; int bufpos; int bufsize; byte buf[1]; }; typedef struct gcry_md_handle *GCRY_MD_HD; GCRY_MD_HD gcry_md_open( int algo, unsigned flags ); void gcry_md_close( GCRY_MD_HD hd ); int gcry_md_enable( GCRY_MD_HD hd, int algo ); GCRY_MD_HD gcry_md_copy( GCRY_MD_HD hd ); void gcry_md_reset( GCRY_MD_HD hd ); int gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen); void gcry_md_write( GCRY_MD_HD hd, const byte *buffer, size_t length); byte *gcry_md_read( GCRY_MD_HD hd, int algo ); void gcry_md_hash_buffer( int algo, char *digest, const char *buffer, size_t length); int gcry_md_get_algo( GCRY_MD_HD hd ); unsigned int gcry_md_get_algo_dlen( int algo ); /*??int gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen );*/ int gcry_md_info( GCRY_MD_HD h, int what, void *buffer, size_t *nbytes); int gcry_md_algo_info( int algo, int what, void *buffer, size_t *nbytes); const char *gcry_md_algo_name( int algo ); int gcry_md_map_name( const char* name ); int gcry_md_setkey( GCRY_MD_HD hd, const char *key, size_t keylen ); #define gcry_md_putc(h,c) \ do { \ if( (h)->bufpos == (h)->bufsize ) \ gcry_md_write( (h), NULL, 0 ); \ (h)->buf[(h)->bufpos++] = (c) & 0xff; \ } while(0) #define gcry_md_final(a) \ gcry_md_ctl( (a), GCRYCTL_FINALIZE, NULL, 0 ) #define gcry_md_is_secure(a) \ gcry_md_info( (a), GCRYCTL_IS_SECURE, NULL, NULL ) #define gcry_md_test_algo(a) \ gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) #define gcry_md_start_debug(a,b) \ gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 ) #define gcry_md_stop_debug(a,b) \ gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 ) /********************************************* ******* random generating functions ******* *********************************************/ void gcry_randomize( byte *buffer, size_t length, enum gcry_random_level level ); void *gcry_random_bytes( size_t nbytes, enum gcry_random_level level ); void *gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level ); /***************************************** ******* miscellaneous stuff ********** *****************************************/ enum gcry_log_levels { GCRY_LOG_CONT = 0, /* continue the last log line */ GCRY_LOG_INFO = 10, GCRY_LOG_WARN = 20, GCRY_LOG_ERROR = 30, GCRY_LOG_FATAL = 40, GCRY_LOG_BUG = 50, GCRY_LOG_DEBUG = 100, }; /* Provide custom functions for special tasks of libgcrypt. */ void gcry_set_allocation_handler( void *(*new_alloc_func)(size_t n), void *(*new_alloc_secure_func)(size_t n), int (*new_is_secure_func)(const void*), void *(*new_realloc_func)(void *p, size_t n), void (*new_free_func)(void*) ); void gcry_set_outofcore_handler( int (*h)( void*, size_t, unsigned int ), void *opaque ); void gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *opaque ); void gcry_set_gettext_handler( const char *(*f)(const char*) ); void gcry_set_log_handler( void (*f)(void*,int, const char*, va_list ), void *opaque ); /* Access to the memory function of libgcrypt. * Especially the gcry_free() should be used for memory * allocated by gcry_ functions. */ void *gcry_malloc( size_t n ); void *gcry_calloc( size_t n, size_t m ); void *gcry_malloc_secure( size_t n ); void *gcry_calloc_secure( size_t n, size_t m ); void *gcry_realloc( void *a, size_t n ); void *gcry_xmalloc( size_t n ); void *gcry_xcalloc( size_t n, size_t m ); void *gcry_xmalloc_secure( size_t n ); void *gcry_xcalloc_secure( size_t n, size_t m ); void *gcry_xrealloc( void *a, size_t n ); char *gcry_xstrdup( const char * a); void gcry_free( void *a ); int gcry_is_secure( const void *a ); #ifndef GCRYPT_NO_MPI_MACROS # ifndef DID_MPI_TYPEDEF typedef struct gcry_mpi *MPI; # define DID_MPI_TYPEDEF # endif #endif /* GCRYPT_NO_MPI_MACROS */ #ifdef __cplusplus } #endif #endif /* _GCRYPT_H */ diff --git a/src/global.c b/src/global.c index 8466dace..f78b6f78 100644 --- a/src/global.c +++ b/src/global.c @@ -1,444 +1,457 @@ /* global.c - global control functions * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include "g10lib.h" #include "../cipher/random.h" #include "stdmem.h" /* our own memory allocator */ #include "secmem.h" /* our own secmem allocator */ /**************** * flag bits: 0 : general cipher debug * 1 : general MPI debug */ static unsigned int debug_flags; static int last_ec; /* fixme: make thread safe */ static void *(*alloc_func)(size_t n) = NULL; static void *(*alloc_secure_func)(size_t n) = NULL; static int (*is_secure_func)(const void*) = NULL; static void *(*realloc_func)(void *p, size_t n) = NULL; static void (*free_func)(void*) = NULL; static int (*outofcore_handler)( void*, size_t, unsigned int ) = NULL; static void *outofcore_handler_value = NULL; static const char* parse_version_number( const char *s, int *number ) { int val = 0; if( *s == '0' && isdigit(s[1]) ) return NULL; /* leading zeros are not allowed */ for ( ; isdigit(*s); s++ ) { val *= 10; val += *s - '0'; } *number = val; return val < 0? NULL : s; } static const char * parse_version_string( const char *s, int *major, int *minor, int *micro ) { s = parse_version_number( s, major ); if( !s || *s != '.' ) return NULL; s++; s = parse_version_number( s, minor ); if( !s || *s != '.' ) return NULL; s++; s = parse_version_number( s, micro ); if( !s ) return NULL; return s; /* patchlevel */ } /**************** * Check that the the version of the library is at minimum the requested one * and return the version string; return NULL if the condition is not * satisfied. If a NULL is passed to this function, no check is done, * but the version string is simply returned. */ const char * gcry_check_version( const char *req_version ) { const char *ver = VERSION; int my_major, my_minor, my_micro; int rq_major, rq_minor, rq_micro; const char *my_plvl, *rq_plvl; if ( !req_version ) return ver; my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro ); if ( !my_plvl ) return NULL; /* very strange our own version is bogus */ rq_plvl = parse_version_string( req_version, &rq_major, &rq_minor, &rq_micro ); if ( !rq_plvl ) return NULL; /* req version string is invalid */ if ( my_major > rq_major || (my_major == rq_major && my_minor > rq_minor) || (my_major == rq_major && my_minor == rq_minor && my_micro > rq_micro) || (my_major == rq_major && my_minor == rq_minor && my_micro == rq_micro && strcmp( my_plvl, rq_plvl ) >= 0) ) { return ver; } return NULL; } int gcry_control( enum gcry_ctl_cmds cmd, ... ) { va_list arg_ptr ; va_start( arg_ptr, cmd ) ; switch( cmd ) { #if 0 case GCRYCTL_NO_MEM_IS_FATAL: break; case GCRYCTL_SET_FATAL_FNC: break; #endif case GCRYCTL_ENABLE_M_GUARD: _gcry_private_enable_m_guard(); break; case GCRYCTL_DUMP_RANDOM_STATS: _gcry_random_dump_stats(); break; case GCRYCTL_DUMP_MEMORY_STATS: /*m_print_stats("[fixme: prefix]");*/ break; case GCRYCTL_DUMP_SECMEM_STATS: _gcry_secmem_dump_stats(); break; case GCRYCTL_DROP_PRIVS: _gcry_secmem_init( 0 ); break; case GCRYCTL_INIT_SECMEM: _gcry_secmem_init( va_arg( arg_ptr, unsigned int ) ); break; case GCRYCTL_TERM_SECMEM: _gcry_secmem_term(); break; case GCRYCTL_DISABLE_SECMEM_WARN: _gcry_secmem_set_flags( (_gcry_secmem_get_flags() | 1) ); break; case GCRYCTL_SUSPEND_SECMEM_WARN: _gcry_secmem_set_flags( (_gcry_secmem_get_flags() | 2) ); break; case GCRYCTL_RESUME_SECMEM_WARN: _gcry_secmem_set_flags( (_gcry_secmem_get_flags() & ~2) ); break; case GCRYCTL_USE_SECURE_RNDPOOL: _gcry_secure_random_alloc(); /* put random number into secure memory */ break; case GCRYCTL_SET_VERBOSITY: _gcry_set_log_verbosity( va_arg( arg_ptr, int ) ); break; case GCRYCTL_SET_DEBUG_FLAGS: debug_flags |= va_arg( arg_ptr, unsigned int ); break; case GCRYCTL_CLEAR_DEBUG_FLAGS: debug_flags &= ~va_arg( arg_ptr, unsigned int ); break; default: va_end(arg_ptr); return GCRYERR_INV_OP; } va_end(arg_ptr); return 0; } int gcry_errno() { return last_ec; } const char* gcry_strerror( int ec ) { const char *s; static char buf[20]; if( ec == -1 ) ec = gcry_errno(); #define X(n,a) case GCRYERR_##n : s = a; break; switch( ec ) { - X(SUCCESS, N_("no error")) - X(GENERAL, N_("general error")) + X(SUCCESS, N_("no error")) + X(GENERAL, N_("general error")) + + X(INV_PK_ALGO, N_("invalid public key algorithm")) + X(INV_MD_ALGO, N_("invalid hash algorithm")) + X(BAD_PUBLIC_KEY ,N_("bad public key")) + X(BAD_SECRET_KEY ,N_("bad secret key")) + X(BAD_SIGNATURE , N_("bad signature")) + + X(INV_CIPHER_ALGO,N_("invalid cipher algorithm")) + X(BAD_MPI, N_("bad big integer")) + X(WRONG_PK_ALGO, N_("unusable public key algorithm")) + X(WEAK_KEY, N_("weak encryption key")) + X(INV_KEYLEN, N_("invalid key length")) + X(INV_ARG, N_("invalid argument")) + X(SELFTEST, N_("selftest failed")) + X(INV_OP, N_("invalid operation code or ctl command")) X(NO_MEM, N_("out of core")) - X(INV_ARG, N_("invalid argument")) X(INTERNAL, N_("internal error")) X(EOF, N_("EOF")) + X(INV_OBJ, N_("an object is not valid")) X(TOO_SHORT, N_("provided buffer too short")) X(TOO_LARGE, N_("object is too large")) - X(INV_OBJ, N_("an object is not valid")) - X(WEAK_KEY, N_("weak encryption key")) - X(INV_PK_ALGO, N_("invalid public key algorithm")) - X(INV_CIPHER_ALGO,N_("invalid cipher algorithm")) - X(INV_MD_ALGO, N_("invalid hash algorithm")) - X(WRONG_PK_ALGO, N_("unusable public key algorithm")) + X(NO_OBJ, N_("no object")) + X(NOT_IMPL, N_("not implemented")) X(CONFLICT, N_("conflict")) X(INV_CIPHER_MODE,N_("invalid cipher mode")) + + default: sprintf( buf, "ec=%d", ec ); s = buf; } #undef X return s; } int _gcry_set_lasterr( int ec ) { if( ec ) last_ec = ec == -1 ? GCRYERR_EOF : ec; return ec; } /**************** * NOTE: All 5 functions should be set. */ void gcry_set_allocation_handler( void *(*new_alloc_func)(size_t n), void *(*new_alloc_secure_func)(size_t n), int (*new_is_secure_func)(const void*), void *(*new_realloc_func)(void *p, size_t n), void (*new_free_func)(void*) ) { alloc_func = new_alloc_func; alloc_secure_func = new_alloc_secure_func; is_secure_func = new_is_secure_func; realloc_func = new_realloc_func; free_func = new_free_func; } /**************** * Set an optional handler which is called in case the xmalloc functions * ran out of memory. This handler may do one of these things: * o free some memory and return true, so that the xmalloc function * tries again. * o Do whatever it like and return false, so that the xmalloc functions * use the default fatal error handler. * o Terminate the program and don't return. * * The handler function is called with 3 arguments: The opaque value set with * this function, the requested memory size, and a flag with these bits * currently defined: * bit 0 set = secure memory has been requested. */ void gcry_set_outofcore_handler( int (*f)( void*, size_t, unsigned int ), void *value ) { outofcore_handler = f; outofcore_handler_value = value; } void * gcry_malloc( size_t n ) { if( alloc_func ) return alloc_func( n ) ; return _gcry_private_malloc( n ); } void * gcry_malloc_secure( size_t n ) { if( alloc_secure_func ) return alloc_secure_func( n ) ; return _gcry_private_malloc_secure( n ); } int gcry_is_secure( const void *a ) { if( is_secure_func ) return is_secure_func( a ) ; return _gcry_private_is_secure( a ); } void _gcry_check_heap( const void *a ) { /* FIXME: implement this*/ #if 0 if( some_handler ) some_handler(a) else _gcry_private_check_heap(a) #endif } void * gcry_realloc( void *a, size_t n ) { /* FIXME: Make sure that the realloced memory is cleared out */ if( realloc_func ) return realloc_func( a, n ) ; return _gcry_private_realloc( a, n ); } void gcry_free( void *p ) { if( !p ) return; if( free_func ) free_func( p ); else _gcry_private_free( p ); } void * gcry_calloc( size_t n, size_t m ) { void *p = gcry_malloc( n*m ); if( p ) memset( p, 0, n*m ); return p; } void * gcry_calloc_secure( size_t n, size_t m ) { void *p = gcry_malloc_secure( n*m ); if( p ) memset( p, 0, n*m ); return p; } void * gcry_xmalloc( size_t n ) { void *p; while ( !(p = gcry_malloc( n )) ) { if( !outofcore_handler || !outofcore_handler( outofcore_handler_value, n, 0 ) ) { _gcry_fatal_error(GCRYERR_NO_MEM, NULL ); } } return p; } void * gcry_xrealloc( void *a, size_t n ) { void *p; while ( !(p = gcry_realloc( a, n )) ) { if( !outofcore_handler || !outofcore_handler( outofcore_handler_value, n, 2 ) ) { _gcry_fatal_error(GCRYERR_NO_MEM, NULL ); } } return p; } void * gcry_xmalloc_secure( size_t n ) { void *p; while ( !(p = gcry_malloc_secure( n )) ) { if( !outofcore_handler || !outofcore_handler( outofcore_handler_value, n, 1 ) ) { _gcry_fatal_error(GCRYERR_NO_MEM, _("out of core in secure memory")); } } return p; } void * gcry_xcalloc( size_t n, size_t m ) { void *p = gcry_xmalloc( n*m ); memset( p, 0, n*m ); return p; } void * gcry_xcalloc_secure( size_t n, size_t m ) { void *p = gcry_xmalloc_secure( n* m ); memset( p, 0, n*m ); return p; } char * gcry_xstrdup( const char *string ) { void *p = gcry_xmalloc( strlen(string)+1 ); strcpy( p, string ); return p; } int _gcry_get_debug_flag( unsigned int mask ) { return debug_flags & mask; } diff --git a/tests/ChangeLog b/tests/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..9875feb9 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,38 @@ +# Copyright (C) 2001 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +## Process this file with automake to produce Makefile.in + + +# TESTS_ENVIRONMENT = + +TESTS = basic + +EXTRA_DIST = + +INCLUDES = +LDADD = ../src/libgcrypt.la + +noinst_PROGRAMS = $(TESTS) + + + + + + + diff --git a/tests/basic.c b/tests/basic.c new file mode 100644 index 00000000..c850ca69 --- /dev/null +++ b/tests/basic.c @@ -0,0 +1,166 @@ +/* basic.c - basic regression tests + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include "../src/gcrypt.h" + +static int error_count; + +static void +fail ( const char *format, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + error_count++; +} + +static void +die ( const char *format, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + exit (1); +} + + +static void +check_one_cipher (int algo, int mode) +{ + GCRY_CIPHER_HD hd; + char key[32], plain[16], in[16], out[16]; + int keylen; + + memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF", 32); + memcpy (plain, "foobar42FOOBAR17", 16); + + keylen = gcry_cipher_get_algo_keylen (algo); + if (keylen < 40/8 || keylen > 32 ) { + fail ("algo %d, mode %d, keylength problem (%d)\n", + algo, mode, keylen ); + return; + } + + hd = gcry_cipher_open (algo, mode, 0); + if (!hd) { + fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n", + algo, mode, gcry_strerror (-1) ); + return; + } + + + if (gcry_cipher_setkey (hd, key, keylen)) { + fail ("algo %d, mode %d, gcry_cipher_setkey failed: %s\n", + algo, mode, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + if ( gcry_cipher_encrypt (hd, out, 16, plain, 16)) { + fail ("algo %d, mode %d, gcry_cipher_encrypt failed: %s\n", + algo, mode, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + gcry_cipher_close (hd); + hd = gcry_cipher_open (algo, mode, 0); + if (!hd) { + fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n", + algo, mode, gcry_strerror (-1) ); + return; + } + + if (gcry_cipher_setkey (hd, key, keylen)) { + fail ("algo %d, mode %d, gcry_cipher_setkey[2] failed: %s\n", + algo, mode, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + if ( gcry_cipher_decrypt (hd, in, 16, out, 16)) { + fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n", + algo, mode, gcry_strerror (-1) ); + gcry_cipher_close (hd); + return; + } + + gcry_cipher_close (hd); + + if ( memcmp (plain, in, 16) ) + fail ("algo %d, mode %d, encrypt-decrypt mismatch\n", algo, mode); +} + + +static void +check_ciphers (void) +{ + static int algos[] = { + GCRY_CIPHER_3DES, + GCRY_CIPHER_CAST5, + GCRY_CIPHER_BLOWFISH, + GCRY_CIPHER_RIJNDAEL, + GCRY_CIPHER_RIJNDAEL192, + GCRY_CIPHER_RIJNDAEL256, + GCRY_CIPHER_TWOFISH, + 0 + }; + int i; + + for (i=0; algos[i]; i++ ) { + check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB); + check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC); + } + + check_one_cipher (GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM); + /* we have now run all cipher's selftests */ + /* TODO: add some extra encryption to test the higher level functions */ + +} + + +static void +check_digests () +{ + /* TODO */ +} + + +int +main (int argc, char **argv) +{ + if (!gcry_check_version (GCRYPT_VERSION)) + die ("Version mismatch\n"); + check_ciphers (); + check_digests (); + + return error_count? 1:0; +} + +