diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..224e7f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.pc/ diff --git a/README b/README new file mode 120000 index 0000000..4baf228 --- /dev/null +++ b/README @@ -0,0 +1 @@ +doc/README \ No newline at end of file diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..b5ba955 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,47 @@ +John the Ripper and word lists +------------------------------ +(or how to remove the false sense of security) + +The Debian version of John the Ripper can be configured to run as a +cron job, which will make it periodically check the passwords used +on the system in order to determine if they are really "secure" +(that is, not easy to guess or crack by brute force). + +Currently, john provides its own word list for password cracking, which +contains a lot of common passwords, as provided by john's author, and +can be found on /usr/share/john/password.lst. However, user passwords +strongly depend on the mother tongue and the cultural background, hence, +the default word list alone might not be ideal for every system. + +This is the reason why, in some cases, installing john and running it +often might give sense of security that is not necessarily true. While +you think it will be able to guess easy passwords, it is only able to +guess easy and common English passwords. + +If you think this is the case, there are a number of wordlists you can +use: provided by Debian or other sources (FTP servers related to security +often provide a directory with those). + +Some spell checkers in Debian provide the word lists used by them (26 at +the time of writing these lines). They may be useful to look for passwords +based on words, and are available for many foreign languages. You can see +the list of packages providing wordlists by running + +$ grep-available -e wordlist -n -F Provides -s package + +Notice that there are some other Debian packages (such as 'jargon') that +might provide word lists useful for password-checking purposes too. + +Some word lists suitable for password cracking can be found on, among +others: + ftp://ftp.zedz.net/pub/crypto/wordlists/ + ftp://ftp.cerias.purdue.edu/pub/dict/ + ftp://ftp.ox.ac.uk/pub/wordlists/ + +They are not simply dictionaries, but a compendium of common names, +heroes, popular teams, etc., which may provide even more useful input +for john. + +-- +The Debian Maintainers of john +Tue, 19 Jul 2005 14:15:15 -0300 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..829d66e --- /dev/null +++ b/debian/changelog @@ -0,0 +1,839 @@ +john (1.8.0-4) unstable; urgency=medium + + * Also unconditionally and always call "mkdir -p $RUNDIR" in cron + job. (Really closes: #640288) + + Make sure that /var/lib/john/ and /var/run/john/ are removed again + on purge if empty. + * Adopt package under the Debian Security Tools Team. (Closes: #981055). + + Set Debian Security Tools as + Maintainer. + + Set Julián Moreno Patiño and myself as Uploaders. + + Switch to DEP14-style branches and add a debian/gbp.conf. + + Update Vcs-* headers for moving to the pkg-security-team's repo. + + Create a debian/salsa-ci.yml file. + + -- Axel Beckert Fri, 05 Feb 2021 04:59:29 +0100 + +john (1.8.0-3) unstable; urgency=medium + + * QA upload of recently orphaned package. + * Set Maintainer to Debian QA Group , removing + the Uploaders field. (See #981055, closes: #979054) + * Add Vcs-* headers and let them point to Salsa. + * Run "wrap-and-sort -a". + * Remove trailing whitespace from ancient debian/changelog entries and + in debian/rules. Thanks Lintian! + * Use secure copyright file specification URI. + * Use secure URI in debian/watch. + * Bump debhelper from deprecated 9 to 13. + + Pass --no-parallel to dh as john otherwise FTBFS. + * Set debhelper-compat version in Build-Depends. + * Enable all hardening flags. + * Set "Rules-Requires-Root: no". + * Bump debian/watch version from 3 to 4. Thanks Lintian! + * Declare compliance with Debian Policy 4.5.1. + * Update debian/watch to prefer .xz instead of .gz. + * Replace the no more usable GPGv1 upstream signing key with a minified + version of the Openwall offline signing key from + https://www.openwall.com/signatures/openwall-offline-signatures.asc + * Unconditionally and always call "mkdir -p $PIDDIR" in cron job. It's + idempotent anyways. (Closes: #502878, #640288) + * Enable OpenMP parallelization in upstream Makefile. (Closes: #824107) + * Mark john-data as "Multi-Arch: foreign" as suggested by the Multiarch + hinter. + + -- Axel Beckert Tue, 26 Jan 2021 05:01:27 +0100 + +john (1.8.0-2.1) unstable; urgency=medium + + * Non maintainer upload by the Reproducible Builds team. + * No source change upload to rebuild on buildd with .buildinfo files. + + -- Holger Levsen Fri, 01 Jan 2021 15:34:58 +0100 + +john (1.8.0-2) unstable; urgency=medium + + * Add myself to Uploaders. Thanks to Ruben Molina + for the permission. + * Add missing hardening fortify functions export. + * Bump Standards-Version to 3.9.5. (no changes). + * Add support to check upstream gpg signature. + * Add myself to debian copyright. + + -- Julián Moreno Patiño Wed, 19 Mar 2014 15:37:37 -0500 + +john (1.8.0-1) unstable; urgency=low + + * New upstream release (Closes: #670582) + * Fixing $PIDDIR logic in crontab (Closes: #660822). Thanks Phil. + * Reefreshing patches + * Updating to Standards-Version 3.9.4 (no changes) + * Updating install scripts + * Updating debian/copyright for machine-readable format, version 1.0 + * Updating compatibility level to 9 + * Adding versioned Build-Depends on dpkg-dev (>= 1.16.1~) + + -- Ruben Molina Mon, 26 Nov 2012 14:35:38 -0500 + +john (1.7.8-1) unstable; urgency=low + + * New upstream release (Fix: CVE-2011-2483, LP: #805258) + * Fix john's manpage for debian file locations (Closes: #592401) + + -- Ruben Molina Mon, 04 Jul 2011 15:49:59 -0500 + +john (1.7.7-2) unstable; urgency=low + + * Forcing the 'generic' target for hurd + * Adding new escaping rules in order to solve FTBFS in armel, mips, + mipsel, and s390 (all using the 'generic' target) + * Updating copyright dates to 2011 + * Removing unused patch: single-have_words-fix-1.diff + + -- Ruben Molina Wed, 15 Jun 2011 23:23:04 -0500 + +john (1.7.7-1) unstable; urgency=low + + * New upstream release (Closes: #585464, #563698, LP: #586544) + * Standards-Version bumped to 3.9.2 (no changes) + * Fully reworked debian/rules (Closes: #583367) + + New targets: *-kfreebsd, ia64, ppc* + + Generate optimized binaries (Closes: #629517) + + 64bits (amd64, kfreebsd-amd64) + + 32bits + sse2 (i386, kfreebsd-i386) + + Use CPU fallbacks (i386, freebsd-i386): sse2 → mmx → any + Delete debian/extra/john → no longer needed with CPU fallbacks + * Remove third-party patches (??-add_*.patches), making easier to + test new rules. Patches can be re-added later as needed. + * Remove some patches. Testing if they are still needed. + Some regresions are expectable: #420980, #460697, #415738. + Patches will be re-added as needed. + * Fix a spelling-error-in-manpage for john.8 + * Update debian/watch in order to exclude jumbo patches. + + -- Ruben Molina Tue, 07 Jun 2011 08:09:28 -0500 + +john (1.7.3.1-1) unstable; urgency=low + + [David Paleino] + * New upstream release + * debian/man/john.8: + - updated the locations of john's session files (Closes: #360591) + - updated descriptions of --rules and --test (Closes: #485422) + * debian/extra/: + - john-mailer.conf and cronjob extended to allow per-group password + cracking -- thanks to Fabian Zeindl (LP: #194036) + * debian/patches/: + - 01-add_NTLM-MD4.patch, + 02-add_MS-Credential-Cache.patch, + 03-add_NetLM-NetNTLM.patch, + 05-mipsel.patch, + 07-update_FAQ.patch refreshed. + - 08-add_BFEgg.patch, + 10-add_DOMINOSEC.patch, + 11-add_lotus5.patch, + 12-add_raw-md5.patch, + 13-add_raw-sha1.patch, + 14-add_IPB2.patch, + 16-add_NSLDAP.patch, + 17-add_OPENLDAPS.patch, + 18-add_HDAA.patch added (from "Jumbo Patch" available on upstream's + homepage). + - series updated + - these will be the only patches added, in case of problems in future + some might be removed as well (Closes: #220005) + * debian/docs updated + * debian/copyright updated + * debian/watch updated + * debian/README.wordlists: typo fixed (Closes: #512158) + * debian/control: + - moved to git, updated Vcs-* fields + - updated Standards-Version to 3.8.0 + + debian/README.source added + - DMUA set + * debian/man/john-mmx.8 added (Closes: #132223) + + [Ruben Molina] + * New Maintainer + * Remove David Paleino from Uploaders as requested (Thanks for all!) + * Remove DM-Upload-Allowed bit + * Bump Standards-Version to 3.8.3 (no changes) + * Add headers to patches + * Add versioned references to licences on debian/copyright + * Improve debian/watch + * Add exec-stack.patch from Ubuntu to turn off executable stacks when + assembling (thanks Kees). Closes: #543451 + * Avoid creation of /var/run/john (must be created dynamically, and is not + in use on current versions anyway). Fixed maintainer scripts according. + (Fix dir-or-file-in-var-run) + + -- Ruben Molina Sat, 17 Oct 2009 12:48:20 -0500 + +john (1.7.2-3) unstable; urgency=low + + * Merged debian/changelog from old experimental version (1.7-1 and + 1.7-2). + * debian/patches/: + - 06-fix_paths.patch updated (Closes: #484109). + - 07-update_FAQ.patch added: point users to README.wordlists. + - added support for Microsoft Windows NT/2000/XP/2003 NTLM (MD4) hash + (patch by Alain Espinosa ) + - added support for Windows 2000/XP/2003 credentials cache hash (patch + by Alain Espinosa ) + - added support for LM/NTLMv1 challenge/response (ported from 1.7.0.2) + (patch by by JoMo-Kun ) + * debian/control: + - set "John Packaging Team" as the Maintainer + - moved myself to Uploaders + - debhelper dependency bumped to >= 6.0.7~ (dh_lintian) + - added Build-Depends on libssl-dev + * debian/man/john.8 fixed (Closes: #482886) + * debian/rules updated: + - binary-common target added, binary-{arch,indep} depending on it + (Closes: #477450) + - conditionally unset OPT_NORMAL (i.e. remove -funroll-loops) on arm + machines + * debian/compat bumped to 6 + * debian/copyright updated: + - included files created by patches + + -- David Paleino Mon, 02 Jun 2008 17:21:00 +0200 + +john (1.7.2-2) unstable; urgency=low + + * Fixing undeclared conflict between john-data and previous versions + of john (Closes: #477974) + + -- David Paleino Sat, 26 Apr 2008 09:48:09 +0200 + +john (1.7.2-1) unstable; urgency=low + + * Package adopted (Closes: #461992) + * New upstream release (Closes: #385858, #353151, #353108, #127920) + * debian/control: + - added Vcs-* fields + - updated Maintainer field + - dropped dependency on dpkg + - updated dependency on debhelper (>= 5) + - added dependency on quilt + - added an Arch: all package -- john-data + * debian/watch added + * debian/preinst - now invokes dpkg-query + * debian/man/john.8 - fixed errors from man + * debian/rules: + - refactored to use debhelper + - refactored to use quilt + * debian/README removed (no more applicable): + - also fixes dead symlink error (Closes: #354634, #372154) + * debian/john-data.install added: + - also includes alnum.chr in /usr/share/john/ (Closes: #385856) + * debian/patches/: + - bashisms.diff removed -- patching a debian/ file, no need to make a + separate patch. + - faq.diff removed -- the same info that the patch adds can be found in + README.wordlists. + - system-wide.diff removed -- john 1.7.* supports system-wide installation + via a compiler flag. + - all other old patches have been kept (but not applied at build-time) for + future reference. + * debian/copyright updated. + * debian/compat updated. + + -- David Paleino Fri, 18 Apr 2008 17:24:58 +0200 + +john (1.6-40.4) unstable; urgency=medium + + * Non-maintainer upload. + * Add 'bashisms.diff' to fix bashisms in /usr/sbin/mailer script + (Closes: #468685) + * debian/control: + - Bump Standards-Version to 3.7.3. + - Use Homepage: field for upstream URL. + + -- Chris Lamb Sat, 12 Apr 2008 04:40:32 +0100 + +john (1.6-40.3) unstable; urgency=low + + * Non-maintainer upload. + * Fixed build failure on !(i386 || alpha). Revert to the state of version + 1.6-40.1, and used Ubuntu's sysconf-based patch instead of Thiemo's + CLOCKS_PER_SEC patch. Closes: #460697. + * Add debian/patches/mips.diff: patch from Thiemo Seufer to fix FTBFS on + mips and mipsel. Closes: #415738. + + -- Lucas Nussbaum Mon, 14 Jan 2008 20:00:36 +0100 + +john (1.6-40.2) unstable; urgency=low + + * Non-maintainer upload. + * Applied patch from Thiemo Seufer to replace CLK_TCK by CLOCKS_PER_SEC. + Fixes FTBFS (Closes: #420980). + + -- Lucas Nussbaum Sat, 12 Jan 2008 22:11:08 +0100 + +john (1.6-40.1) unstable; urgency=high + + * Non-maintainer upload. + * High-urgency for RC bugfix. + * The following bug fixes are mostly cherry-picked from an omnibus patch + by Justin Pryzby : + * Complete rewrite of maintainer scripts to neither remove nor edit + conffiles (Closes: #375850) + - the debconf settings are not necessary for package operation, + so just don't use debconf, and remove debconf-related files from + debian directory (incidentally closes: #412797) + - preserves settings in preinst, rather than moving conffiles to + foo.old + - do the conffile relocation in preinst (not postinst, which + inhibits dpkg diffs when they should be displayed) + - the cronjob in /etc/cron.d does nothing if the executable isn't + +x, so doesn't need to be commented out on uninstallation + - minor edits to debian/README to reflect these changes + * Set /var/run/john to mode 0700 in postinst configure unless a + dpkg-statoverride exists (Closes: #403855) + * On uninstallation, remove restore file from /var/lib, not /usr/share; + and do so in postrm remove, not prerm remove. On upgrade, if restore + file exists in /usr/share but not in /var/lib, move it in postinst. + + -- Kevin B. McCarty Wed, 14 Mar 2007 17:06:16 -0400 + +john (1.6-40) unstable; urgency=low + + * debian/control: updated my e-mail address. + + * debian/preinst, debian/postinst, debian/postrm: + - reorganized the code + - added debhelper token + * debian/postrm: + - changed interpreter to /bin/sh + * debian/prerm: + - always remove temporary file. (Closes: #350423) + + -- Guilherme de S. Pastore Tue, 18 Apr 2006 23:40:20 -0300 + +john (1.7-2) experimental; urgency=low + + * Patches changes: + - Drop the am64 patch (the AMD 64 bugs are fixed upstream and the patch + introduced new bugs) + - Drop the makefile patch (test code, should have been removed a long + time ago) + Neither are needed for these release any more + * Build changes: + - Use the MMX for i386 and amd64 and let john use the runtime fallback + if MMX is not present + - Introduce a build-john-stamp target in debian/rules to prevent cdbs from running the + build/john target twice (lead to FTBFS) + * Documentation changeS: + - Add doc/CONTACT to the documentation under debian/docs + - Added a debian/TODO + - Ofuscate the email addresses in the Debian manpages as + requested by Solar Designer + - Review the manpage and add double dashes to all options and equal + signs (GNU-style syntax). It still needs to be reviewed to adapt + it to 1.7... + + -- Javier Fernandez-Sanguino Pen~a Mon, 20 Feb 2006 18:10:28 +0100 + +john (1.7-1) experimental; urgency=low + + * New upstream release (Closes: #353151) + * Fix debian/copyright with information from doc/LICENSE, the + debian/copyright file said it was GPLv2 or later and the LICENSE + does not. Include other information from that file missing. + * Modify debian/patches/faq.diff since the fix is already applied + upstream + * Modify debian/patches/makefile.diff since the fix is carried upstesam + * Adjust debian/patches/systemwide.diff so that it uses the new SYSTEM_WIDE + definition + * Disable the MMX target for i386 (it does not work for the moment) and + use a single generic binary as with other architectures + * Create a link for /usr/share/john/john.conf that points to + /etc/john/john.conf (even though we have a systemwide configuration + pointing there, just in case) + + -- Javier Fernandez-Sanguino Pen~a Thu, 16 Feb 2006 14:53:36 +0100 + +john (1.6-39) unstable; urgency=low + + * debian/man/john.8: + - escape the apostrophe at the beginning of like 139. + * debian/extra/mailer: + - fixed configuration file parser in order to, among other things, + appropriately ignore comments (Closes: #340902) + + -- Guilherme de S. Pastore Thu, 29 Dec 2005 10:21:25 -0200 + +john (1.6-38) unstable; urgency=low + + * debian/control: + - update to Standards-Version 3.6.2.1 with no changes + * debian/patches: + - faq.diff, makefile.diff, system-wide.diff: transformed changes made to + the source tree directly and stored in the .diff.gz file into patches, + so it's possible to maintain the package in an SVN repository + * debian/postinst: + - modify indentation + - remove $tmp if $cronfile doesn't exist (Closes: #332488) + * Updated Swedish debconf templates translation; thanks to + Daniel Nylander (Closes: #334883) + + -- Guilherme de S. Pastore Fri, 11 Nov 2005 22:39:25 -0200 + +john (1.6-37) unstable; urgency=medium + + * debian/control: + - updated maintainer's e-mail address + * debian/config, debian/postrm, debian/preinst: + - Removed bashisms + * debian/man/john.8: + - fixed typo, thanks to A Costa (Closes: #325683) + * debian/extra/john: + - remove the /proc existence check, which will make the script + simply fall back to john-any if MMX can't be checked for + * debian/copyright: + - cosmetic fixes + - updated FSF's address + + -- Guilherme de S. Pastore Fri, 12 Aug 2005 17:36:04 -0300 + +john (1.6-36) unstable; urgency=medium + + * debian/control: + - added debconf-2.0 as alternative to debconf dependency + * debian/extra/john: + - run john-{any,mmx} with the same we've been given, so it + works with unshadow and friends (Closes: #322442) + * debian/rules: + - install john.conf with the right permissions + - append to binary-install/john instead of binary-post-install/john + + -- Guilherme de S. Pastore Thu, 4 Aug 2005 14:11:07 -0300 + +john (1.6-35) unstable; urgency=low + + * Moved john-any and john-mmx to /usr/lib/john on i386, as the user + is not supposed (and won't be able) to run them directly + * Fix stupid usage of debian/john.install that broke a couple of things + in -34 (not uploaded to Debian, at least) + * debian/extra/john-mail.conf: + - Make it clear(er) that one shouldn't put the path to the system + password file in the passfile directive (Closes: #296766) + + -- Guilherme de S. Pastore Sat, 30 Jul 2005 12:20:02 -0300 + +john (1.6-34) unstable; urgency=low + + * debian/control: + - Rewrote both short and long description + - Updated Standards-Version to 3.6.2 with no changes + - Christian Kurz is really MIA, as he stated he would be. Removed + him from Uploaders. Thanks for the great work! + * debian/docs: + - Move installation of doc/NEWS to john.install, so we don't have to + manually rename it in debian/rules + * debian/examples: + - Removed run/john.ini from the list, it's the configuration file + * debian/po: + - de.po, es.po: unfuzzied header + - pt_BR.po: converted from ISO-8859-1 to UTF-8 + - vi.po: added Vietnamese translation from Clytie Siddall (Closes: #314258) + * debian/rules: + - General cleanups + - Don't strip files manually: dh_strip handles this + - Moved manpages installation to debian/john.manpages + - Don't include cdbs's buildcore.mk: it's included by debhelper.mk + - Properly use dpkg-architecture instead of dpkg --print-architecture + - Added /var/run/john to DEB_FIXPERMS_EXCLUDE: the location needs to + be safe from normal user reading + - Symlinks are now handled within debian/john.links, and always point + to /usr/sbin/john, as the script should handle non-MMX machines + * debian/README.wordlists: + - Rewritten from scratch for better language + - Removed references to non-free costly word lists + + -- Guilherme de S. Pastore Mon, 18 Jul 2005 13:27:24 -0300 + +john (1.6-33) unstable; urgency=medium + + * Fixed cronjob so that it doesn't send empty e-mails when no + password is cracked (Closes: #272065) + * Debconf templates: + - Updated Czech translation from Miroslav Kure (Closes: #273839) + - Updated Brazilian Portuguese translation from Tiago Vaz (Closes: #272432) + + -- Guilherme de S. Pastore Fri, 19 Nov 2004 21:09:15 -0200 + +john (1.6-32) unstable; urgency=medium + + * Fix "errors" displayed to user during purge (Closes: #268938) + * Debconf templates: + - Added Turkish translation from Recai Oktas (Closes: #269518) + - Updated Japanese translation from Hideki Yamane (Closes: #269530) + - Updated Dutch translation from Frans Pop (Closes: #269825) + - Updated German translation from Florian Ernst (Closes: #271299) + - Updated French translation from Frédéric Zulian (Closes: 271433, 271440) + [ Javier Fernandez-Sanguino ] + * The cronjob will now echo the output of the mailer script so that + root gets a mail about easy passwords like it previously did + + -- Guilherme de S. Pastore Sun, 12 Sep 2004 19:43:23 -0300 + +john (1.6-31) unstable; urgency=low + + * Added versioned dependency on dpkg >= 1.10.16, to have correct version + of start-stop-daemon and not wipe out system's /etc/shadow + (Closes: #266737) + + -- Guilherme de S. Pastore Wed, 18 Aug 2004 22:56:17 -0300 + +john (1.6-30) unstable; urgency=low + + * Rewrote debconf templates (Closes: #259299) + - Added Danish translation from Claus Hindsgaul + - Added Russian translation from Yuri Kozlov + * Fixed handling of warning of "No configuration file" when upgrading + from a version that used the old path, /etc/john.ini (Closes: #259320) + [ Javier Fernandez-Sanguino ] + * Updated Spanish translation of debconf templates + - Revision by Rudy Godoy + * debian/extra/cronjob: + - Remove all comments before grepping and only use the first definition. + Supposedly closes: #262316 + + -- Guilherme de S. Pastore Wed, 14 Jul 2004 06:31:47 -0300 + +john (1.6-29) unstable; urgency=high + + * debian/extra/cronjob: + - Installed again with execution permitions (+x) (Closes: #259084) + * Fixes related to configuration files move from /etc to /etc/john: + - debian/man/john.8 + - debian/extra/mailer (Closes: #259085) + - Debconf template and pt_BR translation + [ Javier Fernandez-Sanguino ] + * Minor typo fixes in the templates as suggested by Nicolas François in + #259191 + * Unfuzzied spanish translations after revision. + * Added missing entries of previous version to the changelog + * Remove files under /var/run/john and /etc/john on purge + + -- Guilherme de S. Pastore Mon, 12 Jul 2004 21:03:47 -0300 + +john (1.6-28) unstable; urgency=medium + + * Ported debian/rules to use CDBS + - Removed debian/conffiles, debhelper handles this + - Uses debian/dirs and others instead of polluting debian/rules + - Made cleanups and removed things that remained there from older + releases, such as unnecessary directories + * Bumped Standards-Version to 3.6.1.1 + * Moved manpages to section 8 (Closes: #252206) + - Fixed problems (Closes: #252506) + * Re-added sparc support with generic target (Closes: #220928) + * Added real alternative to suggestion on wordlist + * Removed lintian/linda overrides, don't need them anymore + * Moved configuration files to /etc/john/ (Closes: #141741, #229597) + * Only check for configuration file in config if it's an upgrade + (Closes: #251227, #253194) + * Added patch from Goswin von Brederlow to avoid segfaults when + casting signed char to unsigned int on amd64 (Closes: #251095) + * Added clarification to the manpage about having to run john with + -show from the same directory where the password was cracked, so + that it works (Closes: #228750) + [ Javier Fernandez-Sanguino ] + * Build on all architectures Debian supports, using the 'generic' + target for the ones not supported by john (Closes: #138689, #224883) + * Major rewrite of the cronjob which will now work as follows: + - Mailer uses the latest password file to avoid mailing users warning + about passwords if they have changed it (Closes: #251172) + - Stale files are now removed under some circunstances (so /var/run/john + does not fill up with cronpasswd files) + - John is started/stopped using start-stop-daemon which makes it + write the pid file properly (unlike previously). Also, + the start-stop-daemon usage makes it possible to run john as a + non-root user (if everything is 'chowned' to him). + - This new cronjob will now restore interrupted sessions correctly + (and uses the john.rec files) (Closes: #213164) + + -- Guilherme de S. Pastore Thu, 27 May 2004 18:14:28 -0300 + +john (1.6-27) unstable; urgency=low + + * New maintainer + * Bumped Standards-Version to 3.6.1.0 + * Removed Origin: field from debian/control + * Corrected typo on debian/man/mailer.1 (Closes: #249574) + * Added Czech translation provided by Miroslav Kure (Closes: #244363) + * Dropped Sparc support so that bug fixes can progress into testing. + This will remain until there is a proper fix for this issue. + [ Javier Fernandez-Sanguino ] + * Updated debian/po/fr.po with patch provided by Christian Perrier (merged + manually the changes since they are not using the latest version) + (Closes #229624) + * Updated the Spanish translation (debian/po/es.po) + * Added the ldap-extract script provided by Klaus Ethgen to the examples + (Closes: #226980) + * Nice John's cron job per default (nobody rejected this and seems + a reasonable request since john should be able to recover nicely) + (Closes: #228799) + * Fixed PID loop in the cronjob (Closes: #227323) + [ Christian Kurz] + * Updated debian/po/pt_BR.po with patch provided by Andre Luis Lopes + (Closes: #228122) + * Updated debian/po/ja.po with a patch provided by Hideki Yamane + (Closes: #235647) + * Updated debian/po/de.po with a patch provided by Florian Ernst + (Closes: #244524) + + -- Guilherme de S. Pastore Mon, 17 May 2004 22:39:21 -0300 + +john (1.6-26) unstable; urgency=medium + + * The "I should not forget to dupload stuff" Release. + [ Javier Fernandez-Sanguino ] + * Created a new template, and modified the config so it checks + whether john.ini exists or not (Closes: #226897) + * The default john.ini file is now included as an example (so the user can + use it for restoration of the config file) + * Added a proper charset to the de.po file. + * Updated the spanish po file. + [ Christian Kurz ] + * Updated debian/po/fr.po with patch provided by Christian Perrier (Closes: #227024) + + -- Javier Fernandez-Sanguino Pen~a Mon, 12 Jan 2004 20:29:35 +0100 + +john (1.6-25) unstable; urgency=low + + * The "I still have to submit the code to alioth... Merry Xmas!" Release + * Added debconf loading to prerm script, thanks to Bastian Kleineidam + (Closes: #224160) + * Removed debbugs call in debian/control (Closes: #220069) + * Added japanese translation provided by Hideki Yamane (Closes: #224182) + * Removed lintian/override creation from debian/rules (Closes: #223374) + + -- Javier Fernandez-Sanguino Pen~a Fri, 26 Dec 2003 14:22:11 +0100 + +john (1.6-24) unstable; urgency=low + + * When upgrading, do not ask to enable the cronjob if the user has + not chosen to replace it. + + -- Javier Fernandez-Sanguino Pen~a Mon, 17 Nov 2003 01:05:47 +0100 + +john (1.6-23) unstable; urgency=low + + * Fixed the cronjob in order to avoid mails with just + "Usage: /usr/sbin/mailer PASSWORD-FILE" since it seems that under + some circumstances the restoration of jobs does not work properly. + Also added usage line. + * Modified prerm script in order to deinstall the cronjob if the + user is removing the package and has enabled the cronjob (Closes: #220845) + * Also modified the cron.d file to only run the cronjob if the file + exists and is executable. + + -- Javier Fernandez-Sanguino Pen~a Fri, 14 Nov 2003 01:34:22 +0100 + +john (1.6-22) unstable; urgency=low + + * Really fixed src/Makefile (I should have noticed that sparc.h was + not being created) since it still fails to build in sparc. + + -- Javier Fernandez-Sanguino Pen~a Wed, 12 Nov 2003 17:36:35 +0100 + +john (1.6-21) unstable; urgency=low + + * Modified src/Makefile in an attempt to fix the sparc build (broken since + 1.6-19) + + -- Javier Fernandez-Sanguino Pen~a Wed, 12 Nov 2003 11:15:04 +0100 + +john (1.6-20) unstable; urgency=low + + * New co-maintainer (myself) in an attempt to offload Christian + of some of work in this package. + * Fixed typos in debian/rules (Closes: #220013, #213154) + * Included some more information in the description as well as the + upstream location (Closes: #220008) + * Added template in order to allow for configuration of wordlists + by the user, as well as a README.wordlist document + (Closes: #159488, #123837, #220015) + * Recovered configuration note regarding cron jobs so john will now + properly enable/disable it if asked to (Closes: #220021) + * Included Spanish debconf translation (Closes: #220011) + * Recovered German translation of the cronjob and added a de.po file. + * Added Dutch debconf translation provided by Philippe Faes + (Closes: #211349) + * Added French debconf translation provided by Frederic Zulian + (Closes: #211540) + * Added author's name and updated email address in copyright. + * Creation of /var/run/john/ in order to use this location + for the temporary file in john-mail.conf (this is mode 0700 so that + even if the passwords are stored there the impact is reduced) + + -- Javier Fernandez-Sanguino Pen~a Mon, 10 Nov 2003 22:01:00 +0100 + +john (1.6-19) unstable; urgency=low + + * This release wouldn't have been possible without the help from Jeronimo + Pellegrini and Gergely Nagy. Both were a great help for me and so it's + only fair to credit them here and say a big "THANK YOU"! + * john will create now the files john.pot, john.ini and restore in the + directory where it was started from. + * Changed the unshadow.1 manpage as suggested by Colin Watson. This means + that one occurance of .br was replaced by .PP and an newline was added. + This will address the issue of the slightly broken unshadow manpage, + that has been reported as bug #142848. + * The manpage john.1 won't mention the non-existing john-ini.5 anymore. This + is going to fix the bug #122438. + * Integrated two patches from Jeronimo Pellegrini that are going to improve + the cronjob. Also thanks to Gergely Nagy for his help with devising and + developing the patches. This should address bug #162991. + * Also the whole setup and behaviour of the cronjob has been modified. This + should also fix the bug #118012 since the code has been changed. + * Updated the URL pointer in the FAQ. This should fix the bug report + #159580. + * Changed the wrong comment in the file /etc/john-mail.conf. This will fix + the bug #162599. + * Fixed the location of password.lst and the location of the files for the + incremental mode in /etc/john.ini. This will fix the bugreport #79831. + * Reworked support for translation of debconf messages. Now this package is + using po-debconf for this purpose. + + -- Christian Kurz Wed, 11 Dec 2002 22:17:09 +0100 + +john (1.6-18) unstable; urgency=low + + * Applied a patch from Jeronimo Pellegrini to remove the reference + to the unexisting john.ini(5) manpage. (Closes: #122438) + * Applied a fix from Ben Okopnik to the unshadow manpage. + (Closes: #142848) + + -- Christian Kurz Sun, 14 Apr 2002 23:33:09 +0200 + +john (1.6-17) unstable; urgency=low + + * Rewording of comments in config file. (Closes: #115556) + (Thanks to Martin F Krafft) + * Included hack to remove cronjob if needed. (Closes: #114835,#117034) + + -- Christian Kurz Sun, 14 Oct 2001 20:14:42 +0200 + +john (1.6-16) unstable; urgency=low + + * Integrated patch from Damyan Ivanov to fix unquoted sed + expressions. (Closes: #113557) + + -- Christian Kurz Wed, 26 Sep 2001 12:57:53 +0200 + +john (1.6-15) unstable; urgency=low + + * Fixed typo in debconf templates. (Closes: #112058,#113166) + * Should fix another problem with the lock-file. (Closes: #113332) + + -- Christian Kurz Wed, 12 Sep 2001 16:08:30 +0200 + +john (1.6-14) unstable; urgency=low + + * Added german debconf translation from Sebastian Feltel. + (Closes: #109980) + * Fixed two typos in the john.1 manpage, noted by Stephen Frost. + * Applied patch from Daniel Kobras to fix two oversights in the + cronjob script. (Closes: #110272) + * Applied patch from Jeronimo Pellegrini to fix some small problems + in the scripts. (Closes: #110957) + + -- Christian Kurz Sat, 25 Aug 2001 09:09:18 +0200 + +john (1.6-13) unstable; urgency=low + + * We'll gzip the example file, which is about 12k. But the other files + which are just 2-6k will be stay uncompressed, until some very good + reasons are presented to convince me. (Closes: #96650) + * Integration of Patch from Jeronimo Pellegrini to support the + installation and deinstallation of a cronjob. (Closes: #101970) + + -- Christian Kurz Thu, 12 Jul 2001 22:55:09 +0200 + +john (1.6-12) unstable; urgency=low + + * Now we finally added manpages for john which have been written by + Jordi Mallach and Jeronimo Pellegrini. (Closes: #62498) + * Applied a patch from Jeronimo Pellegrini to make the mailer script + more configurable. (Closes: #101968) + + -- Christian Kurz Sun, 20 May 2001 10:18:56 +0200 + +john (1.6-11) unstable; urgency=low + + * Fixed Symlinks for $ARCHITECURE != i386. (Closes: #92280) + + -- Christian Kurz Sat, 31 Mar 2001 18:34:42 +0200 + +john (1.6-10) unstable; urgency=low + + * Fixed the symlinks, since we didn't notice that we broke them with + the 1.6-8 release. Now, it should work fine again. (Closes: #91824) + + -- Christian Kurz Wed, 28 Mar 2001 08:22:18 +0200 + +john (1.6-9) unstable; urgency=low + + * Fixed the name of the override file for john and also it' + location. (Closes: #81218) + + -- Christian Kurz Sun, 25 Mar 2001 00:30:33 +0100 + +john (1.6-8) unstable; urgency=low + + * Fixed the startup script for john to correctly use bash. + + -- Christian Kurz Thu, 1 Mar 2001 20:00:13 +0100 + +john (1.6-7) unstable; urgency=low + + * Fixed a typo to build john also on Alpha (Closes: #83696) + + -- Christian Kurz Sat, 27 Jan 2001 09:13:13 +0100 + +john (1.6-6) unstable; urgency=low + + * Added sparc-fix from Solar Designer (Closes: #81756). + * Changed rules file to build two different versions of john, one with + mmx extensions, and one without. + * Added wrapper script to start john. + + -- Christian Kurz Fri, 12 Jan 2001 22:31:05 +0100 + +john (1.6-5) unstable; urgency=low + + * Moved overrides file to correct location (Closes: 81218). + * Added 3 lines to overrides file for the symlinks. + + -- Christian Kurz Thu, 4 Jan 2001 20:51:32 +0100 + +john (1.6-4) unstable; urgency=low + + * Hopefully I fixed now the logfile-path-bug. + + -- Christian Kurz Fri, 8 Dec 2000 22:26:26 +0100 + +john (1.6-3) unstable; urgency=low + + * Fixed pre-rm to allow removal of package (Closes: 74091). + + -- Christian Kurz Thu, 5 Oct 2000 21:55:51 +0200 + +john (1.6-2) unstable; urgency=low + + * Changed debian/rules to be faster and more portable. + * Fixed prerm-script to run only on purges. + * Fixed some pathes to better defaults. + + -- Christian Kurz Mon, 15 May 2000 19:37:07 +0200 + +john (1.6-1) unstable; urgency=low + + * First Debian release. + + -- Christian Kurz Sat, 1 Apr 2000 12:23:57 +0200 diff --git a/debian/clean b/debian/clean new file mode 100644 index 0000000..0679e6b --- /dev/null +++ b/debian/clean @@ -0,0 +1 @@ +run/john-* diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..412a33a --- /dev/null +++ b/debian/control @@ -0,0 +1,43 @@ +Source: john +Section: admin +Priority: optional +Maintainer: Debian Security Tools +Uploaders: Julián Moreno Patiño , + Axel Beckert +Build-Depends: debhelper-compat (= 13), + dpkg-dev (>= 1.16.1~) +Standards-Version: 4.5.1 +Homepage: http://www.openwall.com/john/ +Vcs-Browser: https://salsa.debian.org/pkg-security-team/john +Vcs-Git: https://salsa.debian.org/pkg-security-team/john.git +Rules-Requires-Root: no + +Package: john +Architecture: any +Depends: john-data (= ${source:Version}), + ${misc:Depends}, + ${shlibs:Depends} +Suggests: wordlist +Description: active password cracking tool + John the Ripper is a tool designed to help systems administrators to + find weak (easy to guess or crack through brute force) passwords, and + even automatically mail users warning them about it, if it is desired. + . + Besides several crypt(3) password hash types most commonly found on + various Unix flavors, supported out of the box are Kerberos AFS and + Windows NT/2000/XP/2003 LM hashes, plus several more with contributed + patches. + +Package: john-data +Architecture: all +Enhances: john +Depends: ${misc:Depends} +Breaks: john (<= 1.7.2-1) +Multi-Arch: foreign +Description: active password cracking tool - character sets + John the Ripper is a tool designed to help systems administrators to + find weak (easy to guess or crack through brute force) passwords, and + even automatically mail users warning them about it, if it is desired. + . + This package contains architecture-independent character sets usable by + john. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..3f9e8a7 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,85 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: John the Ripper +Upstream-Contact: Alexander Peslyak (Solar Designer) +Source: http://www.openwall.com/john/ + +Files: * +Copyright: © 1996-2011, Solar Designer +License: GPL-2 + This program 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; version 2. + . + This program 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 package; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file + `/usr/share/common-licenses/GPL-2'. + +Files: debian/* +Copyright: © 2009-2013, Ruben Molina + © 2014, Julián Moreno Patiño + © 2008-2009. David Paleino + © 2004-2006, Guilherme de S. Pastore + © 2003-2004, Javier Fernandez-Sanguino Peña + © 2000-2004, Christian Kurz +License: GPL-2+ + +Files: debian/man/* +Copyright: © 1999-2001, Jordi Mallach + © 1999-2001, Jeronimo Pellegrini +License: GPL-2+ + +Files:src/MD5_std.* +Copyright: © 1996-2006, Solar Designer +License: GPL-2+ + +License: GPL-2+ + This program 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; version 2 or (at + your option) any later version. + . + This program 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 package; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file + `/usr/share/common-licenses/GPL-2'. + +Files: src/crc32.* +Copyright: © 1998-2005, Solar Designer +License: public-domain + Written by Solar Designer in 1998, revised in + 2005 for use in John the Ripper, and placed in the public domain. + +Files: src/BF_std.* +Copyright: © 1996-2010, Solar Designer +License: public-domain + A public domain version of this code, with reentrant and crypt(3) + interfaces added, but optimizations specific to password cracking + removed, is available at: http://www.openwall.com/crypt/ + +Files: src/nonstd.c + src/sboxes.c +Copyright: © 1998, Matthew Kwan +License: permissive + This software may be modified, redistributed, and used for any purpose, + so long as its origin is acknowledged. diff --git a/debian/cron.d b/debian/cron.d new file mode 100644 index 0000000..7cfe459 --- /dev/null +++ b/debian/cron.d @@ -0,0 +1,14 @@ +# +# Start john everyday at the same to try to crack the passwords. The +# second line will then later stop the process so that it doesn't +# consume system resources that are needed otherwise. You are +# encouraged to change the times. +# +# Also notice that John is 'nice'd, if you don't like this (you +# believe that your system can run fine with john doing its work) +# just remove the 'nice' call +# +# JOHN_OPTIONS = foo bar (man 5 crontab) +# +#00 1 * * * root [ -x /usr/share/john/cronjob ] && nice /usr/share/john/cronjob start +#00 7 * * * root [ -x /usr/share/john/cronjob ] && /usr/share/john/cronjob stop diff --git a/debian/extra/CONFIG.mailer b/debian/extra/CONFIG.mailer new file mode 100644 index 0000000..b781aa4 --- /dev/null +++ b/debian/extra/CONFIG.mailer @@ -0,0 +1,59 @@ +This version of john has two new conffiles for the mailer script: + +/etc/john/john-mail.conf +----------------------- + +This is where you define the command used to send messages to users, +and the shells to be ignored when sending the messages. A working +example is already installed. + +You can set the shells to be ignored, for example: + +shells=-,/bin/false,/dev/null,/bin/sync,/usr/bin/falselogin + +The default is set to: + +shells=-,/bin/false,/dev/null,/bin/sync + +And you may set the command used to send the message (the message +will be piped into this command): + +mailcmd=/usr/sbin/sendmail + +That is the default. If you use sendmail, or if your mailer provides +a "sendmail" executable, you may use the above line. + +And if you want to pass extra arguments to your mailer, set +mailargs: + +mailargs= ... + +The default is not to define mailargs. + +/etc/john/john-mail.msg +----------------------- + +This is the message template to be sent to the user. In the message, +the strings @LOGIN and @HOSTNAME will be substituted for the user's +login and the host name. + +If you use sendmail as mail command, you may include the headers +at the top of the template message, like this: + + +============================================================= +Subject: Gotcha! +Cc: root + +Just cracked your password for account @LOGIN at @HOSTNAME. +Please change it. + +John the Ripper. +============================================================= + +You may also use some binary of yours as the mail command; then it +will be called, and the template (with the variables already +substituted) will be piped into it. This may be useful if you want +to use complex logging (using a DBMS, for example), or if you +want to automatically run scripts (that block the account, +perhaps?) diff --git a/debian/extra/cronjob b/debian/extra/cronjob new file mode 100755 index 0000000..4ef0d2d --- /dev/null +++ b/debian/extra/cronjob @@ -0,0 +1,225 @@ +#!/bin/bash +# +# This script runs every day, trying to crack passwords, and then calls +# mailer to warn the users (and maybe also root) about that. + +# One of two options should be passed to this script: +# start -- start running john +# stop -- stops running john +# The script will run/stop john (as a background process if started) +# and exit. + +# The time when the script is called can be configured in /etc/cron.d/john + +# You can pass options to john in /etc/cron.d/john. See john(1) for the possible +# options, and include them after "JOHN_OPTIONS=" below. + +JOHNDIR=/usr/sbin +PASSWD=/etc/passwd +SHADOW=/etc/shadow +RUNDIR=/var/lib/john +PIDDIR=/var/run/john +RESTORE=$RUNDIR/restore + +PASSFILE=`grep -v ^# /etc/john/john-mail.conf | grep -e "[ ]*passfile[ ]*=[ ]*" | sed -e "s/#.*//" -e "s/.*=[ ]*//" |head -1` +GROUP=`grep -v ^# /etc/john/john-mail.conf | grep -e "[ ]*group[ ]*=[ ]*" | sed -e "s/#.*//" -e "s/.*=[ ]*//" | head -1` + +mkdir -p $PIDDIR $RUNDIR +cd $RUNDIR + +# Gets the PID of the process that should be running john, +# and sends SIGHUP to it. +# +john_stop() +{ + + RESTOREFILE="" + if [ -f $RESTORE ]; then + RESTOREFILE=`grep ^$PASSFILE $RESTORE` + fi + + if [ -f $PIDDIR/john.pid ] + then + # Stop john, we don't really care too much about the error + # messages (just in case, the john cronjob might have finished + # its job and exited) + /sbin/start-stop-daemon --stop -q -o --pidfile $PIDDIR/john.pid 2>&1 >/dev/null + rm $PIDDIR/john.pid + else + # Try the old (deprecated) method if we don't have a piddfile + john_stop_all + fi + + + # Once finished we determine if we need to mail anything + rm -f /var/lock/john + if [ ! -z "$RESTOREFILE" -a -f "$RESTOREFILE" ] ; then + # But use the latest shadow file + TMPFILE=`mktemp $PASSFILE.XXXXXX` || exit 1 + chmod og-rwx $TMPFILE + if [ -n "$SHADOW" -a -f "$SHADOW" ]; then + $JOHNDIR/unshadow $PASSWD $SHADOW >> $TMPFILE + else + cat $PASSWD >> $TMPFILE + fi + # Move to the directory where john.pot resides + OUTPUT=`$JOHNDIR/mailer $TMPFILE 2>&1` + # Mailer mails to root if there is something relevant + # this could be done by configuring john-mail.msg too.. + if [ -n "$OUTPUT" ]; then + echo $OUTPUT + fi + rm -f $TMPFILE + fi +} + +# Gets the PID of all the processes called "john" processes, try to checks +# which one we want, and sends SIGHUP to it. +# +john_stop_all() +{ + +PID=`/bin/pidof john` +for p in $PID; do + PROCPATH=$(readlink /proc/$p/exe) + RELEVANTPATH=`echo $PROCPATH | sed -e"s^$JOHNDIR/john.*^$JOHNDIR/john^"` + if [ "$RELEVANTPATH" = $JOHNDIR/john ]; then + kill -2 $p + fi +done + +} + +# Starts john +# +john_start() +{ + +if [ -z $PASSFILE ]; then + mail -s "John cronjob is not configured yet!" root <> $TMPFILE + else + cat $PASSWD >> $TMPFILE + fi +fi + +# We capture the output of john, and check if there was a line with +# "guesses: 0" in it. If not, then either john exited abnormally, or +# passwords were guessed -- and in both cases we send all the output +# to stdout. +# +if [ ! -f /var/lock/john -a ! -f $PIDDIR/john.pid ]; then + touch /var/lock/john + + # Run john in background + # TODO: start-stop-daemon is flexible enought we could run + # it using a different user + if [ -z "$RESTORE_OPTION" ] ; then + /sbin/start-stop-daemon --start --chdir $RUNDIR -b -m \ + --pidfile $PIDDIR/john.pid --exec $JOHNDIR/john -- \ + $JOHN_OPTIONS $TMPFILE > /dev/null + else + # Note: If we are restoring the session all the options are already + # there... + /sbin/start-stop-daemon --start --chdir $RUNDIR -b -m \ + --pidfile $PIDDIR/john.pid --exec $JOHNDIR/john -- \ + $RESTORE_OPTION $JOHN_OPTIONS $TMPFILE > /dev/null + fi +else + PID=`cat $PIDDIR/john.pid` + # Redundant check (just in case) + PROCPATH=$(readlink /proc/$PID/exe) + RELEVANTPATH=`echo $PROCPATH | sed -e"s^$JOHNDIR/john.*^$JOHNDIR/john^"` + if [ "$RELEVANTPATH" = $JOHNDIR/john ]; then + mail -s "John is already running" root <> $ALTEREDPASSWD + done + PASSWD=$ALTEREDPASSWD + fi +} + +# removes the altered file +remove_altered_passwd() +{ + rm -f $PASSWD.altered.for.john +} +if [ $# -ne 1 ]; then + echo "$0 {start|stop} " + exit 1; +else + case "$1" in + start) + alter_passwd + john_start + ;; + stop) + john_stop + remove_altered_passwd + ;; + *) + exit 1; + ;; + esac +fi diff --git a/debian/extra/john-mail.conf b/debian/extra/john-mail.conf new file mode 100644 index 0000000..99290a0 --- /dev/null +++ b/debian/extra/john-mail.conf @@ -0,0 +1,30 @@ +# Sample configuration file for john. +# + +# These are the shells that should be ignored by john. If you +# install falselogin, for example, you may want to add it to +# the list. +shells=-,/bin/false,/dev/null,/bin/sync + +# This is the mail command. You may actually use any program +# here; the message in /etc/john/john-mail.msg will be piped into it, +# with the login name and host name substituted. +# You may want to use a program to log information about +# weak passwords (but that means sensitive information would be +# kept somewhere - be careful!) +mailcmd=/usr/sbin/sendmail + +# The passfile directive specifies a *temporary* file which will have +# the contents of /etc/passwd and /etc/shadow while the john cronjob +# is running. +# +# ***WARNING***: this will be a copy of your password file, that will +# be broken by the end of the operation. DO *NOT* PUT THE PATH FOR YOUR +# REAL PASSWORD FILE HERE, OR IT WILL BE LOST. Simply specify a location +# that is considered safe for john to put a copy of the password file. +passfile=/var/run/john/cronpasswd + +# The group directive specifies the group whose members' passwords will +# be checked by john. This is useful, for example, if you want to check +# just the group which is allowed to login remotely, ... +#group=ssh diff --git a/debian/extra/john-mail.msg b/debian/extra/john-mail.msg new file mode 100644 index 0000000..3b2b104 --- /dev/null +++ b/debian/extra/john-mail.msg @@ -0,0 +1,8 @@ +Subject: Bad password! + +Hello! + +Your password for account @LOGIN at host @HOSTNAME is too easy! +Please change it as soon as possible. + +John the Ripper, an automated password cracker. diff --git a/debian/extra/ldap-extract b/debian/extra/ldap-extract new file mode 100644 index 0000000..ec739d1 --- /dev/null +++ b/debian/extra/ldap-extract @@ -0,0 +1,60 @@ +#! /usr/bin/perl +# +# Script to extract passwords from an LDAP directory server +# The script has to be called with: +# +# ldap-extract ldap://server baseDN AdminDN Adminpassword +# +# This script requires the 'libnet-ldap-perl' package +# +# (c) 2004 Klaus Ethgen +# Licensed under the GNU General Public License version 2. +# +# TODO +# - The script will only retrieve passwords in crypt format +# other formats (MD5, SHA-1...) are not supported. + +use strict; +use warnings; +use Getopt::Std; +our($opt_h); +getopts('h'); +if ( $opt_h || @ARGV != 4 ) { + print "Usage: $0 ldap://server baseDN AdminDN Adminpassword\n"; + exit 1; +} +eval "use Net::LDAP"; +if ($@) { + print "ERROR: Could not load the Net::LDAP module\n"; + print "(Hint: If you are running this in Debian install the libnet-ldap-perl package)\n"; + exit 1; +} + +my ($host) = $ARGV[0] =~ /ldap:\/\/(.*)/; +my $ldap = Net::LDAP->new("localhost") or die $@; +$ldap->bind($ARGV[2], password => $ARGV[3], version => 3) or die "Cannot bind to ldap server $ARGV[2]: $!"; +my $res = $ldap->search(base => $ARGV[1], scope => "sub", attrs => + [qw(cn uid userPassword loginShell homeDirectory uidNumber gidNumber)],filter => "cn=*"); +my $x = $res->as_struct; +foreach (keys %$x) +{ + print $x->{$_}->{uid}->[0]; + my $pw = $x->{$_}->{userpassword}->[0]; + if ($pw =~ /^\{crypt\}(.*)$/) + { + $pw = $1; + } +# else +# { +# $pw =~ s/^\{.+\}/\$1\$/; +# } + print ":$pw"; + foreach my $i (qw(uidnumber gidnumber cn homedirectory loginshell)) + { + print ":", $x->{$_}->{$i}->[0]; + } + print "\n"; +} +$ldap->unbind; + +exit 0; diff --git a/debian/extra/mailer b/debian/extra/mailer new file mode 100644 index 0000000..f4119c1 --- /dev/null +++ b/debian/extra/mailer @@ -0,0 +1,53 @@ +#!/bin/sh +# +# This file is part of John the Ripper password cracker, +# Copyright (c) 1996-98 by Solar Designer +# + +if [ $# -ne 1 ]; then + echo "Usage: $0 PASSWORD-FILE" + exit 0 +fi + +if [ ! -f /etc/john/john-mail.conf ]; then + echo "Couldn't find /etc/john/john-mail.conf -- stopping!" + exit 0 +fi + +if [ ! -f /etc/john/john-mail.msg ]; then + echo "Couldn't find /etc/john/john-mail.msg -- stopping!" + exit 0 +fi + +# In Debian, john should be in /usr/sbin. "john" binaries in other +# locations should not be used. +JOHNDIR=/usr/sbin + +# Let's get stuff from conf file: +SHELLS=`grep -e "^[ ]*shells[ ]*=[ ]*" /etc/john/john-mail.conf | sed "s/.*=[ ]*//"` +MAILCMD=`grep -e "^[ ]*mailcmd[ ]*=[ ]*" /etc/john/john-mail.conf | sed "s/.*=[ ]*//"` +MAILARGS=`grep -e "^[ ]*mailargs[ ]*=[ ]*" /etc/john/john-mail.conf | sed "s/.*=[ ]*//"` + +# Let's start +$JOHNDIR/john -show "$1" -shells:$SHELLS | sed -n 's/:.*//p' | +( + SENT=0 + + while read LOGIN; do + echo Sending mail to "$LOGIN"... + +# Sends a message to each user; a template is in /etc/john/john.msg +# Subject, Reply-to, and other header lines should be put +# at the top of that file. + sed -e 's/@LOGIN/'$LOGIN'/g' \ + -e 's/@HOSTNAME/'$(hostname)'/g' /etc/john/john-mail.msg | + $MAILCMD $MAILARGS $LOGIN + + SENT=$(($SENT+1)) + done + + if [ ! $SENT -eq 0 ]; then + echo "John has cracked $SENT passwords. If you want to see them," + echo "use john -show . (See john(1) for details)." + fi +) diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000..c749a1c --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,12 @@ +[DEFAULT] +debian-branch = debian/master +pristine-tar = True + +[buildpackage] +sign-tags = True + +[import-orig] +filter-pristine-tar = True + +[dch] +multimaint-merge = True diff --git a/debian/john-data.install b/debian/john-data.install new file mode 100644 index 0000000..cac4edc --- /dev/null +++ b/debian/john-data.install @@ -0,0 +1,2 @@ +run/*.chr /usr/share/john/ +run/*.lst /usr/share/john/ diff --git a/debian/john.docs b/debian/john.docs new file mode 100644 index 0000000..469610b --- /dev/null +++ b/debian/john.docs @@ -0,0 +1,13 @@ +#doc/CHANGES +#doc/CONTACT +#doc/INSTALL +#doc/LICENSE +doc/CONFIG +doc/CREDITS +doc/EXAMPLES +doc/EXTERNAL +doc/FAQ +doc/MODES +doc/OPTIONS +doc/README +doc/RULES diff --git a/debian/john.install b/debian/john.install new file mode 100644 index 0000000..31a3bd7 --- /dev/null +++ b/debian/john.install @@ -0,0 +1,6 @@ +debian/extra/cronjob /usr/share/john/ +debian/extra/john-mail.conf /etc/john/ +debian/extra/john-mail.msg /etc/john/ +debian/extra/mailer /usr/sbin/ +run/john /usr/sbin/ +run/john.conf /etc/john/ diff --git a/debian/john.links b/debian/john.links new file mode 100644 index 0000000..b4895d7 --- /dev/null +++ b/debian/john.links @@ -0,0 +1,3 @@ +usr/sbin/john usr/sbin/unafs +usr/sbin/john usr/sbin/unique +usr/sbin/john usr/sbin/unshadow diff --git a/debian/man/john-mmx.8 b/debian/man/john-mmx.8 new file mode 100644 index 0000000..b89e751 --- /dev/null +++ b/debian/man/john-mmx.8 @@ -0,0 +1,22 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" john-mmx.8 is copyright 2009 by +.\" David Paleino +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH JOHN 8 "January 18, 2009" john-mmx +.\" Please adjust this date whenever revising the manpage. +.SH NAME +john \- a tool to find weak passwords of your users +.SH SYNOPSIS +.B john +.RI [ options ] +password-files +.SH DESCRIPTION +\fBjohn-mmx\fP is the MMX-optimized version of \fBjohn\fP. +.PP +Please see \fBman john\fP to read a proper manual page. +.SH SEE ALSO +.BR john (8) +.SH AUTHOR +This manual page was written by David Paleino . diff --git a/debian/man/john.8 b/debian/man/john.8 new file mode 100644 index 0000000..cb1e428 --- /dev/null +++ b/debian/man/john.8 @@ -0,0 +1,236 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" john.8 is copyright 1999-2001 by +.\" Jordi Mallach +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH JOHN 8 "June 09, 2008" john +.\" Please adjust this date whenever revising the manpage. +.SH NAME +john \- a tool to find weak passwords of your users +.SH SYNOPSIS +.B john +.RI [ options ] +password-files +.SH DESCRIPTION +This manual page documents briefly the +.B john +command. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +\fBjohn\fP, better known as John the Ripper, is a tool to find weak +passwords of users in a server. John can use a dictionary or some search +pattern as well as a password file to check for passwords. John supports +different cracking modes and understands many ciphertext formats, like +several DES variants, MD5 and blowfish. It can also be used to extract AFS +and Windows NT passwords. +.SH USAGE +To use John, you just need to supply it a password file and the desired +options. If no mode is specified, john will try "single" first, then +"wordlist" and finally "incremental". +.P +Once John finds a password, it will be printed to the terminal and saved +into a file called ~/.john/john.pot. John will read this file when it +restarts so it doesn't try to crack already done passwords. +.P +To see the cracked passwords, use +.P +john \-show passwd +.P +Important: do this under the same directory where the password was cracked +(when using the cronjob, /var/lib/john), otherwise it won't work. +.P +While cracking, you can press any key for status, or Ctrl+C to abort the +session, saving point information to a file ( +.I ~/.john/john.rec +by default). By the +way, if you press Ctrl+C twice John will abort immediately without saving. +The point information is also saved every 10 minutes (configurable in the +configuration file, +.I ~/.john/john.ini +or +.I ~/.john/john.conf +) in case of a crash. +.P +To continue an interrupted session, run: +.P +john \-restore +.P +Now, you may notice that many accounts have a disabled shell, you can make +John ignore these (assume that shell is called +.I /etc/expired +): +.P +john \-show \-shells:\-/etc/expired passwd +.P +You might want to mail all the users who got weak passwords, +to tell them to change the passwords. It's not always a good idea though +(unfortunately, lots of people seem to ignore such mail, it can be used +as a hint for crackers, etc), but anyway, I'll assume you know what you're +doing. Get a copy of the 'mailer' script supplied with John, so you won't +change anything that's under +.I /usr/sbin +; edit the message it sends, and +possibly the mail command inside it (especially if the password file is +from a different box than you got John running on). +Then run: +.P + ./mailer passwd +.P +Anyway, you probably should have a look at +.I /usr/share/doc/john/OPTIONS +for a list of all the command line options, and at +.I /usr/share/doc/john/EXAMPLES +for more John usage examples with other cracking modes. +.SH OPTIONS +All the options recognized by john start with a single dash (`\-'). +A summary of options is included below. +.TP +.B \-external:MODE +Enables an external mode, using external functions defined in ~/john.ini's +[List.External:MODE] section. +.TP +.B \-format:NAME +Allows you to override the ciphertext format detection. Currently, valid +format names are DES, BSDI, MD5, BF, AFS, LM. You can use this option when +cracking or with '\-test'. Note that John can't crack password files with +different ciphertext formats at the same time. +.TP +.B \-groups:[\-]GID[,..] +Tells John to load users of the specified group(s) only. +.TP +.B \-incremental[:MODE] +Enables the incremental mode, using the specified ~/john.ini definition +(section [Incremental:MODE], or [Incremental:All] by default). +.TP +.B \-makechars:FILE +Generates a charset file, based on character frequencies from +~/.john/john.pot, for use with the incremental mode. The entire +~/.john/john.pot will be used for the charset file unless you specify +some password files. You can also use an external filter() routine with +this option. +.TP +.B \-restore[:FILE] +Continues an interrupted cracking session, reading point information from +the specified file (~/.john/john.rec by default). +.TP +.B \-rules +Enables wordlist rules, that are read from [List.Rules:Wordlist] in +.I /etc/john/john.conf +(or the alternative configuration file you might specify on the command +line). +.br +This option +.B requires +the +.B -wordlist +option to be passed as well. +.TP +.B \-salts:[\-]COUNT +This feature sometimes allows you to achieve better performance. For example +you can crack only some salts using '\-salts:2' faster, and then crack the +rest using '\-salts:\-2'. Total cracking time will be about the same, but +you will get some passwords cracked earlier. +.TP +.B \-savemem:LEVEL +You might need this option if you don't have enough memory, or don't want +John to affect other processes too much. Level 1 tells John not to waste +memory on login names, so you won't see them while cracking. Higher levels +have a performance impact: you should probably avoid using them unless John +doesn't work or gets into swap otherwise. +.TP +.B \-session:FILE +Allows you to specify another point information file's name to use for +this cracking session. This is useful for running multiple instances of +John in parallel, or just to be able to recover an older session later, +not always continue the latest one. +.TP +.B \-shells:[\-]SHELL[,..] +This option is useful to load accounts with a valid shell only, or not to +load accounts with a bad shell. You can omit the path before a shell name, +so '\-shells:csh' will match both '/bin/csh' and '/usr/bin/csh', while +\'\-shells:/bin/csh' will only match '/bin/csh'. +.TP +.B \-show +Shows the cracked passwords in a convenient form. You should also specify +the password files. You can use this option while another John is cracking, +to see what it did so far. +.TP +.B \-single +Enables the "single crack" mode, using rules from [List.Rules:Single]. +.TP +.B \-status[:FILE] +Prints status of an interrupted or running session. To get an up to date +status information of a detached running session, send that copy of John +a SIGHUP before using this option. +.TP +.B \-stdin +These are used to enable the wordlist mode (reading from stdin). +.TP +.B \-stdout[:LENGTH] +When used with a cracking mode, except for "single crack", makes John +print the words it generates to stdout instead of cracking. While applying +wordlist rules, the significant password length is assumed to be LENGTH, +or unlimited by default. +.TP +.B \-test +Benchmarks all the enabled ciphertext format crackers, and tests them for +correct operation at the same time. +.br +This option does +.B not +need any file passed as argument. Its only function is to benchmark the +system john is running on. +.TP +.B \-users:[\-]LOGIN|UID[,..] +Allows you to filter a few accounts for cracking, etc. A dash before the +list can be used to invert the check (that is, load all the users that +aren't listed). +.TP +.B \-wordlist:FILE +These are used to enable the wordlist mode, reading words from FILE. +.SH MODES +John can work in the following modes: +.TP +\fBWordlist\fP +John will simply use a file with a list of words that will be checked +against the passwords. See RULES for the format of wordlist files. +.TP +\fBSingle crack\fP +In this mode, john will try to crack the password using the login/GECOS +information as passwords. +.TP +\fBIncremental\fP +This is the most powerful mode. John will try any character combination +to resolve the password. +Details about these modes can be found in the MODES file in john's +documentation, including how to define your own cracking methods. +.SH FILES +.TP +.I /etc/john/john.conf +is where you configure how john will behave. +.TP +.I /etc/john/john\-mail.msg +has the message sent to users when their passwords are successfully cracked. +.TP +.I /etc/john/john\-mail.conf +is used to configure how john will send messages to users that had their passwords +cracked. +.P +.SH SEE ALSO +.BR mailer (8), +.BR unafs (8), +.BR unique (8), +.BR unshadow (8), +.PP +The programs and the configuration files are documented fully by John's +documentation, which should be available in \fI/usr/share/doc/john\fP or +other location, depending on your system. +.SH AUTHOR +This manual page was written by Jordi Mallach +and Jeronimo Pellegrini , for the +Debian GNU/Linux system (but may be used by others). +.br +John the Ripper was written by Solar Designer . +The complete list of contributors can be found in the CREDITS file +in the documentation directory. diff --git a/debian/man/mailer.8 b/debian/man/mailer.8 new file mode 100644 index 0000000..4f2102a --- /dev/null +++ b/debian/man/mailer.8 @@ -0,0 +1,44 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" mailer.8 is copyright 1999-2001 by +.\" Jordi Mallach +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH MAILER 8 "June 03, 2004" john +.\" Please adjust this date whenever revising the manpage. +.SH NAME +mailer \- script to warn users about their weak passwords +.SH SYNOPSIS +.B mailer +\fIpassword-files\fP +.SH DESCRIPTION +This manual page documents briefly the +.B mailer +command, which is part of the john package. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +\fBjohn\fP, better known as John the Ripper, is a tool to find weak +passwords of users in a server. +.br +The \fBmailer\fP tool is useful to inform users which have been found to +be using weak passwords by mail. +.P +You should edit the message mailer will send to the users, but remember to +copy the script to a safe place before editing it, as it's +generally a bad idea to modify things living in /usr. +.SH SEE ALSO +.BR john (8), +.BR unafs (8), +.BR unique (8), +.BR unshadow (8). +.PP +The programs are documented fully by John's documentation, +which should be available in \fI/usr/share/doc/john\fP or other +location, depending on your system. +.SH AUTHOR +This manual page was written by Jordi Mallach , +for the Debian GNU/Linux system (but may be used by others). +.br +John the Ripper and mailer were written by Solar Designer +. The complete list of contributors can be found in +the CREDITS file in the documentation directory. diff --git a/debian/man/unafs.8 b/debian/man/unafs.8 new file mode 100644 index 0000000..bdcb29d --- /dev/null +++ b/debian/man/unafs.8 @@ -0,0 +1,40 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" unafs.8 is copyright 1999-2001 by +.\" Jordi Mallach +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH UNAFS 8 "June 03, 2004" john +.\" Please adjust this date whenever revising the manpage. +.SH NAME +unafs \- script to warn users about their weak passwords +.SH SYNOPSIS +.B unafs +\fIpassword-files cell-name\fP +.SH DESCRIPTION +This manual page documents briefly the +.B unafs +command, which is part of the john package. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +\fBjohn\fP, better known as John the Ripper, is a tool to find weak +passwords of users in a server. +.br +The \fBunafs\fP tool gets password hashes out of the binary AFS +database, and produces a file usable by John. +.SH SEE ALSO +.BR john (8), +.BR mailer (8), +.BR unique (8), +.BR unshadow (8). +.PP +The programs are documented fully by John's documentation, +which should be available in \fI/usr/share/doc/john\fP or other +location, depending on your system. +.SH AUTHOR +This manual page was written by Jordi Mallach , +for the Debian GNU/Linux system (but may be used by others). +.br +John the Ripper and mailer were written by Solar Designer +. The complete list of contributors can be found in +the CREDITS file in the documentation directory. diff --git a/debian/man/unique.8 b/debian/man/unique.8 new file mode 100644 index 0000000..ef98df9 --- /dev/null +++ b/debian/man/unique.8 @@ -0,0 +1,41 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" unique.8 is copyright 1999-2001 by +.\" Jordi Mallach +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH UNIQUE 8 "June 03, 2004" john +.\" Please adjust this date whenever revising the manpage. +.SH NAME +unique \- removes duplicates from a wordlist +.SH SYNOPSIS +.B unique +\fIoutput-file\fP +.SH DESCRIPTION +This manual page documents briefly the +.B unique +command, which is part of the john package. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +\fBjohn\fP, better known as John the Ripper, is a tool to find weak +passwords of users in a server. +.br +The \fBunique\fP tool finds and removes duplicate entries from a +wordlist (read from stdin), without changing the order. This is important +to increase the performance of john when using the wordlist method. +.SH SEE ALSO +.BR john (8), +.BR mailer (8), +.BR unafs (8), +.BR unshadow (8). +.PP +The programs are documented fully by John's documentation, +which should be available in \fI/usr/share/doc/john\fP or other +location, depending on your system. +.SH AUTHOR +This manual page was written by Jordi Mallach , +for the Debian GNU/Linux system (but may be used by others). +.br +John the Ripper and mailer were written by Solar Designer +. The complete list of contributors can be found in +the CREDITS file in the documentation directory. diff --git a/debian/man/unshadow.8 b/debian/man/unshadow.8 new file mode 100644 index 0000000..f79d3ca --- /dev/null +++ b/debian/man/unshadow.8 @@ -0,0 +1,43 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" +.\" unshadow.8 is copyright 1999-2001 by +.\" Jordi Mallach +.\" This is free documentation, see the latest version of the GNU General +.\" Public License for copying conditions. There is NO warranty. +.TH UNSHADOW 8 "June 03, 2004" john +.\" Please adjust this date whenever revising the manpage. +.SH NAME +unshadow \- combines passwd and shadow files +.SH SYNOPSIS +.B unshadow +\fIpassword-file shadow-file\fP +.SH DESCRIPTION +This manual page documents briefly the +.B unshadow +command, which is part of the john package. +This manual page was written for the Debian GNU/Linux distribution +because the original program does not have a manual page. +\fBjohn\fP, better known as John the Ripper, is a tool to find weak +passwords of users in a server. +.PP +The \fBunshadow\fP tool combines the passwd and shadow files so John can +use them. You might need this since if you only used your shadow file, the +GECOS information wouldn't be used by the "single crack" mode, and also you +wouldn't be able to use the '\-shells' option. On a normal system you'll need +to run unshadow as root to be able to read the shadow file. +.SH SEE ALSO +.BR john (8), +.BR mailer (8), +.BR unafs (8), +.BR unique (8). +.PP +The programs are documented fully by John's documentation, +which should be available in \fI/usr/share/doc/john\fP or other +location, depending on your system. +.SH AUTHOR +This manual page was written by Jordi Mallach , +for the Debian GNU/Linux system (but may be used by others). +.br +John the Ripper and mailer were written by Solar Designer +. The complete list of contributors can be found in +the CREDITS file in the documentation directory. diff --git a/debian/manpages b/debian/manpages new file mode 100644 index 0000000..df7b6dd --- /dev/null +++ b/debian/manpages @@ -0,0 +1,5 @@ +debian/man/john.8 +debian/man/mailer.8 +debian/man/unafs.8 +debian/man/unique.8 +debian/man/unshadow.8 diff --git a/debian/patches/allow-cflags-overriding.diff b/debian/patches/allow-cflags-overriding.diff new file mode 100644 index 0000000..bed78a7 --- /dev/null +++ b/debian/patches/allow-cflags-overriding.diff @@ -0,0 +1,32 @@ +Description: allows FLAGS modification from debian/rules +Author: Ruben Molina +Last-Update: 2013-06-04 +Forwarded: no + +Index: john-1.8.0/src/Makefile +=================================================================== +--- john-1.8.0.orig/src/Makefile 2013-05-29 18:21:25.000000000 -0500 ++++ john-1.8.0/src/Makefile 2013-06-04 01:17:22.272040456 -0500 +@@ -18,7 +18,7 @@ + TR = tr + SED = sed + NULL = /dev/null +-CPPFLAGS = -E ++CPPFLAGS += -E + OMPFLAGS = + # gcc with OpenMP + #OMPFLAGS = -fopenmp +@@ -28,11 +28,11 @@ + #OMPFLAGS = -fopenmp -D_FORTIFY_SOURCE=0 + # Sun Studio with OpenMP (set the OMP_NUM_THREADS env var at runtime) + #OMPFLAGS = -xopenmp +-CFLAGS = -c -Wall -Wdeclaration-after-statement -O2 -fomit-frame-pointer $(OMPFLAGS) ++CFLAGS += -c -Wall -Wdeclaration-after-statement -O2 -fomit-frame-pointer $(OMPFLAGS) + # CFLAGS for use on the main john.c file only + CFLAGS_MAIN = $(CFLAGS) + ASFLAGS = -c $(OMPFLAGS) +-LDFLAGS = -s $(OMPFLAGS) ++LDFLAGS += -s $(OMPFLAGS) + OPT_NORMAL = -funroll-loops + # Remove the "-Os" if you're using an ancient version of gcc + OPT_INLINE = -Os -funroll-loops -finline-functions diff --git a/debian/patches/arm-unroll-loops-ftbfs-476460.diff b/debian/patches/arm-unroll-loops-ftbfs-476460.diff new file mode 100644 index 0000000..c4070f1 --- /dev/null +++ b/debian/patches/arm-unroll-loops-ftbfs-476460.diff @@ -0,0 +1,20 @@ +Description: removes -funroll-loops (FTBFS in arm) + It will be conditionally set in debian/rules +Author: David Paleino +Reviewed-By: Ruben Molina +Bug-Debian: http://bugs.debian.org/476460 +Last-Update: 2013-06-04 +Forwarded: no + +Index: john-1.8.0/src/Makefile +=================================================================== +--- john-1.8.0.orig/src/Makefile 2013-06-04 01:19:37.244046143 -0500 ++++ john-1.8.0/src/Makefile 2013-06-04 01:19:38.876046194 -0500 +@@ -33,7 +33,6 @@ + CFLAGS_MAIN = $(CFLAGS) + ASFLAGS = -c $(OMPFLAGS) + LDFLAGS += -s $(OMPFLAGS) +-OPT_NORMAL = -funroll-loops + # Remove the "-Os" if you're using an ancient version of gcc + OPT_INLINE = -Os -funroll-loops -finline-functions + diff --git a/debian/patches/define-cfg-name.diff b/debian/patches/define-cfg-name.diff new file mode 100644 index 0000000..4b27e7e --- /dev/null +++ b/debian/patches/define-cfg-name.diff @@ -0,0 +1,25 @@ +Description: allows CFG_FULL_NAME/CFG_ALT_NAME modification from debian/rules +Author: Kees Cook +Reviewed-By: Ruben Molina +Last-Update: 2013-06-04 +Forwarded: no + +Index: john-1.8.0/src/params.h +=================================================================== +--- john-1.8.0.orig/src/params.h 2013-05-29 22:32:02.000000000 -0500 ++++ john-1.8.0/src/params.h 2013-06-04 01:20:08.292047105 -0500 +@@ -135,8 +135,12 @@ + /* + * File names. + */ +-#define CFG_FULL_NAME "$JOHN/john.conf" +-#define CFG_ALT_NAME "$JOHN/john.ini" ++#ifndef CFG_FULL_NAME ++#define CFG_FULL_NAME "$JOHN/john.conf" ++#endif ++#ifndef CFG_ALT_NAME ++#define CFG_ALT_NAME "$JOHN/john.ini" ++#endif + #if JOHN_SYSTEMWIDE + #define CFG_PRIVATE_FULL_NAME JOHN_PRIVATE_HOME "/john.conf" + #define CFG_PRIVATE_ALT_NAME JOHN_PRIVATE_HOME "/john.ini" diff --git a/debian/patches/enable-openmp-support.diff b/debian/patches/enable-openmp-support.diff new file mode 100644 index 0000000..be065ec --- /dev/null +++ b/debian/patches/enable-openmp-support.diff @@ -0,0 +1,20 @@ +Description: Enable OpenMP support +Origin: https://www.openwall.com/john/doc/ +Forwarded: not-needed +Author: Axel Beckert +Bug-Debian: https://bugs.debian.org/824107 + +--- a/src/Makefile ++++ b/src/Makefile +@@ -19,9 +19,9 @@ + SED = sed + NULL = /dev/null + CPPFLAGS += -E +-OMPFLAGS = ++#OMPFLAGS = + # gcc with OpenMP +-#OMPFLAGS = -fopenmp ++OMPFLAGS = -fopenmp + # gcc with OpenMP on 32-bit x86 with SSE2 + #OMPFLAGS = -fopenmp -msse2 + # Mac OS X (llvm-gcc) with OpenMP diff --git a/debian/patches/kfreebsd-c3_fmt.diff b/debian/patches/kfreebsd-c3_fmt.diff new file mode 100644 index 0000000..e731a42 --- /dev/null +++ b/debian/patches/kfreebsd-c3_fmt.diff @@ -0,0 +1,39 @@ +Description: adds c3_fmt.o to JOHN_OBJS in freebsd-* targets +Author: Julián Moreno Patiño +Reviewed-By: Ruben Molina +Last-Update: 2013-06-04 +Forwarded: no + +Index: john-1.8.0/src/Makefile +=================================================================== +--- john-1.8.0.orig/src/Makefile 2013-06-04 01:19:38.876046194 -0500 ++++ john-1.8.0/src/Makefile 2013-06-04 01:20:00.164046852 -0500 +@@ -308,24 +308,24 @@ + freebsd-x86-64: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ +- JOHN_OBJS="$(JOHN_OBJS) x86-64.o" ++ JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" + + freebsd-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ +- JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ ++ JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + + freebsd-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ +- JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ ++ JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-mmx.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + + freebsd-x86-any: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ +- JOHN_OBJS="$(JOHN_OBJS) x86.o" \ ++ JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + + freebsd-x86-any-a.out: diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..8f4eca5 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,5 @@ +allow-cflags-overriding.diff +arm-unroll-loops-ftbfs-476460.diff +kfreebsd-c3_fmt.diff +define-cfg-name.diff +enable-openmp-support.diff diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..237d7ce --- /dev/null +++ b/debian/postinst @@ -0,0 +1,68 @@ +#!/bin/sh +set -e + +# Versions earlier than 1.6-34 and later than (perhaps) 1.6-19 include +# /var/run/john as mode 0755, which could allow users to read cracked +# passwords. Later versions fixed the permissions of the included +# directory, but dpkg doesn't automatically make changes to directory +# modes. +fixperms () +{ + p=/var/run/john + # If the admin has an override, don't touch it + # (even if the override is to mode 0700?) + if [ -d $p ]; then + dpkg-statoverride --list $p >/dev/null && return + curmod=`stat -c %a $p` + [ $(( 0$curmod & 07077 )) -eq 0 ] && return + chmod -v 0700 $p + fi +} + +# Commit conffile move from preinst +rm_conffile_do () +{ + c=0 + # a=1 is a search if the files exist, + # a=2 is removal of those which do + for a in 1 2; do + for f in john-mail.conf john-mail.msg john.ini; do + g=/etc/$f.moved_by_preinst + [ -e $g ] || continue + c=$(( $c + 1 )) + [ "$a" -eq 1 ] && break + echo -n " " + rm -fv $g + done + + [ "$c" -eq 0 ] && return + [ "$a" -eq 1 ] || continue + echo "Committing removal of unmodified conffiles:" + done >&2 +} + +case $1 in +configure|abort-upgrade|abort-remove|abort-deconfigure) + fixperms + rm_conffile_do + + # this state file has moved to /var/lib/john quite some time ago + old=/usr/share/john/restore + new=/var/lib/john/restore + + if [ -e $old ] ; then + if [ -e $new ] ; then + rm -f $old + else + mv -f $old $new + fi + fi + ;; + +*) + echo "$0: undocumented call $@" >&2 + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000..cd8a8a3 --- /dev/null +++ b/debian/postrm @@ -0,0 +1,65 @@ +#!/bin/sh +set -e + +# Revert relocation of a conffile from one location to another. +# The forward path is preinst install|upgrade. +# $1 is the original pathname of the conffile, +# $2 is the pathname of the current conffile. +unmv_conffile () +{ + if [ -e "$1" ] ; then + echo "Not reverting conffile relocation to $2;" + echo "original pathname $1 exists." + elif [ -e "$1.moved_by_preinst" ] ; then + echo "Reverting removal of unmodified conffile:" + echo -n " " + mv -v "$1.moved_by_preinst" "$1" + elif [ -e "$2" ] ; then + echo "Reverting relocation of modified conffile to original location:" + echo -n " " + mv -fv $2 $1 + fi >&2 +} + +case $1 in +disappear|remove) + # These are the restore and cracked-password file used by the + # cronjob for attacking the system password file for a short + # period each day: + d=/var/lib/john + rm -f $d/restore $d/john.pot + d=/var/run/john +# FIXME: this is configurable... + rm -f "$d/john.pid $d/cronpasswd.*" + ;; + +abort-install|abort-upgrade) + # Revert relocation of conffiles: + p1=/etc + p2=/etc/john + if dpkg --compare-versions "$2" le-nl 1.6-27; then + unmv_conffile $p1/john.ini $p2/john.conf + unmv_conffile $p1/john-mail.conf $p2/john-mail.conf + unmv_conffile $p1/john-mail.msg $p2/john-mail.msg + + # "Display the warning, but don't fail if nonempty": + rmdir $p2 || rmdir --ignore-fail-on-non-empty $p2 + fi + ;; + +purge) + rmdir -pv /var/lib/john /var/run/john || true + ;; + +purge|upgrade|failed-upgrade) + # These cases need no actions here + : + ;; + +*) + echo "$0: undocumented call: $@" >&2 + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000..ec8e228 --- /dev/null +++ b/debian/preinst @@ -0,0 +1,61 @@ +#!/bin/sh +set -e + +# Relocate a conffile from one location to another; it is removed iff +# unmodified, and moved iff modified. +# The undo path is postrm abort-install|abort-upgrade. +# $1 is the old pathname of the conffile, +# $2 is the new pathname of the conffile. +mv_conffile () +{ + [ ! -f "$1" ] && return + if [ -e "$2" ] ; then + echo "Not moving conffile $1 to $2; new file exists" + return + fi + + orgmd5=`dpkg-query -W -f='${Conffiles}' dpkg | cut -d' ' -f3` + curmd5=`md5sum $1 |sed -e 's/ .*//'` + if [ "$orgmd5" = "$curmd5" ]; then + # conffile unmodified; prepare to remove it, allowing + # dpkg to install a new copy to the new location + # before "configuration" + echo "Preparing to remove unmodified conffile:" + echo -n " " + mv -fv $1 $1.moved_by_preinst + else + # conffile modified by admin; relocate it, causing + # dpkg to prompt, as intended + echo "Relocating modified conffile to new location:" + echo -n " " + mv -fv $1 $2 + fi >&2 +} + +p1=/etc +p2=/etc/john +case $1 in +install|upgrade) + [ -d $p2 ] || mkdir $p2 + if dpkg --compare-versions "$2" le-nl 1.6-27; then + mv_conffile $p1/john.ini $p2/john.conf + mv_conffile $p1/john-mail.conf $p2/john-mail.conf + mv_conffile $p1/john-mail.msg $p2/john-mail.msg + + # No need to remove the obsolete conffile + # /etc/cron.daily/john, since old prerm does so + # unconditionally (and there is nothing we can do to stop it) + fi + ;; + +abort-upgrade) + # This case needs no actions here + ;; + +*) + echo "$0: undocumented call: $@" + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/debian/prerm b/debian/prerm new file mode 100644 index 0000000..5f55c97 --- /dev/null +++ b/debian/prerm @@ -0,0 +1,20 @@ +#!/bin/sh +set -e + +case $1 in +remove) + /usr/share/john/cronjob stop + ;; + +upgrade|failed-upgrade|deconfigure) + # These cases need no actions here + : + ;; + +*) + echo "$0: undocumented call: $@" >&2 + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..f97f38f --- /dev/null +++ b/debian/rules @@ -0,0 +1,126 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This has to be exported to make some magic below work. +export DH_OPTIONS + +# Enable all hardening +export DEB_BUILD_MAINT_OPTIONS=hardening=+all + +# This is for the target selection +CPU := $(shell dpkg-architecture -qDEB_HOST_ARCH_CPU) +OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS) + +# This is to add missing hardening fortify functions export +CFLAGS += $(shell dpkg-buildflags --get CPPFLAGS) + +CFLAGS += -DJOHN_SYSTEMWIDE +# See src/params.h + +ifeq ($(OS),kfreebsd) + # enabling crypt(3) for kfreebsd, there is a patch adding fmt_c3.o + CFLAGS += -DHAVE_CRYPT + LDFLAGS += -lcrypt + # as we will use $(OS)-x86-*, it must be named freebsd, not kfreebsd + OS := freebsd +endif + +# arm FTBFS with -funroll-loops. Please see #476460 +ifneq ($(CPU),arm) + CFLAGS += -funroll-loops +endif + +# selecting compilation target +ifeq ($(OS),hurd) + TARGET := generic +else ifeq ($(CPU),i386) + # targeting an unoptimized binary first + TARGET := $(OS)-x86-any + # enabling i386 fallbacks + CFLAGS += -DCPU_FALLBACK +else ifeq ($(CPU),amd64) + TARGET := $(OS)-x86-64 +else ifeq ($(CPU),powerpc) + TARGET := linux-ppc32 +else ifeq ($(CPU),ppc64) + TARGET := linux-ppc64 +else ifeq ($(CPU),alpha) + TARGET := linux-alpha +else ifeq ($(CPU),sparc) + TARGET := linux-sparc +else ifeq ($(CPU),ia64) + TARGET := linux-ia64 +else + TARGET := generic +endif + +# please take a look at: +# https://buildd.debian.org/status/logs.php?pkg=john&ver=1.7.7-1 +ifeq ($(OS),freebsd) + # seems like freebsd targets don't like too much escaping + CFLAGS += -DJOHN_SYSTEMWIDE_EXEC=\"/usr/lib/john\" + CFLAGS += -DCFG_FULL_NAME=\"/etc/john/john.conf\" +else ifeq ($(TARGET),generic) + # and it is just the same for generic targets: + # armel, hurd-i386, mips, mipsel, and s390 + CFLAGS += -DJOHN_SYSTEMWIDE_EXEC=\"/usr/lib/john\" + CFLAGS += -DCFG_FULL_NAME=\"/etc/john/john.conf\" +else + # but, we need a lot of escaping for: + # amd64, i386, ia64, powerpc, and sparc + CFLAGS += -DJOHN_SYSTEMWIDE_EXEC=\\\"/usr/lib/john\\\" + CFLAGS += -DCFG_FULL_NAME=\\\"/etc/john/john.conf\\\" +endif + +# testing i386 for mmx instructions and sse2 extensions +ifeq ($(CPU),i386) + ifneq ($(OS),hurd) + MMX := $(shell grep -c '^flags.* mmx' /proc/cpuinfo) + ifneq ($(MMX),0) + HAVEMMX := 1 + endif + SSE := $(shell grep -c '^flags.* sse2' /proc/cpuinfo) + ifneq ($(SSE),0) + HAVESSE := 1 + endif + endif +endif + +%: + dh $@ --sourcedirectory=src --no-parallel + +override_dh_auto_build: + # building the selected target + dh_auto_build -- clean $(TARGET) +ifeq ($(HAVEMMX),1) + # renaming the non-mmx binary + mv run/john run/john-non-mmx + # building i386-mmx optimized binary + dh_auto_build -- clean $(OS)-x86-mmx +endif +ifeq ($(HAVESSE),1) + # renaming the non-sse2 binary + mv run/john run/john-non-sse + # building i386-sse2 optimized binary + dh_auto_build -- clean $(OS)-x86-sse2 +endif + +override_dh_auto_install: + # install the selected target + dh_auto_install + # install fallbacks as needed +ifeq ($(HAVEMMX),1) + dh_install run/john-non-mmx /usr/lib/john +endif +ifeq ($(HAVESSE),1) + dh_install run/john-non-sse /usr/lib/john +endif + +override_dh_auto_clean: + dh_auto_clean + # script-not-executable + chmod +x debian/extra/cronjob + +override_dh_auto_test: diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml new file mode 100644 index 0000000..0c22dc4 --- /dev/null +++ b/debian/salsa-ci.yml @@ -0,0 +1,3 @@ +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc new file mode 100644 index 0000000..6ddafe2 --- /dev/null +++ b/debian/upstream/signing-key.asc @@ -0,0 +1,50 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFoQgb0BEAC+DksApeHsB/nZYwbmXzoWCYCGZvzRzoXVVJOqYTZbumYqlgWv +pieSSIuHUfbpeAaDjchlJWy3w0xkPW+TP63XTLnwViATsTJtdkACHfT8P792Tfrn +XhYer3c/N3tSWwFTN+wLZF3OpH4XdOfXaFxRIvVWxych/WHmcteVinCjeXZvAwLg +ZbYnADLW/db8CK+kfXFiuGssmrYKkJcTqNhIi05EkQhatwtmgHPMqxyIPHdnlU+q +/0uN4J+XQvkzbUXVjuEqwvbRlOHNDgb6Q9j+tMULefBFb7FGvanw0fgjV0rWtvHy +sY3r9GGxrwAt1GP/TLAPkuL2EVRVtsOmpjTFxj5GgTn6NngpDB4YMsuQB+zCLlPe +yPuwlFvQ6Hk+2GlVG/FtSVwIYmWkFNUyvrQg/l9gLZGAv3Lo/csTUka+9IH6rLXZ +tnL5LiUd/zQexV2jmwenaxQOjaoPGuwzyo+rJjGrL7xF3O4b5Rkk9TnUG27zR7Vl +MwZ4nyQNyabLWmJAFjWeHoQfbRv6ma9iKAZiwprGv+AIccB6psX5o2HLjMqX0uCC +WnWqpZa+vAsDfx1XaXdS5gp9I8ZNKgnZUtys1OswCkx2nHhA1f995jcSkJanEztY +uTDXGbC+Arh+i43KtbfVtGygfFwvIOnE+JuJgOaE4TuJHfiVX343ANIrbQARAQAB +tBxPcGVud2FsbCBvZmZsaW5lIHNpZ25pbmcga2V5iQI4BBMBAgAiBQJaEIG9AhsD +BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAFwCf9S9wTbutbD/wP+Wpp2RzP +zhUtVeAeTAbwuZUBVXMvuqnxCoAaUGTr3SKTGe2bLjjSvy1T5Zh+I6wCA5sy7AX7 +LRwgG3frn4Gt+6D4tIbx5xjxx4bJiR5gn33MKl+8DelkB3feS0TLsWoDnrkKnTSk +vEEi8sYi3obdkZRCEE+LdDs3xiy2bC0WYRYKe8CGyKQQRNh6B2eq9IK4saCPCmaZ +9OgoW6DVvkC4qHGVlvhHews9XRXm7xnJ3awh1ru1pKDNedygk8klYGWc+AXkLppG +eMQ/sVv2rQXCU8ADrr+jGW4Goiki5YJqNCul1gijThTppL+BazZV0FWEyj0X8eXE +wR+mgwa+4Q+6v+75S67kkQcFUw8GH8NKcU/LRjslFf4aDIDnu6Yy4L8bKsDENjPj +g3zMHi53Ts8FMNLfepUpAtBLzqnZOm9ylU+PrmJ5GkMC5Ka9N/Rg8yRsRI/XuOzb +Kj//721XN9M+JbjZ5bfI0TxLk0TJhCSFjHpbuPYfUl4kjpx4kZlMPuyzbkQxRWGN +b1hnMfnfdCFGnJa9kVil8YQ+hmPi5RIHVD24yD86Rc1tLSZR2HNes8Ly2dhdnaKR +SFrNzLAhfZ5XldJbwsNKysNVED1cx6t6sYYj8LsZSETcp7LWONNxvA/2MwsbFet4 +YvDolumaqLr46KOQjSIB0AY62RoWq3hv0bkCDQRaEIG9ARAAtyk4JFIRkP1vyADr +xoAZK9OzwhYdhPON21bJK4ppq2Jm7m/yhhoLHUMJ22jNSq/wq0MUJXL8U8zcN0E6 +jDyucdo+4IBPuGZl4cdIuN53qMTzy9WOC7SNTQMeXIflAqVYRPHJILomwB2sYYoe +84zpKyP/U6skdpISgYYobfzR9G1CbXzefVOHi3b7y7HmCHy/oGMpIf5iTwOQYxCz +OqOd2lTGGbIZ1oaPF4PuQT+OiGsMidgwz+odRzyjtLeoIBtxgtEJ8VeHl/Z7Nh5u +EQkrPd0Q10A63hlaLiB3+OizEzbuNYJUS4JydWe6pVNExNP4CyyU6evOskUeTyU/ +jSfHNZ5JCiolOcyio6g/lFVBlqsATt9LM6qyPSUGdg55xRjCmTQzoVAAuhHiWXSY +Xv3Lg5q5KHqN978eX5of/hRTmwExoG+J6L7OPOCLCivDybjGNljoQwIYgt6gDMtW +q/dqs8KvySBliWTeaN+sjwVwUQVjujtB7hYrVzRvpCM8mK2aGAbOCnInMo0FSG5C +ZwsMrZvZGIszyj9HhnYkTRtPRWtBDBkiNxBcEEkRUlDF2rTy/FY9aQ4WfjdkhHEq +Yo2fW669wWUJzA8fqcMerfnqjzA8O4kw+DBy3LE2RjlOT7Irm4ij1p3ZO78hXbsW +7FBp8Tcf+HtTAC856glDglSaxEUAEQEAAYkCHwQYAQIACQUCWhCBvQIbDAAKCRAF +wCf9S9wTbka5D/9g3Y3vt4o9Sh9jDSaVpuJFSPJ1GK7faycsgDDs+y5RlI/zis7J +UGOXg2WoqiFb2nEc2wEy2P4Pl0/ROjfPQEOH16jOWur+GFhSxrrMaVhnSP1UJsih +Pp9wCCRRJVrI6mNy2zHHQlJw/JYxUDnyhNwVYs6q4J27vifqhQTcgS6SGE2xowdK +y44FRtyCpXeNUomWMyY7RRfDD4O2FQ5raZaaAD1ym4G3hwZ1593WdjaI9qKrW9ho +40I0yVM1i1Yic7sUjroaLwKEFBr+JzOJYUbp3TMHvjNqbnsOaJlAsKPECExqc1GK +07NmlZugVAaQ5d6JJEo7NxY5PJglbDHGXEuC19geNSQTZWak9/tBR5yYTReLZVBf +jhb+CUIsPnkDEjL/XgzXCJp9pPHXrcpudEu2xLbf5opvWDiDCCW5xUMfKIf9l3pA +TC/1xFDEf/LPuXZYDDjZZP5speb3gGVqYteMNJpmetJoJ3LOdXN8Uchk5nTfsfmh +Wo2nuFp6FyqeRQNTbuSCGyJmXSuX62q5LksgVzTd3OgOCHjsjzEbVU58+TX7Z/V2 ++iBqlnWwg/W+/bRWAvbUsEEhhN0TDFsHEIkYrkKN3iKn6oeI75hVKxZJWH3EVX/Y +uadXcCs/e77lKhuFz3jofL4/VGTumzkCN1C44iChUlJZPDme3LmQEFWqDw== +=kkUp +-----END PGP PUBLIC KEY BLOCK----- diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..4d172b6 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +version=4 +opts=pgpsigurlmangle=s/$/.sign/ \ +https://www.openwall.com/john/ ./john-([\d\.]+)\.tar\.xz diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 0000000..b81646a --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,331 @@ +The following changes have been made between John 1.7.9.8 and 1.8.0: + +* Revised the incremental mode to let the current character counts grow for +each character position independently, with the aim to improve efficiency in +terms of successful guesses per candidate passwords tested. +* Revised the pre-defined incremental modes, as well as external mode filters +that are used to generate .chr files. +* Added makechr, a script to (re-)generate .chr files. +* Enhanced the status reporting to include four distinct speed metrics (g/s, +p/s, c/s, and C/s). +* Added the "--fork=N" and "--node=MIN[-MAX]/TOTAL" options for trivial +parallel and distributed processing. +* In the external mode compiler, treat character literals as unsigned. +* Renamed many of the formats. +* Updated the documentation. +* Relaxed the license for many source files to cut-down BSD. +* Relaxed the license for John the Ripper as a whole from GPLv2 (exact version) +to GPLv2 or newer with optional OpenSSL and unRAR exceptions. +* Assorted other changes have been made. + +The following changes have been made between John 1.7.9 and 1.7.9.8: + +* Enhanced the support for DES-based tripcodes by making use of the bitslice +DES implementation and supporting OpenMP parallelization. +* Implemented bitmaps for fast initial comparison of computed hashes against +those loaded for cracking. This is applied before hash table lookups, and it +allows for the use of smaller hash tables (thereby saving memory) while +achieving the same or greater speed that larger hash tables previously did. +The speed increase is due to improved locality of reference (where only the +smaller bitmap is accessed all the time, whereas the larger hash table behind +it is only accessed for a percentage of comparisons and additionally it is +smaller than it would otherwise need to be). +* Tuned the bitmap and hash table sizes and thresholds based on testing on +saltless hashes on a Core 2'ish CPU. +* When cracking LM hashes, don't store the ASCII encodings of the hashes in +memory, but instead reconstruct them from the binary hashes for writing into +john.pot when a password gets cracked. +* With 32-bit x86 builds and at least MMX enabled, the "two hashes at a time" +code for bcrypt is now enabled for GCC 4.2 and newer. This change is made +based on benchmark results for different builds made with different versions of +GCC on CPUs ranging from Pentium 3 to Core i7. Unfortunately, there's a known +performance regression with this change on Atom. Previously, this code was +only enabled for x86-64 and/or OpenMP-enabled builds. +* The formats interface has been enhanced to better support GPU implementations +(in jumbo), as well as fast hashes on multi-CPU systems (not yet made use of). +* Assorted minor corrections to Cygwin builds were made. +* Fixed a bug in the Keyboard external mode (uninitialized variables on +"--restore" or when minlength is greater than 1). +* Enhanced the generic crypt(3) format to handle possible NULL returns from +crypt() and crypt_r(). +* Updated the FAQ. + +The following changes have been made between John 1.7.8 and 1.7.9: + +* Added optional parallelization of the MD5-based crypt(3) code with OpenMP. +* Added optional parallelization of the bitslice DES code with OpenMP. +* Replaced the bitslice DES key setup algorithm with a faster one, which +significantly improves performance at LM hashes, as well as at DES-based +crypt(3) hashes when there's just one salt (or very few salts). +* Optimized the DES S-box x86-64 (16-register SSE2) assembly code. +* Added support for 10-character DES-based tripcodes (not optimized yet). +* Added support for the "$2y$" prefix of bcrypt hashes. +* Added two more hash table sizes (16M and 128M entries) for faster processing +of very large numbers of hashes per salt (over 1M). +* Added two pre-defined external mode variables: "abort" and "status", which +let an external mode request the current cracking session to be aborted or the +status line to be displayed, respectively. +* Made some minor optimizations to external mode function calls and virtual +machine implementation. +* The "--make-charset" option now uses floating-point rather than 64-bit +integer operations, which allows for larger CHARSET_* settings in params.h. +* Added runtime detection of Intel AVX and AMD XOP instruction set extensions, +with optional fallback to an alternate program binary. +* In OpenMP-enabled builds, added support for fallback to a non-OpenMP build +when the requested thread count is 1. +* Added relbench, a Perl script to compare two "john --test" benchmark runs, +such as for different machines, "make" targets, C compilers, optimization +options, or/and versions of John the Ripper. +* Additional public lists of "top N passwords" have been merged into the +bundled common passwords list, and some insufficiently common passwords were +removed from the list. +* Many minor enhancements and a few bug fixes were made. + +The following changes have been made between John 1.7.7 and 1.7.8: + +* The bitslice DES S-box expressions have been replaced with those generated +by Roman Rusakov specifically for John the Ripper. The corresponding assembly +code for x86 with MMX, SSE2, and for x86-64 with SSE2 has been re-generated. +For other CPUs and for AVX/XOP, C compilers do a reasonably good job of +generating the code from the supplied C source files (with intrinsics where +relevant). The S-box expressions that we were using before had a 21% larger +gate count, so theoretically this could provide a 21% speedup. In practice, +though, a 12% to 14% speedup at DES-based crypt(3) hashes is typical. +This effort has been sponsored by Rapid7: http://www.rapid7.com +* Corrected support for bcrypt (OpenBSD Blowfish) hashes of passwords +containing non-ASCII characters (that is, characters with the 8th bit set). +Added support for such hashes produced by crypt_blowfish up to 1.0.4, which +contained a sign extension bug (inherited from older versions of John). +The old buggy behavior may be enabled per-hash, using the "$2x$" prefix. +* The external mode virtual machine's performance has been improved through +additional multi-op instructions matching common instruction sequences +(assign-pop and some triple- and quad-push VM instructions were added). +* A few minor bug fixes and enhancements were made. + +The following changes have been made between John 1.7.6.1 and 1.7.7: + +* Added Intel AVX and AMD XOP instruction sets support for bitslice DES +(with C compiler intrinsics). New make targets: linux-x86-64-avx, +linux-x86-64-xop, linux-x86-avx, and linux-x86-xop (these require recent +versions of GCC and GNU binutils). +* A "dummy" "format" is now supported (plaintext passwords encoded in +hexadecimal and prefixed with "$dummy$") - for faster testing and tuning of +custom wordlists, rule sets, .chr files, and external modes on already known or +artificial passwords, as well as for testing of future and modified versions of +John itself. +* Apache "$apr1$" MD5-based password hashes are now supported along with the +FreeBSD-style MD5-based crypt(3) hashes that were supported previously. Hashes +of both of these types may be loaded for cracking simultaneously. +* The "--salts" option threshold is now applied before removal of previously +cracked hashes for consistent behavior with interrupted and continued sessions. +* The "Idle = Y" setting (which is the default) is now ignored for +OpenMP-enabled hash types when the actual number of threads is greater than 1. +(Unfortunately, it did not work right at least with GNU libgomp on Linux.) +* When a cracking session terminates or is interrupted, John will now warn the +user if the cracked passwords printed to the terminal while cracking are +potentially incomplete. It will advise the user to use the "--show" option to +see the complete set of cracked passwords with proper post-processing. +* When loading hashes specified on a line on their own (feature introduced in +1.7.6), the loader will now ignore leading and trailing whitespace. +* Unless a hash type is forced from the command line, the loader will now print +warnings about additional hash types seen in the input files (beyond the hash +type autodetected initially). +* For use primarily by the jumbo patch (and later by future enhancements to the +official versions as well), the loader now includes logic to warn the user of +ambiguous hash encodings (e.g. LM vs. NTLM vs. raw-MD5, all of which may be +represented as 32 hexadecimal characters) and of excessive partial hash +collisions, which it works around (these are typically caused by an incomplete +implementation of a new hash type). +* The "unique" and "unshadow" programs have been made significantly faster. +* "DateTime", "Repeats", "Subsets", "AtLeast1-Simple", "AtLeast1-Generic", and +"Policy" external mode samples have been added to the default john.conf. +* The self-tests have been enhanced to detect more kinds of program bugs. +* A few minor bug fixes and enhancements were made. + +The following changes have been made between John 1.7.6 and 1.7.6.1: + +* Corrected a logic error introduced in JtR 1.7.4.2: in "single crack" mode, +we need a salt's key buffer even when we have no words corresponding to that +salt's hashes to base candidate passwords on. We need this buffer to hold +other salts' successful guesses for testing against this salt's hashes. + +The following changes have been made between John 1.7.5.1 and 1.7.6: + +* Generic crypt(3) support (enabled with "--format=crypt") has been added for +auditing password hash types supported by the system but not yet supported by +John's own optimized cryptographic routines (such as SHA-crypt and SunMD5). +* Optional parallelization of the above has been implemented by means of OpenMP +along with glibc's crypt_r(3) or Solaris' MT-safe crypt(3C). +* Optional parallelization of John's own optimized code for the OpenBSD-style +Blowfish-based crypt(3) (bcrypt) hashes with OpenMP has been added. +* A more suitable version of 32-bit x86 assembly code for Blowfish is now +chosen on Core i7 and similar CPUs (when they happen to run a 32-bit build). +* More optimal DES S-box expressions for PowerPC with AltiVec (making use of +the conditional select operation) contributed by Dumplinger Boy (Dango-Chu) +have been integrated. +* The bitslice DES C source code has been reworked to allow for the use of +arbitrary SIMD intrinsics, which was previously only implemented for AltiVec +as a special case. +* Support for SSE2 and MMX intrinsics with bitslice DES (as an alternative to +the supplied assembly code) has been added (currently only enabled for SSE2 on +x86-64 when compiling with GCC 4.4+). +* Support for mixed-type longer virtual vectors (such as SSE2+MMX, SSE2+ALU, +AltiVec+ALU, and other combinations) with bitslice DES has been added (not +enabled by default yet, primarily intended for easy benchmarks on future CPUs, +with future compiler versions, with even more SIMD instruction sets, and with +different DES S-box expressions that might be available in the future). +* The obsolete 32-bit SPARC assembly implementation of DES has been dropped. +* The loader will now detect password hashes specified on a line on their own, +not only as part of an /etc/passwd or PWDUMP format file. +* When run in "--stdin" mode and reading candidate passwords from a terminal +(to be typed by the user), John will no longer mess with the terminal settings. +* John will now restore terminal settings not only on normal termination or +interrupt, but also when forcibly interrupted with two Ctrl-C keypresses. + +The following changes have been made between John 1.7.5 and 1.7.5.1: + +* A new numeric variable has been added to the word mangling rules engine: +"p" for position of the character last found with the "/" or "%" commands. + +The following changes have been made between John 1.7.4.2 and 1.7.5: + +* Support for the use of "--format" along with "--show" or "--make-charset" has +been added. +* The choice of .rec and .log filenames for custom session names has been made +more intuitive. +* Support for "\r" (character lists with repeats) and "\p0" (reference to the +immediately preceding character list/range) has been added to the word mangling +rules preprocessor. +* The undefined and undocumented behavior of some subtle word mangling rules +preprocessor constructs has been changed to arguably be more sensible. +* Some bugs were fixed, most notably JtR crashing on no password hashes loaded +(bug introduced in 1.7.4.2). + +The following changes have been made between John 1.7.4 and 1.7.4.2: + +* Major performance improvements for processing of very large password files +or sets of files, especially with salt-less or same-salt hashes, achieved +primarily through introduction of two additional hash table sizes (64K and 1M +entries), changes to the loader, and smarter processing of successful guesses +(to accommodate getting thousands of hashes successfully cracked per second). +* Many default buffer and hash table sizes have been increased and thresholds +for the use of hash tables lowered, meaning that John will now tend to use +more memory to achieve better speed (unless it is told not to with the +"--save-memory" option). +* Some previously missed common website passwords found on public lists of +"top N passwords" have been added to the bundled common passwords list. +* Some bugs introduced in 1.7.4 and affecting wordlist mode's elimination of +consecutive duplicate candidate passwords have been fixed. + +The following changes have been made between John 1.7.3.4 and 1.7.4: + +* Support for back-references and "parallel" ranges has been added to the +word mangling rules preprocessor. +* The notion of numeric variables (to be used for character positions +and substring lengths along with numeric constants supported previously) +has been introduced into the rules engine. Two pre-defined variables +("l" for initial or updated word's length and "m" for initial or +memorized word's last character position) and 11 user-defined variables +("a" through "k") have been added. Additionally, there's a new numeric +constant: "z" for "infinite" position or length. +* New rule commands have been added: "A" (append, insert, or prefix with a +string), "X" (extract a substring from memory and insert), "v" (subtract +and assign to a numeric variable). +* New rule reject flags have been added: ":" (no-op, for use along with the +"parallel" ranges feature of the preprocessor) and "p" (reject unless word +pair commands are allowed, for sharing of the same ruleset between "single +crack" and wordlist modes). +* Processing of word mangling rules has been made significantly faster in +multiple ways (caching of the current length, less copying of data, code +and data placement changes for better branch prediction and L1 cache usage, +compiler-friendly use of local variables, code micro-optimizations, +removal of no-op rule commands in an initial pass). +* The default rulesets for "single crack" and wordlist modes have been +revised to make use of the new features, for speed, to produce fewer +duplicates, and to attempt additional kinds of candidate passwords (such +as for years 2010 through 2019 with "year-based" rules). +* The idle priority emulation code has been optimized for lower overhead when +there appears to be no other demand for CPU time. +* The default for the Idle setting has been changed from N to Y. + +The following changes have been made between John 1.7.3.1 and 1.7.3.4: + +* "make check" has been implemented (for Unix-like systems only). +* The "--test" option will now take an optional argument - the duration of each +benchmark in seconds. +* Section .note.GNU-stack has been added to all assembly files to avoid the +stack area unnecessarily being made executable on Linux systems that use this +mechanism. +* Some very minor bugs that did not affect normal operation have been fixed. +* Some unimportant compiler warnings have been fixed, a source code comment has +been made more verbose and more complete. + +The following changes have been made between John 1.7.3 and 1.7.3.1: + +* Corrected the x86 assembly files for building on Mac OS X. +* Merged in some generic changes from JtR Pro. + +The following changes have been made between John 1.7.2 and 1.7.3: + +* Two Blowfish-based crypt(3) hashes may now be computed in parallel for much +better performance on modern multi-issue CPUs with a sufficient number of +registers (e.g., x86-64). +* Bitslice DES assembly code for x86-64 has been converted to use +instruction pointer relative addressing (needed for Mac OS X support). +* New make targets: macosx-universal, macosx-x86-64, solaris-x86-64-cc, +solaris-x86-64-gcc, solaris-x86-sse2-cc, solaris-x86-sse2-gcc, +solaris-x86-mmx-cc, solaris-x86-mmx-gcc, solaris-x86-any-cc, linux-ia64; +other changes to the Makefile. +* Minor bug fixes. +* "DumbForce" and "KnownForce" external mode samples have been added to the +default john.conf. + +The following changes have been made between John 1.7.1 and 1.7.2: + +* Bitslice DES assembly code for x86-64 making use of the 64-bit mode +extended SSE2 with 16 XMM registers has been added for better performance +at DES-based crypt(3) hashes with x86-64 builds on AMD processors. +* New make target for FreeBSD/x86-64. + +The following changes have been made between John 1.7.0.2 and 1.7.1: + +* Bitslice DES code for x86 with SSE2 has been added for better performance +at DES-based crypt(3) hashes on Pentium 4 and SSE2-capable AMD processors. +* Assorted high-level changes have been applied to improve performance +on current x86-64 processors. +* New make target for NetBSD/SPARC64. +* Minor source code cleanups. + +The following changes have been made between John 1.7 and 1.7.0.2: + +* Minor bug and portability fixes. +* Better handling of certain uncommon scenarios and improper uses of John. +* Bonus: "Keyboard" cracker included in the default john.conf (john.ini) +that will try sequences of adjacent keys on a keyboard as passwords. + +The following changes have been made between John 1.6 and 1.7: + +* Bitslice DES code for x86 with MMX: more than twice faster than older +non-bitslice MMX code. +* Bitsliced the LM hash code as well: now several times faster. +* Significant improvements to the generic bitslice DES code: +20% on RISC. +* PowerPC G4+ AltiVec support (Mac OS X and Linux): effective 128-bitness +for bitslice DES, resulting in huge speedups. +* First attempt at generic vectorization support for bitslice DES. +* Two MD5 hashes at a time for extra ILP on RISC: up to +80% on Alpha EV5+. +* Generic Blowfish x86 assembly code in addition to the original Pentium +version: +15% on the Pentium Pro family (up to and including Pentium III), ++20% on AMD K6 (Pentium 4 and newer AMD CPUs are more happy running the +original Pentium code for Blowfish). +* Verbose logging of events to the global or a session-specific log file. +* Better idle priority emulation with POSIX.1b (POSIX.4) scheduling calls. +* System-wide installation support for *BSD ports and Linux distributions. +* AIX, DU/Tru64 C2, HP-UX tcb files support in unshadow. +* New make targets for Linux/x86-64, Linux/PowerPC, FreeBSD/Alpha, +OpenBSD/x86-64, OpenBSD/Alpha, OpenBSD/SPARC, OpenBSD/SPARC64, +OpenBSD/PowerPC, OpenBSD/PA-RISC, OpenBSD/VAX, NetBSD/VAX, Solaris/SPARC64, +Mac OS X (PowerPC and x86), SCO, BeOS. +* Bug and portability fixes, and new bugs. +* Bonus: "Strip" cracker included in the default john.conf (john.ini). + +$Owl: Owl/packages/john/john/doc/CHANGES,v 1.91 2013/05/30 03:11:02 solar Exp $ diff --git a/doc/CONFIG b/doc/CONFIG new file mode 100644 index 0000000..92f4543 --- /dev/null +++ b/doc/CONFIG @@ -0,0 +1,125 @@ + Customizing John the Ripper. + +John the Ripper's behavior can be customized by editing its +configuration file. The configuration file can be named either +john.conf (on Unix-like systems) or john.ini (on systems which have a +notion of filename "extensions" and limit them to 3 characters). + +This file is searched for in private John's "home directory" and, if +not found in the private directory and John is installed system-wide, +also in John's system-wide shared data files directory. + +You can set global options, define wordlist and "single crack" mode +rules, define parameters for "incremental" modes, or even define a new +external cracking mode. + +The configuration file consists of several sections. Each section +starts with a line containing its name, in brackets ("[...]"). Sections +consist either of "variable = value" assignments (each on its own line) +or of some other content specific to the particular section's type +(names of such sections start with "List."). Section and variable names +are not case sensitive. Comment lines start with a hash character ("#") +or a semicolon (";") and are ignored. Also ignored are any empty lines. + + + General options. + +Some global options can be defined in the [Options] section. Currently, +you can set the following options: + +Wordlist = FILENAME + +Set this to your wordlist file name, to be used in batch mode (which is +activated when you start John with password files, but not specifying a +cracking mode). The default is "$JOHN/password.lst", that is, the file +named "password.lst" in John's "home directory". + +Idle = Y|N + +If set to "Y" (yes), John will try to use idle processor cycles only, +thereby greatly reducing its impact on other system processes. The +impact on performance of John itself is negligible except on otherwise +overloaded systems. This setting does not affect John's startup time +and non-cracking invocations of John; it only affects the actual +cracking. The default is "Y" (yes). + +Starting with version 1.7.7, this setting is ignored for OpenMP-enabled +hash types when the actual number of threads is greater than 1. +Unfortunately, it did not work right at least with GNU libgomp on Linux. + +Save = SECONDS + +This is the time interval (in seconds) between crash recovery file +updates. The default is 600 seconds (10 minutes). + +Beep = Y|N + +If set to "Y" (yes), John will beep when a password is found. On +Unix-like systems, it does this by sending the bell character (ASCII +code 7) to the "standard error" file descriptor (which is normally +directed to the terminal). The default is "N" (no). + + + Defining wordlist and "single crack" modes rules. + +The word mangling rules for wordlist and "single crack" modes are +defined in separate sections, [List.Rules:Wordlist] and +[List.Rules:Single], respectively. John the Ripper uses an extension of +Crack's syntax for the rules. John supports all of the commands of +Crack 5.0a plus a few more and, most importantly, it adds a +preprocessor, which can generate multiple rules from a single source +line. + +When defining rules, simply place one rule (which may include +preprocessor commands) per line. See RULES for information on the rules +syntax and on the preprocessor. + + + "Incremental" mode parameters. + +To define the incremental mode parameters you need to create a section +called [Incremental:MODE], where MODE is any name that you assign to the +mode. There are some pre-defined incremental modes in the default +configuration file supplied with John, you can use them as templates. + +The following parameters are supported: + +File = FILENAME + +Set this to your charset file name. See EXAMPLES for an example on how +to generate a custom charset file. There's no default. + +MinLen = LENGTH + +Minimum password length (the number of characters) to try. The default +is 0. + +MaxLen = LENGTH + +Maximum password length to try. The default is 8 (or CHARSET_LENGTH as +defined in src/params.h at compile time). + +CharCount = COUNT + +This allows you to limit the number of different characters (or rather, +character indices) used. The effect is that John would favor simple +longer candidate passwords over more complicated shorter ones, and would +never attempt rare characters and character combinations, not even for +really short passwords. Most of the time, this is undesired. Another +use for this option is to make John print a warning if the charset only +defines less than CharCount characters; this is how the pre-defined +"incremental" modes use it. The default is to use as many different +characters as are defined. + +Extra = CHARACTERS + +This can be used to make John try some extra characters that don't +appear in the charset file. Just list all those characters here and +they will be added, but considered the least probable. + + + Defining an external mode. + +See EXTERNAL. + +$Owl: Owl/packages/john/john/doc/CONFIG,v 1.5 2011/02/27 07:16:16 solar Exp $ diff --git a/doc/CONTACT b/doc/CONTACT new file mode 100644 index 0000000..727e279 --- /dev/null +++ b/doc/CONTACT @@ -0,0 +1,30 @@ +John the Ripper homepage is located at: + + http://www.openwall.com/john/ + +There you will find instructions on joining the john-users mailing list. +You will also be able to browse archives of past discussions. Please +share your experience with using John the Ripper and ask questions +(preferably advanced ones) on the list. Be sure to specify an +informative message subject whenever you post to the list (that is, +something better than "question" or "problem") and mention the version +of John the Ripper, operating system, compiler, make target, etc. that +you're using (if applicable). If you need to provide a binary file, +place it on a private URL and post that, do not attach the file to your +message. + +If you absolutely need to contact me (the original author of John the +Ripper) privately, please e-mail me at: + + Solar Designer + +although most messages should really be directed to the list instead +(and you're more likely to receive a response if you write to the list). + +Please don't ask questions until you read the FAQ. + +Commercial support for John the Ripper is available from Openwall: + + http://www.openwall.com/services/ + +$Owl: Owl/packages/john/john/doc/CONTACT,v 1.4 2013/05/30 00:10:11 solar Exp $ diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/doc/CREDITS b/doc/CREDITS new file mode 100644 index 0000000..22a075b --- /dev/null +++ b/doc/CREDITS @@ -0,0 +1,75 @@ + John the Ripper credits. + +John the Ripper has been developed and is maintained by Solar Designer. + +I would like to thank the following people for their direct or indirect +help in making John what it is now: + +* Matthew Kwan - for producing and letting everyone use his optimized +DES S-box expressions (previously found in nonstd.c and sboxes.c, now +replaced with Roman Rusakov's): + + http://www.darkside.com.au/bitslice/ + +* Bruce Ford and Rémi Guyomarch - for producing and permitting the use +of their MMX implementation of Matthew Kwan's S-box expressions +(previously found in x86-mmx.S and x86-sse.S, with modifications, now +replaced with code based on Roman Rusakov's S-box expressions). + +* Dumplinger Boy (Dango-Chu) - for producing and letting everyone use +his optimized DES S-box expressions making use of a vector conditional +select operation such as on PowerPC with AltiVec (previously found in +sboxes-s.c, now replaced with Roman Rusakov's): + + http://dango.chu.jp/hiki/?Enhanced+Bitslice+DES + +* Roman Rusakov - for the DES S-box expressions that current versions of +John the Ripper use, as well as for optimization hints during early +development of John the Ripper. + +* Eli Biham - for the great "bitslice" paper: + + http://www.cs.technion.ac.il/~biham/Reports/cs0891.ps.gz + +* Lionel Cons - for making me add Kerberos AFS passwords support, for +reporting some bugs, and for many good suggestions. + +* stran9er - for tracking down the section alignment problem with MMX in +the DOS and Win32 ports. + +* Authors of the contributed patches ever listed on John the Ripper +homepage and/or placed into contrib/ directory on the FTP server - for +those patches which, while not included into the official John the +Ripper for various reasons, are nevertheless very helpful to many users. + +* All the people who have developed freeware crypt(3) implementations - +for various tricks that I combined in my routines. + +* Niels Provos and Poul-Henning Kamp - for original Blowfish-based and +MD5-based crypt(3), respectively, that my implementations are compatible +with. + +* Alec Muffett - for the original wordlist rules syntax. + +* The SOrCErEr - for proving the large charset tables are worth +implementing, and for introducing "-groups" in his cracker. + +* Jackal - for the format of john.pot and parts of the user interface. + +* Anton Ertl - for "Labels as Values" optimization that I use in +compiler.c: + + http://www.complang.tuwien.ac.at/papers/ertl96diss.ps.gz + +* The developers of Cygwin - for Cygwin (at the time called Cygnus +Developer's Kit) that I used for the Win32 port: + + http://www.cygwin.com + +* DJ Delorie - for DJGPP that I used for the DOS port: + + http://www.delorie.com/djgpp/ + +* Charles W Sandmann - for CWSDPMI, the DPMI server used with DJGPP. + +$Owl: Owl/packages/john/john/doc/CREDITS,v 1.15 2011/06/22 13:03:43 solar Exp $ diff --git a/doc/EXAMPLES b/doc/EXAMPLES new file mode 100644 index 0000000..2024ab4 --- /dev/null +++ b/doc/EXAMPLES @@ -0,0 +1,407 @@ + John the Ripper usage examples. + +These examples are to give you some tips on what John's features can be +used for. + + + Command line. + +1. First, you need to get a copy of your password file. If your system +uses shadow passwords, you may use John's "unshadow" utility to obtain +the traditional Unix password file, as root: + + umask 077 + unshadow /etc/passwd /etc/shadow > mypasswd + +(You may need to replace the filenames as needed.) + +Then make "mypasswd" available to your non-root user account that you +will run John under. No further commands will need to be run as root. + +If your system is ancient enough that it keeps passwords right in the +world-readable /etc/passwd, simply make a copy of that file. + +If you're going to be cracking Kerberos AFS passwords, use John's +"unafs" utility to obtain a passwd-like file. + +Similarly, if you're going to be cracking Windows passwords, use any of +the many utilities that dump Windows password hashes (LM and/or NTLM) in +Jeremy Allison's PWDUMP output format. Some of these utilities may be +obtained here: + + http://www.openwall.com/passwords/pwdump + +2. Now, let's assume you've got a password file, "mypasswd", and want to +crack it. The simplest way is to let John use its default order of +cracking modes: + + john mypasswd + +This will try "single crack" mode first, then use a wordlist with rules, +and finally go for "incremental" mode. Please refer to MODES for more +information on these modes. + +It is highly recommended that you obtain a larger wordlist than John's +default password.lst and edit the "Wordlist = ..." line in the +configuration file (see CONFIG) before running John. Some wordlists may +be obtained here: + + http://www.openwall.com/wordlists/ + +Of those available in the collection at the URL above, all.lst +(downloadable as all.gz) and huge.lst (only available on the CD) are +good candidates for the "Wordlist = ..." setting. + +3. If you've got some passwords cracked, they are stored in +$JOHN/john.pot. The john.pot file is not meant to be human-friendly. +You should be using John itself to display the contents of its "pot +file" in a convenient format: + + john --show mypasswd + +If the account list gets large and doesn't fit on the screen, you +should, of course, use your shell's output redirection. + +You might notice that many accounts have a disabled shell. You can make +John skip those in the report. Assuming that the disabled shell is +called "/etc/expired", the command would be: + + john --show --shells=-/etc/expired mypasswd + +or shorter, but will also match "/any/path/expired": + + john --show --shells=-expired mypasswd + +or if you also want to ignore some other shell, say "/etc/newuser": + + john --show --shells=-expired,newuser mypasswd + +To check if any root (UID 0) accounts got cracked: + + john --show --users=0 mypasswd + +or to check for cracked root (UID 0) accounts in multiple files: + + john --show --users=0 *passwd* *.pwd + +To display the root (username "root") account only: + + john --show --users=root mypasswd + +And finally, to check for privileged groups: + + john --show --groups=0,1 mypasswd + +4. You might prefer to manage the cracking modes manually. It is wise +to start with "single crack" mode: + + john --single mypasswd + +or since the GNU-style double dashes are optional and since option +names can be abbreviated for as long as they remain unambiguous: + + john -si mypasswd + +You should not abbreviate options in scripts which you would want to +work with future versions of John since what is unambiguous now might +become ambiguous with the addition of more options. + +If you have more files to crack, it is preferable to load them at the +same time: + + john --single passwd1 passwd2 + +or even: + + john --single *passwd* *.pwd + +This way, John will run faster and might even crack more passwords than +it would if you ran it on each password file separately. + +5. To catch weak passwords not derived from readily available users' +personal information, you should proceed with cracking modes demanding +more processor time. First, let's try a tiny wordlist with word +mangling rules enabled: + + john --wordlist=password.lst --rules mypasswd + +or abbreviating the options: + + john -w=password.lst -ru mypasswd + +Then proceed with a larger wordlist, also applying the mangling rules: + + john --wordlist=all.lst --rules mypasswd + +If you've got a lot of spare disk space to trade for performance and the +hash type of your password files is relatively slow, you may use John's +"unique" utility to eliminate any duplicate candidate passwords: + + john --wordlist=all.lst --rules --stdout | unique mangled.lst + john --wordlist=mangled.lst mypasswd + +If you know that your target hash type truncates passwords at a given +length, you may optimize this even further: + + john --wordlist=all.lst --rules --stdout=8 | unique mangled8.lst + john --wordlist=mangled8.lst mypasswd + +Alternatively, you may simply use huge.lst available on Openwall +wordlist collection CDs. It has word mangling rules pre-applied for the +most common languages and it has any duplicates purged. + +Depending on target hash type, the number of different salts (if +applicable), the size of your wordlist, rules, and processor +performance, wordlist-based cracking may take anywhere from under a +second to many days. + +You do not have to leave John running on a (pseudo-)terminal. If +running John on a Unix-like system, you can simply disconnect from the +server, close your xterm, etc. John will catch the SIGHUP ("hangup" +signal) and continue running. Alternatively, you may prefer to start it +in the background right away: + + john --wordlist=all.lst --rules mypasswd & + +Obviously, the "&" is specific to Unix shells and will not work on most +other platforms. + +You may further enhance this by specifying a session name: + + john --session=allrules --wordlist=all.lst --rules mypasswd & + +This ensures that you won't accidentally interfere with the instance of +John running in the background if you proceed to start other sessions. + +To view the status of a running session, use: + + john --status + +for the default session or: + + john --status=allrules + +for any other session. This works for both interrupted and running +sessions. To obtain the most up-to-date information from a running +session on a Unix-like system, send a SIGHUP to the appropriate "john" +process. + +Any interrupted sessions may be continued with: + + john --restore + +or: + + john --restore=allrules + +Finally, to make John have less impact on other processes, you should +set the option "Idle = Y" in the configuration file (see CONFIG). The +default may vary depending on the version and build of JtR. + +To only crack accounts with a "good" shell (in general, the shell, user, +and group filters described above work for all cracking modes as well): + + john --wordlist=all.lst --rules --shells=sh,csh,tcsh,bash mypasswd + +Like with all other cracking modes, it is faster to crack all the files +you need cracked simultaneously: + + john --wordlist=all.lst --rules passwd1 passwd2 + +You can crack some passwords only. This will try cracking all root +(UID 0) accounts in all the password files: + + john --wordlist=all.lst --rules --users=0 *passwd* + +Alternatively, you may wish to not waste time cracking your very own +passwords, if you're sure they're uncrackable: + + john --wordlist=all.lst --rules --users=-root,solar *passwd* + +Sometimes it is useful to split your password hashes into two sets which +you crack separately, like: + + john --wordlist=all.lst --rules --salts=2 *passwd* + john --wordlist=all.lst --rules --salts=-2 *passwd* + +This will make John try salts used on two or more password hashes first +and then try the rest. Total cracking time will be almost the same, but +you will get some passwords cracked earlier, which is useful, for +example, for penetration testing and demonstrations to management. +Similarly, you may check all password hashes with a small wordlist, but +only those that you can check faster (with "--salts=2") with a larger +one. With large numbers of password hashes and/or with a highly +non-uniform distribution of salts, it may be appropriate to use a +threshold larger than 2 with "--salts" (sometimes even values as high as +1000 will do). + +Note that the default wordlist rules include ":" (a no-op - try words as +they are in the list) on the first line. If you already ran through a +wordlist without using rules, and then decided to also try the same +wordlist with rules, you'd better comment this line out. + +6. The most powerful cracking mode in John is called "incremental" (not a +proper name, but kept for historical reasons). You can simply run: + + john --incremental mypasswd + +or: + + john -i mypasswd + +This will use the default "incremental" mode parameters, which are +defined in the configuration file's section named either +[Incremental:ASCII] (for most hash types) or [Incremental:LM_ASCII] (for +Windows LM hashes). By default, the [Incremental:ASCII] parameters are +set to use the full printable ASCII character set (95 characters) and +to try all possible password lengths from 0 to 13 (if the current hash +type has a lower maximum password length, incremental mode's length +limit is reduced accordingly). [Incremental:LM_ASCII] is similar, +except that it takes advantage of LM hashes being case-insensitive and +of their halves being limited to 7 characters each. + +Don't expect "incremental" mode sessions to terminate in a reasonable +time (unless all the passwords are weak and get cracked), read MODES for +an explanation of this. + +In some cases it is faster to use some other pre-defined incremental mode +parameters and only crack simpler passwords, from a limited character +set. The following command will try 10 different characters only, +passwords from "0" to "99999999999999999999" (in an optimal order): + + john -i=digits mypasswd + +Of course, you can use most of the additional features demonstrated +above for wordlist mode with "incremental" mode as well. For example, +on a large-scale penetration test, you may have John crack only root +(UID 0) accounts in a set of password files: + + john -i -u=0 *.pwd + +7. If you've got a password file for which you already have a lot of +passwords cracked or obtained by other means, and the passwords are +unusual, then you may want to generate a new charset file, based on +character frequencies from that password file only: + + john --make-charset=custom.chr mypasswd + +Then use that new file with "incremental" mode. + +If you've got many password files from a particular country, +organization, etc., it might be useful to use all of them for the +charset file that you then use to crack even more passwords from these +files or from some other password files from the same place: + + john --make-charset=custom.chr passwd1 passwd2 + [ Configure your custom "incremental" mode now. See below. ] + john -i=custom passwd3 + +You can use some pre-defined or custom word filters when generating the +charset file to have John consider some simpler passwords only: + + john --make-charset=my_alpha.chr --external=filter_alpha mypasswd + +If your "pot file" got large enough (or if you don't have any charset +files at all), you might want to use it to generate a new set of main +charset files: + + makechr + +where "makechr" is a script that invokes "john --make-charset=..." with +varying filenames, for all of the external mode word filters defined in +the configuration file. In this example, John will overwrite the +charset files with new ones that are based on your entire $JOHN/john.pot +(John uses the entire "pot file" if you don't specify any password +files). + +8. Finally, you might want to e-mail all users with weak passwords to +tell them to change their passwords. (This is not always a good idea, +though, since lots of people do not check their e-mail or ignore such +messages, and the messages can be a hint for crackers.) Edit the +"mailer" script supplied with John: the message it sends and possibly +the mail command (especially if the password file is from a different +machine). Then run: + + mailer mypasswd + + + Configuration file. + +Please refer to CONFIG for general information on the configuration file +and its possible locations. + +1. Let's assume that you notice that in some password file a lot of +users have their passwords set to login names with "?!" appended. Then +you just make a new "single crack" mode rule (see RULES for information +on the syntax) and place it somewhere near the beginning: + + [List.Rules:Single] + Az"?!" + +Hint: if you want to temporarily disable all of the default rules, you +can simply rename the section to something John doesn't use and define +a new one with the section's old name, but be sure to leave the "List." +prefix of the name intact to maintain correct configuration file syntax. + +All the same applies to wordlist mode rules as well. + +2. If you generate a custom charset file (described above) you will also +need to define a configuration file section with the "incremental" mode +parameters. In the simplest case it will be like this (where "Custom" +can be replaced with any name you like): + + [Incremental:Custom] + File = custom.chr + +This way, John will only use characters from passwords used to generate +the charset file only. To make John try some more characters, add: + + Extra = !@#$% + +These extra characters will then be added, but still considered the +least probable. If you want to make sure that, with your extra +characters, John will try 95 different characters, you can add: + + CharCount = 95 + +This will make John print a warning if it only has fewer than 95 +characters in its charset. + +You can also use CharCount to limit the number of different characters +that John tries, even if the charset file has more: + + CharCount = 20 + +If you didn't use any filters when generating the charset file, setting +CharCount this low will make John never attempt rare characters and +character combinations, not even for really short passwords, spending +the time on simple longer candidate passwords instead. However, the +default length switching is usually smart enough so that you shouldn't +need this trick. + +To make John try passwords of certain lengths only, use the following +lines: + + MinLen = 6 + MaxLen = 8 + +Setting "MinLen" high, as in the example above, is reasonable if shorter +passwords weren't allowed to set on the machine you got the password file +from (however, note that root can usually set any password for any user +and there are often loopholes in operating systems' password policy +enforcement capabilities). + +On the contrary, you may want to set "MaxLen" low if you think there are +a lot of short passwords. + +3. Another example: a lot of users at some site use short duplicated +words as their passwords, such as "fredfred". As the number of such +potential passwords is fairly low, it makes sense to code a new external +cracking mode that tries them all, up to some length. + +You can find the actual implementation of such a cracking mode with lots +of comments in the default configuration file supplied with John. +Please refer to EXTERNAL for information on the programming language +used. + +$Owl: Owl/packages/john/john/doc/EXAMPLES,v 1.10 2013/05/29 18:14:35 solar Exp $ diff --git a/doc/EXTERNAL b/doc/EXTERNAL new file mode 100644 index 0000000..311a4da --- /dev/null +++ b/doc/EXTERNAL @@ -0,0 +1,90 @@ + Defining an external mode. + +To define an external cracking mode you need to create a configuration +file section called [List.External:MODE], where MODE is any name that +you assign to the mode. The section should contain some functions +programmed in a subset of the C language. John will compile and use the +functions if you enable this cracking mode via the command line. + + + External functions. + +The following functions are currently used by John: + +init() called at startup, should initialize global variables +filter() called for each word to be tried, can filter some words out +generate() called to generate words, when no other cracking modes used +restore() called when restoring an interrupted session + +All of them are of type "void", with no arguments, and should use the +global variable "word" (pre-defined as "int word[]"), except for init() +which is called before "word" is initialized. The variable "word" +contains the current candidate password to be tried, one character in +each array element, terminated with a zero. + +The functions, if defined, should do the following with "word": + +* filter() can modify the word, or zero out "word[0]" to skip it; + +* generate() should set "word" to the next word to be tried, or zero out +"word[0]" when cracking is complete (this will cause John to terminate); + +* restore() should set global variables to continue from the "word". + +You can use an external mode on its own or with some other cracking +mode, in which case only init() and filter() will be used (and only +filter() will be required). Using an external filter is compatible with +all the other cracking modes and with the "--make-charset" command line +option. + +It is recommended that you don't use filter() or at least don't filter +too many words out when using an external mode with your own generate(). +It is better to modify generate() not to generate words that would get +filtered out. + + + Pre-defined variables. + +Besides the "word" variable documented above, John the Ripper 1.7.9 and +newer pre-defines two additional variables: "abort" and "status", both +of type "int". When set to 1 by an external mode, these cause the +current cracking session to be aborted or the status line to be +displayed (just like on a keypress), respectively. These actions are +taken after having tested at least all of the candidate passwords that +were in external mode's "word" so far. In other words, the actions may +be delayed in order to process any buffered candidate passwords. + + + The language. + +As it has been mentioned above, the compiler supports a subset of C. +The supported keywords are: void, int, if, else, while, continue, break, +and return. + +You can define functions to be called by John (the ones described +above), define global and local variables (including single dimensional +arrays), use all the integer operations supported in C, and use C and +C++ comments. + +The following C features are missing from John's compiler: + +* function calls (any functions defined as a part of an external mode +can only be called by John core, but not from within other external mode +functions); + +* only "while" loops are supported; + +* only "int" and "void" data types are supported; + +* only single dimensional arrays are supported; + +* structs/unions are not supported; + +* pointers are not supported (array name refers to the first element); + +* probably something else... + +You can find some external mode examples in the default configuration +file supplied with John. + +$Owl: Owl/packages/john/john/doc/EXTERNAL,v 1.3 2011/09/18 07:44:58 solar Exp $ diff --git a/doc/FAQ b/doc/FAQ new file mode 100644 index 0000000..e54b35f --- /dev/null +++ b/doc/FAQ @@ -0,0 +1,306 @@ + John the Ripper FAQ. + +The latest version of this FAQ may be viewed online at: + + http://www.openwall.com/john/doc/FAQ.shtml + + + Help! I can't run John. + +If you're not familiar with your OS, you should probably not be using +John in the first place since John is primarily a tool for system +administrators. This is starting to change with the "community +enhanced" -jumbo versions' support for things such as password-protected +archives, though. + +Here are the answers to a few (not very) common questions to avoid +having them asked over and over and for amusement. For more serious +matters, please skip over to the next section. + +Q: When I type "john" (or "john passwd", etc.), it says "command not +found" (or equivalent)?! +A: The examples given in John the Ripper documentation assume that you +know how to invoke newly-built programs from your shell. On Unix-like +systems, it is typical to not have "." (the current directory) in your +$PATH (the list of directories to search for programs). In that case, +you need to type "./john" (dot, slash, and "john", without the quotes) +to invoke the John binary executable located in the current directory. + +Q: ...but I am on a Unix-like system and I don't seem to readily have a +John binary executable. +A: Please follow the instructions in INSTALL. + +Q: When I double-click on "john.exe", a window flashes and disappears?! +A: You're not supposed to click. You're supposed to run John from a +command-line shell. On Windows, some of those shells would be cmd.exe, +command.com, or bash (the latter is available with Cygwin). + + + Other typical new user questions. + +Q: How do I start John on my password file, use a specific cracking +mode, see the passwords it cracked, etc? +A: See README and EXAMPLES. :-) + +Q: Why doesn't John load my password file? It says "No password hashes +loaded", "No password hashes loaded (see FAQ)", or "No password hashes +left to crack (see FAQ)". +A: Your password file taken from a Unix-like system might be shadowed. +You need to get both /etc/passwd and the shadow file (typically +/etc/shadow or /etc/master.passwd), and combine them into one file using +"unshadow" (which is supplied with John). Please refer to EXAMPLES. +A: All of the password hashes found in the file (that are of the same +type as the very first recognized hash in the file unless you're using +the "--format=..." option) might be already cracked by previous +invocations of John. (The message printed in that case has been changed +to "No password hashes left to crack (see FAQ)" starting with version +1.7.7.) To display cracked passwords, use "john --show" on your +password hash file(s). To force John to crack those same hashes again, +remove the john.pot file. +A: With PWDUMP-format files, John focuses on LM rather than NTLM hashes +by default, and it might not load any hashes at all if there are no LM +hashes to crack. To have JtR Pro or a -jumbo version focus on NTLM +hashes instead, you need to pass the "--format=nt" option. +A: If you're using the "--format" option, try dropping it. Except for +the special case mentioned in the answer above, "--format" is normally a +way to choose one of multiple hash/cipher types found in the same file +or to clarify the hash/cipher type if it would otherwise be ambiguous +(e.g., a 32 hexadecimal character string may correspond to one of many +distinct hash types). That is, you normally only need to use "--format" +when John would otherwise misdetect your hash/cipher type (e.g., when it +says LM and you know that your hashes are in fact raw MD5, you'd use +"--format=raw-md5" with -jumbo) or if it would load undesired entries +from the file. If John does not load anything, then your use of +"--format" is probably unreasonable (or you should be using a different +version/build of John - see the answer below). +A: Your password hash or cipher type(s) might not be supported by John, +or at least by the version and build of John that you're using. If +you're using a non-jumbo version, you will likely want to try -jumbo +instead, which supports a lot of additional hash and cipher types (e.g., +you currently need -jumbo for raw MD5). If unsuccessful with that and +if other answers (above and below this one) don't apply, please post a +note to the mailing list (see CONTACT) including a sample password file +line that John does not load (please make sure that the password is +already changed by the time you post). +A: John only loads properly formatted text files directly. It can load +/etc/passwd and PWDUMP format files. Starting with version 1.7.6, it +can also load text files containing one password hash per line (and +nothing else on that line). Some other file formats are supported via +extra tools (supplied with John): unafs (Kerberos AFS database files), +undrop (Eggdrop IRC bot userfiles), ssh2john (OpenSSH private keys), +pdf2john (some password-protected PDF files), rar2john (some +password-protected RAR archives), zip2john (some password-protected +PKZIP and WinZip archives). You need -jumbo for most of these. To use +the proper one of these (for your file format), run it on your file(s) +and redirect the output to a new file (using your shell's output +redirection feature - e.g., "./ssh2john ~/.ssh/id_rsa > sshpasswd"). +Then run John on the resulting file (e.g., "./john sshpasswd"). +A: The file you're trying to run John on might in fact not be a password +file at all. +A: Your command line syntax might be wrong, resulting in John trying to +load a wrong file. + +Q: John appears to misdetect my hash type. I have raw MD5 hashes from a +web application, but John wrongly says they're LM hashes. How do I get +them detected correctly? +A: Some hash and cipher types use ambiguous encodings - e.g., a 32 +hexadecimal character string may correspond to one of many hash types, +including raw MD5, LM, NTLM, and many others supported in -jumbo. First +of all, you need a version and build of John that supports your hash and +cipher type. Starting with version 1.7.7 (and 1.7.7-jumbo*) John will +suggest alternate hash and cipher types for encodings that it finds +ambiguous (that is, those corresponding to more than one of its +supported hash and cipher types). When doing so, it will suggest +specific "--format=..." options to use. For example, when you run a +recent enough -jumbo version on raw MD5 hashes, it loads those as LM +(because they could in fact be LM, as well as for compatibility with +non-jumbo), but it suggests that you use "--format=raw-md5", which is +what you should in fact use in this case. It makes other suggestions as +well because it does not know whether your hashes are raw MD5 or +something else. You're supposed to know this and choose the right one +of the suggested "--format=..." options. If you're not getting a +suggestion like this from John 1.7.7 or newer even though you're not yet +using the "--format" option, this means that your version and build of +John does not recognize the encodings as ambiguous, which may mean that +it does not support the actual hash or cipher type that you have in +mind. If you're already using the "--format" option, try dropping the +option to receive the suggestions. If you're using a non-jumbo version +of John, the first step is for you to try -jumbo instead. As of this +writing, you do need -jumbo for some popular hash types such as raw MD5 +and NTLM. + +Q: What do the various numbers printed on the status line mean? +A: As of version 1.8.0, the status line may include: successful guess +count ("g"), session duration (in the D:HH:MM:SS format for days, hours, +minutes, and seconds), progress indicator (percent done and optionally +pass number out of the total number of passes), up to four speed metrics +("g/s", "p/s", "c/s", and "C/s"), and the current (range of) candidate +password(s) being tested (John is often able to test multiple candidate +passwords in parallel for better performance, hence a range). The four +speed metrics are as follows: g/s is successful guesses per second (so +it'll stay at 0 until at least one password is cracked), p/s is +candidate passwords tested per second, c/s is "crypts" (password hash or +cipher computations) per second, and C/s is combinations of candidate +password and target hash per second. Versions of John prior to 1.8.0 +displayed only the C/s rate (calling it c/s). When you restore a +pre-1.8.0 session with version 1.8.0 or newer, only the g/s and C/s +rates will be displayed, because the older .rec file format lacked +information needed to compute p/s and c/s. + +Q: I am running John for 10 days and it is still not finished?! +Q: How long should I expect John to run? +A: It primarily depends on the cracking mode(s) and on your password +files (in particular, the type of hashes and the number of different +salts, if applicable). Most importantly, you should note that the +"incremental" mode, which a default John run (with no command line +options) proceeds with after being done with the quicker checks, is not +supposed to terminate in a reasonable time. It is up to you to decide +how long you're going to let it run, then consider any uncracked +passwords strong enough. "Single crack" mode runs typically take from +under a second to one day (depending on the type and number of password +hashes). Wordlist mode runs may also be quick (under a second) for +tiny wordlists and fast hashes or they may take multiple days with large +wordlists, with word mangling rules, and with slow hash types and +substantial numbers of different salts. The status line John reports +whenever you hit a key includes a progress indicator (percent complete) +for "single crack" and wordlist modes. With no cracking mode requested +explicitly, John will start with "single crack" mode (pass 1), then +proceed with wordlist mode (pass 2), and finally with "incremental" mode +(pass 3). The pass numbers are reported on the status line, too. It is +reasonable to let John reach "incremental" mode (pass 3) and run that +for a while (some days). You will notice that John's success rate (the +number of passwords cracked per hour or per day) will be dropping +rapidly. When you determine that the success rate is low enough, you +interrupt John. + +Q: Does John support multi-processing or distributed processing? +A: Yes, but you need to explicitly enable this if desired. Starting +with version 1.8.0, there's the "--fork" option on Unix-like systems (to +make use of multiple CPUs and/or CPU cores in a single system) and the +"--node" option on all systems (this one allows for a trivial form of +distributed processing). The "--fork" and "--node" options may also be +used together. Please refer to OPTIONS for a description of these +options. Additionally, there's built-in parallel processing support +using OpenMP for all crypt(3) hash flavors (DES-, MD5-, and +Blowfish-based) supported by John natively, and when running on Linux or +Solaris also for the underlying system's thread-safe password hashing +function. The latter is only reasonable to use for crypt(3) hash types +not yet supported by John natively (such as for glibc 2.7+ SHA-crypt +hashes as used by recent versions of Fedora and Ubuntu, and for SunMD5 +hashes, which may optionally be enabled on Solaris). In "community +enhanced" -jumbo versions, parallelization with OpenMP is also supported +for many (but not all) of the hash and cipher types added in those +versions (including for their built-in implementation of SHA-crypt). +To use John's OpenMP support, you need to either use an existing +OpenMP-enabled build (e.g., "john-omp.exe" on Windows) or make an +OpenMP-enabled build by uncommenting one of the OMPFLAGS lines near the +beginning of Makefile. This requires GCC 4.2 or newer, or another +OpenMP-capable C compiler. For other hash or cipher types and/or to +distribute the workload between multiple machines, other approaches need +to be used. One of those approaches is to use the "--fork" and "--node" +options. For a very small number of nodes (CPUs, CPU cores, and/or +machines), it is also reasonable to use a manual approach, such as to +have your nodes try different password lengths. This is easily +accomplished with "incremental" mode's "MinLen" and "MaxLen" settings +(see CONFIG). You might not need to split the workload for "single +crack" and wordlist modes since these are typically relatively quick, +although "--fork" and "--node" are supported for these modes too. You +may safely run multiple instances of John in the same working directory, +all writing to the same "pot file" (this is a feature). You do, +however, need to assign each of them a unique session name, with +"--session" (please note that doing so does not eliminate the need to +also distribute the workload with "--node" or otherwise, as discussed +above). Other approaches, such as splitting password files naively +(without regard to salts), are typically less efficient (in some cases +to the extent where there's no speedup from using multiple nodes at +all). Some other approaches, such as using MPI, are listed on the wiki +at: http://openwall.info/wiki/john/parallelization + +Q: Where do I get wordlists for use with John? +A: http://www.openwall.com/wordlists/ + +Q: Where do I get new versions of John the Ripper? +Q: Where do I get the source code for John? +Q: I only have the source code for John the Ripper, where do I get it +pre-compiled for my OS (if supported)? +Q: What is the primary website for John the Ripper? +A: http://www.openwall.com/john/ + +Q: How can I contact you (the author)? +A: See CONTACT. + + + Questions sometimes asked by existing users. + +Q: I've recently switched my system to Blowfish-based password hashes, +but there are still some DES-based and MD5-based hashes in the password +file. How do I handle multiple hash types in one file? +A: Use the "--format=..." option to tell John which hashes you would +like it to load. Unfortunately, you will have to run John for each hash +type separately. This requirement may sometimes be avoided with the use +of "--format=crypt", but this is not recommended. Please see the +description of the "--format" option in OPTIONS for more detail. + +Q: I have 10 users, but John said it loaded 15 password hashes. What's +going on? +A: Some extremely poorly designed hash types (Windows LM hashes and +DES-based crypt(3) hashes known as "bigcrypt") have a property that +allows John to split their encodings into two separate hashes +(corresponding to "halves" of plaintext passwords) on load. John then +proceeds to crack those hashes separately, so at a given time it might +have only one of two halves of some passwords cracked. If interrupted +and restarted, it would need to only load the hashes that correspond to +uncracked password halves, so the number of such hashes is what John +reports (in all cases, for consistency). + +Q: Are the strings tried with "-i" ("incremental" mode) random? They +certainly look like they are almost random. +A: No, they are not. No single candidate password will be tried for a +second time and the order in which they are tried is in fact very smart: +it is based on frequencies of different trigraphs, stored and processed +separately for each character position and for each password length. + +Q: Why doesn't John display a progress indicator for the "incremental" +mode? +A: Do you really want to see a 0% all the time? As explained in MODES, +"incremental" mode is not supposed to terminate in a reasonable time. +(There are a few exceptions to this, so a progress indicator has been +added in -jumbo and it might be added in official versions later.) + +Q: I just noticed that the p/s, c/s, and C/s rates reported while using +"incremental" mode are a lot lower than they are with other cracking +modes. Why is that? +A: You're probably running John for a few seconds only. The current +"incremental" mode implementation uses large character sets, which need +to be expanded into even larger data structures in memory each time John +switches to a different password length. Fortunately, this is only +noticeable when John has just started since the length switches become +rare after a few minutes. For long-living sessions, which is where we +care about performance the most, this overhead is negligible. This is a +very low price for the better order of candidate passwords tried. + +Q: What are the "real" and "virtual" c/s rates as reported by "--test" +(on Unix-like operating systems)? +A: These correspond to real and virtual (processor) time, respectively. +The two results would differ when the system is under other load, with +the "virtual" c/s rate indicating roughly what you could expect to get +from the same machine if it were not loaded. + +Q: How can I test John's password hashing routines for proper operation? +A: John always performs a self-test when you run it on a password file +and refuses to work if an error occurs. If you need to test all of the +low-level routines at once, use "--test". + +Q: What is the format of the crash recovery files ("john.rec", other +.rec's)? What do the numbers mean? +A: The format of these files is deliberately undocumented and is subject +to change without notice. (However, each release of John the Ripper is +likely to be able to read .rec files produced by at least the +immediately preceding release. Whenever compatibility is broken, John +will refuse to recover the session, leaving the .rec file intact.) +Although the meaning of some of the numbers that get into .rec files is +trivial to explain, it is not possible to reasonably describe some +others without going into great detail on John internals. If you really +need to know, read the source code. + +$Owl: Owl/packages/john/john/doc/FAQ,v 1.34 2013/05/29 22:44:35 solar Exp $ diff --git a/doc/INSTALL b/doc/INSTALL new file mode 100644 index 0000000..26a1a23 --- /dev/null +++ b/doc/INSTALL @@ -0,0 +1,70 @@ + Installing John the Ripper. + +First of all, most likely you do not need to install John the Ripper +system-wide. Instead, after you extract the distribution archive and +possibly compile the source code (see below), you may simply enter the +"run" directory and invoke John from there. + +System-wide installation is also supported, but it is intended for use +by packagers of John for *BSD "ports", Linux distributions, etc., rather +than by end-users. (If you're in fact preparing a package of John, +please refer to the JOHN_SYSTEMWIDE setting in src/params.h.) + +You may have obtained the source code or a "binary" (pre-compiled) +distribution of John the Ripper. On Unix-like systems, it is typical +to get the source code and compile it into "binary" executables right +on the system you intend to run John on. On DOS and Windows, however, +it is typical to get a binary distribution which is ready for use. + +The following instructions apply to the source code distribution of +John only. If you have a binary distribution, then there's nothing +for you to compile and you can start using John right away. + + + Compiling the sources on a Unix-like system. + +Enter the directory into which you extracted the source code +distribution of John. Enter the "src" subdirectory and invoke "make" +to obtain a list of operating systems for which specific support +exists: + + cd src + make + +Note the make target for your system and type: + + make clean SYSTEM + +where SYSTEM is the appropriate make target. Alternatively, if your +system is not listed, use: + + make clean generic + +If everything goes well, this will create the executables for John and +its related utilities under "../run/". You can change directory to +there and start John, like this: + + cd ../run + ./john --test + +Alternatively, you may copy the entire "run" directory to anywhere you +like and use John from there. + + + A note on moving binaries between systems. + +With the "generic" make target, certain machine hardware performance +parameters are detected at compile time. Additionally, some OS-specific +make targets tell the C compiler to generate and optimize code for the +machine's specific CPU type (this currently applies to C compilers other +than gcc only). If you then move the binary executable to a different +machine, you might not get the best performance or the program might +not run at all if the CPU lacks features that the C compiler assumed it +would have. Thus, it is recommended to recompile John on each system if +you use one of these make targets. + +Since Linux and *BSD distributions' packages of John typically use make +targets other than "generic" and since they typically use gcc, they are +usually not affected by this potential problem. + +$Owl: Owl/packages/john/john/doc/INSTALL,v 1.5 2010/05/27 13:37:48 solar Exp $ diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 0000000..42d7b13 --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,61 @@ + John the Ripper copyright and license. + +John the Ripper password cracker, +Copyright (c) 1996-2013 by Solar Designer. + +This program 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. + +This program 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. + +As a special exception to the GNU General Public License terms, +permission is hereby granted to link the code of this program, with or +without modification, with any version of the OpenSSL library and/or any +version of unRAR, and to distribute such linked combinations. You must +obey the GNU GPL in all respects for all of the code used other than +OpenSSL and unRAR. If you modify this program, you may extend this +exception to your version of the program, but you are not obligated to +do so. (In other words, you may release your derived work under pure +GNU GPL version 2 or later as published by the FSF.) + +(This exception from the GNU GPL is not required for the core tree of +John the Ripper, but arguably it is required for -jumbo.) + + + Relaxed terms for certain components. + +In addition or alternatively to the license above, many components are +available to you under more relaxed terms (most commonly under cut-down +BSD license) as specified in the corresponding source files. + +Furthermore, as the copyright holder for the bcrypt (Blowfish-based +password hashing) implementation found in John the Ripper, I have placed +a derived version of this implementation in the public domain. This +derived version may be obtained at: + + http://www.openwall.com/crypt/ + +The intent is to provide modern password hashing for your servers and +your software (where the GPL restrictions could be a problem). + + + Commercial licensing. + +Commercial licenses (non-GPL) are available upon request. + + + Copyright holder contact information. + +For the core John the Ripper tree: + +Alexander Peslyak aka Solar Designer + +(There are additional copyright holders for "community enhanced" -jumbo +versions of John the Ripper.) + +$Owl: Owl/packages/john/john/doc/LICENSE,v 1.16 2013/05/30 00:42:06 solar Exp $ diff --git a/doc/MODES b/doc/MODES new file mode 100644 index 0000000..2bb9832 --- /dev/null +++ b/doc/MODES @@ -0,0 +1,126 @@ + John the Ripper's cracking modes. + +Mode descriptions here are short and only cover the basic things. +Check other documentation files for information on customizing the +modes. + + + Wordlist mode. + +This is the simplest cracking mode supported by John. All you need to +do is specify a wordlist (a text file containing one word per line) +and some password files. You can enable word mangling rules (which +are used to modify or "mangle" words producing other likely +passwords). If enabled, all of the rules will be applied to every +line in the wordlist file producing multiple candidate passwords from +each source word. + +The wordlist should not contain duplicate lines. John does not sort +entries in the wordlist since that would consume a lot of resources +and would prevent you from making John try the candidate passwords in +the order that you define (with more likely candidate passwords listed +first). However, if you don't list your candidate passwords in a +reasonable order, it'd be better if you sort the wordlist +alphabetically: with some hash types, John runs a bit faster if each +candidate password it tries only differs from the previous one by a +few characters. Most wordlists that you may find on the Net are +already sorted anyway. + +On the other hand, if your wordlist is sorted alphabetically, you do +not need to bother about some wordlist entries being longer than the +maximum supported password length for the hash type you're cracking. +To give an example, for traditional DES-based crypt(3) hashes only +the first 8 characters of passwords are significant. This means that +if there are two or more candidate passwords in the wordlist whose +first 8 characters are exactly the same, they're effectively the same +8 character long candidate password which only needs to be tried once. +As long as the wordlist is sorted alphabetically, John is smart enough +to handle this special case right. + +In fact, it is recommended that you do not truncate candidate +passwords in your wordlist file since the rest of the characters +(beyond the length limit of your target hash type) are likely still +needed and make a difference if you enable word mangling rules. + +The recommended way to sort a wordlist for use with default wordlist +rule set is: + + tr A-Z a-z < SOURCE | sort -u > TARGET + +See RULES for information on writing your own wordlist rules. + + + "Single crack" mode. + +This is the mode you should start cracking with. It will use the +login names, "GECOS" / "Full Name" fields, and users' home directory +names as candidate passwords, also with a large set of mangling rules +applied. Since the information is only used against passwords for the +accounts it was taken from (and against password hashes which happened +to be assigned the same salt), "single crack" mode is much faster than +wordlist mode. This permits for the use of a much larger set of word +mangling rules with "single crack", and their use is always enabled +with this mode. Successfully guessed passwords are also tried against +all loaded password hashes just in case more users have the same +password. + +Note that running this mode on many password files simultaneously may +sometimes get more passwords cracked than it would if you ran it on +the individual password files separately. + + + "Incremental" mode. + +This is the most powerful cracking mode, it can try all possible +character combinations as passwords. However, it is assumed that +cracking with this mode will never terminate because of the number of +combinations being too large (actually, it will terminate if you set a +low password length limit or make it use a small charset), and you'll +have to interrupt it earlier. + +That's one reason why this mode deals with trigraph frequencies, +separately for each character position and for each password length, +to crack as many passwords as possible within a limited time. + +To use the mode you need a specific definition for the mode's +parameters, including password length limits and the charset to use. +These parameters are defined in the configuration file sections called +[Incremental:MODE], where MODE is any name that you assign to the mode +(it's the name that you will need to specify on John's command line). +You can either use a pre-defined incremental mode definition or define a +custom one. + +As of version 1.8.0, pre-defined incremental modes are "ASCII" (all 95 +printable ASCII characters), "LM_ASCII" (for use on LM hashes), "Alnum" +(all 62 alphanumeric characters), "Alpha" (all 52 letters), "LowerNum" +(lowercase letters plus digits, for 36 total), "UpperNum" (uppercase +letters plus digits, for 36 total), "LowerSpace" (lowercase letters plus +space, for 27 total), "Lower" (lowercase letters), "Upper" (uppercase +letters), and "Digits" (digits only). The supplied .chr files include +data for lengths up to 13 for all of these modes except for "LM_ASCII" +(where password portions input to the LM hash halves are assumed to be +truncated at length 7) and "Digits" (where the supplied .chr file and +pre-defined incremental mode work for lengths up to 20). Some of the +many .chr files needed by these pre-defined incremental modes might not +be bundled with every version of John the Ripper, being available as a +separate download. + +See CONFIG and EXAMPLES for information on defining custom modes. + + + External mode. + +You can define an external cracking mode for use with John. This is +done with the configuration file sections called [List.External:MODE], +where MODE is any name that you assign to the mode. The section +should contain program code of some functions that John will use to +generate the candidate passwords it tries. The functions are coded in +a subset of C and are compiled by John at startup when you request the +particular external mode on John's command line. See EXTERNAL. + + + What modes should I use? + +See EXAMPLES for a reasonable order of cracking modes to use. + +$Owl: Owl/packages/john/john/doc/MODES,v 1.6 2013/05/29 17:57:56 solar Exp $ diff --git a/doc/OPTIONS b/doc/OPTIONS new file mode 100644 index 0000000..072fada --- /dev/null +++ b/doc/OPTIONS @@ -0,0 +1,345 @@ + John the Ripper's command line syntax. + +When invoked with no command line arguments, "john" prints its usage +summary. + +The supported command line arguments are password file names and +options. Many of the supported options accept additional arguments. + +You can list any number of password files right on the command line of +"john". You do not have to specify any options. If valid password +files are specified but no options are given, John will go through +the default selection of cracking modes with their default settings. + +Options may be specified along with password files or on their own, +although some require that password files be specified and some do not +support operation on password files. + +All options are case sensitive, can be abbreviated as long as the +abbreviations are unambiguous, can be prefixed with two dashes +(GNU-style) or with one dash, and can use "=" or ":" to indicate an +argument (if supported for a given option). + +The supported options are as follows, square brackets denote optional +arguments: + +--single "single crack" mode + +Enables the "single crack" mode, using rules from the configuration +file section [List.Rules:Single]. + +--wordlist=FILE wordlist mode, read words from FILE, +--stdin or from stdin + +These are used to enable the wordlist mode. + +--rules enable word mangling rules for wordlist mode + +Enables word mangling rules that are read from [List.Rules:Wordlist]. + +--incremental[=MODE] "incremental" mode [using section MODE] + +Enables the "incremental" mode, using the specified configuration file +definition (section [Incremental:MODE]). If MODE is omitted, the +default is "ASCII" for most hash types and "LM_ASCII" for LM hashes. + +--external=MODE external mode or word filter + +Enables an external mode, using external functions defined in section +[List.External:MODE]. + +--stdout[=LENGTH] just output candidate passwords + +When used with a cracking mode, except for "single crack", makes John +output the candidate passwords it generates to stdout instead of +actually trying them against password hashes; no password files may be +specified when this option is used. If a LENGTH is given, John +assumes that to be the significant password length and only produces +passwords up to that length. + +--restore[=NAME] restore an interrupted session + +Continues an interrupted cracking session, reading state information +from the specified session file or from $JOHN/john.rec by default. + +--session=NAME give a new session the NAME + +This option can only be used when starting a new cracking session and +its purpose is to give the new session a name (to which John will +append the ".rec" suffix to form the session file name). This is +useful for running multiple instances of John in parallel or to be +able to later recover a session other than the last one you interrupt. + +--status[=NAME] print status of a session [called NAME] + +Prints status of an interrupted or running session. Note that on a +Unix-like system, you can get a detached running session to update its +session file by sending a SIGHUP to the appropriate "john" process; +then use this option to read in and display the status. + +--make-charset=FILE make a charset, overwriting FILE + +Generates a charset file based on character frequencies from +$JOHN/john.pot, for use with the "incremental" mode. The entire +$JOHN/john.pot will be used for the charset generation by default. You +may restrict the set of passwords used by specifying some password files +(in which case only the cracked passwords that correspond to those +password files will be used), "--format", or/and "--external" (with an +external mode that defines a filter() function). + +--show show cracked passwords + +Shows the cracked passwords for given password files (which you must +specify). You can use this option while another instance of John is +cracking to see what John did so far; to get the most up to date +information, first send a SIGHUP to the appropriate "john" process. + +--test[=TIME] run tests and benchmarks for TIME seconds each + +Tests all of the compiled in hashing algorithms for proper operation and +benchmarks them. The "--format" option can be used to restrict this to +a specific algorithm. + +--users=[-]LOGIN|UID[,..] [do not] load this (these) user(s) + +Allows you to select just a few accounts for cracking or for other +operations. A dash before the list can be used to invert the check +(that is, load information for all the accounts that are not listed). + +--groups=[-]GID[,..] load users [not] of this (these) group(s) + +Tells John to load (or to not load) information for accounts in the +specified group(s) only. + +--shells=[-]SHELL[,..] load users with[out] this (these) shell(s) + +This option is useful to load accounts with a valid shell only or to +not load accounts with a bad shell. You can omit the path before a +shell name, so "--shells=csh" will match both "/bin/csh" and +"/usr/bin/csh", while "--shells=/bin/csh" will only match "/bin/csh". + +--salts=[-]N load salts with[out] at least N passwords + +This is a feature which allows to achieve better performance in some +special cases. For example, you can crack only some salts using +"--salts=2" faster and then crack the rest using "--salts=-2". Total +cracking time will be about the same, but you will likely get some +passwords cracked earlier. + +--save-memory=LEVEL enable memory saving, at LEVEL 1..3 + +You might need this option if you don't have enough memory or don't +want John to affect other processes too much. Level 1 tells John to +not waste memory on login names; it is only supported when a cracking +mode other than "single crack" is explicitly requested. The only +impact is that you won't see the login names while cracking. Higher +memory saving levels have a performance impact; you should probably +avoid using them unless John doesn't work or gets into swap otherwise. + +--node=MIN[-MAX]/TOTAL this node's number range out of TOTAL count + +This option is intended to allow for some trivial manually-configured +parallel and distributed processing. For example, to split the workload +across two nodes (which could be machines, CPU cores, etc.), you'd +specify "--node=1/2" on one invocation of John and "--node=2/2" on the +other. (If you do this on just one machine and with the same build of +John, you will also need to specify different "--session" names for the +two simultaneous invocations.) The nodes are assumed to be same speed +(if this is not the case, one will get ahead of the other and is likely +to be done sooner, unless you're using a cracking mode and settings such +that the session is not expected to ever "complete" - which is fine.) +If your nodes are of very different speed, you may compensate for that +by allocating ranges of node numbers to individual invocations. For +example, if you use OpenMP-enabled builds of John on two machines, +OpenMP is supported (with good scalability) for the hash type you're +cracking, and one of the machines has twice more of similar speed CPU +cores than the other, then you may use "--node=1-2/3" on the twice +bigger machine (let it be nodes 1 and 2 out of 3 nodes total) and +"--node=3/3" on the smaller one. + +Efficiency of this approach to parallel processing, as currently +implemented, varies by cracking mode and its settings (efficiency is +higher for incremental mode and for wordlist mode with many rules, and +lower for other cracking modes and for wordlist mode without rules or +with few rules), hash type (efficiency is higher for slower to compute +hashes), salt count (efficiency is higher for higher salt counts), and +node count (efficiency is higher for lower node counts). Scalability +may be limited. The highest node count you can reasonably use varies by +cracking mode, its settings, hash type, and salt count. With +incremental mode, efficiency in terms of c/s rate is nearly perfect +(there's essentially no overhead), but some nodes may currently receive +too little work - and this problem is exacerbated by high node counts +(such as 100 or more) and/or restrictive settings (such as MinLen and +MaxLen set to the same value or to a narrow range, and/or a charset file +with few characters being used). With wordlist mode, for high +efficiency the rule count (after preprocessor expansion) needs to be +many times higher than node count, unless the p/s rate is low anyway +(due to slow hash type and/or high salt count). + +Since there's no communication between the nodes, hashes successfully +cracked by one node continue being cracked by other nodes. This is +mostly OK for saltless hash types or when there's just one salt (since +the same number of hash computations is to be made anyway - namely, only +one per candidate password tested), but it is a serious drawback when +many different salts are present and their number could potentially be +decreasing as some hashes get cracked. + +--fork=N fork N processes + +This option is only available on Unix-like systems. It is an easy way +to make use of multiple CPUs or CPU cores - you simply specify the +number of John processes that you'd like to run. You may use "--fork" +as an alternative to OpenMP, for formats currently lacking OpenMP +support, or/and along with OpenMP (e.g., on a machine with 64 logical +CPUs you might choose to run with "--fork=8" for 8 processes and use +OpenMP to run 8 threads per process). + +You may use "--fork" along with "--node" to use multiple machines while +also running multiple John processes per machine. For example, to use +two similar 8-core machines you may run "--fork=8 --node=1-8/16" on one +of the machines and "--fork=8 --node=9-16/16" on the other. For a more +complicated example, if you have an 8-core machine and a 64-core machine +with similar per-core performance, you could run an OpenMP-enabled build +on both of them and use "--node=1/9" (without "--fork") on the first +machine (8 threads in 1 process) and "--fork=8 --node=2-9/9" on the +64-core machine (8 threads in 8 processes, for 64 threads total on this +machine). With the current implementation, the node numbers range +assigned to each John invocation must match the "--fork" process count. + +When running with "--fork", multiple ".rec" files are created, which are +then read back by "--status" and "--restore" if you use those options. +Just like with other options, you must not specify "--fork" along with +"--status" or "--restore", because these read the main (unnumbered) +".rec" file first, which contains the right "--fork" option in it, +resulting in further (numbered) ".rec" files being read as appropriate. + +Under the hood, "--fork" makes use of the same functionality that +"--node" does, so the same efficiency and scalability limitations apply. +Despite of those, "--fork" is often much more efficient than OpenMP - +especially for fast to compute hash types (such as LM hashes), where +OpenMP overhead is often unacceptable. + +Similarly to "--node", there's almost no communication between the +processes with "--fork". Hashes successfully cracked by one process +continue being cracked by other processes. Just like with "--node", +this is mostly OK for saltless hash types or when there's just one salt, +but it is a serious drawback when many different salts are present and +their number could potentially be decreasing as some hashes get cracked. +To have the cracked hashes (and possibly salts) removed from all +processes, you may interrupt and restore the session once in a while. + +--format=NAME force hash type NAME + +Allows you to override the hash type detection. As of John the Ripper +version 1.8.0, valid "format names" are descrypt, bsdicrypt, md5crypt, +bcrypt, LM, AFS, tripcode, dummy, and crypt (and many more are added in +jumbo). You can use this option when you're starting a cracking session +or along with one of: "--test", "--show", "--make-charset". Note that +John can't crack hashes of different types at the same time. If you +happen to get a password file that uses more than one hash type, then +you have to invoke John once for each hash type and you need to use this +option to make John crack hashes of types other than the one it would +autodetect by default. + +"--format=crypt" may or may not be supported in a given build of John. +In default builds of John, this support is currently only included on +Linux and Solaris. When specified (and supported), this option makes +John use the system's crypt(3) or crypt_r(3) function. This may be +needed to audit password hashes supported by the system, but not yet +supported by John's own optimized cryptographic routines. Currently, +this is the case for glibc 2.7+ SHA-crypt hashes as used by recent +versions of Fedora and Ubuntu, and for SunMD5 hashes supported (but not +used by default) on recent versions of Solaris. In fact, you do not +have to explicitly specify "--format=crypt" for hashes of these specific +types unless you have other hash types (those supported by John +natively) in the password file(s) as well (in which case another hash +type may get detected unless you specify this option). + +"--format=crypt" is also a way to make John crack crypt(3) hashes of +different types at the same time, but doing so results in poor +performance and in unnecessarily poor results (in terms of passwords +cracked) for hashes of the "faster" types (as compared to the "slower" +ones loaded for cracking at the same time). So you are advised to use +separate invocations of John, one per hash type. + + + Additional utilities (compiled/installed along with John). + +There are some related utilities in John's run directory. (Depending on +platform, these may be symlinks to the main John program binary.) + + unshadow PASSWORD-FILE SHADOW-FILE + +Combines the "passwd" and "shadow" files (when you already have access +to both) for use with John. You might need this since if you only +used your shadow file, the "Full Name" or "GECOS" information wouldn't +be used by the "single crack" mode (thus reducing its efficiency) and +you wouldn't be able to use the "--groups" and "--shells" options and +to select by UID with "--users". You probably also want to see all of +the passwd file fields with "--show". + +You'll usually want to redirect the output of "unshadow" to a file +which you then pass to John. + + unafs DATABASE-FILE CELL-NAME + +Gets password hashes out of the binary AFS database and produces +output usable by John (you should redirect the output to a file). + + unique OUTPUT-FILE + +Removes duplicates from a wordlist (read from stdin) without changing +the order of entries. You might want to use this with John's +"--stdout" option if you've got a lot of disk space to trade for the +reduced cracking time (on possibly trying some duplicates as they +might be produced with word mangling rules). + + + Scripts. + +There are also some related scripts supplied in John's run directory. +(Binary packages of John may choose to install these along with the +documentation instead.) + + relbench BENCHMARK-FILE-1 BENCHMARK-FILE-2 + +relbench is a Perl script to compare two "john --test" benchmark runs, +such as for different machines, "make" targets, C compilers, +optimization options, or/and versions of John the Ripper. To use it, +redirect the output of each "john --test" run to a file, then run the +script on the two files. Most values output by the script indicate +relative performance seen on the second benchmark run as compared to the +first one, with the value of 1.0 indicating no change, values higher +than 1.0 indicating speedup, and values lower than 1.0 indicating +slowdown. Specifically, the script outputs the minimum, maximum, +median, and geometric mean for the speedup (or slowdown) seen across the +many individual benchmarks that "john --test" performs. It also outputs +the median absolute deviation (relative to the median) and geometric +standard deviation (relative to the geometric mean). Of these two, a +median absolute deviation of 0.0 would indicate that no deviation from +the median is prevalent, whereas a geometric standard deviation of 1.0 +would indicate that all benchmarks were sped up or slowed down by the +exact same ratio or their speed remained unchanged. In practice, these +values will tend to deviate from 0.0 and 1.0, respectively. + + mailer PASSWORD-FILE + +A shell script to send mail to all users whose passwords got cracked. +This is not always a good idea, though, since lots of people do not +check their e-mail or ignore such messages, and the messages can be a +hint for crackers. + +You should probably deploy proactive password strength checking, such as +with passwdqc, before you ask users to change their passwords - whether +using this script or otherwise. And you should edit the message inside +the script before possibly using it. + + makechr + +This is a script to (re-)generate the .chr files using passwords in +john.pot and applying all of the defined external mode filters. To +speed it up on a sufficiently large computer (RAM and CPUs), "&" may be +added after the John invocation inside the script (to run all of them in +parallel). + +$Owl: Owl/packages/john/john/doc/OPTIONS,v 1.19 2013/05/29 20:20:08 solar Exp $ diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..bd67f56 --- /dev/null +++ b/doc/README @@ -0,0 +1,142 @@ + John the Ripper password cracker. + +John the Ripper is a fast password cracker, currently available for +many flavors of Unix (11 are officially supported, not counting +different architectures), Windows, DOS, BeOS, and OpenVMS (the latter +requires a contributed patch). Its primary purpose is to detect weak +Unix passwords. Besides several crypt(3) password hash types most +commonly found on various Unix flavors, supported out of the box are +Kerberos/AFS and Windows LM hashes, as well as DES-based tripcodes, plus +many more hashes and ciphers in "community enhanced" -jumbo versions +and/or with other contributed patches. + + + How to install. + +See INSTALL for information on installing John on your system. + + + How to use. + +To run John, you need to supply it with some password files and +optionally specify a cracking mode, like this, using the default order +of modes and assuming that "passwd" is a copy of your password file: + + john passwd + +or, to restrict it to the wordlist mode only, but permitting the use +of word mangling rules: + + john --wordlist=password.lst --rules passwd + +Cracked passwords will be printed to the terminal and saved in the +file called $JOHN/john.pot (in the documentation and in the +configuration file for John, "$JOHN" refers to John's "home +directory"; which directory it really is depends on how you installed +John). The $JOHN/john.pot file is also used to not load password +hashes that you already cracked when you run John the next time. + +To retrieve the cracked passwords, run: + + john --show passwd + +While cracking, you can press any key for status, or 'q' or Ctrl-C to +abort the session saving its state to a file ($JOHN/john.rec by +default). If you press Ctrl-C for a second time before John had a +chance to complete handling of your first Ctrl-C, John will abort +immediately without saving. By default, the state is also saved every +10 minutes to permit for recovery in case of a crash. + +To continue an interrupted session, run: + + john --restore + +These are just the most essential things you can do with John. For +a complete list of command line options and for more complicated usage +examples you should refer to OPTIONS and EXAMPLES, respectively. + +Please note that "binary" (pre-compiled) distributions of John may +include alternate executables instead of just "john". You may need to +choose the executable that fits your system best, e.g. "john-omp" to +take advantage of multiple CPUs and/or CPU cores. + + + Features and performance. + +John the Ripper is designed to be both feature-rich and fast. It +combines several cracking modes in one program and is fully +configurable for your particular needs (you can even define a custom +cracking mode using the built-in compiler supporting a subset of C). +Also, John is available for several different platforms which enables +you to use the same cracker everywhere (you can even continue a +cracking session which you started on another platform). + +Out of the box, John supports (and autodetects) the following Unix +crypt(3) hash types: traditional DES-based, "bigcrypt", BSDI extended +DES-based, FreeBSD MD5-based (also used on Linux and in Cisco IOS), and +OpenBSD Blowfish-based (now also used on some Linux distributions and +supported by recent versions of Solaris). Also supported out of the box +are Kerberos/AFS and Windows LM (DES-based) hashes, as well as DES-based +tripcodes. + +When running on Linux distributions with glibc 2.7+, John 1.7.6+ +additionally supports (and autodetects) SHA-crypt hashes (which are +actually used by recent versions of Fedora and Ubuntu), with optional +OpenMP parallelization (requires GCC 4.2+, needs to be explicitly +enabled at compile-time by uncommenting the proper OMPFLAGS line near +the beginning of the Makefile). + +Similarly, when running on recent versions of Solaris, John 1.7.6+ +supports and autodetects SHA-crypt and SunMD5 hashes, also with +optional OpenMP parallelization (requires GCC 4.2+ or recent Sun Studio, +needs to be explicitly enabled at compile-time by uncommenting the +proper OMPFLAGS line near the beginning of the Makefile and at runtime +by setting the OMP_NUM_THREADS environment variable to the desired +number of threads). + +John the Ripper Pro adds support for Windows NTLM (MD4-based) and Mac +OS X 10.4+ salted SHA-1 hashes. + +"Community enhanced" -jumbo versions add support for many more password +hash types, including Windows NTLM (MD4-based), Mac OS X 10.4-10.6 +salted SHA-1 hashes, Mac OS X 10.7 salted SHA-512 hashes, raw MD5 and +SHA-1, arbitrary MD5-based "web application" password hash types, hashes +used by SQL database servers (MySQL, MS SQL, Oracle) and by some LDAP +servers, several hash types used on OpenVMS, password hashes of the +Eggdrop IRC bot, and lots of other hash types, as well as many +non-hashes such as OpenSSH private keys, S/Key skeykeys files, Kerberos +TGTs, PDF files, ZIP (classic PKZIP and WinZip/AES) and RAR archives. + +Unlike older crackers, John normally does not use a crypt(3)-style +routine. Instead, it has its own highly optimized modules for different +hash types and processor architectures. Some of the algorithms used, +such as bitslice DES, couldn't have been implemented within the crypt(3) +API; they require a more powerful interface such as the one used in +John. Additionally, there are assembly language routines for several +processor architectures, most importantly for x86-64 and x86 with SSE2. + + + Documentation. + +The rest of documentation is located in separate files, listed here in +the recommended order of reading: + +* INSTALL - installation instructions +* OPTIONS - command line options and additional utilities +* MODES - cracking modes: what they are +* CONFIG (*) - how to customize +* RULES (*) - wordlist rules syntax +* EXTERNAL (*) - defining an external mode +* EXAMPLES - usage examples - strongly recommended +* FAQ - guess +* CHANGES (*) - history of changes +* CONTACT (*) - how to contact the author or otherwise obtain support +* CREDITS (*) - credits +* LICENSE - copyrights and licensing terms +* COPYING - GNU GPL version 2, as referenced by LICENSE above + +(*) most users can safely skip these. + +Happy reading! + +$Owl: Owl/packages/john/john/doc/README,v 1.25 2013/05/30 00:22:14 solar Exp $ diff --git a/doc/RULES b/doc/RULES new file mode 100644 index 0000000..a9f0166 --- /dev/null +++ b/doc/RULES @@ -0,0 +1,292 @@ + Wordlist rules syntax. + +Each wordlist rule consists of optional rule reject flags followed by +one or more simple commands, listed all on one line and optionally +separated with spaces. There's also a preprocessor, which generates +multiple rules for a single source line. Below you will find +descriptions of the rule reject flags, the rule commands (many of them +are compatible with those of Crack 5.0a), and the preprocessor syntax. + + + Rule reject flags. + +-: no-op: don't reject +-c reject this rule unless current hash type is case-sensitive +-8 reject this rule unless current hash type uses 8-bit characters +-s reject this rule unless some password hashes were split at loading +-p reject this rule unless word pair commands are currently allowed + + + Numeric constants and variables. + +Numeric constants may be specified and variables referred to with the +following characters: + +0...9 for 0...9 +A...Z for 10...35 +* for max_length +- for (max_length - 1) ++ for (max_length + 1) +a...k user-defined numeric variables (with the "v" command) +l initial or updated word's length (updated whenever "v" is used) +m initial or memorized word's last character position +p position of the character last found with the "/" or "%" commands +z "infinite" position or length (beyond end of word) + +Here max_length is the maximum plaintext length supported for the +current hash type. + +These may be used to specify character positions, substring lengths, and +other numeric parameters to rule commands as appropriate for a given +command. Character positions are numbered starting with 0. Thus, for +example, the initial value of "m" (last character position) is one less +than that of "l" (length). + + + Character classes. + +?? matches "?" +?v matches vowels: "aeiouAEIOU" +?c matches consonants: "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ" +?w matches whitespace: space and horizontal tabulation characters +?p matches punctuation: ".,:;'?!`" and the double quote character +?s matches symbols "$%^&*()-_+=|\<>[]{}#@/~" +?l matches lowercase letters [a-z] +?u matches uppercase letters [A-Z] +?d matches digits [0-9] +?a matches letters [a-zA-Z] +?x matches letters and digits [a-zA-Z0-9] +?z matches all characters + +The complement of a class can be specified by uppercasing its name. For +example, "?D" matches everything but digits. + + + Simple commands. + +: no-op: do nothing to the input word +l convert to lowercase +u convert to uppercase +c capitalize +C lowercase the first character, and uppercase the rest +t toggle case of all characters in the word +TN toggle case of the character in position N +r reverse: "Fred" -> "derF" +d duplicate: "Fred" -> "FredFred" +f reflect: "Fred" -> "FredderF" +{ rotate the word left: "jsmith" -> "smithj" +} rotate the word right: "smithj" -> "jsmith" +$X append character X to the word +^X prefix the word with character X + + + String commands. + +AN"STR" insert string STR into the word at position N + +To append a string, specify "z" for the position. To prefix the word +with a string, specify "0" for the position. + +Although the use of the double-quote character is good for readability, +you may use any other character not found in STR instead. This is +particularly useful when STR contains the double-quote character. +There's no way to escape your quotation character of choice within a +string (preventing it from ending the string and the command), but you +may achieve the same effect by specifying multiple commands one after +another. For example, if you choose to use the forward slash as your +quotation character, yet it happens to be found in a string and you +don't want to reconsider your choice, you may write "Az/yes/$/Az/no/", +which will append the string "yes/no". Of course, it is simpler and +more efficient to use, say, "Az,yes/no," for the same effect. + + + Length control commands. + +N reject the word unless it is greater than N characters long +'N truncate the word at length N + + + English grammar commands. + +p pluralize: "crack" -> "cracks", etc. (lowercase only) +P "crack" -> "cracked", etc. (lowercase only) +I "crack" -> "cracking", etc. (lowercase only) + + + Insert/delete commands. + +[ delete the first character +] delete the last character +DN delete the character in position N +xNM extract substring from position N for up to M characters +iNX insert character X in position N and shift the rest right +oNX overstrike character in position N with character X + +Also see the "X" command (extract and insert substring) under "Memory +access commands" below. + +Note that square brackets ("[" and "]") are special characters to the +preprocessor: you should escape them with a backslash ("\") if using +these commands. + + + Charset conversion commands. + +S shift case: "Crack96" -> "cRACK(^" +V lowercase vowels, uppercase consonants: "Crack96" -> "CRaCK96" +R shift each character right, by keyboard: "Crack96" -> "Vtsvl07" +L shift each character left, by keyboard: "Crack96" -> "Xeaxj85" + + + Memory access commands. + +M memorize the word (for use with "Q", "X", or to update "m") +Q query the memory and reject the word unless it has changed +XNMI extract substring NM from memory and insert into current word at I + +If "Q" or "X" are used without a preceding "M", they read from the +initial "word". In other words, you may assume an implied "M" at the +start of each rule, and there's no need to ever start a rule with "M" +(that "M" would be a no-op). The only reasonable use for "M" is in the +middle of a rule, after some commands have possibly modified the word. + +The intended use for the "Q" command is to help avoid duplicate +candidate passwords that could result from multiple similar rules. For +example, if you have the rule "l" (lowercase) somewhere in your ruleset +and you want to add the rule "lr" (lowercase and reverse), you could +instead write the latter as "lMrQ" in order to avoid producing duplicate +candidate passwords for palindromes. + +The "X" command extracts a substring from memory (or from the initial +word if "M" was never used) starting at position N (in the memorized or +initial word) and going for up to M characters. It inserts the +substring into the current word at position I. The target position may +be "z" for appending the substring, "0" for prefixing the word with it, +or it may be any other valid numeric constant or variable. Some example +uses, assuming that we're at the start of a rule or after an "M", would +be "X011" (duplicate the first character), "Xm1z" (duplicate the last +character), "dX0zz" (triplicate the word), "<4X011X113X215" (duplicate +every character in a short word), ">9x5zX05z" (rotate long words left by +5 characters, same as ">9{{{{{" but faster due to fewer commands), +">9vam4Xa50'l" (rotate right by 5 characters, same as ">9}}}}}"). + + + Numeric commands. + +vVNM update "l" (length), then subtract M from N and assign to variable V + +V must be one of "a" through "k". N and M may be any valid numeric +constants or initialized variables. It is OK to refer to the same +variable in the same command more than once, even three times. For +example, "va00" and "vaaa" will both set the variable "a" to zero (but +the latter will require "a" to have been previously initialized), +whereas "vil2" will set the variable "i" to the current word's length +minus 2. If "i" is then used as a character position before the word is +modified further, it will refer to the second character from the end. +It is OK for intermediate variable values to become negative, but such +values should not be directly used as positions or lengths. For +example, if we follow our "vil2" somewhere later in the same rule with +"vj02vjij", we'll set "j" to "i" plus 2, or to the word's length as of +the time of processing of the "vil2" command earlier in the rule. + + + Character class commands. + +sXY replace all characters X in the word with Y +s?CY replace all characters of class C in the word with Y +@X purge all characters X from the word +@?C purge all characters of class C from the word +!X reject the word if it contains character X +!?C reject the word if it contains a character in class C +/X reject the word unless it contains character X +/?C reject the word unless it contains a character in class C +=NX reject the word unless character in position N is equal to X +=N?C reject the word unless character in position N is in class C +(X reject the word unless its first character is X +(?C reject the word unless its first character is in class C +)X reject the word unless its last character is X +)?C reject the word unless its last character is in class C +%NX reject the word unless it contains at least N instances of X +%N?C reject the word unless it contains at least N characters of class C + + + Extra "single crack" mode commands. + +When defining "single crack" mode rules, extra commands are available +for word pairs support, to control if other commands are applied to the +first, the second, or to both words: + +1 first word only +2 second word only ++ the concatenation of both (should only be used after a "1" or "2") + +If you use some of the above commands in a rule, it will only process +word pairs (e.g., full names from the GECOS field) and reject single +words. A "+" is assumed at the end of any rule that uses some of these +commands, unless you specify it manually. For example, "1l2u" will +convert the first word to lowercase, the second one to uppercase, and +use the concatenation of both. The use for a "+" might be to apply some +more commands: "1l2u+r" will reverse the concatenation of both words, +after applying some commands to them separately. + + + The rule preprocessor. + +The preprocessor is used to combine similar rules into one source line. +For example, if you need to make John try lowercased words with digits +appended, you could write a rule for each digit, 10 rules total. Now +imagine appending two-digit numbers - the configuration file would get +large and ugly. + +With the preprocessor you can do these things easier. Simply write one +source line containing the common part of these rules followed by the +list of characters you would have put into separate rules, in square +brackets (the way you would do in a regexp). The preprocessor will then +generate the rules for you (at John startup for syntax checking, and +once again while cracking, but never keeping all of the expanded rules +in memory). For the examples above, the source lines will be "l$[0-9]" +(lowercase and append a digit) and "l$[0-9]$[0-9]" (lowercase and append +two digits). These source lines will be expanded to 10 and 100 rules, +respectively. By the way, preprocessor commands are processed +right-to-left while character lists are processed left-to-right, which +results in natural ordering of numbers in the above examples and in +other typical cases. Note that arbitrary combinations of character +ranges and character lists are valid. For example, "[aeiou]" will use +vowels, whereas "[aeiou0-9]" will use vowels and digits. If you need to +have John try vowels followed by all other letters, you can use +"[aeioua-z]" - the preprocessor is smart enough not to produce duplicate +rules in such cases (although this behavior may be disabled with the +"\r" magic escape sequence described below). + +There are some special characters in rules ("[" starts a preprocessor +character list, "-" marks a range inside the list, etc.) You should +prefix them with a backslash ("\") if you want to put them inside a rule +without using their special meaning. Of course, the same applies to "\" +itself. Also, if you need to start a preprocessor character list at the +very beginning of a line, you'll have to prefix it with a ":" (the no-op +rule command), or it would be treated as a new section start. + +Finally, the preprocessor supports some magic escape sequences. These +start with a backslash and use characters that you would not normally +need to escape. In the following paragraph describing the escapes, the +word "range" refers to a single instance of a mix of character lists +and/or ranges placed in square brackets as illustrated above. + +Currently supported are "\1" through "\9" for back-references to prior +ranges (these will be substituted by the same character that is +currently substituted for the referenced range, with ranges numbered +from 1, left-to-right), "\0" for back-reference to the immediately +preceding range, "\p" before a range to have that range processed "in +parallel" with preceding ranges, "\p1" through "\p9" to have the range +processed "in parallel" with the specific referenced range, "\p0" to +have the range processed "in parallel" with the immediately preceding +range, and "\r" to allow the range to produce repeated characters. The +"\r" escape is only useful if the range is "parallel" to another one or +if there's at least one other range "parallel" to this one, because you +should not want to actually produce duplicate rules. + +Please refer to the default configuration file for John the Ripper for +many example uses of the features described in here. + +$Owl: Owl/packages/john/john/doc/RULES,v 1.11 2010/02/26 01:13:37 solar Exp $ diff --git a/run/ascii.chr b/run/ascii.chr new file mode 100644 index 0000000..8633c64 Binary files /dev/null and b/run/ascii.chr differ diff --git a/run/digits.chr b/run/digits.chr new file mode 100644 index 0000000..d6ab68b Binary files /dev/null and b/run/digits.chr differ diff --git a/run/john.conf b/run/john.conf new file mode 100644 index 0000000..b5ac1aa --- /dev/null +++ b/run/john.conf @@ -0,0 +1,1404 @@ +# +# This file is part of John the Ripper password cracker, +# Copyright (c) 1996-2006,2008-2013 by Solar Designer +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# +# There's ABSOLUTELY NO WARRANTY, express or implied. +# +# Please note that although this configuration file is under the cut-down BSD +# license above, many source files in John the Ripper are under GPLv2. +# For licensing terms for John the Ripper as a whole, see doc/LICENSE. +# + +[Options] +# Wordlist file name, to be used in batch mode +Wordlist = $JOHN/password.lst +# Use idle cycles only +Idle = Y +# Crash recovery file saving delay in seconds +Save = 600 +# Beep when a password is found (who needs this anyway?) +Beep = N + +# "Single crack" mode rules +[List.Rules:Single] +# Simple rules come first... +: +-s x** +-c (?a c Q +-c l Q +-s-c x** /?u l +# These were not included in crackers I've seen, but are pretty efficient, +# so I include them near the beginning +>6 '6 +>7 '7 l +-c >6 '6 /?u l +>5 '5 +# Weird order, eh? Can't do anything about it, the order is based on the +# number of successful cracks... +<* d +r c +-c <* (?a d c +-c >5 '5 /?u l +-c u Q +-c )?a r l +-[:c] <* !?A \p1[lc] p +-c <* c Q d +-c >7 '7 /?u +>4 '4 l +-c <+ (?l c r +-c <+ )?l l Tm +>3 '3 +-c >4 '4 /?u +-c >3 '3 /?u l +-c u Q r +<* d M 'l f Q +-c <* l Q d M 'l f Q +# About 50% of single-mode-crackable passwords get cracked by now... +# >2 x12 ... >8 x18 +>[2-8] x1\1 +>9 \[ +# >3 x22 ... >9 x28 +>[3-9] x2\p[2-8] +# >4 x32 ... >9 x37 +>[4-9] x3\p[2-7] +# >2 x12 /?u l ... >8 x18 /?u l +-c >[2-8] x1\1 /?u l +-c >9 \[ /?u l +# >3 x22 /?u l ... >9 x28 /?u l +-c >[3-9] x2\p[2-8] /?u l +# >4 x32 /?u l ... >9 x37 /?u l +-c >[4-9] x3\p[2-7] /?u l +# Now to the suffix stuff... +<* l $[1-9!0a-rt-z"-/:-@\[-`{-~] +-c <* (?a c $[1-9!0a-rt-z"-/:-@\[-`{-~] +-[:c] <* !?A (?\p1[za] \p1[lc] $s M 'l p Q X0z0 'l $s +-[:c] <* /?A (?\p1[za] \p1[lc] $s +<* l r $[1-9!] +-c <* /?a u $[1-9!] +-[:c] <- (?\p1[za] \p1[lc] Az"'s" +-[:c] <- (?\p1[za] \p1[lc] Az"!!" +-[:c] (?\p1[za] \p1[lc] $! <- Az"!!" +# Removing vowels... +-[:c] /?v @?v >2 (?\p1[za] \p1[lc] +/?v @?v >2 <* d +# crack -> cracked, crack -> cracking +<* l [PI] +-c <* l [PI] (?a c +# mary -> marie +-[:c] <* (?\p1[za] \p1[lc] )y omi $e +# marie -> mary +-[:c] <* (?\p1[za] \p1[lc] )e \] )i val1 oay +# The following are some 3l33t rules +-[:c] l /[aelos] s\0\p[4310$] (?\p1[za] \p1[:c] +-[:c] l /a /[elos] sa4 s\0\p[310$] (?\p1[za] \p1[:c] +-[:c] l /e /[los] se3 s\0\p[10$] (?\p1[za] \p1[:c] +-[:c] l /l /[os] sl1 s\0\p[0$] (?\p1[za] \p1[:c] +-[:c] l /o /s so0 ss$ (?\p1[za] \p1[:c] +-[:c] l /a /e /[los] sa4 se3 s\0\p[10$] (?\p1[za] \p1[:c] +-[:c] l /a /l /[os] sa4 sl1 s\0\p[0$] (?\p1[za] \p1[:c] +-[:c] l /a /o /s sa4 so0 ss$ (?\p1[za] \p1[:c] +-[:c] l /e /l /[os] se3 sl1 s\0\p[0$] (?\p1[za] \p1[:c] +-[:c] l /[el] /o /s s\0\p[31] so0 ss$ (?\p1[za] \p1[:c] +-[:c] l /a /e /l /[os] sa4 se3 sl1 s\0\p[0$] (?\p1[za] \p1[:c] +-[:c] l /a /[el] /o /s sa4 s\0\p[31] so0 ss$ (?\p1[za] \p1[:c] +-[:c] l /e /l /o /s se3 sl1 so0 ss$ (?\p1[za] \p1[:c] +-[:c] l /a /e /l /o /s sa4 se3 sl1 so0 ss$ (?\p1[za] \p1[:c] +# Now to the prefix stuff... +l ^[1a-z2-90] +-c l Q ^[A-Z] +^[A-Z] +l ^["-/:-@\[-`{-~] +-[:c] <9 (?a \p1[lc] A0"[tT]he" +-[:c] <9 (?a \p1[lc] A0"[aA]my" +-[:c] <9 (?a \p1[lc] A0"[mdMD]r" +-[:c] <9 (?a \p1[lc] A0"[mdMD]r." +-[:c] <9 (?a \p1[lc] A0"__" +<- !?A l p ^[240-9] +# Some word pair rules... +# johnsmith -> JohnSmith, johnSmith +-p-c (?a 2 (?a c 1 [cl] +# JohnSmith -> john smith, john_smith, john-smith +-p 1 <- $[ _\-] + l +# JohnSmith -> John smith, John_smith, John-smith +-p-c 1 <- (?a c $[ _\-] 2 l +# JohnSmith -> john Smith, john_Smith, john-Smith +-p-c 1 <- l $[ _\-] 2 (?a c +# johnsmith -> John Smith, John_Smith, John-Smith +-p-c 1 <- (?a c $[ _\-] 2 (?a c +# Applying different simple rules to each of the two words +-p-[c:] 1 \p1[ur] 2 l +-p-c 2 (?a c 1 [ur] +-p-[c:] 1 l 2 \p1[ur] +-p-c 1 (?a c 2 [ur] +# jsmith -> smithj, etc... +-[:c] (?a \p1[lc] [{}] +-[:c] (?a \p1[lc] [{}] \0 +# Toggle case... +-c <+ )?u l Tm +-c T0 Q M c Q l Q u Q C Q X0z0 'l +-c T[1-9A-E] Q M l Tm Q C Q u Q l Q c Q X0z0 'l +-c l Q T[1-9A-E] Q M T\0 Q l Tm Q C Q u Q X0z0 'l +-c >2 2 /?l /?u t Q M c Q C Q l Tm Q X0z0 'l +# Deleting chars... +>[2-8] D\p[1-7] +>[8-9A-E] D\1 +-c /?u >[2-8] D\p[1-7] l +-c /?u >[8-9A-E] D\1 l +=1?a \[ M c Q +-c (?a >[1-9A-E] D\1 c +# Inserting a dot... +-[:c] >3 (?a \p1[lc] i[12]. +# More suffix stuff... +<- l Az"[190][0-9]" +-c <- (?a c Az"[190][0-9]" +<- l Az"[782][0-9]" +-c <- (?a c Az"[782][0-9]" +<* l $[A-Z] +-c <* (?a c $[A-Z] +# cracking -> CRACKiNG +-c u /I sIi +# Crack96 -> cRACK96 +%2?a C Q +# Crack96 -> cRACK(^ +/?A S Q +# Crack96 -> CRaCK96 +-c /?v V Q +# Really weird charset conversions, like "england" -> "rmh;smf" +:[RL] Q +l Q [RL] +-c (?a c Q [RL] +:[RL] \0 Q +# Both prefixing and suffixing... +<- l ^[1!@#$%^&*\-=_+.?|:'"] $\1 +<- l ^[({[<] $\p[)}\]>] +# The rest of two-digit suffix stuff, less common numbers... +<- l Az"[63-5][0-9]" +-c <- (?a c Az"[63-5][0-9]" +# Some multi-digit numbers... +-[:c] (?a \p1[lc] Az"007" <+ +-[:c] (?a \p1[lc] Az"123" <+ +-[:c] (?a \p1[lc] Az"[0-9]\0\0" <+ +-[:c] (?a \p1[lc] Az"1234" <+ +-[:c] (?a \p1[lc] Az"[0-9]\0\0\0" <+ +-[:c] (?a \p1[lc] Az"12345" <+ +-[:c] (?a \p1[lc] Az"[0-9]\0\0\0\0" <+ +-[:c] (?a \p1[lc] Az"123456" <+ +-[:c] (?a \p1[lc] Az"[0-9]\0\0\0\0\0" <+ +# Some [birth] years... +l Az"19[7-96-0]" <+ >- +l Az"20[01]" <+ >- +l Az"19[7-9][0-9]" <+ +l Az"20[01][0-9]" <+ +l Az"19[6-0][9-0]" <+ +# Uncomment the following lines if you're really crazy +;# Insert/overstrike some characters... +;!?A >[1-6] l i\0[a-z] +;!?A l o0[a-z] +;!?A >[1-7] l o\0[a-z] +;# Toggle case everywhere (up to length 8), assuming that certain case +;# combinations were already tried. +;-c T1 Q M T0 Q +;-c T2 Q M T[z0] T[z1] Q +;-c T3 Q M T[z0] T[z1] T[z2] Q +;-c T4 Q M T[z0] T[z1] T[z2] T[z3] Q +;-c T5 Q M T[z0] T[z1] T[z2] T[z3] T[z4] Q +;-c T6 Q M T[z0] T[z1] T[z2] T[z3] T[z4] T[z5] Q +;-c T7 Q M T[z0] T[z1] T[z2] T[z3] T[z4] T[z5] T[z6] Q +;# Very slow stuff... +;l Az"[1-90][0-9][0-9]" <+ +;-c (?a c Az"[1-90][0-9][0-9]" <+ +;<[\-9] l A\p[z0]"[a-z][a-z]" +;<- l ^[a-z] $[a-z] + +# Wordlist mode rules +[List.Rules:Wordlist] +# Try words as they are +: +# Lowercase every pure alphanumeric word +-c >3 !?X l Q +# Capitalize every pure alphanumeric word +-c (?a >2 !?X c Q +# Lowercase and pluralize pure alphabetic words +<* >2 !?A l p +# Lowercase pure alphabetic words and append '1' +<* >2 !?A l $1 +# Capitalize pure alphabetic words and append '1' +-c <* >2 !?A c $1 +# Duplicate reasonably short pure alphabetic words (fred -> fredfred) +<7 >1 !?A l d +# Lowercase and reverse pure alphabetic words +>3 !?A l M r Q +# Prefix pure alphabetic words with '1' +>2 !?A l ^1 +# Uppercase pure alphanumeric words +-c >2 !?X u Q M c Q u +# Lowercase pure alphabetic words and append a digit or simple punctuation +<* >2 !?A l $[2!37954860.?] +# Words containing punctuation, which is then squeezed out, lowercase +/?p @?p >3 l +# Words with vowels removed, lowercase +/?v @?v >3 l +# Words containing whitespace, which is then squeezed out, lowercase +/?w @?w >3 l +# Capitalize and duplicate short pure alphabetic words (fred -> FredFred) +-c <7 >1 !?A c d +# Capitalize and reverse pure alphabetic words (fred -> derF) +-c <+ >2 !?A c r +# Reverse and capitalize pure alphabetic words (fred -> Derf) +-c >2 !?A l M r Q c +# Lowercase and reflect pure alphabetic words (fred -> fredderf) +<7 >1 !?A l d M 'l f Q +# Uppercase the last letter of pure alphabetic words (fred -> freD) +-c <+ >2 !?A l M r Q c r +# Prefix pure alphabetic words with '2' or '4' +>2 !?A l ^[24] +# Capitalize pure alphabetic words and append a digit or simple punctuation +-c <* >2 !?A c $[2!3957468.?0] +# Prefix pure alphabetic words with digits +>2 !?A l ^[379568] +# Capitalize and pluralize pure alphabetic words of reasonable length +-c <* >2 !?A c p +# Lowercase/capitalize pure alphabetic words of reasonable length and convert: +# crack -> cracked, crack -> cracking +-[:c] <* >2 !?A \p1[lc] M [PI] Q +# Try the second half of split passwords +-s x** +-s-c x** M l Q + +# Case toggler for cracking MD4-based NTLM hashes (with the contributed patch) +# given already cracked DES-based LM hashes. +# Rename this section to [List.Rules:Wordlist] to activate it. +[List.Rules:NT] +: +-c T0Q +-c T1QT[z0] +-c T2QT[z0]T[z1] +-c T3QT[z0]T[z1]T[z2] +-c T4QT[z0]T[z1]T[z2]T[z3] +-c T5QT[z0]T[z1]T[z2]T[z3]T[z4] +-c T6QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5] +-c T7QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6] +-c T8QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7] +-c T9QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8] +-c TAQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9] +-c TBQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA] +-c TCQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB] +-c TDQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB]T[zC] + +# Incremental modes +[Incremental:ASCII] +File = $JOHN/ascii.chr +MinLen = 0 +MaxLen = 13 +CharCount = 95 + +[Incremental:LM_ASCII] +File = $JOHN/lm_ascii.chr +MinLen = 0 +MaxLen = 7 +CharCount = 69 + +[Incremental:Alnum] +File = $JOHN/alnum.chr +MinLen = 1 +MaxLen = 13 +CharCount = 62 + +[Incremental:Alpha] +File = $JOHN/alpha.chr +MinLen = 1 +MaxLen = 13 +CharCount = 52 + +[Incremental:LowerNum] +File = $JOHN/lowernum.chr +MinLen = 1 +MaxLen = 13 +CharCount = 36 + +[Incremental:UpperNum] +File = $JOHN/uppernum.chr +MinLen = 1 +MaxLen = 13 +CharCount = 36 + +[Incremental:LowerSpace] +File = $JOHN/lowerspace.chr +MinLen = 1 +MaxLen = 13 +CharCount = 27 + +[Incremental:Lower] +File = $JOHN/lower.chr +MinLen = 1 +MaxLen = 13 +CharCount = 26 + +[Incremental:Upper] +File = $JOHN/upper.chr +MinLen = 1 +MaxLen = 13 +CharCount = 26 + +[Incremental:Digits] +File = $JOHN/digits.chr +MinLen = 1 +MaxLen = 20 +CharCount = 10 + +# Some pre-defined word filters as used to generate the supplied .chr files +[List.External:Filter_ASCII] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (c < 0x20 || c > 0x7e || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_LM_ASCII] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i]) { + if (c < 0x20 || c > 0x7e || // Require ASCII-only + i >= 14) { // of up to 14 characters long + word = 0; return; + } + if (c >= 'a' && c <= 'z') // Convert to uppercase + word[i] &= 0xDF; + i++; + } + + word[7] = 0; // Truncate at 7 characters +} + +[List.External:Filter_Alnum] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (((c < '0' || c > '9') && ((c &= 0xDF) < 'A' || c > 'Z')) || + i > 13) { + word = 0; return; + } +} + +[List.External:Filter_Alpha] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if ((c &= 0xDF) < 'A' || c > 'Z' || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_LowerNum] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (((c < 'a' || c > 'z') && (c < '0' || c > '9')) || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_UpperNum] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (((c < 'A' || c > 'Z') && (c < '0' || c > '9')) || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_LowerSpace] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (((c < 'a' || c > 'z') && c != ' ') || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_Lower] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (c < 'a' || c > 'z' || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_Upper] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (c < 'A' || c > 'Z' || i > 13) { + word = 0; return; + } +} + +[List.External:Filter_Digits] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (c < '0' || c > '9' || i > 20) { + word = 0; return; + } +} + +# A simple cracker for LM hashes +[List.External:LanMan] +int length; // Current length + +void init() +{ + word[0] = 'A' - 1; // Start with "A" + word[length = 1] = 0; +} + +void generate() +{ + int i; + + i = length - 1; // Start from the last character + while (++word[i] > 'Z') // Try to increase it + if (i) // Overflow here, any more positions? + word[i--] = 'A'; // Yes, move to the left, and repeat + else // No + if (length < 7) { + word[i = ++length] = 0; // Switch to the next length + while (i--) + word[i] = 'A'; + return; + } else { + word = 0; return; // We're done + } +} + +void restore() +{ + length = 0; // Calculate the length + while (word[length]) length++; +} + +# Simple and well-commented, yet useful external mode example +[List.External:Double] +/* + * This cracking mode tries all the possible duplicated lowercase alphabetic + * "words" of up to 8 characters long. Since word halves are the same, it + * only has to try about 500,000 words. + */ + +/* Global variables: current length and word */ +int length, current[9]; + +/* Called at startup to initialize the global variables */ +void init() +{ + int i; + + i = length = 2; // Start with 4 character long words + while (i--) current[i] = 'a'; // Set our half-word to "aa" +} + +/* Generates a new word */ +void generate() +{ + int i; + +/* Export last generated word, duplicating it at the same time; here "word" + * is a pre-defined external variable. */ + word[(i = length) << 1] = 0; + while (i--) word[length + i] = word[i] = current[i]; + +/* Generate a new word */ + i = length - 1; // Start from the last character + while (++current[i] > 'z') // Try to increase it + if (i) // Overflow here, any more positions? + current[i--] = 'a'; // Yes, move to the left, and repeat + else { // No + current = 0; // Request a length switch + break; // Break out of the loop + } + +/* Switch to the next length, unless we were generating 8 character long + * words already. */ + if (!current && length < 4) { + i = ++length; + while (i--) current[i] = 'a'; + } +} + +/* Called when restoring an interrupted session */ +void restore() +{ + int i; + +/* Import the word back */ + i = 0; + while (current[i] = word[i]) i++; + +/* ...and calculate the half-word length */ + length = i >> 1; +} + +# Strip 0.5 ("Secure Tool for Recalling Important Passwords") cracker, +# based on analysis done by Thomas Roessler and Ian Goldberg. This will +# crack passwords you may have generated with Strip; other uses of Strip +# are unaffected. +[List.External:Strip] +int minlength, maxlength, mintype, maxtype; +int crack_seed, length, type; +int count, charset[128]; + +void init() +{ + int c; + +/* Password lengths to try; Strip can generate passwords of 4 to 16 + * characters, but traditional crypt(3) hashes are limited to 8. */ + minlength = 4; // 4 + maxlength = 8; // 16 + +/* Password types to try (Numeric, Alpha-Num, Alpha-Num w/ Meta). */ + mintype = 0; // 0 + maxtype = 2; // 2 + + crack_seed = 0x10000; + length = minlength - 1; + type = mintype; + + count = 0; + c = '0'; while (c <= '9') charset[count++] = c++; +} + +void generate() +{ + int seed, random; + int i, c; + + if (crack_seed > 0xffff) { + crack_seed = 0; + + if (++length > maxlength) { + length = minlength; + + if (++type > maxtype) { + word[0] = 0; + return; + } + } + + count = 10; + if (type >= 1) { + c = 'a'; while (c <= 'f') charset[count++] = c++; + c = 'h'; while (c <= 'z') charset[count++] = c++; + c = 'A'; while (c <= 'Z') charset[count++] = c++; + } + if (type == 2) { + charset[count++] = '!'; + c = '#'; while (c <= '&') charset[count++] = c++; + c = '('; while (c <= '/') charset[count++] = c++; + c = '<'; while (c <= '>') charset[count++] = c++; + charset[count++] = '?'; charset[count++] = '@'; + charset[count++] = '['; charset[count++] = ']'; + charset[count++] = '^'; charset[count++] = '_'; + c = '{'; while (c <= '~') charset[count++] = c++; + } + } + + seed = (crack_seed++ << 16 >> 16) * 22695477 + 1; + + i = 0; + while (i < length) { + random = ((seed = seed * 22695477 + 1) >> 16) & 0x7fff; + word[i++] = charset[random % count]; + } + + word[i] = 0; +} + +# Try sequences of adjacent keys on a keyboard as candidate passwords +[List.External:Keyboard] +int maxlength, length; // Maximum password length to try, current length +int fuzz; // The desired "fuzz factor", either 0 or 1 +int id[15]; // Current character indices for each position +int m[0x800]; // The keys matrix +int mc[0x100]; // Counts of adjacent keys +int f[0x40], fc; // Characters for the first position, their count + +void init() +{ + int minlength; + int i, j, c, p; + int k[0x40]; + + minlength = 1; // Initial password length to try + maxlength = 15; // Maximum password length to try, up to 15 + fuzz = 1; // "Fuzz factor", set to 0 for much quicker runs + +/* + * This defines the keyboard layout, by default for a QWERTY keyboard. + */ + i = 0; while (i < 0x40) k[i++] = 0; + k[0] = '`'; + i = 0; while (++i <= 9) k[i] = '0' + i; + k[10] = '0'; k[11] = '-'; k[12] = '='; + k[0x11] = 'q'; k[0x12] = 'w'; k[0x13] = 'e'; k[0x14] = 'r'; + k[0x15] = 't'; k[0x16] = 'y'; k[0x17] = 'u'; k[0x18] = 'i'; + k[0x19] = 'o'; k[0x1a] = 'p'; k[0x1b] = '['; k[0x1c] = ']'; + k[0x1d] = '\\'; + k[0x21] = 'a'; k[0x22] = 's'; k[0x23] = 'd'; k[0x24] = 'f'; + k[0x25] = 'g'; k[0x26] = 'h'; k[0x27] = 'j'; k[0x28] = 'k'; + k[0x29] = 'l'; k[0x2a] = ';'; k[0x2b] = '\''; + k[0x31] = 'z'; k[0x32] = 'x'; k[0x33] = 'c'; k[0x34] = 'v'; + k[0x35] = 'b'; k[0x36] = 'n'; k[0x37] = 'm'; k[0x38] = ','; + k[0x39] = '.'; k[0x3a] = '/'; + + i = 0; while (i < 0x100) mc[i++] = 0; + fc = 0; + + /* rows */ + c = 0; + i = 0; + while (i < 0x40) { + p = c; + c = k[i++] & 0xff; + if (!c) continue; + f[fc++] = c; + if (!p) continue; + m[(c << 3) + mc[c]++] = p; + m[(p << 3) + mc[p]++] = c; + } + f[fc] = 0; + + /* columns */ + i = 0; + while (i < 0x30) { + p = k[i++] & 0xff; + if (!p) continue; + j = 1 - fuzz; + while (j <= 1 + fuzz) { + c = k[i + 0x10 - j++] & 0xff; + if (!c) continue; + m[(c << 3) + mc[c]++] = p; + m[(p << 3) + mc[p]++] = c; + } + } + + length = 0; + while (length < minlength) + id[length++] = 0; +} + +void generate() +{ + int i, p, maxcount; + + word[i = 0] = p = f[id[0]]; + while (++i < length) + word[i] = p = m[(p << 3) + id[i]]; + word[i--] = 0; + + if (i) maxcount = mc[word[i - 1]]; else maxcount = fc; + while (++id[i] >= maxcount) { + if (!i) { + if (length < maxlength) { + id[0] = 0; + id[length++] = 0; + } + return; + } + id[i--] = 0; + if (i) maxcount = mc[word[i - 1]]; else maxcount = fc; + } +} + +void restore() +{ + int i; + + /* Calculate the length */ + length = 0; + while (word[length]) + id[length++] = 0; + + /* Infer the first character index */ + i = -1; + while (++i < fc) { + if (f[i] == word[0]) { + id[0] = i; + break; + } + } + + /* This sample can be enhanced to infer the rest of the indices here */ +} + +# Generic implementation of "dumb" exhaustive search, given a range of lengths +# and an arbitrary charset. This is pre-configured to try 8-bit characters +# against LM hashes, which is only reasonable to do for very short password +# half lengths. +[List.External:DumbForce] +int maxlength; // Maximum password length to try +int last; // Last character position, zero-based +int lastid; // Character index in the last position +int id[0x7f]; // Current character indices for other positions +int charset[0x100], c0; // Character set + +void init() +{ + int minlength; + int i, c; + + minlength = 1; // Initial password length to try, must be at least 1 + maxlength = 7; // Must be at least same as minlength + +/* + * This defines the character set. + * + * Let's say, we want to try TAB, all non-control ASCII characters, and all + * 8-bit characters, including the 8-bit terminal controls range (as these are + * used as regular national characters with some 8-bit encodings), but except + * for known terminal controls (risky for the terminal we may be running on). + * + * Also, let's say our hashes are case-insensitive, so skip lowercase letters + * (this is right for LM hashes). + */ + i = 0; + charset[i++] = 9; // Add horizontal TAB (ASCII 9), then + c = ' '; // start with space (ASCII 32) and + while (c < 'a') // proceed till lowercase 'a' + charset[i++] = c++; + c = 'z' + 1; // Skip lowercase letters and + while (c <= 0x7e) // proceed for all printable ASCII + charset[i++] = c++; + c++; // Skip DEL (ASCII 127) and + while (c < 0x84) // proceed over 8-bit codes till IND + charset[i++] = c++; + charset[i++] = 0x86; // Skip IND (84 hex) and NEL (85 hex) + charset[i++] = 0x87; + c = 0x89; // Skip HTS (88 hex) + while (c < 0x8d) // Proceed till RI (8D hex) + charset[i++] = c++; + c = 0x91; // Skip RI, SS2, SS3, DCS + while (c < 0x96) // Proceed till SPA (96 hex) + charset[i++] = c++; + charset[i++] = 0x99; // Skip SPA, EPA, SOS + c = 0xa0; // Skip DECID, CSI, ST, OSC, PM, APC + while (c <= 0xff) // Proceed with the rest of 8-bit codes + charset[i++] = c++; + +/* Zero-terminate it, and cache the first character */ + charset[i] = 0; + c0 = charset[0]; + + last = minlength - 1; + i = 0; + while (i <= last) { + id[i] = 0; + word[i++] = c0; + } + lastid = -1; + word[i] = 0; +} + +void generate() +{ + int i; + +/* Handle the typical case specially */ + if (word[last] = charset[++lastid]) return; + + lastid = 0; + word[i = last] = c0; + while (i--) { // Have a preceding position? + if (word[i] = charset[++id[i]]) return; + id[i] = 0; + word[i] = c0; + } + + if (++last < maxlength) { // Next length? + id[last] = lastid = 0; + word[last] = c0; + word[last + 1] = 0; + } else // We're done + word = 0; +} + +void restore() +{ + int i, c; + +/* Calculate the current length and infer the character indices */ + last = 0; + while (c = word[last]) { + i = 0; while (charset[i] != c && charset[i]) i++; + if (!charset[i]) i = 0; // Not found + id[last++] = i; + } + lastid = id[--last]; +} + +# Generic implementation of exhaustive search for a partially-known password. +# This is pre-configured for length 8, lowercase and uppercase letters in the +# first 4 positions (52 different characters), and digits in the remaining 4 +# positions - however, the corresponding part of init() may be modified to use +# arbitrary character sets or even fixed characters for each position. +[List.External:KnownForce] +int last; // Last character position, zero-based +int lastofs; // Last character position offset into charset[] +int lastid; // Current character index in the last position +int id[0x7f]; // Current character indices for other positions +int charset[0x7f00]; // Character sets, 0x100 elements for each position + +void init() +{ + int length; + int pos, ofs, i, c; + + length = 8; // Password length to try + +/* This defines the character sets for different character positions */ + pos = 0; + while (pos < 4) { + ofs = pos++ << 8; + i = 0; + c = 'a'; + while (c <= 'z') + charset[ofs + i++] = c++; + c = 'A'; + while (c <= 'Z') + charset[ofs + i++] = c++; + charset[ofs + i] = 0; + } + while (pos < length) { + ofs = pos++ << 8; + i = 0; + c = '0'; + while (c <= '9') + charset[ofs + i++] = c++; + charset[ofs + i] = 0; + } + + last = length - 1; + pos = -1; + while (++pos <= last) + word[pos] = charset[id[pos] = pos << 8]; + lastid = (lastofs = last << 8) - 1; + word[pos] = 0; +} + +void generate() +{ + int pos; + +/* Handle the typical case specially */ + if (word[last] = charset[++lastid]) return; + + word[pos = last] = charset[lastid = lastofs]; + while (pos--) { // Have a preceding position? + if (word[pos] = charset[++id[pos]]) return; + word[pos] = charset[id[pos] = pos << 8]; + } + + word = 0; // We're done +} + +void restore() +{ + int i, c; + +/* Calculate the current length and infer the character indices */ + last = 0; + while (c = word[last]) { + i = lastofs = last << 8; + while (charset[i] != c && charset[i]) i++; + if (!charset[i]) i = lastofs; // Not found + id[last++] = i; + } + lastid = id[--last]; +} + +# A variation of KnownForce configured to try likely date and time strings. +[List.External:DateTime] +int last; // Last character position, zero-based +int lastofs; // Last character position offset into charset[] +int lastid; // Current character index in the last position +int id[0x7f]; // Current character indices for other positions +int charset[0x7f00]; // Character sets, 0x100 elements for each position + +void init() +{ + int length; + int pos, ofs, i, c; + + length = 8; // Must be one of: 4, 5, 7, 8 + +/* This defines the character sets for different character positions */ + pos = 0; + while (pos < length - 6) { + ofs = pos++ << 8; + i = 0; + c = '0'; + while (c <= '9') + charset[ofs + i++] = c++; + charset[ofs + i] = 0; + } + if (pos) { + ofs = pos++ << 8; + charset[ofs] = '/'; + charset[ofs + 1] = '.'; + charset[ofs + 2] = ':'; + charset[ofs + 3] = 0; + } + while (pos < length - 3) { + ofs = pos++ << 8; + i = 0; + c = '0'; + while (c <= '9') + charset[ofs + i++] = c++; + charset[ofs + i] = 0; + } + ofs = pos++ << 8; + charset[ofs] = '/'; + charset[ofs + 1] = '.'; + charset[ofs + 2] = ':'; + charset[ofs + 3] = 0; + while (pos < length) { + ofs = pos++ << 8; + i = 0; + c = '0'; + while (c <= '9') + charset[ofs + i++] = c++; + charset[ofs + i] = 0; + } + + last = length - 1; + pos = -1; + while (++pos <= last) + word[pos] = charset[id[pos] = pos << 8]; + lastid = (lastofs = last << 8) - 1; + word[pos] = 0; +} + +void generate() +{ + int pos; + +/* Handle the typical case specially */ + if (word[last] = charset[++lastid]) return; + + word[pos = last] = charset[lastid = lastofs]; + while (pos--) { // Have a preceding position? + if (word[pos] = charset[++id[pos]]) return; + word[pos] = charset[id[pos] = pos << 8]; + } + + word = 0; // We're done +} + +void restore() +{ + int i, c; + +/* Calculate the current length and infer the character indices */ + last = 0; + while (c = word[last]) { + i = lastofs = last << 8; + while (charset[i] != c && charset[i]) i++; + if (!charset[i]) i = lastofs; // Not found + id[last++] = i; + } + lastid = id[--last]; +} + +# Try strings of repeated characters. +[List.External:Repeats] +int minlength, maxlength, minc, maxc, length, c; + +void init() +{ + minlength = 1; + maxlength = 72; + minc = 0x20; + maxc = 0xff; + + length = minlength; c = minc; +} + +void generate() +{ + int i; + + i = 0; + while (i < length) + word[i++] = c; + word[i] = 0; + + if (c++ < maxc) + return; + + c = minc; + if (++length > maxlength) + c = 0; // Will NUL out the next "word" and thus terminate +} + +# Generate candidate passwords from many small subsets of characters from a +# much larger full character set. This will test for passwords containing too +# few different characters. As currently implemented, this code will produce +# some duplicates, although their number is relatively small when the maximum +# number of different characters (the maxdiff setting) is significantly lower +# than the maximum length (the maxlength setting). Nevertheless, you may want +# to pass the resulting candidate passwords through "unique" if you intend to +# test them against hashes that are salted and/or of a slow to compute type. +[List.External:Subsets] +int minlength; // Minimum password length to try +int maxlength; // Maximum password length to try +int startdiff; // Initial number of characters in a subset to try +int maxdiff; // Maximum number of characters in a subset to try +int last; // Last character position, zero-based +int lastid; // Character index in the last position +int id[0x7f]; // Current character indices for other positions +int subset[0x100], c0; // Current subset +int subcount; // Number of characters in the current subset +int subid[0x100]; // Indices into charset[] of characters in subset[] +int charset[0x100]; // Full character set +int charcount; // Number of characters in the full charset + +void init() +{ + int i, c; + + minlength = 1; // Minimum password length to try, must be at least 1 + maxlength = 8; // Must be at least same as minlength + + startdiff = 1; // Initial number of different characters to try + maxdiff = 3; // Maximum number of different characters to try + +/* This defines the character set */ + i = 0; + c = 0x20; + while (c <= 0x7e) + charset[i++] = c++; + + if (maxdiff > (charcount = i)) + maxdiff = i; + if (maxdiff > maxlength) + maxdiff = maxlength; + +/* + * Initialize the variables such that generate() gets to its "next subset" + * code, which will initialize everything for real. + */ + subcount = (i = startdiff) - 1; + while (i--) + subid[i] = charcount; + subset[0] = c0 = 0; + last = maxlength - 1; + lastid = -1; +} + +void generate() +{ + int i; + +/* Handle the typical case specially */ + if (word[last] = subset[++lastid]) return; + + lastid = 0; + word[i = last] = c0; + while (i--) { // Have a preceding position? + if (word[i] = subset[++id[i]]) return; + id[i] = 0; + word[i] = c0; + } + + if (++last < maxlength) { // Next length? + id[last] = lastid = 0; + word[last] = c0; + word[last + 1] = 0; + return; + } + +/* Next subset */ + if (subcount) { + int j; + i = subcount - 1; + j = charcount; + while (++subid[i] >= j) { + if (i--) { + j--; + continue; + } + subid[i = 0] = 0; + subset[++subcount] = 0; + break; + } + } else { + subid[i = 0] = 0; + subset[++subcount] = 0; + } + subset[i] = charset[subid[i]]; + while (++i < subcount) + subset[i] = charset[subid[i] = subid[i - 1] + 1]; + + if (subcount > maxdiff) { + word = 0; // Done + return; + } + +/* + * We won't be able to fully use the subset if the length is smaller than the + * character count. We assume that we've tried all smaller subsets before, so + * we don't bother with such short lengths. + */ + if (minlength < subcount) + last = subcount - 1; + else + last = minlength - 1; + c0 = subset[0]; + i = 0; + while (i <= last) { + id[i] = 0; + word[i++] = c0; + } + lastid = 0; + word[i] = 0; +} + +# Simple password policy matching: require at least one digit. +[List.External:AtLeast1-Simple] +void filter() +{ + int i, c; + + i = 0; + while (c = word[i++]) + if (c >= '0' && c <= '9') + return; // Found at least one suitable character, good + + word = 0; // No suitable characters found, skip this "word" +} + +# The same password policy implemented in a more efficient and more generic +# fashion (easy to expand to include other "sufficient" characters as well). +[List.External:AtLeast1-Generic] +int mask[0x100]; + +void init() +{ + int c; + + mask[0] = 0; // Terminate the loop in filter() on NUL + c = 1; + while (c < 0x100) + mask[c++] = 1; // Continue looping in filter() on most chars + + c = '0'; + while (c <= '9') + mask[c++] = 0; // Terminate the loop in filter() on digits +} + +void filter() +{ + int i; + + i = -1; + while (mask[word[++i]]) + continue; + if (word[i]) + return; // Found at least one suitable character, good + + word = 0; // No suitable characters found, skip this "word" +} + +# An efficient and fairly generic password policy matcher. The policy to match +# is specified in the check at the end of filter() and in mask[]. For example, +# lowercase and uppercase letters may be treated the same by initializing the +# corresponding mask[] elements to the same value, then adjusting the value to +# check "seen" for accordingly. +[List.External:Policy] +int mask[0x100]; + +void init() +{ + int c; + + mask[0] = 0x100; + c = 1; + while (c < 0x100) + mask[c++] = 0x200; + + c = 'a'; + while (c <= 'z') + mask[c++] = 1; + c = 'A'; + while (c <= 'Z') + mask[c++] = 2; + c = '0'; + while (c <= '9') + mask[c++] = 4; +} + +void filter() +{ + int i, seen; + +/* + * This loop ends when we see NUL (sets 0x100) or a disallowed character + * (sets 0x200). + */ + i = -1; seen = 0; + while ((seen |= mask[word[++i]]) < 0x100) + continue; + +/* + * We should have seen at least one character of each type (which "add up" + * to 7) and then a NUL (adds 0x100), but not any other characters (would + * add 0x200). The length must be 8. + */ + if (seen != 0x107 || i != 8) + word = 0; // Does not conform to policy +} + +# Append the Luhn algorithm digit to arbitrary all-digit strings. Optimized +# for speed, not for size nor simplicity. The primary optimization trick is to +# compute the length and four sums in parallel (in two SIMD'ish variables). +# Then whether the length is even or odd determines which two of the four sums +# are actually used. Checks for non-digits and for NUL are packed into the +# SIMD'ish bitmasks as well. +[List.External:AppendLuhn] +int map1[0x100], map2[0x1fff]; + +void init() +{ + int i; + + map1[0] = ~0x7fffffff; + i = 1; + while (i < 0x100) + map1[i++] = ~0x7effffff; + i = -1; + while (++i < 10) + map1['0' + i] = i + ((i * 2 % 10 + i / 5) << 12); + i = -1; + while (++i < 0x1fff) { + if (i % 10) + map2[i] = '9' + 1 - i % 10; + else + map2[i] = '0'; + } +} + +void filter() +{ + int i, o, e; + + i = o = e = 0; + while ((o += map1[word[i++]]) >= 0) { + if ((e += map1[word[i++]]) >= 0) + continue; + if (e & 0x01000000) + return; // Not all-digit, leave unmodified + word[i--] = 0; + word[i] = map2[(e & 0xfff) + (o >> 12)]; + return; + } + if (o & 0x01000000) + return; // Not all-digit, leave unmodified + word[i--] = 0; + word[i] = map2[(o & 0xfff) + (e >> 12)]; +} + +# Trivial parallel processing example (obsoleted by the "--node" option) +[List.External:Parallel] +/* + * This word filter makes John process some of the words only, for running + * multiple instances on different CPUs. It can be used with any cracking + * mode except for "single crack". Note: this is not a good solution, but + * is just an example of what can be done with word filters. + */ + +int node, total; // This node's number, and node count +int number; // Current word number + +void init() +{ + node = 1; total = 2; // Node 1 of 2, change as appropriate + number = node - 1; // Speedup the filter a bit +} + +void filter() +{ + if (number++ % total) // Word for a different node? + word = 0; // Yes, skip it +} + +# Interrupt the cracking session after "max" words tried +[List.External:AutoAbort] +int max; // Maximum number of words to try +int number; // Current word number + +void init() +{ + max = 1000; + number = 0; +} + +void filter() +{ + if (++number > max) + abort = 1; // Interrupt the cracking session +} + +# Print the status line after every "interval" words tried +[List.External:AutoStatus] +int interval; // How often to print the status +int number; // Current word number + +void init() +{ + interval = 1000; + number = 0; +} + +void filter() +{ + if (number++ % interval) + return; + status = 1; // Print the status line +} diff --git a/run/lm_ascii.chr b/run/lm_ascii.chr new file mode 100644 index 0000000..dec756c Binary files /dev/null and b/run/lm_ascii.chr differ diff --git a/run/mailer b/run/mailer new file mode 100755 index 0000000..52da380 --- /dev/null +++ b/run/mailer @@ -0,0 +1,54 @@ +#!/bin/sh +# +# This is a script to send mail to all users whose passwords got cracked. +# This is not always a good idea, though, since lots of people do not +# check their e-mail or ignore such messages, and the messages can be a +# hint for crackers. +# +# You should probably deploy proactive password strength checking, such as +# with passwdqc, before you ask users to change their passwords - whether +# using this script or otherwise. And you should edit the message inside +# the script before possibly using it. +# +# Copyright (c) 1996-98 by Solar Designer +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# There's ABSOLUTELY NO WARRANTY, express or implied. +# (This is a heavily cut-down "BSD license".) +# + +if [ $# -ne 1 ]; then + echo "Usage: $0 PASSWORD-FILE" + exit 0 +fi + +# There's no need to mail users with these shells +SHELLS=-,/bin/false,/dev/null,/bin/sync + +# Look for John in the same directory with this script +DIR="`echo "$0" | sed 's,/[^/]*$,,'`" + +# Let's start +$DIR/john -show "$1" -shells:$SHELLS | sed -n 's/:.*//p' | +( + SENT=0 + + while read LOGIN; do + echo Sending mail to "$LOGIN"... + +# You'll probably want to edit the message below + mail -s 'Bad password' "$LOGIN" << EOF +Hello! + +Your password for account "$LOGIN" is insecure. Please change it as soon +as possible. + +Yours, + Password Checking Robot. +EOF + + SENT=$(($SENT+1)) + done + + echo $SENT messages sent +) diff --git a/run/makechr b/run/makechr new file mode 100755 index 0000000..df36821 --- /dev/null +++ b/run/makechr @@ -0,0 +1,22 @@ +#!/bin/sh +# +# This is a script to (re-)generate the .chr files using passwords in john.pot +# and applying all of the defined external mode filters. To speed it up on a +# sufficiently large computer (RAM and CPUs), "&" may be added after the John +# invocation (to run all of them in parallel). +# +# Copyright (c) 2013 by Solar Designer +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# There's ABSOLUTELY NO WARRANTY, express or implied. +# (This is a heavily cut-down "BSD license".) +# + +# Look for John in the same directory with this script +DIR="`echo "$0" | sed 's,/[^/]*$,,'`" + +sed -n 's/^\[List.External:Filter_\([A-Za-z_]\+\)\]$/\1/p' < john.conf | + while read CHR; do + CHR_LOWER="`echo -n $CHR | tr A-Z a-z`" + $DIR/john --make-charset=${CHR_LOWER}.chr --external=Filter_${CHR} +done diff --git a/run/password.lst b/run/password.lst new file mode 100644 index 0000000..588c64e --- /dev/null +++ b/run/password.lst @@ -0,0 +1,3559 @@ +#!comment: This list has been compiled by Solar Designer of Openwall Project +#!comment: in 1996 through 2011. It is assumed to be in the public domain. +#!comment: +#!comment: This list is based on passwords most commonly seen on a set of Unix +#!comment: systems in mid-1990's, sorted for decreasing number of occurrences +#!comment: (that is, more common passwords are listed first). It has been +#!comment: revised to also include common website passwords from public lists +#!comment: of "top N passwords" from major community website compromises that +#!comment: occurred in 2006 through 2010. +#!comment: +#!comment: Last update: 2011/11/20 (3546 entries) +#!comment: +#!comment: For more wordlists, see http://www.openwall.com/wordlists/ +123456 +12345 +password +password1 +123456789 +12345678 +1234567890 +abc123 +computer +tigger +1234 +qwerty +money +carmen +mickey +secret +summer +internet +a1b2c3 +123 +service + +canada +hello +ranger +shadow +baseball +donald +harley +hockey +letmein +maggie +mike +mustang +snoopy +buster +dragon +jordan +michael +michelle +mindy +patrick +123abc +andrew +bear +calvin +changeme +diamond +fuckme +fuckyou +matthew +miller +tiger +trustno1 +alex +apple +avalon +brandy +chelsea +coffee +falcon +freedom +gandalf +green +helpme +linda +magic +merlin +newyork +soccer +thomas +wizard +asdfgh +bandit +batman +boris +butthead +dorothy +eeyore +fishing +football +george +happy +iloveyou +jennifer +jonathan +love +marina +master +missy +monday +monkey +natasha +ncc1701 +pamela +pepper +piglet +poohbear +pookie +rabbit +rachel +rocket +rose +smile +sparky +spring +steven +success +sunshine +victoria +whatever +zapata +8675309 +amanda +andy +angel +august +barney +biteme +boomer +brian +casey +cowboy +delta +doctor +fisher +island +john +joshua +karen +marley +orange +please +rascal +richard +sarah +scooter +shalom +silver +skippy +stanley +taylor +welcome +zephyr +111111 +aaaaaa +access +albert +alexander +andrea +anna +anthony +asdfjkl; +ashley +basketball +beavis +black +bob +booboo +bradley +brandon +buddy +caitlin +camaro +charlie +chicken +chris +cindy +cricket +dakota +dallas +daniel +david +debbie +dolphin +elephant +emily +friend +fucker +ginger +goodluck +hammer +heather +iceman +jason +jessica +jesus +joseph +jupiter +justin +kevin +knight +lacrosse +lakers +lizard +madison +mary +mother +muffin +murphy +nirvana +paris +pentium +phoenix +picture +rainbow +sandy +saturn +scott +shannon +shithead +skeeter +sophie +special +stephanie +stephen +steve +sweetie +teacher +tennis +test +test123 +tommy +topgun +tristan +wally +william +wilson +1q2w3e +654321 +666666 +a12345 +a1b2c3d4 +alpha +amber +angela +angie +archie +asdf +blazer +bond007 +booger +charles +christin +claire +control +danny +david1 +dennis +digital +disney +edward +elvis +felix +flipper +franklin +frodo +honda +horses +hunter +indigo +james +jasper +jeremy +julian +kelsey +killer +lauren +marie +maryjane +matrix +maverick +mayday +mercury +mitchell +morgan +mountain +niners +nothing +oliver +peace +peanut +pearljam +phantom +popcorn +princess +psycho +pumpkin +purple +randy +rebecca +reddog +robert +rocky +roses +salmon +samson +sharon +sierra +smokey +startrek +steelers +stimpy +sunflower +superman +support +sydney +techno +walter +willie +willow +winner +ziggy +zxcvbnm +alaska +alexis +alice +animal +apples +barbara +benjamin +billy +blue +bluebird +bobby +bonnie +bubba +camera +chocolate +clark +claudia +cocacola +compton +connect +cookie +cruise +douglas +dreamer +dreams +duckie +eagles +eddie +einstein +enter +explorer +faith +family +ferrari +flamingo +flower +foxtrot +francis +freddy +friday +froggy +giants +gizmo +global +goofy +happy1 +hendrix +henry +herman +homer +honey +house +houston +iguana +indiana +insane +inside +irish +ironman +jake +jasmin +jeanne +jerry +joey +justice +katherine +kermit +kitty +koala +larry +leslie +logan +lucky +mark +martin +matt +minnie +misty +mitch +mouse +nancy +nascar +nelson +pantera +parker +penguin +peter +piano +pizza +prince +punkin +pyramid +raymond +robin +roger +rosebud +route66 +royal +running +sadie +sasha +security +sheena +sheila +skiing +snapple +snowball +sparrow +spencer +spike +star +stealth +student +sunny +sylvia +tamara +taurus +teresa +theresa +thunderbird +tigers +tony +toyota +travel +tuesday +victory +viper1 +wesley +whisky +winnie +winter +wolves +xyz123 +zorro +123123 +1234567 +696969 +888888 +Anthony +Joshua +Matthew +Tigger +aaron +abby +abcdef +adidas +adrian +alfred +arthur +athena +austin +awesome +badger +bamboo +beagle +bears +beatles +beautiful +beaver +benny +bigmac +bingo +bitch +blonde +boogie +boston +brenda +bright +bubba1 +bubbles +buffy +button +buttons +cactus +candy +captain +carlos +caroline +carrie +casper +catch22 +chance +charity +charlotte +cheese +cheryl +chloe +chris1 +clancy +compaq +conrad +cooper +cooter +copper +cosmos +cougar +cracker +crawford +crystal +curtis +cyclone +dance +diablo +dollars +dookie +dumbass +dundee +elizabeth +eric +europe +farmer +firebird +fletcher +fluffy +france +freak1 +friends +fuckoff +gabriel +galaxy +gambit +garden +garfield +garnet +genesis +genius +godzilla +golfer +goober +grace +greenday +groovy +grover +guitar +hacker +harry +hazel +hector +herbert +horizon +hornet +howard +icecream +imagine +impala +jack +janice +jasmine +jason1 +jeanette +jeffrey +jenifer +jenni +jesus1 +jewels +joker +julie +julie1 +junior +justin1 +kathleen +keith +kelly +kelly1 +kennedy +kevin1 +knicks +larry1 +leonard +lestat +library +lincoln +lionking +london +louise +lucky1 +lucy +maddog +margaret +mariposa +marlboro +martin1 +marty +master1 +mensuck +mercedes +metal +midori +mikey +millie +mirage +molly +monet +money1 +monica +monopoly +mookie +moose +moroni +music +naomi +nathan +nguyen +nicholas +nicole +nimrod +october +olive +olivia +online +oscar +oxford +pacific +painter +peaches +penelope +pepsi +petunia +philip +phoenix1 +photo +pickle +player +poiuyt +porsche +porter +puppy +python +quality +raquel +raven +remember +robbie +robert1 +roman +rugby +runner +russell +ryan +sailing +sailor +samantha +savage +scarlett +school +sean +seven +shadow1 +sheba +shelby +shit +shoes +simba +simple +skipper +smiley +snake +snickers +sniper +snoopdog +snowman +sonic +spitfire +sprite +spunky +starwars +station +stella +stingray +storm +stormy +stupid +sunny1 +sunrise +surfer +susan +tammy +tango +tanya +teddy1 +theboss +theking +thumper +tina +tintin +tomcat +trebor +trevor +tweety +unicorn +valentine +valerie +vanilla +veronica +victor +vincent +viper +warrior +warriors +weasel +wheels +wilbur +winston +wisdom +wombat +xavier +yellow +zeppelin +1111 +1212 +Andrew +Family +Friends +Michael +Michelle +Snoopy +abcd1234 +abcdefg +abigail +account +adam +alex1 +alice1 +allison +alpine +andre1 +andrea1 +angel1 +anita +annette +antares +apache +apollo +aragorn +arizona +arnold +arsenal +asdfasdf +asdfg +asdfghjk +avenger +baby +babydoll +bailey +banana +barry +basket +batman1 +beaner +beast +beatrice +bella +bertha +bigben +bigdog +biggles +bigman +binky +biology +bishop +blondie +bluefish +bobcat +bosco +braves +brazil +bruce +bruno +brutus +buffalo +bulldog +bullet +bullshit +bunny +business +butch +butler +butter +california +carebear +carol +carol1 +carole +cassie +castle +catalina +catherine +cccccc +celine +center +champion +chanel +chaos +chelsea1 +chester1 +chicago +chico +christian +christy +church +cinder +colleen +colorado +columbia +commander +connie +cookies +cooking +corona +cowboys +coyote +craig +creative +cuddles +cuervo +cutie +daddy +daisy +daniel1 +danielle +davids +death +denis +derek +design +destiny +diana +diane +dickhead +digger +dodger +donna +dougie +dragonfly +dylan +eagle +eclipse +electric +emerald +etoile +excalibur +express +fender +fiona +fireman +flash +florida +flowers +foster +francesco +francine +francois +frank +french +fuckface +gemini +general +gerald +germany +gilbert +goaway +golden +goldfish +goose +gordon +graham +grant +gregory +gretchen +gunner +hannah +harold +harrison +harvey +hawkeye +heaven +heidi +helen +helena +hithere +hobbit +ibanez +idontknow +integra +ireland +irene +isaac +isabel +jackass +jackie +jackson +jaguar +jamaica +japan +jenny1 +jessie +johan +johnny +joker1 +jordan23 +judith +julia +jumanji +kangaroo +karen1 +kathy +keepout +keith1 +kenneth +kimberly +kingdom +kitkat +kramer +kristen +laura +laurie +lawrence +lawyer +legend +liberty +light +lindsay +lindsey +lisa +liverpool +lola +lonely +louis +lovely +loveme +lucas +madonna +malcolm +malibu +marathon +marcel +maria1 +mariah +mariah1 +marilyn +mario +marvin +maurice +maxine +maxwell +me +meggie +melanie +melissa +melody +mexico +michael1 +michele +midnight +mike1 +miracle +misha +mishka +molly1 +monique +montreal +moocow +moore +morris +mouse1 +mulder +nautica +nellie +newton +nick +nirvana1 +nissan +norman +notebook +ocean +olivier +ollie +oranges +oregon +orion +panda +pandora +panther +passion +patricia +pearl +peewee +pencil +penny +people +percy +person +peter1 +petey +picasso +pierre +pinkfloyd +polaris +police +pookie1 +poppy +power +predator +preston +q1w2e3 +queen +queenie +quentin +ralph +random +rangers +raptor +reality +redrum +remote +reynolds +rhonda +ricardo +ricardo1 +ricky +river +roadrunner +robinhood +rocknroll +rocky1 +ronald +roxy +ruthie +sabrina +sakura +sally +sampson +samuel +sandra +santa +sapphire +scarlet +scorpio +scott1 +scottie +scruffy +seattle +serena +shanti +shark +shogun +simon +singer +skull +skywalker +slacker +smashing +smiles +snowflake +snuffy +soccer1 +soleil +sonny +spanky +speedy +spider +spooky +stacey +star69 +start +steven1 +stinky +strawberry +stuart +sugar +sundance +superfly +suzanne +suzuki +swimmer +swimming +system +taffy +tarzan +teddy +teddybear +terry +theatre +thunder +thursday +tinker +tootsie +tornado +tracy +tricia +trident +trojan +truman +trumpet +tucker +turtle +tyler +utopia +voyager +warcraft +warlock +warren +water +wayne +wendy +williams +willy +winona +woody +woofwoof +wrangler +wright +xfiles +xxxxxx +yankees +yvonne +zebra +zenith +zigzag +zombie +zxc123 +zxcvb +000000 +007007 +11111 +11111111 +123321 +171717 +181818 +1a2b3c +1chris +4runner +54321 +55555 +6969 +7777777 +789456 +88888888 +Alexis +Bailey +Charlie +Chris +Daniel +Dragon +Elizabeth +HARLEY +Heather +Jennifer +Jessica +Jordan +KILLER +Nicholas +Password +Princess +Purple +Rebecca +Robert +Shadow +Steven +Summer +Sunshine +Superman +Taylor +Thomas +Victoria +abcd123 +abcde +accord +active +africa +airborne +alfaro +alicia +aliens +alina +aline +alison +allen +aloha +alpha1 +althea +altima +amanda1 +amazing +america +amour +anderson +andre +andrew1 +andromeda +angels +angie1 +annie +anything +apple1 +apple2 +applepie +april +aquarius +ariane +ariel +arlene +artemis +asdf1234 +asdfjkl +ashley1 +ashraf +ashton +asterix +attila +autumn +avatar +babes +bambi +barbie +barney1 +barrett +bball +beaches +beanie +beans +beauty +becca +belize +belle +belmont +benji +benson +bernardo +berry +betsy +betty +bigboss +bigred +billy1 +birdie +birthday +biscuit +bitter +blackjack +blah +blanche +blood +blowjob +blowme +blueeyes +blues +bogart +bombay +boobie +boots +bootsie +boxers +brandi +brent +brewster +bridge +bronco +bronte +brooke +brother +bryan +bubble +buddha +budgie +burton +butterfly +byron +calendar +calvin1 +camel +camille +campbell +camping +cancer +canela +cannon +carbon +carnage +carolyn +carrot +cascade +catfish +cathy +catwoman +cecile +celica +change +chantal +charger +cherry +chiara +chiefs +china +chris123 +christ1 +christmas +christopher +chuck +cindy1 +cinema +civic +claude +clueless +cobain +cobra +cody +colette +college +colors +colt45 +confused +cool +corvette +cosmo +country +crusader +cunningham +cupcake +cynthia +dagger +dammit +dancer +daphne +darkstar +darren +darryl +darwin +deborah +december +deedee +deeznuts +delano +delete +demon +denise +denny +desert +deskjet +detroit +devil +devine +devon +dexter +dianne +diesel +director +dixie +dodgers +doggy +dollar +dolly +dominique +domino +dontknow +doogie +doudou +downtown +dragon1 +driver +dude +dudley +dutchess +dwight +eagle1 +easter +eastern +edith +edmund +eight +element +elissa +ellen +elliot +empire +enigma +enterprise +erin +escort +estelle +eugene +evelyn +explore +family1 +fatboy +felipe +ferguson +ferret +ferris +fireball +fishes +fishie +flight +florida1 +flowerpot +forward +freddie +freebird +freeman +frisco +fritz +froggie +froggies +frogs +fucku +future +gabby +games +garcia +gaston +gateway +george1 +georgia +german +germany1 +getout +ghost +gibson +giselle +gmoney +goblin +goblue +gollum +grandma +gremlin +grizzly +grumpy +guess +guitar1 +gustavo +haggis +haha +hailey +halloween +hamilton +hamlet +hanna +hanson +happy123 +happyday +hardcore +harley1 +harriet +harris +harvard +health +heart +heather1 +heather2 +hedgehog +helene +hello1 +hello123 +hellohello +hermes +heythere +highland +hilda +hillary +history +hitler +hobbes +holiday +holly +honda1 +hongkong +hootie +horse +hotrod +hudson +hummer +huskies +idiot +iforget +iloveu +impact +indonesia +irina +isabelle +israel +italia +italy +jackie1 +jacob +jakey +james1 +jamesbond +jamie +jamjam +jeffrey1 +jennie +jenny +jensen +jesse +jesse1 +jester +jethro +jimbob +jimmy +joanna +joelle +john316 +jordie +jorge +josh +journey +joyce +jubilee +jules +julien +juliet +junebug +juniper +justdoit +karin +karine +karma +katerina +katie +katie1 +kayla +keeper +keller +kendall +kenny +ketchup +kings +kissme +kitten +kittycat +kkkkkk +kristi +kristine +labtec +laddie +ladybug +lance +laurel +lawson +leader +leland +lemon +lester +letter +letters +lexus1 +libra +lights +lionel +little +lizzy +lolita +lonestar +longhorn +looney +loren +lorna +loser +lovers +loveyou +lucia +lucifer +lucky14 +maddie +madmax +magic1 +magnum +maiden +maine +management +manson +manuel +marcus +maria +marielle +marine +marino +marshall +martha +maxmax +meatloaf +medical +megan +melina +memphis +mermaid +miami +michel +michigan +mickey1 +microsoft +mikael +milano +miles +millenium +million +miranda +miriam +mission +mmmmmm +mobile +monkey1 +monroe +montana +monty +moomoo +moonbeam +morpheus +motorola +movies +mozart +munchkin +murray +mustang1 +nadia +nadine +napoleon +nation +national +nestle +newlife +newyork1 +nichole +nikita +nikki +nintendo +nokia +nomore +normal +norton +noway +nugget +number9 +numbers +nurse +nutmeg +ohshit +oicu812 +omega +openup +orchid +oreo +orlando +packard +packers +paloma +pancake +panic +parola +parrot +partner +pascal +patches +patriots +paula +pauline +payton +peach +peanuts +pedro1 +peggy +perfect +perry +peterpan +philips +phillips +phone +pierce +pigeon +pink +pioneer +piper1 +pirate +pisces +playboy +pluto +poetry +pontiac +pookey +popeye +prayer +precious +prelude +premier +puddin +pulsar +pussy +pussy1 +qwert +qwerty12 +qwertyui +rabbit1 +rachelle +racoon +rambo +randy1 +ravens +redman +redskins +reggae +reggie +renee +renegade +rescue +revolution +richard1 +richards +richmond +riley +ripper +robby +roberts +rock +rocket1 +rockie +rockon +roger1 +rogers +roland +rommel +rookie +rootbeer +rosie +rufus +rusty +ruthless +sabbath +sabina +safety +saint +samiam +sammie +sammy +samsam +sandi +sanjose +saphire +sarah1 +saskia +sassy +saturday +science +scooby +scoobydoo +scooter1 +scorpion +scotty +scouts +search +september +server +seven7 +sexy +shaggy +shanny +shaolin +shasta +shayne +shelly +sherry +shirley +shorty +shotgun +sidney +simba1 +sinatra +sirius +skate +skipper1 +skyler +slayer +sleepy +slider +smile1 +smitty +smoke +snakes +snapper +snoop +solomon +sophia +space +sparks +spartan +spike1 +sponge +spurs +squash +stargate +starlight +stars +steph1 +steve1 +stevens +stewart +stone +stranger +stretch +strong +studio +stumpy +sucker +suckme +sultan +summit +sunfire +sunset +super +superstar +surfing +susan1 +sutton +sweden +sweetpea +sweety +swordfish +tabatha +tacobell +taiwan +tamtam +tanner +target +tasha +tattoo +tequila +terry1 +texas +thankyou +theend +thompson +thrasher +tiger2 +timber +timothy +tinkerbell +topcat +topher +toshiba +tototo +travis +treasure +trees +tricky +trish +triton +trombone +trouble +trucker +turbo +twins +tyler1 +ultimate +unique +united +ursula +vacation +valley +vampire +vanessa +venice +venus +vermont +vicki +vicky +victor1 +vincent1 +violet +violin +virgil +virginia +vision +volley +voodoo +vortex +waiting +wanker +warner +water1 +wayne1 +webster +weezer +wendy1 +western +white +whitney +whocares +wildcat +william1 +wilma +window +winniethepooh +wolfgang +wolverine +wonder +xxxxxxxx +yamaha +yankee +yogibear +yolanda +yomama +yvette +zachary +zebras +zxcvbn +00000000 +121212 +1234qwer +131313 +13579 +90210 +99999999 +ABC123 +action +amelie +anaconda +apollo13 +artist +asshole +benoit +bernard +bernie +bigbird +blizzard +bluesky +bonjour +caesar +cardinal +carolina +cesar +chandler +chapman +charlie1 +chevy +chiquita +chocolat +coco +cougars +courtney +dolphins +dominic +donkey +dusty +eminem +energy +fearless +forest +forever +glenn +guinness +hotdog +indian +jared +jimbo +johnson +jojo +josie +kristin +lloyd +lorraine +lynn +maxime +memory +mimi +mirror +nebraska +nemesis +network +nigel +oatmeal +patton +pedro +planet +players +portland +praise +psalms +qwaszx +raiders +rambo1 +rancid +shawn +shelley +softball +speedo +sports +ssssss +steele +steph +stephani +sunday +tiffany +tigre +toronto +trixie +undead +valentin +velvet +viking +walker +watson +young +babygirl +pretty +hottie +teamo +987654321 +naruto +spongebob +daniela +princesa +christ +blessed +single +qazwsx +pokemon +iloveyou1 +iloveyou2 +fuckyou1 +hahaha +poop +blessing +blahblah +blink182 +123qwe +trinity +passw0rd +google +looking +spirit +iloveyou! +qwerty1 +onelove +mylove +222222 +ilovegod +football1 +loving +emmanuel +1q2w3e4r +red123 +blabla +112233 +hallo +spiderman +simpsons +monster +november +brooklyn +poopoo +darkness +159753 +pineapple +chester +1qaz2wsx +drowssap +monkey12 +wordpass +q1w2e3r4 +coolness +11235813 +something +alexandra +estrella +miguel +iloveme +sayang +princess1 +555555 +999999 +alejandro +brittany +alejandra +tequiero +antonio +987654 +00000 +fernando +corazon +cristina +kisses +myspace +rebelde +babygurl +alyssa +mahalkita +gabriela +pictures +hellokitty +babygirl1 +angelica +mahalko +mariana +eduardo +andres +ronaldo +inuyasha +adriana +celtic +samsung +angelo +456789 +sebastian +karina +hotmail +0123456789 +barcelona +cameron +slipknot +cutiepie +50cent +bonita +maganda +babyboy +natalie +cuteako +javier +789456123 +123654 +bowwow +portugal +777777 +volleyball +january +cristian +bianca +chrisbrown +101010 +sweet +panget +benfica +love123 +lollipop +camila +qwertyuiop +harrypotter +ihateyou +christine +lorena +andreea +charmed +rafael +brianna +aaliyah +johncena +lovelove +gangsta +333333 +hiphop +mybaby +sergio +metallica +myspace1 +babyblue +badboy +fernanda +westlife +sasuke +steaua +roberto +slideshow +asdfghjkl +santiago +jayson +5201314 +jerome +gandako +gatita +babyko +246810 +sweetheart +chivas +alberto +valeria +nicole1 +12345678910 +leonardo +jayjay +liliana +sexygirl +232323 +amores +anthony1 +bitch1 +fatima +miamor +lover +lalala +252525 +skittles +colombia +159357 +manutd +123456a +britney +katrina +christina +pasaway +mahal +tatiana +cantik +0123456 +teiubesc +147258369 +natalia +francisco +amorcito +paola +angelito +manchester +mommy1 +147258 +amigos +marlon +linkinpark +147852 +diego +444444 +iverson +andrei +justine +frankie +pimpin +fashion +bestfriend +england +hermosa +456123 +102030 +sporting +hearts +potter +iloveu2 +number1 +212121 +truelove +jayden +savannah +hottie1 +ganda +scotland +ilovehim +shakira +estrellita +brandon1 +sweets +familia +love12 +omarion +monkeys +loverboy +elijah +ronnie +mamita +999999999 +broken +rodrigo +westside +mauricio +amigas +preciosa +shopping +flores +isabella +martinez +elaine +friendster +cheche +gracie +connor +valentina +darling +santos +joanne +fuckyou2 +pebbles +sunshine1 +gangster +gloria +darkangel +bettyboop +jessica1 +cheyenne +dustin +iubire +a123456 +purple1 +bestfriends +inlove +batista +karla +chacha +marian +sexyme +pogiako +jordan1 +010203 +daddy1 +daddysgirl +billabong +pinky +erika +skater +nenita +tigger1 +gatito +lokita +maldita +buttercup +bambam +glitter +123789 +sister +zacefron +tokiohotel +loveya +lovebug +bubblegum +marissa +cecilia +lollypop +nicolas +puppies +ariana +chubby +sexybitch +roxana +mememe +susana +baller +hotstuff +carter +babylove +angelina +playgirl +sweet16 +012345 +bhebhe +marcos +loveme1 +milagros +lilmama +beyonce +lovely1 +catdog +armando +margarita +151515 +loves +202020 +gerard +undertaker +amistad +capricorn +delfin +cheerleader +password2 +PASSWORD +lizzie +matthew1 +enrique +badgirl +141414 +dancing +cuteme +amelia +skyline +angeles +janine +carlitos +justme +legolas +michelle1 +cinderella +jesuschrist +ilovejesus +tazmania +tekiero +thebest +princesita +lucky7 +jesucristo +buddy1 +regina +myself +lipgloss +jazmin +rosita +chichi +pangit +mierda +741852963 +hernandez +arturo +silvia +melvin +celeste +pussycat +gorgeous +honeyko +mylife +babyboo +loveu +lupita +panthers +hollywood +alfredo +musica +hawaii +sparkle +kristina +sexymama +crazy +scarface +098765 +hayden +micheal +242424 +0987654321 +marisol +jeremiah +mhine +isaiah +lolipop +butterfly1 +xbox360 +madalina +anamaria +yourmom +jasmine1 +bubbles1 +beatriz +diamonds +friendship +sweetness +desiree +741852 +hannah1 +bananas +julius +leanne +marie1 +lover1 +twinkle +february +bebita +87654321 +twilight +imissyou +pollito +ashlee +cookie1 +147852369 +beckham +simone +nursing +torres +damian +123123123 +joshua1 +babyface +dinamo +mommy +juliana +cassandra +redsox +gundam +0000 +ou812 +dave +golf +molson +Monday +newpass +thx1138 +1 +Internet +coke +foobar +abc +fish +fred +help +ncc1701d +newuser +none +pat +dog +duck +duke +floyd +guest +joe +kingfish +micro +sam +telecom +test1 +7777 +absolut +babylon5 +backup +bill +bird33 +deliver +fire +flip +galileo +gopher +hansolo +jane +jim +mom +passwd +phil +phish +porsche911 +rain +red +sergei +training +truck +video +volvo +007 +1969 +5683 +Bond007 +Friday +Hendrix +October +Taurus +aaa +alexandr +catalog +challenge +clipper +coltrane +cyrano +dan +dawn +dean +deutsch +dilbert +e-mail +export +ford +fountain +fox +frog +gabriell +garlic +goforit +grateful +hoops +lady +ledzep +lee +mailman +mantra +market +mazda1 +metallic +ncc1701e +nesbitt +open +pete +quest +republic +research +supra +tara +testing +xanadu +xxxx +zaphod +zeus +0007 +1022 +10sne1 +1973 +1978 +2000 +2222 +3bears +Broadway +Fisher +Jeanne +Killer +Knight +Master +Pepper +Sierra +Tennis +abacab +abcd +ace +acropolis +amy +anders +avenir +basil +bass +beer +ben +bliss +blowfish +boss +bridges +buck +bugsy +bull +cannondale +canon +catnip +chip +civil +content +cook +cordelia +crack1 +cyber +daisie +dark1 +database +deadhead +denali +depeche +dickens +emmitt +entropy +farout +farside +feedback +fidel +firenze +fish1 +fletch +fool +fozzie +fun +gargoyle +gasman +gold +graphic +hell +image +intern +intrepid +jeff +jkl123 +joel +johanna1 +kidder +kim +king +kirk +kris +lambda +leon +logical +lorrie +major +mariner +mark1 +max +media +merlot +midway +mine +mmouse +moon +mopar +mortimer +nermal +nina +olsen +opera +overkill +pacers +packer +picard +polar +polo +primus +prometheus +public +radio +rastafarian +reptile +rob +robotech +rodeo +rolex +rouge +roy +ruby +salasana +scarecrow +scout +scuba1 +sergey +skibum +skunk +sound +starter +sting1 +sunbird +tbird +teflon +temporal +terminal +the +thejudge +time +toby +today +tokyo +tree +trout +vader +val +valhalla +windsurf +wolf +wolf1 +xcountry +yoda +yukon +1213 +1214 +1225 +1313 +1818 +1975 +1977 +1991 +1kitty +2001 +2020 +2112 +2kids +333 +4444 +5050 +57chevy +7dwarfs +Animals +Ariel +Bismillah +Booboo +Boston +Carol +Computer +Creative +Curtis +Denise +Eagles +Esther +Fishing +Freddy +Gandalf +Golden +Goober +Hacker +Harley +Henry +Hershey +Jackson +Jersey +Joanna +Johnson +Katie +Kitten +Liberty +Lindsay +Lizard +Madeline +Margaret +Maxwell +Money +Monster +Pamela +Peaches +Peter +Phoenix +Piglet +Pookie +Rabbit +Raiders +Random +Russell +Sammy +Saturn +Skeeter +Smokey +Sparky +Speedy +Sterling +Theresa +Thunder +Vincent +Willow +Winnie +Wolverine +aaaa +aardvark +abbott +acura +admin +admin1 +adrock +aerobics +agent +airwolf +ali +alien +allegro +allstate +altamira +altima1 +andrew! +ann +anne +anneli +aptiva +arrow +asdf;lkj +assmunch +baraka +barnyard +bart +bartman +beasty +beavis1 +bebe +belgium +beowulf +beryl +best +bharat +bichon +bigal +biker +bilbo +bills +bimmer +biochem +birdy +blinds +blitz +bluejean +bogey +bogus +boulder +bourbon +boxer +brain +branch +britain +broker +bucks +buffett +bugs +bulls +burns +buzz +c00per +calgary +camay +carl +cat +cement +cessna +chad +chainsaw +chameleon +chang +chess +chinook +chouette +chronos +cicero +circuit +cirque +cirrus +clapton +clarkson +class +claudel +cleo +cliff +clock +color +comet +concept +concorde +coolbean +corky +cornflake +corwin +cows +crescent +cross +crowley +cthulhu +cunt +current +cutlass +daedalus +dagger1 +daily +dale +dana +daytek +dead +decker +dharma +dillweed +dipper +disco +dixon +doitnow +doors +dork +doug +dutch +effie +ella +elsie +engage +eric1 +ernie1 +escort1 +excel +faculty +fairview +faust +fenris +finance +first +fishhead +flanders +fleurs +flute +flyboy +flyer +franka +frederic +free +front242 +frontier +fugazi +funtime +gaby +gaelic +gambler +gammaphi +garfunkel +garth +gary +gateway2 +gator1 +gibbons +gigi +gilgamesh +goat +godiva +goethe +gofish +good +gramps +gravis +gray +greed +greg +greg1 +greta +gretzky +guido +gumby +h2opolo +hamid +hank +hawkeye1 +health1 +hello8 +help123 +helper +homerj +hoosier +hope +huang +hugo +hydrogen +ib6ub9 +insight +instructor +integral +iomega +iris +izzy +jazz +jean +jeepster +jetta1 +joanie +josee +joy +julia2 +jumbo +jump +justice4 +kalamazoo +kali +kat +kate +kerala +kids +kiwi +kleenex +kombat +lamer +laser +laserjet +lassie1 +leblanc +legal +leo +life +lions +liz +logger +logos +loislane +loki +longer +lori +lost +lotus +lou +macha +macross +madoka +makeitso +mallard +marc +math +mattingly +mechanic +meister +mercer +merde +merrill +michal +michou +mickel +minou +mobydick +modem +mojo +montana3 +montrose +motor +mowgli +mulder1 +muscle +neil +neutrino +newaccount +nicklaus +nightshade +nightwing +nike +none1 +nopass +nouveau +novell +oaxaca +obiwan +obsession +orville +otter +ozzy +packrat +paint +papa +paradigm +pass +pavel +peterk +phialpha +phishy +piano1 +pianoman +pianos +pipeline +plato +play +poetic +print +printing +provider +qqq111 +quebec +qwer +racer +racerx +radar +rafiki +raleigh +rasta1 +redcloud +redfish +redwing +redwood +reed +rene +reznor +rhino +ripple +rita +robocop +robotics +roche +roni +rossignol +rugger +safety1 +saigon +satori +saturn5 +schnapps +scotch +scuba +secret3 +seeker +services +sex +shanghai +shazam +shelter +sigmachi +signal +signature +simsim +skydive +slick +smegma +smiths +smurfy +snow +sober1 +sonics +sony +spazz +sphynx +spock +spoon +spot +sprocket +starbuck +steel +stephi +sting +stocks +storage +strat +strato +stud +student2 +susanna +swanson +swim +switzer +system5 +t-bone +talon +tarheel +tata +tazdevil +tester +testtest +thisisit +thorne +tightend +tim +tom +tool +total +toucan +transfer +transit +transport +trapper +trash +trophy +tucson +turbo2 +unity +upsilon +vedder +vette +vikram +virago +visual +volcano +walden +waldo +walleye +webmaster +wedge +whale1 +whit +whoville +wibble +will +wombat1 +word +world +x-files +xxx123 +zack +zepplin +zoltan +zoomer +123go +21122112 +5555 +911 +FuckYou +Fuckyou +Gizmo +Hello +Michel +Qwerty +Windows +angus +aspen +ass +bird +booster +byteme +cats +changeit +christia +christoph +classroom +cloclo +corrado +dasha +fiction +french1 +fubar +gator +gilles +gocougs +hilbert +hola +home +judy +koko +lulu +mac +macintosh +mailer +mars +meow +ne1469 +niki +paul +politics +pomme +property +ruth +sales +salut +scrooge +skidoo +spain +surf +sylvie +symbol +forum +rotimi +god +saved +2580 +1998 +xxx +1928 +777 +info +a +netware +sun +tech +doom +mmm +one +ppp +1911 +1948 +1996 +5252 +Champs +Tuesday +bach +crow +don +draft +hal9000 +herzog +huey +jethrotull +jussi +mail +miki +nicarao +snowski +1316 +1412 +1430 +1952 +1953 +1955 +1956 +1960 +1964 +1qw23e +22 +2200 +2252 +3010 +3112 +4788 +6262 +Alpha +Bastard +Beavis +Cardinal +Celtics +Cougar +Darkman +Figaro +Fortune +Geronimo +Hammer +Homer +Janet +Mellon +Merlot +Metallic +Montreal +Newton +Paladin +Peanuts +Service +Vernon +Waterloo +Webster +aki123 +aqua +aylmer +beta +bozo +car +chat +chinacat +cora +courier +dogbert +eieio +elina1 +fly +funguy +fuzz +ggeorge +glider1 +gone +hawk +heikki +histoire +hugh +if6was9 +ingvar +jan +jedi +jimi +juhani +khan +lima +midvale +neko +nesbit +nexus6 +nisse +notta1 +pam +park +pole +pope +pyro +ram +reliant +rex +rush +seoul +skip +stan +sue +suzy +tab +testi +thelorax +tika +tnt +toto1 +tre +wind +x-men +xyz +zxc +369 +Abcdef +Asdfgh +Changeme +NCC1701 +Zxcvbnm +demo +doom2 +e +good-luck +homebrew +m1911a1 +nat +ne1410s +ne14a69 +zhongguo +sample123 +0852 +basf +OU812 +!@#$% +informix +majordomo +news +temp +trek +!@#$%^ +!@#$%^&* +Pentium +Raistlin +adi +bmw +law +m +new +opus +plus +visa +www +y +zzz +1332 +1950 +3141 +3533 +4055 +4854 +6301 +Bonzo +ChangeMe +Front242 +Gretel +Michel1 +Noriko +Sidekick +Sverige +Swoosh +Woodrow +aa +ayelet +barn +betacam +biz +boat +cuda +doc +hal +hallowell +haro +hosehead +i +ilmari +irmeli +j1l2t3 +jer +kcin +kerrya +kissa2 +leaf +lissabon +mart +matti1 +mech +morecats +paagal +performa +prof +ratio +ship +slip +stivers +tapani +targas +test2 +test3 +tula +unix +user1 +xanth +!@#$%^& +1701d +@#$%^& +Qwert +allo +dirk +go +newcourt +nite +notused +sss diff --git a/run/relbench b/run/relbench new file mode 100755 index 0000000..c1d5d81 --- /dev/null +++ b/run/relbench @@ -0,0 +1,162 @@ +#!/usr/bin/perl -w +# +# John the Ripper benchmark output comparison tool, revision 4 +# Copyright (c) 2011 by Solar Designer +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# There's ABSOLUTELY NO WARRANTY, express or implied. +# (This is a heavily cut-down "BSD license".) +# +# This is a Perl script to compare two "john --test" benchmark runs, +# such as for different machines, "make" targets, C compilers, +# optimization options, or/and versions of John the Ripper. To use it, +# redirect the output of each "john --test" run to a file, then run the +# script on the two files. Most values output by the script indicate +# relative performance seen on the second benchmark run as compared to the +# first one, with the value of 1.0 indicating no change, values higher +# than 1.0 indicating speedup, and values lower than 1.0 indicating +# slowdown. Specifically, the script outputs the minimum, maximum, +# median, and geometric mean for the speedup (or slowdown) seen across the +# many individual benchmarks that "john --test" performs. It also outputs +# the median absolute deviation (relative to the median) and geometric +# standard deviation (relative to the geometric mean). Of these two, a +# median absolute deviation of 0.0 would indicate that no deviation from +# the median is prevalent, whereas a geometric standard deviation of 1.0 +# would indicate that all benchmarks were sped up or slowed down by the +# exact same ratio or their speed remained unchanged. In practice, these +# values will tend to deviate from 0.0 and 1.0, respectively. +# + +$warned = 0; + +sub parse +{ + chomp; + if (/^$/) { + undef $id; + undef $name; + undef $kind; undef $real; undef $virtual; + return; + } + my $ok = 0; + if (defined($name)) { + ($kind, $real, $reals, $virtual, $virtuals) = + /^([\w ]+):\s+([\d.]+)([KM]?) c\/s real, ([\d.]+)([KM]?) c\/s virtual$/; + if (!defined($virtual)) { + ($kind, $real, $reals) = + /^([\w ]+):\s+([\d.]+)([KM]?) c\/s$/; + $virtual = $real; $virtuals = $reals; + print "Warning: some benchmark results are missing virtual (CPU) time data\n" unless ($warned); + $warned = 1; + } + undef $id; + if ($kind && $real && $virtual) { + $id = $name . ':' . $kind; + $real *= 1000 if ($reals eq 'K'); + $real *= 1000000 if ($reals eq 'M'); + $virtual *= 1000 if ($virtuals eq 'K'); + $virtual *= 1000000 if ($virtuals eq 'M'); + return; + } + } else { + ($name) = /^Benchmarking: (.+) \[.*\].* DONE$/; + $ok = defined($name); + } + print STDERR "Could not parse: $_\n" if (!$ok); +} + +die "Usage: $0 BENCHMARK-FILE-1 BENCHMARK-FILE-2\n" if ($#ARGV != 1); + +open(B1, '<' . $ARGV[0]) || die "Could not open file: $ARGV[0] ($!)"; +open(B2, '<' . $ARGV[1]) || die "Could not open file: $ARGV[1] ($!)"; + +$_ = ''; +parse(); +while () { + parse(); + next unless (defined($id)); + $b1r{$id} = $real; + $b1v{$id} = $virtual; +} +close(B1); + +$_ = ''; +parse(); +while () { + parse(); + next unless (defined($id)); + $b2r{$id} = $real; + $b2v{$id} = $virtual; +} +close(B2); + +foreach $id (keys %b1r) { + if (!defined($b2r{$id})) { + print "Only in file 1: $id\n"; + next; + } +} + +$minr = $maxr = $minv = $maxv = -1.0; +$mr = $mv = 1.0; +$n = 0; +foreach $id (keys %b2r) { + if (!defined($b1r{$id})) { + print "Only in file 2: $id\n"; + next; + } + my $kr = $b2r{$id} / $b1r{$id}; + my $kv = $b2v{$id} / $b1v{$id}; + $minr = $kr if ($kr < $minr || $minr < 0.0); + $maxr = $kr if ($kr > $maxr); + $minv = $kv if ($kv < $minv || $minv < 0.0); + $maxv = $kv if ($kv > $maxv); + $akr[$n] = $kr; + $akv[$n] = $kv; + $mr *= $kr; + $mv *= $kv; + $n++; +} + +print "Number of benchmarks:\t\t$n\n"; +exit unless ($n); + +printf "Minimum:\t\t\t%.5f real, %.5f virtual\n", $minr, $minv; +printf "Maximum:\t\t\t%.5f real, %.5f virtual\n", $maxr, $maxv; + +@akr = sort @akr; +@akv = sort @akv; +if ($n & 1) { + $medr = $akr[($n - 1) / 2]; + $medv = $akv[($n - 1) / 2]; +} else { + $medr = ($akr[$n / 2 - 1] * $akr[$n / 2]) ** 0.5; + $medv = ($akv[$n / 2 - 1] * $akv[$n / 2]) ** 0.5; +} +printf "Median:\t\t\t\t%.5f real, %.5f virtual\n", $medr, $medv; + +$mr **= 1.0 / $n; +$mv **= 1.0 / $n; +$dr = $dv = 0.0; +for ($i = 0; $i < $n; $i++) { + $adr[$i] = abs($akr[$i] - $medr); + $adv[$i] = abs($akv[$i] - $medv); + $dr += log($akr[$i] / $mr) ** 2; + $dv += log($akv[$i] / $mv) ** 2; +} +$dr = exp(($dr / $n) ** 0.5); +$dv = exp(($dv / $n) ** 0.5); + +@adr = sort @adr; +@adv = sort @adv; +if ($n & 1) { + $madr = $adr[($n - 1) / 2]; + $madv = $adv[($n - 1) / 2]; +} else { + $madr = ($adr[$n / 2 - 1] * $adr[$n / 2]) ** 0.5; + $madv = ($adv[$n / 2 - 1] * $adv[$n / 2]) ** 0.5; +} +printf "Median absolute deviation:\t%.5f real, %.5f virtual\n", $madr, $madv; + +printf "Geometric mean:\t\t\t%.5f real, %.5f virtual\n", $mr, $mv; +printf "Geometric standard deviation:\t%.5f real, %.5f virtual\n", $dr, $dv; diff --git a/src/AFS_fmt.c b/src/AFS_fmt.c new file mode 100644 index 0000000..6dfaaf1 --- /dev/null +++ b/src/AFS_fmt.c @@ -0,0 +1,496 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "DES_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "AFS" +#define FORMAT_NAME "Kerberos AFS" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH 8 + +#define PLAINTEXT_LENGTH 63 +#define CIPHERTEXT_LENGTH 20 + +static struct fmt_tests tests[] = { + {"$K4$e35e9294ecef926d,0123", "U*U*U*U*"}, + {"$K4$64c7c2aedccd70d6,0123456789", "U*U***U*"}, + {"$K4$d9e985b36268f168,01234567", "U*U***U"}, + {"$K4$b9615786dfb53297,longcellname", "longpassword"}, + {"$K4$a8dc8aeaa2c48a97,", ""}, + {"$K4$dfda85c7619183a2,XXXXXXXX", "XXXXXXXX"}, + {"$K4$e3e59de6f1d5eaf4,cell", "password355"}, + {"$K4$b02cc24aefbc865b,", "thisisaverylongpassword"}, + {NULL} +}; + +#define ALGORITHM_NAME DES_STD_ALGORITHM_NAME + +#define BINARY_SIZE (3 * ARCH_SIZE) +#define BINARY_ALIGN ARCH_SIZE +#define SALT_SIZE 40 +#define SALT_ALIGN 1 + +#define MIN_KEYS_PER_CRYPT 0x80 +#define MAX_KEYS_PER_CRYPT 0x100 + +#define AFS_SALT "#~..........." /* An invalid salt */ +#define AFS_long_key "52912979" /* "kerberos" >> 1 */ +#define AFS_long_IV "kerberos" /* :-) */ + +/* + * They're only using 8 characters of crypt(3) output, effectively reducing + * the hash size to 48 bits... We are emulating this behavior with bitmasks. + */ +#define AFS_MASK_16 DES_DO_SIZE_FIX(0xFFF9FFF9) +#if ARCH_BITS >= 64 +#define AFS_BINARY_MASK \ + (AFS_MASK_16 | ((unsigned ARCH_WORD)AFS_MASK_16 << 32)) +#else +#define AFS_BINARY_MASK AFS_MASK_16 +#endif + +#define TOTAL_BINARY_MASK (DES_BINARY_MASK & AFS_BINARY_MASK) + +#if ARCH_LITTLE_ENDIAN +#define AFS_swap(x, y) \ + (y) = (x); +#else +#define AFS_swap(x, y) \ +{ \ + tmp = (x); \ + tmp = (tmp << 16) | (tmp >> 16); \ + (y) = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); \ +} +#endif + +static struct { + union { + double dummy; + DES_binary binary; + } aligned; + int is_long; + char key[PLAINTEXT_LENGTH + 1]; +} buffer[MAX_KEYS_PER_CRYPT]; + +static char cell[SALT_SIZE + 8]; +static int cell_length; + +static ARCH_WORD AFS_salt_binary; +static union { + double dummy; + DES_KS data; +} AFS_long_KS; +static DES_binary AFS_long_IV_binary; + +static void init(struct fmt_main *self) +{ + ARCH_WORD_32 block[2]; +#if !ARCH_LITTLE_ENDIAN + ARCH_WORD_32 tmp; +#endif + + DES_std_init(); + + AFS_salt_binary = DES_std_get_salt(AFS_SALT); + + DES_raw_set_key(AFS_long_key); + memcpy(AFS_long_KS.data, DES_KS_current, sizeof(DES_KS)); + + memcpy(block, AFS_long_IV, 8); +#if !ARCH_LITTLE_ENDIAN + AFS_swap(block[0], block[0]); + AFS_swap(block[1], block[1]); +#endif + DES_std_set_block(block[0], block[1]); + memcpy(AFS_long_IV_binary, DES_IV, sizeof(DES_binary)); +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos; + int index, count; + unsigned int value; + + if (strncmp(ciphertext, "$K4$", 4)) return 0; + + for (pos = &ciphertext[4]; atoi16[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (*pos != ',' || pos - ciphertext != CIPHERTEXT_LENGTH) return 0; + + for (index = 0; index < 16; index += 2) { + value = (int)atoi16[ARCH_INDEX(ciphertext[index + 4])] << 4; + value |= atoi16[ARCH_INDEX(ciphertext[index + 5])]; + + count = 0; + if (value) + do { + count++; + } while ((value &= value - 1)); + + if (!(count & 1)) return 0; + } + + return 1; +} + +static void *get_binary(char *ciphertext) +{ + static ARCH_WORD out[6]; + char base64[14]; + int known_long; + int index; + unsigned int value; + + out[0] = out[1] = 0; + strcpy(base64, AFS_SALT); + known_long = 0; + + for (index = 0; index < 16; index += 2) { + value = (int)atoi16[ARCH_INDEX(ciphertext[index + 4])] << 4; + value |= atoi16[ARCH_INDEX(ciphertext[index + 5])]; + + out[index >> 3] |= (value | 1) << ((index << 2) & 0x18); + + if (atoi64[value >>= 1] == 0x7F) + known_long = 1; + else + base64[(index >> 1) + 2] = value; + } + + if (known_long) + out[2] = ~(ARCH_WORD)0; + else + memcpy(&out[2], DES_std_get_binary(base64), 16); + + return out; +} + +static void *salt(char *ciphertext) +{ + static char out[SALT_SIZE + 1]; + + strncpy(out, &ciphertext[21], SALT_SIZE); + out[SALT_SIZE] = 0; + + return strlwr(out); +} + +static int binary_hash_0(void *binary) +{ + if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) + return *(ARCH_WORD *)binary & 0xF; + + return DES_STD_HASH_0(((ARCH_WORD *)binary)[2]); +} + +static int binary_hash_1(void *binary) +{ + if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) + return *(ARCH_WORD *)binary & 0xFF; + + return DES_STD_HASH_1(((ARCH_WORD *)binary)[2]); +} + +static int binary_hash_2(void *binary) +{ + if (((ARCH_WORD *)binary)[2] == ~(ARCH_WORD)0) + return *(ARCH_WORD *)binary & 0xFFF; + + return DES_STD_HASH_2(((ARCH_WORD *)binary)[2]); +} + +static ARCH_WORD to_short_hash(int index) +{ + char base64[14]; + char *ptr; + int pos, value; + + strcpy(base64, AFS_SALT); + ptr = &base64[2]; + + for (pos = 0; pos < 8; pos++) { + value = buffer[index].aligned.binary[pos >> 2]; + value >>= ((pos & 3) << 3) + 1; + value &= 0x7F; + + if (atoi64[value] == 0x7F) return ~(ARCH_WORD)0; + *ptr++ = value; + } + + return *DES_std_get_binary(base64); +} + +static int get_hash_0(int index) +{ + ARCH_WORD binary; + + if (buffer[index].is_long) { + if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) + return buffer[index].aligned.binary[0] & 0xF; + } else + binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; + return DES_STD_HASH_0(binary); +} + +static int get_hash_1(int index) +{ + ARCH_WORD binary; + + if (buffer[index].is_long) { + if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) + return buffer[index].aligned.binary[0] & 0xFF; + } else + binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; + return DES_STD_HASH_1(binary); +} + +static int get_hash_2(int index) +{ + ARCH_WORD binary; + + if (buffer[index].is_long) { + if ((binary = to_short_hash(index)) == ~(ARCH_WORD)0) + return buffer[index].aligned.binary[0] & 0xFFF; + } else + binary = buffer[index].aligned.binary[0] & AFS_BINARY_MASK; + return DES_STD_HASH_2(binary); +} + +static void set_salt(void *salt) +{ + strnzcpy(cell, salt, SALT_SIZE); + memset(&cell[cell_length = strlen(cell)], 0, 8); +} + +static void set_key(char *key, int index) +{ + strnzcpy(buffer[index].key, key, PLAINTEXT_LENGTH + 1); +} + +static char *get_key(int index) +{ + return buffer[index].key; +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + int index, pos, length; + char xor[8]; + ARCH_WORD_32 space[(PLAINTEXT_LENGTH + SALT_SIZE + 8) / 4 + 1]; + ARCH_WORD_32 *ptr; + ARCH_WORD space_binary[(PLAINTEXT_LENGTH + SALT_SIZE + 8) / 2 + 1]; + ARCH_WORD *ptr_binary; + unsigned ARCH_WORD block[2]; + union { + double dummy; + DES_binary data; + } binary; + ARCH_WORD_32 key[2]; +#if !ARCH_LITTLE_ENDIAN + ARCH_WORD_32 tmp; +#endif + + DES_std_set_salt(AFS_salt_binary); + memset(DES_IV, 0, sizeof(DES_IV)); + DES_count = 25; + + for (index = 0; index < count; index++) + if ((length = strlen(buffer[index].key)) > 8) + buffer[index].is_long = length; + else { + buffer[index].is_long = 0; + + memcpy(xor, cell, 8); + for (pos = 0; pos < 8 && buffer[index].key[pos]; pos++) + xor[pos] ^= buffer[index].key[pos]; + + for (pos = 0; pos < 8; pos++) + if (!xor[pos]) xor[pos] = 'X'; + + DES_std_set_key(xor); + DES_std_crypt(DES_KS_current, buffer[index].aligned.binary); + } + + DES_std_set_salt(0); + DES_count = 1; + + for (index = 0; index < count; index++) + if ((length = buffer[index].is_long)) { + memcpy(space, buffer[index].key, length); + memcpy((char *)space + length, cell, cell_length + 8); + + memcpy(binary.data, AFS_long_IV_binary, sizeof(binary.data)); + + length += cell_length; + ptr = space; + ptr_binary = space_binary; + do { + AFS_swap(*ptr++, block[0]); + AFS_swap(*ptr++, block[1]); + DES_std_set_block(block[0], block[1]); + + *ptr_binary++ = DES_IV[0]; + DES_IV[0] ^= binary.data[0]; + *ptr_binary++ = DES_IV[1]; + DES_IV[1] ^= binary.data[1]; +#if ARCH_BITS < 64 + *ptr_binary++ = DES_IV[2]; + DES_IV[2] ^= binary.data[2]; + *ptr_binary++ = DES_IV[3]; + DES_IV[3] ^= binary.data[3]; +#endif + + DES_std_crypt(AFS_long_KS.data, binary.data); + + length -= 8; + } while (length > 0); + + DES_std_get_block(binary.data, block); + AFS_swap(block[0] >> 1, key[0]); + AFS_swap(block[1] >> 1, key[1]); + DES_raw_set_key((char *)key); + + length = buffer[index].is_long + cell_length; + ptr_binary = space_binary; + do { + DES_IV[0] = binary.data[0] ^ *ptr_binary++; + DES_IV[1] = binary.data[1] ^ *ptr_binary++; +#if ARCH_BITS < 64 + DES_IV[2] = binary.data[2] ^ *ptr_binary++; + DES_IV[3] = binary.data[3] ^ *ptr_binary++; +#endif + + DES_std_crypt(DES_KS_current, binary.data); + + length -= 8; + } while (length > 0); + + DES_std_get_block(binary.data, block); + buffer[index].aligned.binary[0] = block[0] | 0x01010101; + buffer[index].aligned.binary[1] = block[1] | 0x01010101; + } + + return count; +} + +static int cmp_all(void *binary, int count) +{ + int index; + + for (index = 0; index < count; index++) + if (buffer[index].is_long) { + if (*(unsigned ARCH_WORD *)binary == + buffer[index].aligned.binary[0]) + return 1; + } else { + if (((unsigned ARCH_WORD *)binary)[2] == + (buffer[index].aligned.binary[0] & TOTAL_BINARY_MASK)) + return 1; + } + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + if (buffer[index].is_long) + return *(unsigned ARCH_WORD *)binary == + buffer[index].aligned.binary[0]; + + return ((unsigned ARCH_WORD *)binary)[2] == + (buffer[index].aligned.binary[0] & TOTAL_BINARY_MASK); +} + +static int cmp_exact(char *source, int index) +{ + ARCH_WORD *binary; + int word; + + binary = get_binary(source); + + if (buffer[index].is_long) { + if ((unsigned ARCH_WORD)binary[0] != + buffer[index].aligned.binary[0] || + (unsigned ARCH_WORD)binary[1] != + buffer[index].aligned.binary[1]) + return 0; + } else { + for (word = 0; word < 16 / DES_SIZE; word++) + if ((unsigned ARCH_WORD)binary[word + 2] != + (buffer[index].aligned.binary[word] & TOTAL_BINARY_MASK)) + return 0; + } + + return 1; +} + +struct fmt_main fmt_AFS = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + get_binary, + salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + NULL, + NULL, + NULL, + NULL + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + NULL, + NULL, + NULL, + NULL + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/BF_fmt.c b/src/BF_fmt.c new file mode 100644 index 0000000..68737be --- /dev/null +++ b/src/BF_fmt.c @@ -0,0 +1,339 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2008,2010-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "arch.h" +#include "misc.h" +#include "BF_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "bcrypt" +#define FORMAT_NAME "" + +#define BENCHMARK_COMMENT " (\"$2a$05\", 32 iterations)" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 72 +#define CIPHERTEXT_LENGTH 60 + +#define BINARY_SIZE 4 +#define BINARY_ALIGN 4 +#define SALT_SIZE sizeof(BF_salt) +#define SALT_ALIGN 4 + +#define MIN_KEYS_PER_CRYPT BF_Nmin +#define MAX_KEYS_PER_CRYPT BF_N + +static struct fmt_tests tests[] = { + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", + "U*U"}, + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", + "U*U*"}, + {"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", + "U*U*U"}, + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", + ""}, + {"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", + "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "chars after 72 are ignored"}, + {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", + "\xa3"}, + {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", + "\xa3"}, + {"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS", + "\xd1\x91"}, + {"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS", + "\xd0\xc1\xd2\xcf\xcc\xd8"}, + {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "chars after 72 are ignored as usual"}, + {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy", + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" + "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"}, + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", + ""}, + {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe", + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" + "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"}, + {NULL} +}; + +static char saved_key[BF_N][PLAINTEXT_LENGTH + 1]; +static char keys_mode; +static int sign_extension_bug; +static BF_salt saved_salt; + +#ifdef _OPENMP +#include + +struct fmt_main fmt_BF; +#endif + +static void init(struct fmt_main *self) +{ +#ifdef _OPENMP + int n = BF_Nmin * omp_get_max_threads(), max; + if (n < BF_Nmin) + n = BF_Nmin; + if (n > BF_N) + n = BF_N; + fmt_BF.params.min_keys_per_crypt = n; + max = n * BF_cpt; + while (max > BF_N) + max -= n; + fmt_BF.params.max_keys_per_crypt = max; +#endif + + keys_mode = 'y'; + sign_extension_bug = 0; +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + int rounds; + char *pos; + + if (strncmp(ciphertext, "$2a$", 4) && + strncmp(ciphertext, "$2x$", 4) && + strncmp(ciphertext, "$2y$", 4)) + return 0; + + if (ciphertext[4] < '0' || ciphertext[4] > '9') return 0; + if (ciphertext[5] < '0' || ciphertext[5] > '9') return 0; + if (ciphertext[6] != '$') return 0; + rounds = atoi(ciphertext + 4); + if (rounds < 4 || rounds > 31) return 0; + + for (pos = &ciphertext[7]; atoi64[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (*pos || pos - ciphertext != CIPHERTEXT_LENGTH) return 0; + + if (BF_atoi64[ARCH_INDEX(*(pos - 1))] & 3) return 0; + if (BF_atoi64[ARCH_INDEX(ciphertext[28])] & 0xF) return 0; + + return 1; +} + +static int binary_hash_0(void *binary) +{ + return *(BF_word *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(BF_word *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(BF_word *)binary & 0xFFF; +} + +static int binary_hash_3(void *binary) +{ + return *(BF_word *)binary & 0xFFFF; +} + +static int binary_hash_4(void *binary) +{ + return *(BF_word *)binary & 0xFFFFF; +} + +static int binary_hash_5(void *binary) +{ + return *(BF_word *)binary & 0xFFFFFF; +} + +static int binary_hash_6(void *binary) +{ + return *(BF_word *)binary & 0x7FFFFFF; +} + +static int get_hash_0(int index) +{ + return BF_out[index][0] & 0xF; +} + +static int get_hash_1(int index) +{ + return BF_out[index][0] & 0xFF; +} + +static int get_hash_2(int index) +{ + return BF_out[index][0] & 0xFFF; +} + +static int get_hash_3(int index) +{ + return BF_out[index][0] & 0xFFFF; +} + +static int get_hash_4(int index) +{ + return BF_out[index][0] & 0xFFFFF; +} + +static int get_hash_5(int index) +{ + return BF_out[index][0] & 0xFFFFFF; +} + +static int get_hash_6(int index) +{ + return BF_out[index][0] & 0x7FFFFFF; +} + +static int salt_hash(void *salt) +{ + return ((BF_salt *)salt)->salt[0] & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + memcpy(&saved_salt, salt, sizeof(saved_salt)); +} + +static void set_key(char *key, int index) +{ + BF_std_set_key(key, index, sign_extension_bug); + + strnzcpy(saved_key[index], key, PLAINTEXT_LENGTH + 1); +} + +static char *get_key(int index) +{ + return saved_key[index]; +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + + if (keys_mode != saved_salt.subtype) { + int i; + + keys_mode = saved_salt.subtype; + sign_extension_bug = (keys_mode == 'x'); + for (i = 0; i < count; i++) + BF_std_set_key(saved_key[i], i, sign_extension_bug); + } + + BF_std_crypt(&saved_salt, count); + + return count; +} + +static int cmp_all(void *binary, int count) +{ +#if BF_N > 2 + int i; + for (i = 0; i < count; i++) + if (*(BF_word *)binary == BF_out[i][0]) + return 1; + return 0; +#elif BF_N == 2 + return + *(BF_word *)binary == BF_out[0][0] || + *(BF_word *)binary == BF_out[1][0]; +#else + return *(BF_word *)binary == BF_out[0][0]; +#endif +} + +static int cmp_one(void *binary, int index) +{ + return *(BF_word *)binary == BF_out[index][0]; +} + +static int cmp_exact(char *source, int index) +{ +#if BF_mt == 1 + BF_std_crypt_exact(index); +#endif + + return !memcmp(BF_std_get_binary(source), BF_out[index], + sizeof(BF_binary)); +} + +struct fmt_main fmt_BF = { + { + FORMAT_LABEL, + FORMAT_NAME, + BF_ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if BF_mt > 1 + FMT_OMP | +#endif + FMT_CASE | FMT_8_BIT, + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + BF_std_get_binary, + BF_std_get_salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/BF_std.c b/src/BF_std.c new file mode 100644 index 0000000..0bc81ec --- /dev/null +++ b/src/BF_std.c @@ -0,0 +1,843 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2008,2010,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * A public domain version of this code, with reentrant and crypt(3) + * interfaces added, but optimizations specific to password cracking + * removed, is available at: + * + * http://www.openwall.com/crypt/ + * + * This implementation is compatible with OpenBSD bcrypt.c (version 2a) + * by Niels Provos , and uses some of his + * ideas. The password hashing algorithm was designed by David Mazieres + * . + * + * There's a paper on the algorithm that explains its design decisions: + * + * http://www.usenix.org/events/usenix99/provos.html + * + * Some of the tricks in BF_ROUND might be inspired by Eric Young's + * Blowfish library (I can't be sure if I would think of something if I + * hadn't seen his code). + */ + +#include +#include + +#include "arch.h" +#include "common.h" +#include "BF_std.h" + +BF_binary BF_out[BF_N]; + +/* Number of Blowfish rounds, this is also hardcoded into a few places */ +#define BF_ROUNDS 16 + +typedef BF_word BF_key[BF_ROUNDS + 2]; + +struct BF_ctx { + BF_word S[4][0x100]; + BF_key P; +}; + +#if BF_N > 1 +#define INDICES [BF_N] +#define INDEX [index] +#define INDEX0 [index] +#define for_each_index() \ + for (index = 0; index < BF_N; index++) +#else +#define INDICES +#define INDEX +#define INDEX0 [0] +#define for_each_index() +#endif + +#if BF_X2 +#if BF_mt > 1 +#define INDEX2 [index & 1] +#else +#define INDEX2 [index] +#endif +#else +#define INDEX2 +#endif + +#if BF_mt > 1 +#if BF_X2 +#define for_each_t() \ + for (t = 0; t < n; t += 2) +#define for_each_ti() \ + for (index = t; index <= t + 1; index++) +#else +#define for_each_t() \ + for (t = 0; t < n; t++) +#define for_each_ti() \ + index = t; +#endif +#else +#define for_each_t() +#define for_each_ti() \ + for_each_index() +#endif + +#if BF_mt == 1 +/* Current Blowfish context */ +#if BF_ASM +extern +#else +static +#endif +struct BF_ctx CC_CACHE_ALIGN BF_current INDICES; +#endif + +/* Current Blowfish key */ +static BF_key CC_CACHE_ALIGN BF_exp_key INDICES; +#if defined(__linux__) && defined(__sparc__) +static BF_key BF_init_key INDICES; +#else +static BF_key CC_CACHE_ALIGN BF_init_key INDICES; +#endif + +/* + * Magic IV for 64 Blowfish encryptions that we do at the end. + * The string is "OrpheanBeholderScryDoubt" on big-endian. + */ +static BF_word BF_magic_w[6] = { + 0x4F727068, 0x65616E42, 0x65686F6C, + 0x64657253, 0x63727944, 0x6F756274 +}; + +/* + * P-box and S-box tables initialized with digits of Pi. + */ +static struct BF_ctx BF_init_state = { + { + { + 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 + }, { + 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 + }, { + 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 + }, { + 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 + } + }, { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + } +}; + +/* + * Same charset, different order -- can't use the common.c table here. + */ +unsigned char BF_atoi64[0x80] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, + 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, + 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 +}; + +#if ARCH_LITTLE_ENDIAN + +static void BF_swap(BF_word *x, int count) +{ + BF_word tmp; + + do { + tmp = *x; + tmp = (tmp << 16) | (tmp >> 16); + *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); + } while (--count); +} + +#else + +#define BF_swap(x, count) + +#endif + +#if BF_SCALE +/* Architectures that can shift addresses left by 2 bits with no extra cost */ +#define BF_ROUND(ctx, L, R, N, tmp1, tmp2, tmp3, tmp4) \ + tmp1 = L & 0xFF; \ + tmp2 = L >> 8; \ + tmp2 &= 0xFF; \ + tmp3 = L >> 16; \ + tmp3 &= 0xFF; \ + tmp4 = L >> 24; \ + tmp1 = ctx.S[3][tmp1]; \ + tmp2 = ctx.S[2][tmp2]; \ + tmp3 = ctx.S[1][tmp3]; \ + tmp3 += ctx.S[0][tmp4]; \ + tmp3 ^= tmp2; \ + R ^= ctx.P[N + 1]; \ + tmp3 += tmp1; \ + R ^= tmp3; +#else +/* Architectures with no complicated addressing modes supported */ +#define BF_INDEX(S, i) \ + (*((BF_word *)(((unsigned char *)S) + (i)))) +#define BF_ROUND(ctx, L, R, N, tmp1, tmp2, tmp3, tmp4) \ + tmp1 = L & 0xFF; \ + tmp1 <<= 2; \ + tmp2 = L >> 6; \ + tmp2 &= 0x3FC; \ + tmp3 = L >> 14; \ + tmp3 &= 0x3FC; \ + tmp4 = L >> 22; \ + tmp4 &= 0x3FC; \ + tmp1 = BF_INDEX(ctx.S[3], tmp1); \ + tmp2 = BF_INDEX(ctx.S[2], tmp2); \ + tmp3 = BF_INDEX(ctx.S[1], tmp3); \ + tmp3 += BF_INDEX(ctx.S[0], tmp4); \ + tmp3 ^= tmp2; \ + R ^= ctx.P[N + 1]; \ + tmp3 += tmp1; \ + R ^= tmp3; +#endif + +/* + * Encrypt one block, BF_ROUNDS is hardcoded here. + */ +#define BF_ENCRYPT(ctx, L, R) \ + L ^= ctx.P[0]; \ + BF_ROUND(ctx, L, R, 0, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 1, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 2, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 3, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 4, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 5, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 6, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 7, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 8, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 9, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 10, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 11, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 12, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 13, u1, u2, u3, u4); \ + BF_ROUND(ctx, L, R, 14, u1, u2, u3, u4); \ + BF_ROUND(ctx, R, L, 15, u1, u2, u3, u4); \ + u4 = R; \ + R = L; \ + L = u4 ^ ctx.P[BF_ROUNDS + 1]; + +#if BF_ASM + +extern void (*BF_body)(void); + +#else + +#if BF_X2 +/* + * Encrypt two blocks in parallel, BF_ROUNDS is hardcoded here. + */ +#define BF_ENCRYPT2 \ + L0 ^= BF_current[0].P[0]; \ + L1 ^= BF_current[1].P[0]; \ + BF_ROUND(BF_current[0], L0, R0, 0, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 0, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 1, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 1, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 2, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 2, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 3, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 3, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 4, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 4, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 5, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 5, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 6, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 6, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 7, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 7, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 8, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 8, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 9, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 9, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 10, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 10, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 11, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 11, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 12, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 12, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 13, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 13, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], L0, R0, 14, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], L1, R1, 14, v1, v2, v3, v4); \ + BF_ROUND(BF_current[0], R0, L0, 15, u1, u2, u3, u4); \ + BF_ROUND(BF_current[1], R1, L1, 15, v1, v2, v3, v4); \ + u4 = R0; \ + v4 = R1; \ + R0 = L0; \ + R1 = L1; \ + L0 = u4 ^ BF_current[0].P[BF_ROUNDS + 1]; \ + L1 = v4 ^ BF_current[1].P[BF_ROUNDS + 1]; + +#define BF_body() \ + L0 = R0 = L1 = R1 = 0; \ + ptr = BF_current[0].P; \ + do { \ + BF_ENCRYPT2; \ + *ptr = L0; \ + *(ptr + 1) = R0; \ + *(ptr + (BF_current[1].P - BF_current[0].P)) = L1; \ + *(ptr + (BF_current[1].P - BF_current[0].P) + 1) = R1; \ + ptr += 2; \ + } while (ptr < &BF_current[0].P[BF_ROUNDS + 2]); \ +\ + ptr = BF_current[0].S[0]; \ + do { \ + ptr += 2; \ + BF_ENCRYPT2; \ + *(ptr - 2) = L0; \ + *(ptr - 1) = R0; \ + *(ptr - 2 + (BF_current[1].S[0] - BF_current[0].S[0])) = L1; \ + *(ptr - 1 + (BF_current[1].S[0] - BF_current[0].S[0])) = R1; \ + } while (ptr < &BF_current[0].S[3][0xFF]); +#else +#define BF_body() \ + L0 = R0 = 0; \ + ptr = BF_current.P; \ + do { \ + BF_ENCRYPT(BF_current, L0, R0); \ + *ptr = L0; \ + *(ptr + 1) = R0; \ + ptr += 2; \ + } while (ptr < &BF_current.P[BF_ROUNDS + 2]); \ +\ + ptr = BF_current.S[0]; \ + do { \ + ptr += 2; \ + BF_ENCRYPT(BF_current, L0, R0); \ + *(ptr - 2) = L0; \ + *(ptr - 1) = R0; \ + } while (ptr < &BF_current.S[3][0xFF]); +#endif + +#endif + +void BF_std_set_key(char *key, int index, int sign_extension_bug) +{ + char *ptr = key; + int i, j; + BF_word tmp; + + for (i = 0; i < BF_ROUNDS + 2; i++) { + tmp = 0; + for (j = 0; j < 4; j++) { + tmp <<= 8; + if (sign_extension_bug) + tmp |= (int)(signed char)*ptr; + else + tmp |= (unsigned char)*ptr; + + if (!*ptr) ptr = key; else ptr++; + } + + BF_exp_key INDEX[i] = tmp; + BF_init_key INDEX[i] = BF_init_state.P[i] ^ tmp; + } +} + +void BF_std_crypt(BF_salt *salt, int n) +{ +#if BF_mt > 1 + int t; +#endif + +#if BF_mt > 1 && defined(_OPENMP) +#pragma omp parallel for default(none) private(t) shared(n, BF_init_state, BF_init_key, BF_exp_key, salt, BF_magic_w, BF_out) +#endif + for_each_t() { +#if BF_mt > 1 +#if BF_X2 + struct BF_ctx BF_current[2]; +#else + struct BF_ctx BF_current; +#endif +#endif + + BF_word L0, R0; + BF_word u1, u2, u3, u4; +#if BF_X2 + BF_word L1, R1; + BF_word v1, v2, v3, v4; +#endif + BF_word *ptr; + BF_word count; +#if BF_N > 1 + int index; +#endif + + for_each_ti() { + int i; + + memcpy(BF_current INDEX2.S, + BF_init_state.S, sizeof(BF_current INDEX2.S)); + memcpy(BF_current INDEX2.P, + BF_init_key INDEX, sizeof(BF_current INDEX2.P)); + + L0 = R0 = 0; + for (i = 0; i < BF_ROUNDS + 2; i += 2) { + L0 ^= salt->salt[i & 2]; + R0 ^= salt->salt[(i & 2) + 1]; + BF_ENCRYPT(BF_current INDEX2, L0, R0); + BF_current INDEX2.P[i] = L0; + BF_current INDEX2.P[i + 1] = R0; + } + + ptr = BF_current INDEX2.S[0]; + do { + ptr += 4; + L0 ^= salt->salt[(BF_ROUNDS + 2) & 3]; + R0 ^= salt->salt[(BF_ROUNDS + 3) & 3]; + BF_ENCRYPT(BF_current INDEX2, L0, R0); + *(ptr - 4) = L0; + *(ptr - 3) = R0; + + L0 ^= salt->salt[(BF_ROUNDS + 4) & 3]; + R0 ^= salt->salt[(BF_ROUNDS + 5) & 3]; + BF_ENCRYPT(BF_current INDEX2, L0, R0); + *(ptr - 2) = L0; + *(ptr - 1) = R0; + } while (ptr < &BF_current INDEX2.S[3][0xFF]); + } + + count = 1 << salt->rounds; + do { + for_each_ti() { + BF_current INDEX2.P[0] ^= BF_exp_key INDEX[0]; + BF_current INDEX2.P[1] ^= BF_exp_key INDEX[1]; + BF_current INDEX2.P[2] ^= BF_exp_key INDEX[2]; + BF_current INDEX2.P[3] ^= BF_exp_key INDEX[3]; + BF_current INDEX2.P[4] ^= BF_exp_key INDEX[4]; + BF_current INDEX2.P[5] ^= BF_exp_key INDEX[5]; + BF_current INDEX2.P[6] ^= BF_exp_key INDEX[6]; + BF_current INDEX2.P[7] ^= BF_exp_key INDEX[7]; + BF_current INDEX2.P[8] ^= BF_exp_key INDEX[8]; + BF_current INDEX2.P[9] ^= BF_exp_key INDEX[9]; + BF_current INDEX2.P[10] ^= BF_exp_key INDEX[10]; + BF_current INDEX2.P[11] ^= BF_exp_key INDEX[11]; + BF_current INDEX2.P[12] ^= BF_exp_key INDEX[12]; + BF_current INDEX2.P[13] ^= BF_exp_key INDEX[13]; + BF_current INDEX2.P[14] ^= BF_exp_key INDEX[14]; + BF_current INDEX2.P[15] ^= BF_exp_key INDEX[15]; + BF_current INDEX2.P[16] ^= BF_exp_key INDEX[16]; + BF_current INDEX2.P[17] ^= BF_exp_key INDEX[17]; + } + + BF_body(); + + u1 = salt->salt[0]; + u2 = salt->salt[1]; + u3 = salt->salt[2]; + u4 = salt->salt[3]; + for_each_ti() { + BF_current INDEX2.P[0] ^= u1; + BF_current INDEX2.P[1] ^= u2; + BF_current INDEX2.P[2] ^= u3; + BF_current INDEX2.P[3] ^= u4; + BF_current INDEX2.P[4] ^= u1; + BF_current INDEX2.P[5] ^= u2; + BF_current INDEX2.P[6] ^= u3; + BF_current INDEX2.P[7] ^= u4; + BF_current INDEX2.P[8] ^= u1; + BF_current INDEX2.P[9] ^= u2; + BF_current INDEX2.P[10] ^= u3; + BF_current INDEX2.P[11] ^= u4; + BF_current INDEX2.P[12] ^= u1; + BF_current INDEX2.P[13] ^= u2; + BF_current INDEX2.P[14] ^= u3; + BF_current INDEX2.P[15] ^= u4; + BF_current INDEX2.P[16] ^= u1; + BF_current INDEX2.P[17] ^= u2; + } + + BF_body(); + } while (--count); + +#if BF_mt == 1 + for_each_ti() { + L0 = BF_magic_w[0]; + R0 = BF_magic_w[1]; + + count = 64; + do { + BF_ENCRYPT(BF_current INDEX, L0, R0); + } while (--count); + + BF_out INDEX0[0] = L0; + BF_out INDEX0[1] = R0; + } +#else + for_each_ti() { + BF_word L, R; + BF_word u1, u2, u3, u4; + BF_word count; + int i; + + memcpy(&BF_out[index], &BF_magic_w, + sizeof(BF_out[index])); + + count = 64; + do + for (i = 0; i < 6; i += 2) { + L = BF_out[index][i]; + R = BF_out[index][i + 1]; + BF_ENCRYPT(BF_current INDEX2, L, R); + BF_out[index][i] = L; + BF_out[index][i + 1] = R; + } while (--count); + +/* This has to be bug-compatible with the original implementation :-) */ + BF_out[index][5] &= ~(BF_word)0xFF; + } +#endif + } +} + +#if BF_mt == 1 +void BF_std_crypt_exact(int index) +{ + BF_word L, R; + BF_word u1, u2, u3, u4; + BF_word count; + int i; + + memcpy(&BF_out[index][2], &BF_magic_w[2], sizeof(BF_word) * 4); + + count = 64; + do + for (i = 2; i < 6; i += 2) { + L = BF_out[index][i]; + R = BF_out[index][i + 1]; + BF_ENCRYPT(BF_current INDEX, L, R); + BF_out[index][i] = L; + BF_out[index][i + 1] = R; + } while (--count); + +/* This has to be bug-compatible with the original implementation :-) */ + BF_out[index][5] &= ~(BF_word)0xFF; +} +#endif + +/* + * I'm not doing any error checking in the routines below since the + * ciphertext should have already been checked to be fmt_BF.valid(). + */ + +static void BF_decode(BF_word *dst, char *src, int size) +{ + unsigned char *dptr = (unsigned char *)dst; + unsigned char *end = dptr + size; + unsigned char *sptr = (unsigned char *)src; + unsigned int c1, c2, c3, c4; + + do { + c1 = BF_atoi64[ARCH_INDEX(*sptr++)]; + c2 = BF_atoi64[ARCH_INDEX(*sptr++)]; + *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); + if (dptr >= end) break; + + c3 = BF_atoi64[ARCH_INDEX(*sptr++)]; + *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); + if (dptr >= end) break; + + c4 = BF_atoi64[ARCH_INDEX(*sptr++)]; + *dptr++ = ((c3 & 0x03) << 6) | c4; + } while (dptr < end); +} + +void *BF_std_get_salt(char *ciphertext) +{ + static BF_salt salt; + + BF_decode(salt.salt, &ciphertext[7], 16); + BF_swap(salt.salt, 4); + + salt.rounds = atoi(&ciphertext[4]); + if (ciphertext[2] == 'a') + salt.subtype = 'y'; + else + salt.subtype = ciphertext[2]; + + return &salt; +} + +void *BF_std_get_binary(char *ciphertext) +{ + static BF_binary binary; + + binary[5] = 0; + BF_decode(binary, &ciphertext[29], 23); + BF_swap(binary, 6); + binary[5] &= ~(BF_word)0xFF; + + return &binary; +} diff --git a/src/BF_std.h b/src/BF_std.h new file mode 100644 index 0000000..ed357d7 --- /dev/null +++ b/src/BF_std.h @@ -0,0 +1,96 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2008,2010,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * OpenBSD-style Blowfish-based password hash implementation. + */ + +#ifndef _JOHN_BF_STD_H +#define _JOHN_BF_STD_H + +#include "arch.h" +#include "common.h" + +typedef ARCH_WORD_32 BF_word; + +/* + * Binary salt type, also keeps the number of rounds and hash sub-type. + */ +typedef struct { + BF_word salt[4]; + unsigned char rounds; + char subtype; +} BF_salt; + +/* + * Binary ciphertext type. + */ +typedef BF_word BF_binary[6]; + +#if BF_X2 +#define BF_Nmin 2 +#else +#define BF_Nmin 1 +#endif + +#if defined(_OPENMP) && !BF_ASM +#define BF_cpt 3 +#define BF_mt 192 +#define BF_N (BF_Nmin * BF_mt) +#else +#define BF_mt 1 +#define BF_N BF_Nmin +#endif + +/* + * BF_std_crypt() output buffer. + */ +extern BF_binary BF_out[BF_N]; + +/* + * ASCII to binary conversion table, for use in BF_fmt.valid(). + */ +extern unsigned char BF_atoi64[0x80]; + +#if BF_X2 +#define BF_ALGORITHM_NAME "Blowfish 32/" ARCH_BITS_STR " X2" +#else +#define BF_ALGORITHM_NAME "Blowfish 32/" ARCH_BITS_STR +#endif + +/* + * Sets a key for BF_std_crypt(). + */ +extern void BF_std_set_key(char *key, int index, int sign_extension_bug); + +/* + * Main hashing routine, sets first two words of BF_out + * (or all words in an OpenMP-enabled build). + */ +extern void BF_std_crypt(BF_salt *salt, int n); + +#if BF_mt == 1 +/* + * Calculates the rest of BF_out, for exact comparison. + */ +extern void BF_std_crypt_exact(int index); +#endif + +/* + * Returns the salt for BF_std_crypt(). + */ +extern void *BF_std_get_salt(char *ciphertext); + +/* + * Converts an ASCII ciphertext to binary. + */ +extern void *BF_std_get_binary(char *ciphertext); + +#endif diff --git a/src/BSDI_fmt.c b/src/BSDI_fmt.c new file mode 100644 index 0000000..bd14d60 --- /dev/null +++ b/src/BSDI_fmt.c @@ -0,0 +1,464 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2010-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "DES_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "bsdicrypt" +#define FORMAT_NAME "BSDI crypt(3)" + +#define BENCHMARK_COMMENT " (\"_J9..\", 725 iterations)" +#define BENCHMARK_LENGTH 0 + +#define PLAINTEXT_LENGTH 64 +#define CIPHERTEXT_LENGTH 20 + +static struct fmt_tests tests[] = { + {"_J9..CCCCXBrJUJV154M", "U*U*U*U*"}, + {"_J9..CCCCXUhOBTXzaiE", "U*U***U"}, + {"_J9..CCCC4gQ.mB/PffM", "U*U***U*"}, + {"_J9..XXXXvlzQGqpPPdk", "*U*U*U*U"}, + {"_J9..XXXXsqM/YSSP..Y", "*U*U*U*U*"}, + {"_J9..XXXXVL7qJCnku0I", "*U*U*U*U*U*U*U*U"}, + {"_J9..XXXXAj8cFbP5scI", "*U*U*U*U*U*U*U*U*"}, + {"_J9..SDizh.vll5VED9g", "ab1234567"}, + {"_J9..SDizRjWQ/zePPHc", "cr1234567"}, + {"_J9..SDizxmRI1GjnQuE", "zxyDPWgydbQjgq"}, + {"_K9..SaltNrQgIYUAeoY", "726 even"}, + {"_J9..SDSD5YGyRCr4W4c", ""}, + {NULL} +}; + +#if DES_BS + +#include "DES_bs.h" + +#define ALGORITHM_NAME DES_BS_ALGORITHM_NAME + +#define BINARY_SIZE sizeof(ARCH_WORD_32) +#define BINARY_ALIGN sizeof(ARCH_WORD_32) +#define SALT_SIZE (ARCH_SIZE * 2) +#define SALT_ALIGN ARCH_SIZE + +#define MIN_KEYS_PER_CRYPT DES_BS_DEPTH +#define MAX_KEYS_PER_CRYPT DES_BS_DEPTH + +#else + +#define ALGORITHM_NAME DES_STD_ALGORITHM_NAME + +#define BINARY_SIZE ARCH_SIZE +#define BINARY_ALIGN ARCH_SIZE +#define SALT_SIZE (ARCH_SIZE * 2) +#define SALT_ALIGN ARCH_SIZE + +#define MIN_KEYS_PER_CRYPT 4 +#define MAX_KEYS_PER_CRYPT 8 + +static ARCH_WORD saved_salt, current_salt; + +#endif + +static int saved_count; + +static struct { +#if !DES_BS + DES_KS KS; + DES_binary binary; +#endif + char key[PLAINTEXT_LENGTH]; +} *buffer; + +struct fmt_main fmt_BSDI; + +static void init(struct fmt_main *self) +{ + DES_std_init(); + +#if DES_BS + DES_bs_init(0, (DES_bs_cpt + 28) / 29); +#if DES_bs_mt + fmt_BSDI.params.min_keys_per_crypt = DES_bs_min_kpc; + fmt_BSDI.params.max_keys_per_crypt = DES_bs_max_kpc; +#endif + + DES_std_set_salt(0); + DES_count = 1; +#else + current_salt = -1; +#endif + + buffer = mem_alloc_tiny( + sizeof(*buffer) * fmt_BSDI.params.max_keys_per_crypt, + MEM_ALIGN_CACHE); +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos; + + if (ciphertext[0] != '_') return 0; + + for (pos = &ciphertext[1]; pos < &ciphertext[9]; pos++) + if (!*pos) return 0; + + for (pos = &ciphertext[9]; atoi64[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (*pos || pos - ciphertext != CIPHERTEXT_LENGTH) return 0; + + if (atoi64[ARCH_INDEX(*(pos - 1))] & 3) return 0; + + return 1; +} + +static void *salt(char *ciphertext) +{ + static ARCH_WORD out[2]; + +#if DES_BS + out[0] = DES_raw_get_salt(ciphertext); +#else + out[0] = DES_std_get_salt(ciphertext); +#endif + out[1] = DES_raw_get_count(ciphertext); + + return out; +} + +#if DES_BS + +static int binary_hash_0(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFF; +} + +static int binary_hash_3(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFF; +} + +static int binary_hash_4(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFF; +} + +static int binary_hash_5(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFFF; +} + +static int binary_hash_6(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0x7FFFFFF; +} + +#define get_hash_0 DES_bs_get_hash_0 +#define get_hash_1 DES_bs_get_hash_1 +#define get_hash_2 DES_bs_get_hash_2 +#define get_hash_3 DES_bs_get_hash_3 +#define get_hash_4 DES_bs_get_hash_4 +#define get_hash_5 DES_bs_get_hash_5 +#define get_hash_6 DES_bs_get_hash_6 + +static int salt_hash(void *salt) +{ + return *(ARCH_WORD *)salt & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + DES_bs_set_salt(*(ARCH_WORD *)salt); + saved_count = ((ARCH_WORD *)salt)[1]; +} + +#else + +static int binary_hash_0(void *binary) +{ + return DES_STD_HASH_0(*(ARCH_WORD *)binary); +} + +static int binary_hash_1(void *binary) +{ + return DES_STD_HASH_1(*(ARCH_WORD *)binary); +} + +static int binary_hash_2(void *binary) +{ + return DES_STD_HASH_2(*(ARCH_WORD *)binary); +} + +#define binary_hash_3 NULL +#define binary_hash_4 NULL +#define binary_hash_5 NULL +#define binary_hash_6 NULL + +static int get_hash_0(int index) +{ + return DES_STD_HASH_0(buffer[index].binary[0]); +} + +static int get_hash_1(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].binary[0]; + return DES_STD_HASH_1(binary); +} + +static int get_hash_2(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].binary[0]; + return DES_STD_HASH_2(binary); +} + +#define get_hash_3 NULL +#define get_hash_4 NULL +#define get_hash_5 NULL +#define get_hash_6 NULL + +static int salt_hash(void *salt) +{ + return DES_STD_HASH_2(*(ARCH_WORD *)salt) & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + saved_salt = *(ARCH_WORD*)salt; + saved_count = ((ARCH_WORD *)salt)[1]; +} + +#endif + +static void set_key(char *key, int index) +{ + char *ptr, *chr; + int pos, word; + unsigned ARCH_WORD block[2]; + union { + double dummy; + DES_binary binary; + } aligned; + char chars[8]; +#if DES_BS + char *final = key; +#endif + + DES_std_set_key(key); + + for (pos = 0, ptr = key; pos < 8 && *ptr; pos++, ptr++); + block[1] = block[0] = 0; + + while (*ptr) { + ptr -= 8; + for (word = 0; word < 2; word++) + for (pos = 0; pos < 4; pos++) + block[word] ^= (ARCH_WORD)*ptr++ << (1 + (pos << 3)); + +#if !DES_BS + if (current_salt) + DES_std_set_salt(current_salt = 0); + DES_count = 1; +#endif + + DES_std_set_block(block[0], block[1]); + DES_std_crypt(DES_KS_current, aligned.binary); + DES_std_get_block(aligned.binary, block); + + chr = chars; + for (word = 0; word < 2; word++) + for (pos = 0; pos < 4; pos++) { + *chr++ = 0x80 | + ((block[word] >> (1 + (pos << 3))) ^ *ptr); + if (*ptr) ptr++; + } + +#if DES_BS + final = chars; + if (*ptr) +#endif + DES_raw_set_key(chars); + } + +#if DES_BS + DES_bs_set_key(final, index); +#else + memcpy(buffer[index].KS, DES_KS_current, sizeof(DES_KS)); +#endif + strnfcpy(buffer[index].key, key, PLAINTEXT_LENGTH); +} + +static char *get_key(int index) +{ + static char out[PLAINTEXT_LENGTH + 1]; + + return strnzcpy(out, buffer[index].key, PLAINTEXT_LENGTH + 1); +} + +#if DES_BS + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + DES_bs_crypt(saved_count, count); + return count; +} + +static int cmp_one(void *binary, int index) +{ + return DES_bs_cmp_one((ARCH_WORD_32 *)binary, 32, index); +} + +static int cmp_exact(char *source, int index) +{ + return DES_bs_cmp_one(DES_bs_get_binary(source), 64, index); +} + +#else + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + int index; + + if (current_salt != saved_salt) + DES_std_set_salt(current_salt = saved_salt); + + memset(DES_IV, 0, sizeof(DES_IV)); + DES_count = saved_count; + + for (index = 0; index < count; index++) + DES_std_crypt(buffer[index].KS, buffer[index].binary); + + return count; +} + +static int cmp_all(void *binary, int count) +{ + int index; + + for (index = 0; index < count; index++) + if (*(unsigned ARCH_WORD *)binary == + (buffer[index].binary[0] & DES_BINARY_MASK)) + return 1; + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + return *(unsigned ARCH_WORD *)binary == + (buffer[index].binary[0] & DES_BINARY_MASK); +} + +static int cmp_exact(char *source, int index) +{ + ARCH_WORD *binary; + int word; + + binary = DES_std_get_binary(source); + + for (word = 0; word < 16 / DES_SIZE; word++) + if ((unsigned ARCH_WORD)binary[word] != + (buffer[index].binary[word] & DES_BINARY_MASK)) + return 0; + + return 1; +} + +#endif + +struct fmt_main fmt_BSDI = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if DES_BS && DES_bs_mt + FMT_OMP | +#endif +#if DES_BS + FMT_CASE | FMT_BS, +#else + FMT_CASE, +#endif + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + (void *(*)(char *)) +#if DES_BS + DES_bs_get_binary, +#else + DES_std_get_binary, +#endif + salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, +#if DES_BS + (int (*)(void *, int))DES_bs_cmp_all, +#else + cmp_all, +#endif + cmp_one, + cmp_exact + } +}; diff --git a/src/DES_bs.c b/src/DES_bs.c new file mode 100644 index 0000000..f3e79c9 --- /dev/null +++ b/src/DES_bs.c @@ -0,0 +1,563 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2002,2005,2010-2012 by Solar Designer + */ + +#include + +#include "arch.h" +#include "common.h" +#include "DES_std.h" +#include "DES_bs.h" + +#if DES_BS_VECTOR +#define DEPTH [depth] +#define START [0] +#define init_depth() \ + depth = index >> ARCH_BITS_LOG; \ + index &= (ARCH_BITS - 1); +#define for_each_depth() \ + for (depth = 0; depth < DES_BS_VECTOR; depth++) +#else +#define DEPTH +#define START +#define init_depth() +#define for_each_depth() +#endif + +#if DES_bs_mt +#include +#include +int DES_bs_min_kpc, DES_bs_max_kpc; +static int DES_bs_n_alloc; +int DES_bs_nt = 0; +DES_bs_combined *DES_bs_all_p = NULL; +#elif !DES_BS_ASM +DES_bs_combined CC_CACHE_ALIGN DES_bs_all; +#endif + +static unsigned char DES_LM_KP[56] = { + 1, 2, 3, 4, 5, 6, 7, + 10, 11, 12, 13, 14, 15, 0, + 19, 20, 21, 22, 23, 8, 9, + 28, 29, 30, 31, 16, 17, 18, + 37, 38, 39, 24, 25, 26, 27, + 46, 47, 32, 33, 34, 35, 36, + 55, 40, 41, 42, 43, 44, 45, + 48, 49, 50, 51, 52, 53, 54 +}; + +static unsigned char DES_LM_reverse[16] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 +}; + +#if DES_BS_ASM +extern void DES_bs_init_asm(void); +#endif + +void DES_bs_init(int LM, int cpt) +{ + ARCH_WORD **k; + int round, index, bit; + int p, q, s; + int c; +#if DES_bs_mt + int t, n; + +/* + * The array of DES_bs_all's is not exactly tiny, but we use mem_alloc_tiny() + * for its alignment support and error checking. We do not need to free() this + * memory anyway. + * + * We allocate one extra entry (will be at "thread number" -1) to hold "ones" + * and "salt" fields that are shared between threads. + */ + n = omp_get_max_threads(); + if (n < 1) + n = 1; + if (n > DES_bs_mt_max) + n = DES_bs_mt_max; + DES_bs_min_kpc = n * DES_BS_DEPTH; + { + int max = n * cpt; + while (max > DES_bs_mt_max) + max -= n; + n = max; + } + DES_bs_max_kpc = n * DES_BS_DEPTH; + assert(!DES_bs_all_p || n <= DES_bs_n_alloc); + DES_bs_nt = n; + if (!DES_bs_all_p) { + DES_bs_n_alloc = n; + DES_bs_all_p = mem_alloc_tiny( + ++n * DES_bs_all_size, MEM_ALIGN_PAGE); + } +#endif + + for_each_t(n) { +#if DES_BS_EXPAND + if (LM) + k = DES_bs_all.KS.p; + else + k = DES_bs_all.KSp; +#else + k = DES_bs_all.KS.p; +#endif + + s = 0; + for (round = 0; round < 16; round++) { + s += DES_ROT[round]; + for (index = 0; index < 48; index++) { + p = DES_PC2[index]; + q = p < 28 ? 0 : 28; + p += s; + while (p >= 28) p -= 28; + bit = DES_PC1[p + q]; + bit ^= 070; + bit -= bit >> 3; + bit = 55 - bit; + if (LM) bit = DES_LM_KP[bit]; + *k++ = &DES_bs_all.K[bit] START; + } + } + +/* + * Have keys go to bit layers where DES_bs_get_hash() and DES_bs_cmp_one() + * currently expect them. + */ + for (index = 0; index < DES_BS_DEPTH; index++) + DES_bs_all.pxkeys[index] = + &DES_bs_all.xkeys.c[0][index & 7][index >> 3]; + + if (LM) { + for (c = 0; c < 0x100; c++) + if (c >= 'a' && c <= 'z') + DES_bs_all.E.u[c] = c & ~0x20; + else + DES_bs_all.E.u[c] = c; + } else { + for (index = 0; index < 48; index++) + DES_bs_all.Ens[index] = + &DES_bs_all.B[DES_E[index]]; + DES_bs_all.salt = 0xffffff; +#if DES_bs_mt + DES_bs_set_salt_for_thread(t, 0); +#else + DES_bs_set_salt(0); +#endif + } + +#if !DES_BS_ASM + memset(&DES_bs_all.zero, 0, sizeof(DES_bs_all.zero)); + memset(&DES_bs_all.ones, -1, sizeof(DES_bs_all.ones)); + for (bit = 0; bit < 8; bit++) + memset(&DES_bs_all.masks[bit], 1 << bit, + sizeof(DES_bs_all.masks[bit])); +#endif + } + +#if DES_bs_mt +/* Skip the special entry (will be at "thread number" -1) */ + if (n > DES_bs_nt) + DES_bs_all_p = (DES_bs_combined *) + ((char *)DES_bs_all_p + DES_bs_all_size); +#endif + +#if DES_BS_ASM + DES_bs_init_asm(); +#endif +} + +#if DES_bs_mt +void DES_bs_set_salt(ARCH_WORD salt) +{ + DES_bs_all_by_tnum(-1).salt = salt; +} +#endif + +void DES_bs_set_key(char *key, int index) +{ + unsigned char *dst; + + init_t(); + + dst = DES_bs_all.pxkeys[index]; + + DES_bs_all.keys_changed = 1; + + if (!key[0]) goto fill8; + *dst = key[0]; + *(dst + sizeof(DES_bs_vector) * 8) = key[1]; + *(dst + sizeof(DES_bs_vector) * 8 * 2) = key[2]; + if (!key[1]) goto fill6; + if (!key[2]) goto fill5; + *(dst + sizeof(DES_bs_vector) * 8 * 3) = key[3]; + *(dst + sizeof(DES_bs_vector) * 8 * 4) = key[4]; + if (!key[3]) goto fill4; + if (!key[4] || !key[5]) goto fill3; + *(dst + sizeof(DES_bs_vector) * 8 * 5) = key[5]; + if (!key[6]) goto fill2; + *(dst + sizeof(DES_bs_vector) * 8 * 6) = key[6]; + *(dst + sizeof(DES_bs_vector) * 8 * 7) = key[7]; + return; +fill8: + dst[0] = 0; + dst[sizeof(DES_bs_vector) * 8] = 0; +fill6: + dst[sizeof(DES_bs_vector) * 8 * 2] = 0; +fill5: + dst[sizeof(DES_bs_vector) * 8 * 3] = 0; +fill4: + dst[sizeof(DES_bs_vector) * 8 * 4] = 0; +fill3: + dst[sizeof(DES_bs_vector) * 8 * 5] = 0; +fill2: + dst[sizeof(DES_bs_vector) * 8 * 6] = 0; + dst[sizeof(DES_bs_vector) * 8 * 7] = 0; +} + +void DES_bs_set_key_LM(char *key, int index) +{ + unsigned long c; + unsigned char *dst; + + init_t(); + + dst = DES_bs_all.pxkeys[index]; + +/* + * gcc 4.5.0 on x86_64 would generate redundant movzbl's without explicit + * use of "long" here. + */ + c = (unsigned char)key[0]; + if (!c) goto fill7; + *dst = DES_bs_all.E.u[c]; + c = (unsigned char)key[1]; + if (!c) goto fill6; + *(dst + sizeof(DES_bs_vector) * 8) = DES_bs_all.E.u[c]; + c = (unsigned char)key[2]; + if (!c) goto fill5; + *(dst + sizeof(DES_bs_vector) * 8 * 2) = DES_bs_all.E.u[c]; + c = (unsigned char)key[3]; + if (!c) goto fill4; + *(dst + sizeof(DES_bs_vector) * 8 * 3) = DES_bs_all.E.u[c]; + c = (unsigned char)key[4]; + if (!c) goto fill3; + *(dst + sizeof(DES_bs_vector) * 8 * 4) = DES_bs_all.E.u[c]; + c = (unsigned char)key[5]; + if (!c) goto fill2; + *(dst + sizeof(DES_bs_vector) * 8 * 5) = DES_bs_all.E.u[c]; + c = (unsigned char)key[6]; + *(dst + sizeof(DES_bs_vector) * 8 * 6) = DES_bs_all.E.u[c]; + return; +fill7: + dst[0] = 0; +fill6: + dst[sizeof(DES_bs_vector) * 8] = 0; +fill5: + dst[sizeof(DES_bs_vector) * 8 * 2] = 0; +fill4: + dst[sizeof(DES_bs_vector) * 8 * 3] = 0; +fill3: + dst[sizeof(DES_bs_vector) * 8 * 4] = 0; +fill2: + dst[sizeof(DES_bs_vector) * 8 * 5] = 0; + dst[sizeof(DES_bs_vector) * 8 * 6] = 0; +} + +static ARCH_WORD_32 *DES_bs_get_binary_raw(ARCH_WORD *raw, int count) +{ + static ARCH_WORD_32 out[2]; + +/* For odd iteration counts, swap L and R here instead of doing it one + * more time in DES_bs_crypt(). */ + count &= 1; + out[count] = raw[0]; + out[count ^ 1] = raw[1]; + + return out; +} + +ARCH_WORD_32 *DES_bs_get_binary(char *ciphertext) +{ + return DES_bs_get_binary_raw( + DES_raw_get_binary(ciphertext), + DES_raw_get_count(ciphertext)); +} + +ARCH_WORD_32 *DES_bs_get_binary_LM(char *ciphertext) +{ + ARCH_WORD block[2], value; + int l, h; + int index; + + block[0] = block[1] = 0; + for (index = 0; index < 16; index += 2) { + l = atoi16[ARCH_INDEX(ciphertext[index])]; + h = atoi16[ARCH_INDEX(ciphertext[index + 1])]; + value = DES_LM_reverse[l] | (DES_LM_reverse[h] << 4); + block[index >> 3] |= value << ((index << 2) & 0x18); + } + + return DES_bs_get_binary_raw(DES_do_IP(block), 1); +} + +char *DES_bs_get_source_LM(ARCH_WORD_32 *raw) +{ + static char out[17]; + char *p; + ARCH_WORD swapped[2], *block, value; + int l, h; + int index; + + swapped[0] = raw[1]; + swapped[1] = raw[0]; + + block = DES_do_FP(swapped); + + p = out; + for (index = 0; index < 16; index += 2) { + value = (block[index >> 3] >> ((index << 2) & 0x18)) & 0xff; + l = DES_LM_reverse[value & 0xf]; + h = DES_LM_reverse[value >> 4]; + *p++ = itoa16[l]; + *p++ = itoa16[h]; + } + *p = 0; + + return out; +} + +static MAYBE_INLINE int DES_bs_get_hash(int index, int count, int trip) +{ + int result; + DES_bs_vector *b; +#if !ARCH_LITTLE_ENDIAN || DES_BS_VECTOR + int depth; +#endif + + init_t(); + +#if ARCH_LITTLE_ENDIAN +/* + * This is merely an optimization. Nothing will break if this check for + * little-endian archs is removed, even if the arch is in fact little-endian. + */ + init_depth(); + b = (DES_bs_vector *)&DES_bs_all.B[0] DEPTH; +#define GET_BIT(bit) \ + (((unsigned ARCH_WORD)b[(bit)] START >> index) & 1) +#else + depth = index >> 3; + index &= 7; + b = (DES_bs_vector *)((unsigned char *)&DES_bs_all.B[0] START + depth); +#define GET_BIT(bit) \ + (((unsigned int)*(unsigned char *)&b[(bit)] START >> index) & 1) +#endif +#define MOVE_BIT(bit) \ + (GET_BIT(bit) << (bit)) + + result = GET_BIT(0); + result |= MOVE_BIT(1); + result |= MOVE_BIT(2); + result |= MOVE_BIT(3); + if (count == 4) return result; + + result |= MOVE_BIT(4); + result |= MOVE_BIT(5); + result |= MOVE_BIT(6); + b += trip; /* for tripcodes, skip bit 7 */ + result |= MOVE_BIT(7); + if (count == 8) return result; + + result |= MOVE_BIT(8); + result |= MOVE_BIT(9); + result |= MOVE_BIT(10); + result |= MOVE_BIT(11); + if (count == 12) return result; + + result |= MOVE_BIT(12); + result |= MOVE_BIT(13); + b += trip; /* for tripcodes, skip bit 15 */ + result |= MOVE_BIT(14); + result |= MOVE_BIT(15); + if (count == 16) return result; + + result |= MOVE_BIT(16); + result |= MOVE_BIT(17); + result |= MOVE_BIT(18); + result |= MOVE_BIT(19); + if (count == 20) return result; + + result |= MOVE_BIT(20); + b += trip; /* for tripcodes, skip bit 23 */ + result |= MOVE_BIT(21); + result |= MOVE_BIT(22); + result |= MOVE_BIT(23); + if (count == 24) return result; + + result |= MOVE_BIT(24); + result |= MOVE_BIT(25); + result |= MOVE_BIT(26); + +#undef GET_BIT +#undef MOVE_BIT + + return result; +} + +int DES_bs_get_hash_0(int index) +{ + return DES_bs_get_hash(index, 4, 0); +} + +int DES_bs_get_hash_1(int index) +{ + return DES_bs_get_hash(index, 8, 0); +} + +int DES_bs_get_hash_2(int index) +{ + return DES_bs_get_hash(index, 12, 0); +} + +int DES_bs_get_hash_3(int index) +{ + return DES_bs_get_hash(index, 16, 0); +} + +int DES_bs_get_hash_4(int index) +{ + return DES_bs_get_hash(index, 20, 0); +} + +int DES_bs_get_hash_5(int index) +{ + return DES_bs_get_hash(index, 24, 0); +} + +int DES_bs_get_hash_6(int index) +{ + return DES_bs_get_hash(index, 27, 0); +} + +/* + * The trick used here allows to compare one ciphertext against all the + * DES_bs_crypt*() outputs in just O(log2(ARCH_BITS)) operations, assuming + * that DES_BS_VECTOR is 0 or 1. This routine isn't vectorized yet. + */ +int DES_bs_cmp_all(ARCH_WORD_32 *binary, int count) +{ + ARCH_WORD value, mask; + int bit; + DES_bs_vector *b; +#if DES_BS_VECTOR + int depth; +#endif +#if DES_bs_mt + int t, n = (count + (DES_BS_DEPTH - 1)) / DES_BS_DEPTH; +#endif + + for_each_t(n) + for_each_depth() { + value = binary[0]; + b = (DES_bs_vector *)&DES_bs_all.B[0] DEPTH; + + mask = b[0] START ^ -(value & 1); + mask |= b[1] START ^ -((value >> 1) & 1); + if (mask == ~(ARCH_WORD)0) goto next_depth; + mask |= b[2] START ^ -((value >> 2) & 1); + mask |= b[3] START ^ -((value >> 3) & 1); + if (mask == ~(ARCH_WORD)0) goto next_depth; + value >>= 4; + b += 4; + for (bit = 4; bit < 32; bit += 2) { + mask |= b[0] START ^ + -(value & 1); + if (mask == ~(ARCH_WORD)0) goto next_depth; + mask |= b[1] START ^ + -((value >> 1) & 1); + if (mask == ~(ARCH_WORD)0) goto next_depth; + value >>= 2; + b += 2; + } + + return 1; +next_depth: + ; + } + + return 0; +} + +int DES_bs_cmp_one(ARCH_WORD_32 *binary, int count, int index) +{ + DES_bs_vector *b; + int depth; + + init_t(); + + depth = index >> 3; + index &= 7; + + b = (DES_bs_vector *)((unsigned char *)&DES_bs_all.B[0] START + depth); + +#define GET_BIT(bit) \ + ((unsigned int)*(unsigned char *)&b[(bit)] START >> index) +#define CMP_BIT(bit) \ + if ((GET_BIT(bit) ^ (binary[0] >> (bit))) & 1) \ + return 0; + +/* Start by comparing bits that are not part of get_hash*() return value */ + CMP_BIT(30); + CMP_BIT(31); +/* These three overlap with DES_bs_get_hash_6t() return value, unfortunately */ + CMP_BIT(27); + CMP_BIT(28); + CMP_BIT(29); + + { + int bit; + for (bit = 26; bit >= 0; bit--) + CMP_BIT(bit); +#undef CMP_BIT + + b += 32; count -= 32; + for (bit = 0; bit < count; bit++) + if ((GET_BIT(bit) ^ (binary[1] >> bit)) & 1) + return 0; +#undef GET_BIT + } + + return 1; +} + +int DES_bs_get_hash_1t(int index) +{ + return DES_bs_get_hash(index, 8, 1); +} + +int DES_bs_get_hash_2t(int index) +{ + return DES_bs_get_hash(index, 12, 1); +} + +int DES_bs_get_hash_3t(int index) +{ + return DES_bs_get_hash(index, 16, 1); +} + +int DES_bs_get_hash_4t(int index) +{ + return DES_bs_get_hash(index, 20, 1); +} + +int DES_bs_get_hash_5t(int index) +{ + return DES_bs_get_hash(index, 24, 1); +} + +int DES_bs_get_hash_6t(int index) +{ + return DES_bs_get_hash(index, 27, 1); +} diff --git a/src/DES_bs.h b/src/DES_bs.h new file mode 100644 index 0000000..7345a74 --- /dev/null +++ b/src/DES_bs.h @@ -0,0 +1,203 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2010-2012 by Solar Designer + */ + +/* + * Bitslice DES implementation. + */ + +#ifndef _JOHN_DES_BS_H +#define _JOHN_DES_BS_H + +#include "arch.h" +#include "common.h" + +/* For struct db_salt */ +#include "loader.h" + +#ifndef DES_BS_ALGORITHM_NAME +#define DES_BS_ALGORITHM_NAME "DES " ARCH_BITS_STR "/" ARCH_BITS_STR +#endif + +#if DES_BS_VECTOR +#define DES_BS_DEPTH (ARCH_BITS * DES_BS_VECTOR) +#else +#define DES_BS_DEPTH ARCH_BITS +#endif + +#if DES_BS_VECTOR +#ifndef DES_BS_VECTOR_SIZE +#define DES_BS_VECTOR_SIZE DES_BS_VECTOR +#endif +typedef ARCH_WORD DES_bs_vector[DES_BS_VECTOR_SIZE]; +#else +#define DES_bs_vector ARCH_WORD +#endif + +/* + * All bitslice DES parameters combined into one struct for more efficient + * cache usage. Don't re-order unless you know what you're doing, as there + * is an optimization that would produce undefined results if you did. + * + * This must match the definition in x86-mmx.S. + */ +typedef struct { +#if DES_BS_EXPAND + ARCH_WORD *KSp[0x300]; /* Initial key schedule (key bit pointers) */ +#endif + union { + ARCH_WORD *p[0x300]; /* Key bit pointers */ +#if DES_BS_EXPAND + DES_bs_vector v[0x300]; /* Key bit values */ +#endif + } KS; /* Current key schedule */ + union { + ARCH_WORD *E[96]; /* Expansion function (data bit ptrs) */ + unsigned char u[0x100]; /* Uppercase (for LM) */ + } E; + DES_bs_vector K[56]; /* Keys */ + DES_bs_vector B[64]; /* Data blocks */ +#if DES_BS_ASM + DES_bs_vector tmp[16]; /* Miscellaneous temporary storage */ +#else + DES_bs_vector zero; /* All 0 bits */ + DES_bs_vector ones; /* All 1 bits */ + DES_bs_vector masks[8]; /* Each byte set to 0x01 ... 0x80 */ +#endif + union { + unsigned char c[8][8][sizeof(DES_bs_vector)]; + DES_bs_vector v[8][8]; + } xkeys; /* Partially transposed key bits matrix */ + unsigned char *pxkeys[DES_BS_DEPTH]; /* Pointers into xkeys.c */ + int keys_changed; /* If keys have changed */ + unsigned int salt; /* Salt value corresponding to E[] contents */ + DES_bs_vector *Ens[48]; /* Pointers into B[] for non-salted E */ +} DES_bs_combined; + +#if defined(_OPENMP) && !DES_BS_ASM +#define DES_bs_mt 1 +#define DES_bs_cpt 32 +#define DES_bs_mt_max (DES_bs_cpt * 576) +extern int DES_bs_min_kpc, DES_bs_max_kpc; +extern int DES_bs_nt; +extern DES_bs_combined *DES_bs_all_p; +#define DES_bs_all_align 64 +#define DES_bs_all_size \ + ((sizeof(DES_bs_combined) + (DES_bs_all_align - 1)) & \ + ~(DES_bs_all_align - 1)) +#define DES_bs_all_by_tnum(tnum) \ + (*(DES_bs_combined *)((char *)DES_bs_all_p + (tnum) * DES_bs_all_size)) +#ifdef __GNUC__ +#define DES_bs_all \ + (*(DES_bs_combined *)((char *)DES_bs_all_p + t)) +#define for_each_t(n) \ + for (t = 0; t < (n) * DES_bs_all_size; t += DES_bs_all_size) +#define init_t() \ + int t = (unsigned int)index / DES_BS_DEPTH * DES_bs_all_size; \ + index = (unsigned int)index % DES_BS_DEPTH; +#else +/* + * For compilers that complain about the above e.g. with "iteration expression + * of omp for loop does not have a canonical shape". + */ +#define DES_bs_all \ + DES_bs_all_by_tnum(t) +#define for_each_t(n) \ + for (t = 0; t < (n); t++) +#define init_t() \ + int t = (unsigned int)index / DES_BS_DEPTH; \ + index = (unsigned int)index % DES_BS_DEPTH; +#endif +#else +#define DES_bs_mt 0 +#define DES_bs_cpt 1 +extern DES_bs_combined DES_bs_all; +#define for_each_t(n) +#define init_t() +#endif + +/* + * Initializes the internal structures. + */ +extern void DES_bs_init(int LM, int cpt); + +/* + * Sets a salt for DES_bs_crypt(). + */ +extern void DES_bs_set_salt(ARCH_WORD salt); +#if DES_bs_mt +extern void DES_bs_set_salt_for_thread(int t, unsigned int salt); +#endif + +/* + * Set a key for DES_bs_crypt() or DES_bs_crypt_LM(), respectively. + */ +extern void DES_bs_set_key(char *key, int index); +extern void DES_bs_set_key_LM(char *key, int index); + +/* + * Almost generic implementation: 24-bit salts, variable iteration count. + */ +extern void DES_bs_crypt(int count, int keys_count); + +/* + * A simplified special-case implementation: 12-bit salts, 25 iterations. + */ +extern void DES_bs_crypt_25(int keys_count); + +/* + * Another special-case version: a non-zero IV, no salts, no iterations. + */ +extern int DES_bs_crypt_LM(int *keys_count, struct db_salt *salt); + +/* + * Converts an ASCII ciphertext to binary to be used with one of the + * comparison functions. + */ +extern ARCH_WORD_32 *DES_bs_get_binary(char *ciphertext); + +/* + * Similarly, for LM hashes. + */ +extern ARCH_WORD_32 *DES_bs_get_binary_LM(char *ciphertext); + +/* + * The reverse of DES_bs_get_binary_LM(). + */ +extern char *DES_bs_get_source_LM(ARCH_WORD_32 *raw); + +/* + * Calculate a hash for a DES_bs_crypt*() output. + * + * "t"-suffixed versions of these functions are for tripcodes (they skip + * bits that are part of the base-64 character not included in tripcodes). + * There's no DES_bs_get_hash_0t() because it would be exactly the same as + * DES_bs_get_hash_0() (all four initial bits are included in tripcodes). + */ +extern int DES_bs_get_hash_0(int index); +extern int DES_bs_get_hash_1(int index); +extern int DES_bs_get_hash_2(int index); +extern int DES_bs_get_hash_3(int index); +extern int DES_bs_get_hash_4(int index); +extern int DES_bs_get_hash_5(int index); +extern int DES_bs_get_hash_6(int index); +extern int DES_bs_get_hash_1t(int index); +extern int DES_bs_get_hash_2t(int index); +extern int DES_bs_get_hash_3t(int index); +extern int DES_bs_get_hash_4t(int index); +extern int DES_bs_get_hash_5t(int index); +extern int DES_bs_get_hash_6t(int index); + +/* + * Compares 32 bits of a given ciphertext against at least the first count of + * the DES_bs_crypt*() outputs and returns zero if no matches detected. + */ +extern int DES_bs_cmp_all(ARCH_WORD_32 *binary, int count); + +/* + * Compares count bits of a given ciphertext against one of the outputs. + */ +extern int DES_bs_cmp_one(ARCH_WORD_32 *binary, int count, int index); + +#endif diff --git a/src/DES_bs_b.c b/src/DES_bs_b.c new file mode 100644 index 0000000..1c81608 --- /dev/null +++ b/src/DES_bs_b.c @@ -0,0 +1,1566 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2003,2010-2013 by Solar Designer + */ + +#include "arch.h" +#include "common.h" +#include "DES_bs.h" + +#if DES_BS_ASM && defined(_OPENMP) && defined(__GNUC__) +#warning Assembly code and OpenMP are both requested - will provide the former, but not the latter (for DES-based hashes). This may likely be corrected by enabling SIMD intrinsics with the C compiler (try adding -msse2 to OMPFLAGS). +#endif + +#if !DES_BS_ASM + +#define vzero (*(vtype *)&DES_bs_all.zero) +#if DES_bs_mt +#define vones (*(vtype *)&DES_bs_all_by_tnum(-1).ones) +#else +#define vones (*(vtype *)&DES_bs_all.ones) +#endif + +#define DES_BS_VECTOR_LOOPS 0 + +#if defined(__ALTIVEC__) && DES_BS_DEPTH == 128 +#ifdef __linux__ +#include +#endif + +typedef vector signed int vtype; + +#define vst(dst, ofs, src) \ + vec_st((src), (ofs) * sizeof(DES_bs_vector), (dst)) + +#define vxorf(a, b) \ + vec_xor((a), (b)) + +#define vnot(dst, a) \ + (dst) = vec_nor((a), (a)) +#define vand(dst, a, b) \ + (dst) = vec_and((a), (b)) +#define vor(dst, a, b) \ + (dst) = vec_or((a), (b)) +#define vandn(dst, a, b) \ + (dst) = vec_andc((a), (b)) +#define vsel(dst, a, b, c) \ + (dst) = vec_sel((a), (b), (vector bool int)(c)) + +#elif defined(__ALTIVEC__) && \ + ((ARCH_BITS == 64 && DES_BS_DEPTH == 192) || \ + (ARCH_BITS == 32 && DES_BS_DEPTH == 160)) +#ifdef __linux__ +#include +#endif + +typedef struct { + vector signed int f; + unsigned ARCH_WORD g; +} vtype; + +#define vst(dst, ofs, src) \ + vec_st((src).f, (ofs) * sizeof(DES_bs_vector), ((vtype *)&(dst))->f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = vec_xor((a).f, (b).f); \ + (dst).g = (a).g ^ (b).g + +#define vnot(dst, a) \ + (dst).f = vec_nor((a).f, (a).f); \ + (dst).g = ~(a).g +#define vand(dst, a, b) \ + (dst).f = vec_and((a).f, (b).f); \ + (dst).g = (a).g & (b).g +#define vor(dst, a, b) \ + (dst).f = vec_or((a).f, (b).f); \ + (dst).g = (a).g | (b).g +#define vandn(dst, a, b) \ + (dst).f = vec_andc((a).f, (b).f); \ + (dst).g = (a).g & ~(b).g +#define vsel(dst, a, b, c) \ + (dst).f = vec_sel((a).f, (b).f, (vector bool int)(c).f); \ + (dst).g = (((a).g & ~(c).g) ^ ((b).g & (c).g)) + +#elif defined(__ALTIVEC__) && DES_BS_DEPTH == 256 +#ifdef __linux__ +#include +#endif + +typedef struct { + vector signed int f, g; +} vtype; + +#define vst(dst, ofs, src) \ + vec_st((src).f, (ofs) * sizeof(DES_bs_vector), ((vtype *)&(dst))->f); \ + vec_st((src).g, (ofs) * sizeof(DES_bs_vector), ((vtype *)&(dst))->g) + +#define vxor(dst, a, b) \ + (dst).f = vec_xor((a).f, (b).f); \ + (dst).g = vec_xor((a).g, (b).g) + +#define vnot(dst, a) \ + (dst).f = vec_nor((a).f, (a).f); \ + (dst).g = vec_nor((a).g, (a).g) +#define vand(dst, a, b) \ + (dst).f = vec_and((a).f, (b).f); \ + (dst).g = vec_and((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = vec_or((a).f, (b).f); \ + (dst).g = vec_or((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = vec_andc((a).f, (b).f); \ + (dst).g = vec_andc((a).g, (b).g) +#define vsel(dst, a, b, c) \ + (dst).f = vec_sel((a).f, (b).f, (vector bool int)(c).f); \ + (dst).g = vec_sel((a).g, (b).g, (vector bool int)(c).g) + +#elif defined(__AVX__) && DES_BS_DEPTH == 256 && !defined(DES_BS_NO_AVX256) +#include + +/* Not __m256i because bitwise ops are "floating-point" with AVX */ +typedef __m256 vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps((float *)((DES_bs_vector *)&(dst) + (ofs)), (src)) + +#define vxorf(a, b) \ + _mm256_xor_ps((a), (b)) + +#define vand(dst, a, b) \ + (dst) = _mm256_and_ps((a), (b)) +#define vor(dst, a, b) \ + (dst) = _mm256_or_ps((a), (b)) +#define vandn(dst, a, b) \ + (dst) = _mm256_andnot_ps((b), (a)) + +#ifdef __XOP__ +/* This could be _mm256_cmov_ps(), but it does not exist (yet?) */ +#define vsel(dst, a, b, c) \ + (dst) = __builtin_ia32_vpcmov_v8sf256((b), (a), (c)) +#endif + +/* + * We should be able to do 256-bit shifts with one instruction with AVX2, but + * for plain AVX let's use pairs of 128-bit instructions (and likely incur + * extra memory stores/loads because the rest of our AVX code is 256-bit). :-( + */ +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst))[0] = \ + _mm_slli_epi64(((__m128i *)&(src))[0], (shift)); \ + ((__m128i *)&(dst))[1] = \ + _mm_slli_epi64(((__m128i *)&(src))[1], (shift)) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst))[0] = \ + _mm_srli_epi64(((__m128i *)&(src))[0], (shift)); \ + ((__m128i *)&(dst))[1] = \ + _mm_srli_epi64(((__m128i *)&(src))[1], (shift)) + +#elif defined(__AVX__) && DES_BS_DEPTH == 384 && !defined(DES_BS_NO_AVX128) +#include +#ifdef __XOP__ +#include +#endif + +typedef struct { +/* Not __m256i because bitwise ops are "floating-point" with AVX */ + __m256 f; + __m128i g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g, \ + (src).g) + +#define vxor(dst, a, b) \ + (dst).f = _mm256_xor_ps((a).f, (b).f); \ + (dst).g = _mm_xor_si128((a).g, (b).g) + +#define vand(dst, a, b) \ + (dst).f = _mm256_and_ps((a).f, (b).f); \ + (dst).g = _mm_and_si128((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = _mm256_or_ps((a).f, (b).f); \ + (dst).g = _mm_or_si128((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = _mm256_andnot_ps((b).f, (a).f); \ + (dst).g = _mm_andnot_si128((b).g, (a).g) + +#ifdef __XOP__ +/* This could be _mm256_cmov_ps(), but it does not exist (yet?) */ +#define vsel(dst, a, b, c) \ + (dst).f = __builtin_ia32_vpcmov_v8sf256((b).f, (a).f, (c).f); \ + (dst).g = _mm_cmov_si128((b).g, (a).g, (c).g) +#endif + +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_slli_epi64((src).g, (shift)) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_srli_epi64((src).g, (shift)) + +#elif defined(__AVX__) && DES_BS_DEPTH == 512 +#include + +typedef struct { +/* Not __m256i because bitwise ops are "floating-point" with AVX */ + __m256 f, g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g, \ + (src).g) + +#define vxor(dst, a, b) \ + (dst).f = _mm256_xor_ps((a).f, (b).f); \ + (dst).g = _mm256_xor_ps((a).g, (b).g) + +#define vand(dst, a, b) \ + (dst).f = _mm256_and_ps((a).f, (b).f); \ + (dst).g = _mm256_and_ps((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = _mm256_or_ps((a).f, (b).f); \ + (dst).g = _mm256_or_ps((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = _mm256_andnot_ps((b).f, (a).f); \ + (dst).g = _mm256_andnot_ps((b).g, (a).g) + +#ifdef __XOP__ +/* This could be _mm256_cmov_ps(), but it does not exist (yet?) */ +#define vsel(dst, a, b, c) \ + (dst).f = __builtin_ia32_vpcmov_v8sf256((b).f, (a).f, (c).f); \ + (dst).g = __builtin_ia32_vpcmov_v8sf256((b).g, (a).g, (c).g) +#endif + +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + ((__m128i *)&(dst).g)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).g)[0], (shift)); \ + ((__m128i *)&(dst).g)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).g)[1], (shift)) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + ((__m128i *)&(dst).g)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).g)[0], (shift)); \ + ((__m128i *)&(dst).g)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).g)[1], (shift)) + +#elif defined(__AVX__) && defined(__MMX__) && DES_BS_DEPTH == 320 && \ + !defined(DES_BS_NO_MMX) +#include +#include + +typedef struct { +/* Not __m256i because bitwise ops are "floating-point" with AVX */ + __m256 f; + __m64 g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = _mm256_xor_ps((a).f, (b).f); \ + (dst).g = _mm_xor_si64((a).g, (b).g) + +#define vand(dst, a, b) \ + (dst).f = _mm256_and_ps((a).f, (b).f); \ + (dst).g = _mm_and_si64((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = _mm256_or_ps((a).f, (b).f); \ + (dst).g = _mm_or_si64((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = _mm256_andnot_ps((b).f, (a).f); \ + (dst).g = _mm_andnot_si64((b).g, (a).g) + +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_slli_si64((src).g, (shift)) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_srli_si64((src).g, (shift)) + +#elif defined(__AVX__) && \ + ((ARCH_BITS == 64 && DES_BS_DEPTH == 320) || \ + (ARCH_BITS == 32 && DES_BS_DEPTH == 288)) +#include +#include + +typedef struct { +/* Not __m256i because bitwise ops are "floating-point" with AVX */ + __m256 f; + unsigned ARCH_WORD g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = _mm256_xor_ps((a).f, (b).f); \ + (dst).g = (a).g ^ (b).g + +#define vnot(dst, a) \ + (dst).f = _mm256_xor_ps((a).f, vones.f); \ + (dst).g = ~(a).g +#define vand(dst, a, b) \ + (dst).f = _mm256_and_ps((a).f, (b).f); \ + (dst).g = (a).g & (b).g +#define vor(dst, a, b) \ + (dst).f = _mm256_or_ps((a).f, (b).f); \ + (dst).g = (a).g | (b).g +#define vandn(dst, a, b) \ + (dst).f = _mm256_andnot_ps((b).f, (a).f); \ + (dst).g = (a).g & ~(b).g + +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = (src).g << (shift) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = (src).g >> (shift) + +#elif defined(__AVX__) && defined(__MMX__) && \ + ((ARCH_BITS == 64 && DES_BS_DEPTH == 384) || \ + (ARCH_BITS == 32 && DES_BS_DEPTH == 352)) +#include +#include + +typedef struct { +/* Not __m256i because bitwise ops are "floating-point" with AVX */ + __m256 f; + __m64 g; + unsigned ARCH_WORD h; +} vtype; + +#define vst(dst, ofs, src) \ + _mm256_store_ps( \ + (float *)&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g; \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->h = (src).h + +#define vxor(dst, a, b) \ + (dst).f = _mm256_xor_ps((a).f, (b).f); \ + (dst).g = _mm_xor_si64((a).g, (b).g); \ + (dst).h = (a).h ^ (b).h + +#define vnot(dst, a) \ + (dst).f = _mm256_xor_ps((a).f, vones.f); \ + (dst).g = _mm_xor_si64((a).g, vones.g); \ + (dst).h = ~(a).h +#define vand(dst, a, b) \ + (dst).f = _mm256_and_ps((a).f, (b).f); \ + (dst).g = _mm_and_si64((a).g, (b).g); \ + (dst).h = (a).h & (b).h +#define vor(dst, a, b) \ + (dst).f = _mm256_or_ps((a).f, (b).f); \ + (dst).g = _mm_or_si64((a).g, (b).g); \ + (dst).h = (a).h | (b).h +#define vandn(dst, a, b) \ + (dst).f = _mm256_andnot_ps((b).f, (a).f); \ + (dst).g = _mm_andnot_si64((b).g, (a).g); \ + (dst).h = (a).h & ~(b).h + +#define vshl(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_slli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_slli_si64((src).g, (shift)); \ + (dst).h = (src).h << (shift) +#define vshr(dst, src, shift) \ + ((__m128i *)&(dst).f)[0] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[0], (shift)); \ + ((__m128i *)&(dst).f)[1] = \ + _mm_srli_epi64(((__m128i *)&(src).f)[1], (shift)); \ + (dst).g = _mm_srli_si64((src).g, (shift)); \ + (dst).h = (src).h >> (shift) + +#elif defined(__SSE2__) && DES_BS_DEPTH == 128 +#ifdef __AVX__ +#include +#ifdef __XOP__ +#include +#endif +#else +#include +#endif + +typedef __m128i vtype; + +#define vst(dst, ofs, src) \ + _mm_store_si128((vtype *)((DES_bs_vector *)&(dst) + (ofs)), (src)) + +#define vxorf(a, b) \ + _mm_xor_si128((a), (b)) + +#define vand(dst, a, b) \ + (dst) = _mm_and_si128((a), (b)) +#define vor(dst, a, b) \ + (dst) = _mm_or_si128((a), (b)) +#define vandn(dst, a, b) \ + (dst) = _mm_andnot_si128((b), (a)) + +#ifdef __XOP__ +#define vsel(dst, a, b, c) \ + (dst) = _mm_cmov_si128((b), (a), (c)) +#else +#define vsel(dst, a, b, c) \ + (dst) = _mm_xor_si128(_mm_andnot_si128((c), (a)), \ + _mm_and_si128((c), (b))) +#endif + +#define vshl1(dst, src) \ + (dst) = _mm_add_epi8((src), (src)) +#define vshl(dst, src, shift) \ + (dst) = _mm_slli_epi64((src), (shift)) +#define vshr(dst, src, shift) \ + (dst) = _mm_srli_epi64((src), (shift)) + +#elif defined(__SSE2__) && DES_BS_DEPTH == 256 && defined(DES_BS_NO_MMX) +#ifdef __AVX__ +#include +#ifdef __XOP__ +#include +#endif +#else +#include +#endif + +typedef struct { + __m128i f, g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g, \ + (src).g) + +#define vxor(dst, a, b) \ + (dst).f = _mm_xor_si128((a).f, (b).f); \ + (dst).g = _mm_xor_si128((a).g, (b).g) + +#define vand(dst, a, b) \ + (dst).f = _mm_and_si128((a).f, (b).f); \ + (dst).g = _mm_and_si128((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = _mm_or_si128((a).f, (b).f); \ + (dst).g = _mm_or_si128((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = _mm_andnot_si128((b).f, (a).f); \ + (dst).g = _mm_andnot_si128((b).g, (a).g) + +#ifdef __XOP__ +#define vsel(dst, a, b, c) \ + (dst).f = _mm_cmov_si128((b).f, (a).f, (c).f); \ + (dst).g = _mm_cmov_si128((b).g, (a).g, (c).g) +#endif + +#define vshl1(dst, src) \ + (dst).f = _mm_add_epi8((src).f, (src).f); \ + (dst).g = _mm_add_epi8((src).g, (src).g) +#define vshl(dst, src, shift) \ + (dst).f = _mm_slli_epi64((src).f, (shift)); \ + (dst).g = _mm_slli_epi64((src).g, (shift)) +#define vshr(dst, src, shift) \ + (dst).f = _mm_srli_epi64((src).f, (shift)); \ + (dst).g = _mm_srli_epi64((src).g, (shift)) + +#elif defined(__SSE2__) && defined(__MMX__) && DES_BS_DEPTH == 192 && \ + !defined(DES_BS_NO_MMX) +#include +#include + +typedef struct { + __m128i f; + __m64 g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = _mm_xor_si128((a).f, (b).f); \ + (dst).g = _mm_xor_si64((a).g, (b).g) + +#define vand(dst, a, b) \ + (dst).f = _mm_and_si128((a).f, (b).f); \ + (dst).g = _mm_and_si64((a).g, (b).g) +#define vor(dst, a, b) \ + (dst).f = _mm_or_si128((a).f, (b).f); \ + (dst).g = _mm_or_si64((a).g, (b).g) +#define vandn(dst, a, b) \ + (dst).f = _mm_andnot_si128((b).f, (a).f); \ + (dst).g = _mm_andnot_si64((b).g, (a).g) + +#define vshl1(dst, src) \ + (dst).f = _mm_add_epi8((src).f, (src).f); \ + (dst).g = _mm_add_pi8((src).g, (src).g) +#define vshl(dst, src, shift) \ + (dst).f = _mm_slli_epi64((src).f, (shift)); \ + (dst).g = _mm_slli_si64((src).g, (shift)) +#define vshr(dst, src, shift) \ + (dst).f = _mm_srli_epi64((src).f, (shift)); \ + (dst).g = _mm_srli_si64((src).g, (shift)) + +#elif defined(__SSE2__) && \ + ((ARCH_BITS == 64 && DES_BS_DEPTH == 192) || \ + (ARCH_BITS == 32 && DES_BS_DEPTH == 160)) +#include + +typedef struct { + __m128i f; + unsigned ARCH_WORD g; +} vtype; + +#define vst(dst, ofs, src) \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = _mm_xor_si128((a).f, (b).f); \ + (dst).g = (a).g ^ (b).g + +#define vnot(dst, a) \ + (dst).f = _mm_xor_si128((a).f, vones.f); \ + (dst).g = ~(a).g +#define vand(dst, a, b) \ + (dst).f = _mm_and_si128((a).f, (b).f); \ + (dst).g = (a).g & (b).g +#define vor(dst, a, b) \ + (dst).f = _mm_or_si128((a).f, (b).f); \ + (dst).g = (a).g | (b).g +#define vandn(dst, a, b) \ + (dst).f = _mm_andnot_si128((b).f, (a).f); \ + (dst).g = (a).g & ~(b).g + +#define vshl1(dst, src) \ + (dst).f = _mm_add_epi8((src).f, (src).f); \ + (dst).g = (src).g << 1 +#define vshl(dst, src, shift) \ + (dst).f = _mm_slli_epi64((src).f, (shift)); \ + (dst).g = (src).g << (shift) +#define vshr(dst, src, shift) \ + (dst).f = _mm_srli_epi64((src).f, (shift)); \ + (dst).g = (src).g >> (shift) + +#elif defined(__SSE2__) && defined(__MMX__) && \ + ((ARCH_BITS == 64 && DES_BS_DEPTH == 256) || \ + (ARCH_BITS == 32 && DES_BS_DEPTH == 224)) +#include +#include + +typedef struct { + __m128i f; + __m64 g; + unsigned ARCH_WORD h; +} vtype; + +#define vst(dst, ofs, src) \ + _mm_store_si128(&((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f, \ + (src).f); \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g; \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->h = (src).h + +#define vxor(dst, a, b) \ + (dst).f = _mm_xor_si128((a).f, (b).f); \ + (dst).g = _mm_xor_si64((a).g, (b).g); \ + (dst).h = (a).h ^ (b).h + +#define vnot(dst, a) \ + (dst).f = _mm_xor_si128((a).f, vones.f); \ + (dst).g = _mm_xor_si64((a).g, vones.g); \ + (dst).h = ~(a).h +#define vand(dst, a, b) \ + (dst).f = _mm_and_si128((a).f, (b).f); \ + (dst).g = _mm_and_si64((a).g, (b).g); \ + (dst).h = (a).h & (b).h +#define vor(dst, a, b) \ + (dst).f = _mm_or_si128((a).f, (b).f); \ + (dst).g = _mm_or_si64((a).g, (b).g); \ + (dst).h = (a).h | (b).h +#define vandn(dst, a, b) \ + (dst).f = _mm_andnot_si128((b).f, (a).f); \ + (dst).g = _mm_andnot_si64((b).g, (a).g); \ + (dst).h = (a).h & ~(b).h + +#define vshl1(dst, src) \ + (dst).f = _mm_add_epi8((src).f, (src).f); \ + (dst).g = _mm_add_pi8((src).g, (src).g); \ + (dst).h = (src).h << 1 +#define vshl(dst, src, shift) \ + (dst).f = _mm_slli_epi64((src).f, (shift)); \ + (dst).g = _mm_slli_si64((src).g, (shift)); \ + (dst).h = (src).h << (shift) +#define vshr(dst, src, shift) \ + (dst).f = _mm_srli_epi64((src).f, (shift)); \ + (dst).g = _mm_srli_si64((src).g, (shift)); \ + (dst).h = (src).h >> (shift) + +#elif defined(__MMX__) && ARCH_BITS != 64 && DES_BS_DEPTH == 64 +#include + +typedef __m64 vtype; + +#define vxorf(a, b) \ + _mm_xor_si64((a), (b)) + +#define vand(dst, a, b) \ + (dst) = _mm_and_si64((a), (b)) +#define vor(dst, a, b) \ + (dst) = _mm_or_si64((a), (b)) +#define vandn(dst, a, b) \ + (dst) = _mm_andnot_si64((b), (a)) + +#define vshl1(dst, src) \ + (dst) = _mm_add_pi8((src), (src)) +#define vshl(dst, src, shift) \ + (dst) = _mm_slli_si64((src), (shift)) +#define vshr(dst, src, shift) \ + (dst) = _mm_srli_si64((src), (shift)) + +#elif defined(__MMX__) && ARCH_BITS == 32 && DES_BS_DEPTH == 96 +#include + +typedef struct { + __m64 f; + unsigned ARCH_WORD g; +} vtype; + +#define vst(dst, ofs, src) \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->f = (src).f; \ + ((vtype *)((DES_bs_vector *)&(dst) + (ofs)))->g = (src).g + +#define vxor(dst, a, b) \ + (dst).f = _mm_xor_si64((a).f, (b).f); \ + (dst).g = (a).g ^ (b).g + +#define vnot(dst, a) \ + (dst).f = _mm_xor_si64((a).f, vones.f); \ + (dst).g = ~(a).g +#define vand(dst, a, b) \ + (dst).f = _mm_and_si64((a).f, (b).f); \ + (dst).g = (a).g & (b).g +#define vor(dst, a, b) \ + (dst).f = _mm_or_si64((a).f, (b).f); \ + (dst).g = (a).g | (b).g +#define vandn(dst, a, b) \ + (dst).f = _mm_andnot_si64((b).f, (a).f); \ + (dst).g = (a).g & ~(b).g + +#define vshl1(dst, src) \ + (dst).f = _mm_add_pi8((src).f, (src).f); \ + (dst).g = (src).g << 1 +#define vshl(dst, src, shift) \ + (dst).f = _mm_slli_si64((src).f, (shift)); \ + (dst).g = (src).g << (shift) +#define vshr(dst, src, shift) \ + (dst).f = _mm_srli_si64((src).f, (shift)); \ + (dst).g = (src).g >> (shift) + +#else + +#if DES_BS_VECTOR +#undef DES_BS_VECTOR_LOOPS +#define DES_BS_VECTOR_LOOPS 1 +#endif + +typedef unsigned ARCH_WORD vtype; + +#define vxorf(a, b) \ + ((a) ^ (b)) + +#define vnot(dst, a) \ + (dst) = ~(a) +#define vand(dst, a, b) \ + (dst) = (a) & (b) +#define vor(dst, a, b) \ + (dst) = (a) | (b) +#define vandn(dst, a, b) \ + (dst) = (a) & ~(b) +#define vsel(dst, a, b, c) \ + (dst) = (((a) & ~(c)) ^ ((b) & (c))) + +#define vshl(dst, src, shift) \ + (dst) = (src) << (shift) +#define vshr(dst, src, shift) \ + (dst) = (src) >> (shift) + +/* Assume that 0 always fits in one load immediate instruction */ +#undef vzero +#define vzero 0 + +/* Archs friendly to use of immediate values */ +#if defined(__x86_64__) || defined(__i386__) +#undef vones +#define vones (~(vtype)0) +#endif + +#endif + +#ifndef vst +#define vst(dst, ofs, src) \ + *((vtype *)((DES_bs_vector *)&(dst) + (ofs))) = (src) +#endif + +#if !defined(vxor) && defined(vxorf) +#define vxor(dst, a, b) \ + (dst) = vxorf((a), (b)) +#endif +#if !defined(vxorf) && defined(vxor) +/* + * This requires gcc's "Statement Exprs" extension (also supported by a number + * of other C compilers). + */ +#define vxorf(a, b) \ + ({ vtype tmp; vxor(tmp, (a), (b)); tmp; }) +#endif + +#ifndef vnot +#define vnot(dst, a) \ + vxor((dst), (a), vones) +#endif + +#ifndef vshl1 +#define vshl1(dst, src) \ + vshl((dst), (src), 1) +#endif + +#if !DES_BS_VECTOR_LOOPS && defined(vshl) && defined(vshr) +#define DES_BS_VECTOR_LOOPS_K 0 +#define DEPTH_K +#define for_each_depth_k() + +#define kvtype vtype +#define kvand vand +#define kvor vor +#define kvshl1 vshl1 +#define kvshl vshl +#define kvshr vshr +#else +#if DES_BS_VECTOR +#define DES_BS_VECTOR_LOOPS_K 1 +#define DEPTH_K [depth] +#define for_each_depth_k() \ + for (depth = 0; depth < DES_BS_VECTOR; depth++) +#else +#define DES_BS_VECTOR_LOOPS_K 0 +#endif + +typedef unsigned ARCH_WORD kvtype; +#define kvand(dst, a, b) \ + (dst) = (a) & (b) +#define kvor(dst, a, b) \ + (dst) = (a) | (b) +#define kvshl1(dst, src) \ + (dst) = (src) << 1 +#define kvshl(dst, src, shift) \ + (dst) = (src) << (shift) +#define kvshr(dst, src, shift) \ + (dst) = (src) >> (shift) +#endif + +#if !DES_BS_VECTOR || DES_BS_VECTOR_LOOPS_K +#ifdef __x86_64__ +#define mask01 0x0101010101010101UL +#elif __i386__ +#define mask01 0x01010101UL +#else +#undef mask01 +#endif +#ifdef mask01 +#define mask02 (mask01 << 1) +#define mask04 (mask01 << 2) +#define mask08 (mask01 << 3) +#define mask10 (mask01 << 4) +#define mask20 (mask01 << 5) +#define mask40 (mask01 << 6) +#define mask80 (mask01 << 7) +#endif +#endif + +#ifndef mask01 +#define mask01 (*(kvtype *)&DES_bs_all.masks[0]) +#define mask02 (*(kvtype *)&DES_bs_all.masks[1]) +#define mask04 (*(kvtype *)&DES_bs_all.masks[2]) +#define mask08 (*(kvtype *)&DES_bs_all.masks[3]) +#define mask10 (*(kvtype *)&DES_bs_all.masks[4]) +#define mask20 (*(kvtype *)&DES_bs_all.masks[5]) +#define mask40 (*(kvtype *)&DES_bs_all.masks[6]) +#define mask80 (*(kvtype *)&DES_bs_all.masks[7]) +#endif + +#ifdef __i386__ +/* register-starved */ +#define LOAD_V \ + kvtype v0 = *(kvtype *)&vp[0]; \ + kvtype v4 = *(kvtype *)&vp[4]; +#define v1 *(kvtype *)&vp[1] +#define v2 *(kvtype *)&vp[2] +#define v3 *(kvtype *)&vp[3] +#define v5 *(kvtype *)&vp[5] +#define v6 *(kvtype *)&vp[6] +#define v7 *(kvtype *)&vp[7] +#else +#define LOAD_V \ + kvtype v0 = *(kvtype *)&vp[0]; \ + kvtype v1 = *(kvtype *)&vp[1]; \ + kvtype v2 = *(kvtype *)&vp[2]; \ + kvtype v3 = *(kvtype *)&vp[3]; \ + kvtype v4 = *(kvtype *)&vp[4]; \ + kvtype v5 = *(kvtype *)&vp[5]; \ + kvtype v6 = *(kvtype *)&vp[6]; \ + kvtype v7 = *(kvtype *)&vp[7]; +#endif + +#define kvand_shl1_or(dst, src, mask) \ + kvand(tmp, src, mask); \ + kvshl1(tmp, tmp); \ + kvor(dst, dst, tmp) + +#define kvand_shl_or(dst, src, mask, shift) \ + kvand(tmp, src, mask); \ + kvshl(tmp, tmp, shift); \ + kvor(dst, dst, tmp) + +#define kvand_shl1(dst, src, mask) \ + kvand(tmp, src, mask); \ + kvshl1(dst, tmp) + +#define kvand_or(dst, src, mask) \ + kvand(tmp, src, mask); \ + kvor(dst, dst, tmp) + +#define kvand_shr_or(dst, src, mask, shift) \ + kvand(tmp, src, mask); \ + kvshr(tmp, tmp, shift); \ + kvor(dst, dst, tmp) + +#define kvand_shr(dst, src, mask, shift) \ + kvand(tmp, src, mask); \ + kvshr(dst, tmp, shift) + +#define FINALIZE_NEXT_KEY_BIT_0 { \ + kvtype m = mask01, va, vb, tmp; \ + kvand(va, v0, m); \ + kvand_shl1(vb, v1, m); \ + kvand_shl_or(va, v2, m, 2); \ + kvand_shl_or(vb, v3, m, 3); \ + kvand_shl_or(va, v4, m, 4); \ + kvand_shl_or(vb, v5, m, 5); \ + kvand_shl_or(va, v6, m, 6); \ + kvand_shl_or(vb, v7, m, 7); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_1 { \ + kvtype m = mask02, va, vb, tmp; \ + kvand_shr(va, v0, m, 1); \ + kvand(vb, v1, m); \ + kvand_shl1_or(va, v2, m); \ + kvand_shl_or(vb, v3, m, 2); \ + kvand_shl_or(va, v4, m, 3); \ + kvand_shl_or(vb, v5, m, 4); \ + kvand_shl_or(va, v6, m, 5); \ + kvand_shl_or(vb, v7, m, 6); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_2 { \ + kvtype m = mask04, va, vb, tmp; \ + kvand_shr(va, v0, m, 2); \ + kvand_shr(vb, v1, m, 1); \ + kvand_or(va, v2, m); \ + kvand_shl1_or(vb, v3, m); \ + kvand_shl_or(va, v4, m, 2); \ + kvand_shl_or(vb, v5, m, 3); \ + kvand_shl_or(va, v6, m, 4); \ + kvand_shl_or(vb, v7, m, 5); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_3 { \ + kvtype m = mask08, va, vb, tmp; \ + kvand_shr(va, v0, m, 3); \ + kvand_shr(vb, v1, m, 2); \ + kvand_shr_or(va, v2, m, 1); \ + kvand_or(vb, v3, m); \ + kvand_shl1_or(va, v4, m); \ + kvand_shl_or(vb, v5, m, 2); \ + kvand_shl_or(va, v6, m, 3); \ + kvand_shl_or(vb, v7, m, 4); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_4 { \ + kvtype m = mask10, va, vb, tmp; \ + kvand_shr(va, v0, m, 4); \ + kvand_shr(vb, v1, m, 3); \ + kvand_shr_or(va, v2, m, 2); \ + kvand_shr_or(vb, v3, m, 1); \ + kvand_or(va, v4, m); \ + kvand_shl1_or(vb, v5, m); \ + kvand_shl_or(va, v6, m, 2); \ + kvand_shl_or(vb, v7, m, 3); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_5 { \ + kvtype m = mask20, va, vb, tmp; \ + kvand_shr(va, v0, m, 5); \ + kvand_shr(vb, v1, m, 4); \ + kvand_shr_or(va, v2, m, 3); \ + kvand_shr_or(vb, v3, m, 2); \ + kvand_shr_or(va, v4, m, 1); \ + kvand_or(vb, v5, m); \ + kvand_shl1_or(va, v6, m); \ + kvand_shl_or(vb, v7, m, 2); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_6 { \ + kvtype m = mask40, va, vb, tmp; \ + kvand_shr(va, v0, m, 6); \ + kvand_shr(vb, v1, m, 5); \ + kvand_shr_or(va, v2, m, 4); \ + kvand_shr_or(vb, v3, m, 3); \ + kvand_shr_or(va, v4, m, 2); \ + kvand_shr_or(vb, v5, m, 1); \ + kvand_or(va, v6, m); \ + kvand_shl1_or(vb, v7, m); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#define FINALIZE_NEXT_KEY_BIT_7 { \ + kvtype m = mask80, va, vb, tmp; \ + kvand_shr(va, v0, m, 7); \ + kvand_shr(vb, v1, m, 6); \ + kvand_shr_or(va, v2, m, 5); \ + kvand_shr_or(vb, v3, m, 4); \ + kvand_shr_or(va, v4, m, 3); \ + kvand_shr_or(vb, v5, m, 2); \ + kvand_shr_or(va, v6, m, 1); \ + kvand_or(vb, v7, m); \ + kvor(*(kvtype *)kp, va, vb); \ + kp++; \ +} + +#if DES_bs_mt +static MAYBE_INLINE void DES_bs_finalize_keys(int t) +#else +static MAYBE_INLINE void DES_bs_finalize_keys(void) +#endif +{ +#if DES_BS_VECTOR_LOOPS_K + int depth; +#endif + + for_each_depth_k() { + DES_bs_vector *kp = (DES_bs_vector *)&DES_bs_all.K[0] DEPTH_K; + int ic; + for (ic = 0; ic < 8; ic++) { + DES_bs_vector *vp = + (DES_bs_vector *)&DES_bs_all.xkeys.v[ic][0] DEPTH_K; + LOAD_V + FINALIZE_NEXT_KEY_BIT_0 + FINALIZE_NEXT_KEY_BIT_1 + FINALIZE_NEXT_KEY_BIT_2 + FINALIZE_NEXT_KEY_BIT_3 + FINALIZE_NEXT_KEY_BIT_4 + FINALIZE_NEXT_KEY_BIT_5 + FINALIZE_NEXT_KEY_BIT_6 + } + } + +#if DES_BS_EXPAND + { + int index; + for (index = 0; index < 0x300; index++) + for_each_depth_k() { +#if DES_BS_VECTOR_LOOPS_K + DES_bs_all.KS.v[index] DEPTH_K = + DES_bs_all.KSp[index] DEPTH_K; +#else + vst(*(kvtype *)&DES_bs_all.KS.v[index], 0, + *(kvtype *)DES_bs_all.KSp[index]); +#endif + } + } +#endif +} + +#endif + +#if DES_bs_mt +MAYBE_INLINE void DES_bs_set_salt_for_thread(int t, unsigned int salt) +#else +void DES_bs_set_salt(ARCH_WORD salt) +#endif +{ + unsigned int new = salt; + unsigned int old = DES_bs_all.salt; + int dst; + + DES_bs_all.salt = new; + + for (dst = 0; dst < 24; dst++) { + if ((new ^ old) & 1) { + DES_bs_vector *sp1, *sp2; + int src1 = dst; + int src2 = dst + 24; + if (new & 1) { + src1 = src2; + src2 = dst; + } + sp1 = DES_bs_all.Ens[src1]; + sp2 = DES_bs_all.Ens[src2]; + DES_bs_all.E.E[dst] = (ARCH_WORD *)sp1; + DES_bs_all.E.E[dst + 24] = (ARCH_WORD *)sp2; + DES_bs_all.E.E[dst + 48] = (ARCH_WORD *)(sp1 + 32); + DES_bs_all.E.E[dst + 72] = (ARCH_WORD *)(sp2 + 32); + } + new >>= 1; + old >>= 1; + if (new == old) + break; + } +} + +#if !DES_BS_ASM + +/* Include the S-boxes here so that the compiler can inline them */ +#if DES_BS == 3 +#include "sboxes-s.c" +#elif DES_BS == 2 +#include "sboxes.c" +#else +#undef andn +#include "nonstd.c" +#endif + +#define b DES_bs_all.B +#define e DES_bs_all.E.E + +#if DES_BS_VECTOR_LOOPS +#define kd [depth] +#define bd [depth] +#define ed [depth] +#define DEPTH [depth] +#define for_each_depth() \ + for (depth = 0; depth < DES_BS_VECTOR; depth++) +#else +#if DES_BS_EXPAND +#define kd +#else +#define kd [0] +#endif +#define bd +#define ed [0] +#define DEPTH +#define for_each_depth() +#endif + +#define DES_bs_clear_block_8(i) \ + for_each_depth() { \ + vst(b[i] bd, 0, zero); \ + vst(b[i] bd, 1, zero); \ + vst(b[i] bd, 2, zero); \ + vst(b[i] bd, 3, zero); \ + vst(b[i] bd, 4, zero); \ + vst(b[i] bd, 5, zero); \ + vst(b[i] bd, 6, zero); \ + vst(b[i] bd, 7, zero); \ + } + +#define DES_bs_clear_block \ + DES_bs_clear_block_8(0); \ + DES_bs_clear_block_8(8); \ + DES_bs_clear_block_8(16); \ + DES_bs_clear_block_8(24); \ + DES_bs_clear_block_8(32); \ + DES_bs_clear_block_8(40); \ + DES_bs_clear_block_8(48); \ + DES_bs_clear_block_8(56); + +#define DES_bs_set_block_8(i, v0, v1, v2, v3, v4, v5, v6, v7) \ + for_each_depth() { \ + vst(b[i] bd, 0, v0); \ + vst(b[i] bd, 1, v1); \ + vst(b[i] bd, 2, v2); \ + vst(b[i] bd, 3, v3); \ + vst(b[i] bd, 4, v4); \ + vst(b[i] bd, 5, v5); \ + vst(b[i] bd, 6, v6); \ + vst(b[i] bd, 7, v7); \ + } + +#define x(p) vxorf(*(vtype *)&e[p] ed, *(vtype *)&k[p] kd) +#define y(p, q) vxorf(*(vtype *)&b[p] bd, *(vtype *)&k[q] kd) +#define z(r) ((vtype *)&b[r] bd) + +void DES_bs_crypt_25(int keys_count) +{ +#if DES_bs_mt + int t, n = (keys_count + (DES_BS_DEPTH - 1)) / DES_BS_DEPTH; +#endif + +#ifdef _OPENMP +#pragma omp parallel for default(none) private(t) shared(n, DES_bs_all_p, keys_count) +#endif + for_each_t(n) { +#if DES_BS_EXPAND + DES_bs_vector *k; +#else + ARCH_WORD **k; +#endif + int iterations, rounds_and_swapped; +#if DES_BS_VECTOR_LOOPS + int depth; +#endif + + if (DES_bs_all.keys_changed) + goto finalize_keys; + +body: +#if DES_bs_mt + DES_bs_set_salt_for_thread(t, DES_bs_all_by_tnum(-1).salt); +#endif + + { + vtype zero = vzero; + DES_bs_clear_block + } + +#if DES_BS_EXPAND + k = DES_bs_all.KS.v; +#else + k = DES_bs_all.KS.p; +#endif + rounds_and_swapped = 8; + iterations = 25; + +start: + for_each_depth() + s1(x(0), x(1), x(2), x(3), x(4), x(5), + z(40), z(48), z(54), z(62)); + for_each_depth() + s2(x(6), x(7), x(8), x(9), x(10), x(11), + z(44), z(59), z(33), z(49)); + for_each_depth() + s3(y(7, 12), y(8, 13), y(9, 14), + y(10, 15), y(11, 16), y(12, 17), + z(55), z(47), z(61), z(37)); + for_each_depth() + s4(y(11, 18), y(12, 19), y(13, 20), + y(14, 21), y(15, 22), y(16, 23), + z(57), z(51), z(41), z(32)); + for_each_depth() + s5(x(24), x(25), x(26), x(27), x(28), x(29), + z(39), z(45), z(56), z(34)); + for_each_depth() + s6(x(30), x(31), x(32), x(33), x(34), x(35), + z(35), z(60), z(42), z(50)); + for_each_depth() + s7(y(23, 36), y(24, 37), y(25, 38), + y(26, 39), y(27, 40), y(28, 41), + z(63), z(43), z(53), z(38)); + for_each_depth() + s8(y(27, 42), y(28, 43), y(29, 44), + y(30, 45), y(31, 46), y(0, 47), + z(36), z(58), z(46), z(52)); + + if (rounds_and_swapped == 0x100) goto next; + +swap: + for_each_depth() + s1(x(48), x(49), x(50), x(51), x(52), x(53), + z(8), z(16), z(22), z(30)); + for_each_depth() + s2(x(54), x(55), x(56), x(57), x(58), x(59), + z(12), z(27), z(1), z(17)); + for_each_depth() + s3(y(39, 60), y(40, 61), y(41, 62), + y(42, 63), y(43, 64), y(44, 65), + z(23), z(15), z(29), z(5)); + for_each_depth() + s4(y(43, 66), y(44, 67), y(45, 68), + y(46, 69), y(47, 70), y(48, 71), + z(25), z(19), z(9), z(0)); + for_each_depth() + s5(x(72), x(73), x(74), x(75), x(76), x(77), + z(7), z(13), z(24), z(2)); + for_each_depth() + s6(x(78), x(79), x(80), x(81), x(82), x(83), + z(3), z(28), z(10), z(18)); + for_each_depth() + s7(y(55, 84), y(56, 85), y(57, 86), + y(58, 87), y(59, 88), y(60, 89), + z(31), z(11), z(21), z(6)); + for_each_depth() + s8(y(59, 90), y(60, 91), y(61, 92), + y(62, 93), y(63, 94), y(32, 95), + z(4), z(26), z(14), z(20)); + + k += 96; + + if (--rounds_and_swapped) goto start; + k -= (0x300 + 48); + rounds_and_swapped = 0x108; + if (--iterations) goto swap; +#if DES_bs_mt + continue; +#else + return; +#endif + +next: + k -= (0x300 - 48); + rounds_and_swapped = 8; + iterations--; + goto start; + +finalize_keys: + DES_bs_all.keys_changed = 0; +#if DES_bs_mt + DES_bs_finalize_keys(t); +#else + DES_bs_finalize_keys(); +#endif + goto body; + } +} + +void DES_bs_crypt(int count, int keys_count) +{ +#if DES_bs_mt + int t, n = (keys_count + (DES_BS_DEPTH - 1)) / DES_BS_DEPTH; +#endif + +#ifdef _OPENMP +#pragma omp parallel for default(none) private(t) shared(n, DES_bs_all_p, count, keys_count) +#endif + for_each_t(n) { +#if DES_BS_EXPAND + DES_bs_vector *k; +#else + ARCH_WORD **k; +#endif + int iterations, rounds_and_swapped; +#if DES_BS_VECTOR_LOOPS + int depth; +#endif + + if (DES_bs_all.keys_changed) + goto finalize_keys; + +body: +#if DES_bs_mt + DES_bs_set_salt_for_thread(t, DES_bs_all_by_tnum(-1).salt); +#endif + + { + vtype zero = vzero; + DES_bs_clear_block + } + +#if DES_BS_EXPAND + k = DES_bs_all.KS.v; +#else + k = DES_bs_all.KS.p; +#endif + rounds_and_swapped = 8; + iterations = count; + +start: + for_each_depth() + s1(x(0), x(1), x(2), x(3), x(4), x(5), + z(40), z(48), z(54), z(62)); + for_each_depth() + s2(x(6), x(7), x(8), x(9), x(10), x(11), + z(44), z(59), z(33), z(49)); + for_each_depth() + s3(x(12), x(13), x(14), x(15), x(16), x(17), + z(55), z(47), z(61), z(37)); + for_each_depth() + s4(x(18), x(19), x(20), x(21), x(22), x(23), + z(57), z(51), z(41), z(32)); + for_each_depth() + s5(x(24), x(25), x(26), x(27), x(28), x(29), + z(39), z(45), z(56), z(34)); + for_each_depth() + s6(x(30), x(31), x(32), x(33), x(34), x(35), + z(35), z(60), z(42), z(50)); + for_each_depth() + s7(x(36), x(37), x(38), x(39), x(40), x(41), + z(63), z(43), z(53), z(38)); + for_each_depth() + s8(x(42), x(43), x(44), x(45), x(46), x(47), + z(36), z(58), z(46), z(52)); + + if (rounds_and_swapped == 0x100) goto next; + +swap: + for_each_depth() + s1(x(48), x(49), x(50), x(51), x(52), x(53), + z(8), z(16), z(22), z(30)); + for_each_depth() + s2(x(54), x(55), x(56), x(57), x(58), x(59), + z(12), z(27), z(1), z(17)); + for_each_depth() + s3(x(60), x(61), x(62), x(63), x(64), x(65), + z(23), z(15), z(29), z(5)); + for_each_depth() + s4(x(66), x(67), x(68), x(69), x(70), x(71), + z(25), z(19), z(9), z(0)); + for_each_depth() + s5(x(72), x(73), x(74), x(75), x(76), x(77), + z(7), z(13), z(24), z(2)); + for_each_depth() + s6(x(78), x(79), x(80), x(81), x(82), x(83), + z(3), z(28), z(10), z(18)); + for_each_depth() + s7(x(84), x(85), x(86), x(87), x(88), x(89), + z(31), z(11), z(21), z(6)); + for_each_depth() + s8(x(90), x(91), x(92), x(93), x(94), x(95), + z(4), z(26), z(14), z(20)); + + k += 96; + + if (--rounds_and_swapped) goto start; + k -= (0x300 + 48); + rounds_and_swapped = 0x108; + if (--iterations) goto swap; +#if DES_bs_mt + continue; +#else + return; +#endif + +next: + k -= (0x300 - 48); + rounds_and_swapped = 8; + if (--iterations) goto start; +#if DES_bs_mt + continue; +#else + return; +#endif + +finalize_keys: + DES_bs_all.keys_changed = 0; +#if DES_bs_mt + DES_bs_finalize_keys(t); +#else + DES_bs_finalize_keys(); +#endif + goto body; + } +} + +#undef x + +#if DES_bs_mt +static MAYBE_INLINE void DES_bs_finalize_keys_LM(int t) +#else +static MAYBE_INLINE void DES_bs_finalize_keys_LM(void) +#endif +{ +#if DES_BS_VECTOR_LOOPS_K + int depth; +#endif + + for_each_depth_k() { + DES_bs_vector *kp = (DES_bs_vector *)&DES_bs_all.K[0] DEPTH_K; + int ic; + for (ic = 0; ic < 7; ic++) { + DES_bs_vector *vp = + (DES_bs_vector *)&DES_bs_all.xkeys.v[ic][0] DEPTH_K; + LOAD_V + FINALIZE_NEXT_KEY_BIT_0 + FINALIZE_NEXT_KEY_BIT_1 + FINALIZE_NEXT_KEY_BIT_2 + FINALIZE_NEXT_KEY_BIT_3 + FINALIZE_NEXT_KEY_BIT_4 + FINALIZE_NEXT_KEY_BIT_5 + FINALIZE_NEXT_KEY_BIT_6 + FINALIZE_NEXT_KEY_BIT_7 + } + } +} + +#undef v1 +#undef v2 +#undef v3 +#undef v5 +#undef v6 +#undef v7 + +#undef kd +#if DES_BS_VECTOR_LOOPS +#define kd [depth] +#else +#define kd [0] +#endif + +int DES_bs_crypt_LM(int *pcount, struct db_salt *salt) +{ + int keys_count = *pcount; +#if DES_bs_mt + int t, n = (keys_count + (DES_BS_DEPTH - 1)) / DES_BS_DEPTH; +#endif + +#ifdef _OPENMP +#pragma omp parallel for default(none) private(t) shared(n, DES_bs_all_p, keys_count) +#endif + for_each_t(n) { + ARCH_WORD **k; + int rounds; +#if DES_BS_VECTOR_LOOPS + int depth; +#endif + + { + vtype z = vzero, o = vones; + DES_bs_set_block_8(0, z, z, z, z, z, z, z, z); + DES_bs_set_block_8(8, o, o, o, z, o, z, z, z); + DES_bs_set_block_8(16, z, z, z, z, z, z, z, o); + DES_bs_set_block_8(24, z, z, o, z, z, o, o, o); + DES_bs_set_block_8(32, z, z, z, o, z, o, o, o); + DES_bs_set_block_8(40, z, z, z, z, z, o, z, z); + DES_bs_set_block_8(48, o, o, z, z, z, z, o, z); + DES_bs_set_block_8(56, o, z, o, z, o, o, o, o); + } + +#if DES_bs_mt + DES_bs_finalize_keys_LM(t); +#else + DES_bs_finalize_keys_LM(); +#endif + + k = DES_bs_all.KS.p; + rounds = 8; + + do { + for_each_depth() + s1(y(31, 0), y(0, 1), y(1, 2), + y(2, 3), y(3, 4), y(4, 5), + z(40), z(48), z(54), z(62)); + for_each_depth() + s2(y(3, 6), y(4, 7), y(5, 8), + y(6, 9), y(7, 10), y(8, 11), + z(44), z(59), z(33), z(49)); + for_each_depth() + s3(y(7, 12), y(8, 13), y(9, 14), + y(10, 15), y(11, 16), y(12, 17), + z(55), z(47), z(61), z(37)); + for_each_depth() + s4(y(11, 18), y(12, 19), y(13, 20), + y(14, 21), y(15, 22), y(16, 23), + z(57), z(51), z(41), z(32)); + for_each_depth() + s5(y(15, 24), y(16, 25), y(17, 26), + y(18, 27), y(19, 28), y(20, 29), + z(39), z(45), z(56), z(34)); + for_each_depth() + s6(y(19, 30), y(20, 31), y(21, 32), + y(22, 33), y(23, 34), y(24, 35), + z(35), z(60), z(42), z(50)); + for_each_depth() + s7(y(23, 36), y(24, 37), y(25, 38), + y(26, 39), y(27, 40), y(28, 41), + z(63), z(43), z(53), z(38)); + for_each_depth() + s8(y(27, 42), y(28, 43), y(29, 44), + y(30, 45), y(31, 46), y(0, 47), + z(36), z(58), z(46), z(52)); + + for_each_depth() + s1(y(63, 48), y(32, 49), y(33, 50), + y(34, 51), y(35, 52), y(36, 53), + z(8), z(16), z(22), z(30)); + for_each_depth() + s2(y(35, 54), y(36, 55), y(37, 56), + y(38, 57), y(39, 58), y(40, 59), + z(12), z(27), z(1), z(17)); + for_each_depth() + s3(y(39, 60), y(40, 61), y(41, 62), + y(42, 63), y(43, 64), y(44, 65), + z(23), z(15), z(29), z(5)); + for_each_depth() + s4(y(43, 66), y(44, 67), y(45, 68), + y(46, 69), y(47, 70), y(48, 71), + z(25), z(19), z(9), z(0)); + for_each_depth() + s5(y(47, 72), y(48, 73), y(49, 74), + y(50, 75), y(51, 76), y(52, 77), + z(7), z(13), z(24), z(2)); + for_each_depth() + s6(y(51, 78), y(52, 79), y(53, 80), + y(54, 81), y(55, 82), y(56, 83), + z(3), z(28), z(10), z(18)); + for_each_depth() + s7(y(55, 84), y(56, 85), y(57, 86), + y(58, 87), y(59, 88), y(60, 89), + z(31), z(11), z(21), z(6)); + for_each_depth() + s8(y(59, 90), y(60, 91), y(61, 92), + y(62, 93), y(63, 94), y(32, 95), + z(4), z(26), z(14), z(20)); + + k += 96; + } while (--rounds); + } + + return keys_count; +} +#endif diff --git a/src/DES_fmt.c b/src/DES_fmt.c new file mode 100644 index 0000000..e3d530b --- /dev/null +++ b/src/DES_fmt.c @@ -0,0 +1,432 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2010-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "DES_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "descrypt" +#define FORMAT_NAME "traditional crypt(3)" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH 0 + +#define PLAINTEXT_LENGTH 8 +#define CIPHERTEXT_LENGTH_1 13 +#define CIPHERTEXT_LENGTH_2 24 + +static struct fmt_tests tests[] = { + {"CCNf8Sbh3HDfQ", "U*U*U*U*"}, + {"CCX.K.MFy4Ois", "U*U***U"}, + {"CC4rMpbg9AMZ.", "U*U***U*"}, + {"XXxzOu6maQKqQ", "*U*U*U*U"}, + {"SDbsugeBiC58A", ""}, + {NULL} +}; + +#if DES_BS + +#include "DES_bs.h" + +#define ALGORITHM_NAME DES_BS_ALGORITHM_NAME + +#define BINARY_SIZE sizeof(ARCH_WORD_32) +#define BINARY_ALIGN sizeof(ARCH_WORD_32) +#define SALT_SIZE ARCH_SIZE +#define SALT_ALIGN ARCH_SIZE + +#define MIN_KEYS_PER_CRYPT DES_BS_DEPTH +#define MAX_KEYS_PER_CRYPT DES_BS_DEPTH + +#else + +#define ALGORITHM_NAME DES_STD_ALGORITHM_NAME + +#define BINARY_SIZE ARCH_SIZE +#define BINARY_ALIGN ARCH_SIZE +#define SALT_SIZE ARCH_SIZE +#define SALT_ALIGN ARCH_SIZE + +#define MIN_KEYS_PER_CRYPT 0x40 +#if DES_128K +#define MAX_KEYS_PER_CRYPT 0x100 +#else +#define MAX_KEYS_PER_CRYPT 0x80 +#endif + +static struct { + union { + double dummy; + struct { + DES_KS KS; + DES_binary binary; + } data; + } aligned; + char key[PLAINTEXT_LENGTH]; +} buffer[MAX_KEYS_PER_CRYPT]; + +#endif + +#if DES_BS && DES_bs_mt +struct fmt_main fmt_DES; +#endif + +static void init(struct fmt_main *self) +{ +#if DES_BS + DES_bs_init(0, DES_bs_cpt); +#if DES_bs_mt + fmt_DES.params.min_keys_per_crypt = DES_bs_min_kpc; + fmt_DES.params.max_keys_per_crypt = DES_bs_max_kpc; +#endif +#else + DES_std_init(); +#endif +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos; + + if (!ciphertext[0] || !ciphertext[1]) return 0; + + for (pos = &ciphertext[2]; atoi64[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (*pos && *pos != ',') return 0; + + if (atoi64[ARCH_INDEX(*(pos - 1))] & 3) return 0; + + switch (pos - ciphertext) { + case CIPHERTEXT_LENGTH_1: + return 1; + + case CIPHERTEXT_LENGTH_2: + if (atoi64[ARCH_INDEX(ciphertext[12])] & 3) return 0; + return 2; + + default: + return 0; + } +} + +static char *split(char *ciphertext, int index, struct fmt_main *self) +{ + static char out[14]; + + if (index) { + memcpy(out, &ciphertext[2], 2); + memcpy(&out[2], &ciphertext[13], 11); + } else + memcpy(out, ciphertext, 13); + + out[13] = 0; + return out; +} + +static void *salt(char *ciphertext) +{ + static ARCH_WORD out; + +#if DES_BS + out = DES_raw_get_salt(ciphertext); +#else + out = DES_std_get_salt(ciphertext); +#endif + + return &out; +} + +#if DES_BS + +static int binary_hash_0(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFF; +} + +static int binary_hash_3(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFF; +} + +static int binary_hash_4(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFF; +} + +static int binary_hash_5(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFFF; +} + +static int binary_hash_6(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0x7FFFFFF; +} + +#define get_hash_0 DES_bs_get_hash_0 +#define get_hash_1 DES_bs_get_hash_1 +#define get_hash_2 DES_bs_get_hash_2 +#define get_hash_3 DES_bs_get_hash_3 +#define get_hash_4 DES_bs_get_hash_4 +#define get_hash_5 DES_bs_get_hash_5 +#define get_hash_6 DES_bs_get_hash_6 + +static int salt_hash(void *salt) +{ + return *(ARCH_WORD *)salt & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + DES_bs_set_salt(*(ARCH_WORD *)salt); +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + DES_bs_crypt_25(count); + return count; +} + +static int cmp_one(void *binary, int index) +{ + return DES_bs_cmp_one((ARCH_WORD_32 *)binary, 32, index); +} + +static int cmp_exact(char *source, int index) +{ + return DES_bs_cmp_one(DES_bs_get_binary(source), 64, index); +} + +#else + +static int binary_hash_0(void *binary) +{ + return DES_STD_HASH_0(*(ARCH_WORD *)binary); +} + +static int binary_hash_1(void *binary) +{ + return DES_STD_HASH_1(*(ARCH_WORD *)binary); +} + +static int binary_hash_2(void *binary) +{ + return DES_STD_HASH_2(*(ARCH_WORD *)binary); +} + +#define binary_hash_3 NULL +#define binary_hash_4 NULL +#define binary_hash_5 NULL +#define binary_hash_6 NULL + +static int get_hash_0(int index) +{ + return DES_STD_HASH_0(buffer[index].aligned.data.binary[0]); +} + +static int get_hash_1(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].aligned.data.binary[0]; + return DES_STD_HASH_1(binary); +} + +static int get_hash_2(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].aligned.data.binary[0]; + return DES_STD_HASH_2(binary); +} + +#define get_hash_3 NULL +#define get_hash_4 NULL +#define get_hash_5 NULL +#define get_hash_6 NULL + +static int salt_hash(void *salt) +{ + return DES_STD_HASH_2(*(ARCH_WORD *)salt) & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + DES_std_set_salt(*(ARCH_WORD *)salt); +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + int index; + + for (index = 0; index < count; index++) + DES_std_crypt(buffer[index].aligned.data.KS, + buffer[index].aligned.data.binary); + + return count; +} + +static int cmp_all(void *binary, int count) +{ + int index; + + for (index = 0; index < count; index++) + if (*(unsigned ARCH_WORD *)binary == + (buffer[index].aligned.data.binary[0] & DES_BINARY_MASK)) + return 1; + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + return *(unsigned ARCH_WORD *)binary == + (buffer[index].aligned.data.binary[0] & DES_BINARY_MASK); +} + +static int cmp_exact(char *source, int index) +{ + ARCH_WORD *binary; + int word; + + binary = DES_std_get_binary(source); + + for (word = 0; word < 16 / DES_SIZE; word++) + if ((unsigned ARCH_WORD)binary[word] != + (buffer[index].aligned.data.binary[word] & DES_BINARY_MASK)) + return 0; + + return 1; +} + +#endif + +#if !DES_BS +static void set_key(char *key, int index) +{ + DES_std_set_key(key); + memcpy(buffer[index].aligned.data.KS, DES_KS_current, sizeof(DES_KS)); + memcpy(buffer[index].key, key, PLAINTEXT_LENGTH); +} +#endif + +static char *get_key(int index) +{ + static char out[PLAINTEXT_LENGTH + 1]; +#if DES_BS + unsigned char *src; + char *dst; + + init_t(); + + src = DES_bs_all.pxkeys[index]; + dst = out; + while (dst < &out[PLAINTEXT_LENGTH] && (*dst = *src)) { + src += sizeof(DES_bs_vector) * 8; + dst++; + } + *dst = 0; +#else + memcpy(out, buffer[index].key, PLAINTEXT_LENGTH); + out[PLAINTEXT_LENGTH] = 0; +#endif + + return out; +} + +struct fmt_main fmt_DES = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if DES_BS && DES_bs_mt + FMT_OMP | +#endif +#if DES_BS + FMT_CASE | FMT_BS, +#else + FMT_CASE, +#endif + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + split, + (void *(*)(char *)) +#if DES_BS + DES_bs_get_binary, +#else + DES_std_get_binary, +#endif + salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + salt_hash, + set_salt, +#if DES_BS + DES_bs_set_key, +#else + set_key, +#endif + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, +#if DES_BS + (int (*)(void *, int))DES_bs_cmp_all, +#else + cmp_all, +#endif + cmp_one, + cmp_exact + } +}; diff --git a/src/DES_std.c b/src/DES_std.c new file mode 100644 index 0000000..7553e85 --- /dev/null +++ b/src/DES_std.c @@ -0,0 +1,1171 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "common.h" +#include "DES_std.h" + +#if ARCH_BITS >= 64 + +#if !DES_ASM + +static union { + double dummy; + struct { + DES_KS KS; + ARCH_WORD SPE_F[8][64]; +#if DES_128K + ARCH_WORD SPE_W[4][64 * 64]; +#endif + } data; +} CC_CACHE_ALIGN DES_all; + +#else + +extern ARCH_WORD DES_SPE_F[8][64]; +#if DES_128K +extern ARCH_WORD DES_SPE_W[4][64 * 64]; +#endif + +#endif + +static ARCH_WORD DES_SPE[8][64]; + +#else + +#if !DES_ASM + +static union { + double dummy; + struct { + DES_KS KS; + ARCH_WORD SPE_L[8][64]; + ARCH_WORD cache_bank_shift; + ARCH_WORD SPE_H[8][64]; +#if DES_128K + ARCH_WORD restore_double_word_alignment; + ARCH_WORD SPE_W[4][64 * 64][2]; +#endif + } data; +} CC_CACHE_ALIGN DES_all; + +#else + +#if DES_X2 +extern ARCH_WORD DES_SPE_F[8][64][2]; +#else +extern ARCH_WORD DES_SPE_L[8][64], DES_SPE_H[8][64]; +#endif + +#if DES_128K +extern ARCH_WORD DES_SPE_W[4][64 * 64][2]; +#endif + +#endif + +static ARCH_WORD DES_SPE[8][64][2]; + +#endif + +#if !DES_ASM + +#define DES_KS_copy DES_all.data.KS +#define DES_SPE_F DES_all.data.SPE_F +#define DES_SPE_L DES_all.data.SPE_L +#define DES_SPE_H DES_all.data.SPE_H +#define DES_SPE_W DES_all.data.SPE_W + +DES_binary DES_IV; +ARCH_WORD DES_count; + +DES_KS CC_CACHE_ALIGN DES_KS_current; +DES_KS CC_CACHE_ALIGN DES_KS_table[8][128]; + +#endif + +static int DES_KS_updates; +static char DES_key[16]; + +#if DES_COPY +#if DES_ASM +extern DES_KS DES_KS_copy; +#endif +unsigned ARCH_WORD *DES_out; +#endif + +extern DES_KS DES_KS_table[8][128]; + +#if ARCH_BITS >= 64 +static ARCH_WORD DES_IP_E[8][16], DES_C_FP[16][16]; +#else +static ARCH_WORD DES_IP_E[8][16][2], DES_C_FP[16][16][2]; +#endif + +/* + * Some architecture-dependent definitions follow. Be sure to use correct + * options while compiling, this might affect the performance a lot. + */ + +#if (ARCH_BITS >= 64 && (DES_SCALE || !DES_MASK) || DES_128K) && \ + DES_SIZE_FIX == 2 +/* + * 64-bit architectures which can shift addresses left by 1 bit with no extra + * time required (for example by adding a register to itself). + */ +#define DES_INDEX(SPE, i) \ + (*((ARCH_WORD *)(((unsigned char (*)[2])SPE) + (i)))) +#else +#if DES_SIZE_FIX == 0 +/* + * 64-bit architectures which can shift addresses left by 3 bits (but maybe + * not by 1) with no extra time required (for example by using the S8ADDQ + * instruction on DEC Alphas; we would need an ADDQ anyway). + */ +#define DES_INDEX(SPE, i) \ + SPE[i] +#else +/* + * Architectures with no complicated addressing modes supported, or when those + * are not required. + */ +#define DES_INDEX(SPE, i) \ + (*((ARCH_WORD *)(((unsigned char *)SPE) + (i)))) +#if ARCH_BITS < 64 && DES_128K +#define DES_INDEX_L(SPE, i) \ + (*((ARCH_WORD *)(((unsigned char *)&SPE[0][0]) + (i)))) +#define DES_INDEX_H(SPE, i) \ + (*((ARCH_WORD *)(((unsigned char *)&SPE[0][1]) + (i)))) +#endif +#endif +#endif + +/* + * You can choose between using shifts/masks, and using memory store and load + * instructions. + */ + +#if DES_MASK +#if ARCH_BITS >= 64 && !DES_SCALE && DES_SIZE_FIX == 2 +/* + * This method might be good for some 64-bit architectures with no complicated + * addressing modes supported. It would be the best one for DEC Alphas if they + * didn't have the S8ADDQ instruction. + */ +#define DES_MASK_6 (0x3F << 3) +#else +#if DES_EXTB +/* + * Masking whole bytes allows the compiler to use Move with Zero Extension + * instructions (where supported), like MOVZBL (MOVZX in Intel's syntax) on + * x86s, or EXTBL on DEC Alphas. It might only be reasonable to disable this + * if such instructions exist, but are slower than masks/shifts (as they are + * on Pentiums). + */ +#define DES_MASK_6 ((0x3F << DES_SIZE_FIX) | 0xFF) +#else +/* + * Forces using plain shifts/masks, sometimes it's the only choice. Note that + * you don't have to set DES_MASK if this is the case -- store/load method + * might be faster. + */ +#define DES_MASK_6 (0x3F << DES_SIZE_FIX) +#endif +#endif +#endif + +#if !DES_COPY +#undef DES_KS_copy +#define DES_KS_copy KS +#endif +#define DES_KS_INDEX(i) (DES_KS_copy + (i * (16 / DES_SIZE))) + +#define DES_24_TO_32(x) \ + (((x) & 077) | \ + (((x) & 07700) << 2) | \ + (((x) & 0770000) << 4) | \ + (((x) & 077000000) << 6)) + +#define DES_16_TO_32(x) \ + ((((x) & 0xF) << 1) | \ + (((x) & 0xF0) << 5) | \ + (((x) & 0xF00) << 9) | \ + (((x) & 0xF000) << 13)) + +#if DES_128K +#define DES_UNDO_SIZE_FIX(x) \ + ((((x) >> 1) & 0xFF00FF00) | (((x) & 0x00FF00FF) >> 3)) +#else +#define DES_UNDO_SIZE_FIX(x) \ + ((x) >> DES_SIZE_FIX) +#endif + +static unsigned char DES_S[8][4][16] = { + { + {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} + }, { + {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} + }, { + {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} + }, { + {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} + }, { + {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} + }, { + {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} + }, { + {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} + }, { + {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} + } +}; + +static unsigned char DES_P[32] = { + 15, 6, 19, 20, + 28, 11, 27, 16, + 0, 14, 22, 25, + 4, 17, 30, 9, + 1, 7, 23, 13, + 31, 26, 2, 8, + 18, 12, 29, 5, + 21, 10, 3, 24 +}; + +unsigned char DES_E[48] = { + 31, 0, 1, 2, 3, 4, + 3, 4, 5, 6, 7, 8, + 7, 8, 9, 10, 11, 12, + 11, 12, 13, 14, 15, 16, + 15, 16, 17, 18, 19, 20, + 19, 20, 21, 22, 23, 24, + 23, 24, 25, 26, 27, 28, + 27, 28, 29, 30, 31, 0 +}; + +static unsigned char DES_IP[64] = { + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7, + 56, 48, 40, 32, 24, 16, 8, 0, + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6 +}; + +static unsigned char DES_C[64] = { + 0, 1, 2, 3, 16, 17, 18, 19, + 4, 5, 6, 7, 20, 21, 22, 23, + 8, 9, 10, 11, 24, 25, 26, 27, + 12, 13, 14, 15, 28, 29, 30, 31, + 32, 33, 34, 35, 48, 49, 50, 51, + 36, 37, 38, 39, 52, 53, 54, 55, + 40, 41, 42, 43, 56, 57, 58, 59, + 44, 45, 46, 47, 60, 61, 62, 63 +}; + +unsigned char DES_PC1[56] = { + 56, 48, 40, 32, 24, 16, 8, + 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, + 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, + 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, + 20, 12, 4, 27, 19, 11, 3 +}; + +unsigned char DES_ROT[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +unsigned char DES_PC2[48] = { + 13, 16, 10, 23, 0, 4, + 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, + 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, + 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, + 45, 41, 49, 35, 28, 31 +}; + +static void init_SPE(void) +{ + int box, index, row, column, bit; + unsigned int mask, l, h; + + for (box = 0; box < 8; box++) + for (index = 0; index < 64; index++) { + row = + ((index & 1) << 1) | + (index >> 5); + column = + (((index >> 1) & 1) << 3) | + (((index >> 2) & 1) << 2) | + (((index >> 3) & 1) << 1) | + ((index >> 4) & 1); + + mask = (ARCH_WORD)DES_S[box][row][column] << ((7 - box) << 2); + + h = l = 0; + for (bit = 0; bit < 24; bit++) { + if (((unsigned int)0x80000000 >> + DES_P[ARCH_INDEX(DES_E[bit])]) & mask) + l |= 1 << bit; + if (((unsigned int)0x80000000 >> + DES_P[ARCH_INDEX(DES_E[bit + 24])]) & mask) + h |= 1 << bit; + } + + l = DES_24_TO_32(l); h = DES_24_TO_32(h); + +#if ARCH_BITS >= 64 + DES_SPE[box][index] = + DES_DO_SIZE_FIX(l) | + ((unsigned ARCH_WORD)DES_DO_SIZE_FIX(h) << 32); +#else + DES_SPE[box][index][0] = DES_DO_SIZE_FIX(l); + DES_SPE[box][index][1] = DES_DO_SIZE_FIX(h); +#endif + } +} + +static void init_IP_E(void) +{ + int src, dst, dst1, dst2; + int chunk, mask, value; + + memset(DES_IP_E, 0, sizeof(DES_IP_E)); + + for (dst1 = 0; dst1 < 8; dst1++) + for (dst2 = 0; dst2 < 6; dst2++) { + dst = (dst1 << 3) + dst2; + src = DES_IP[ARCH_INDEX(DES_E[dst1 * 6 + dst2])]; + if (src >= 32) src -= 32; else src--; + src ^= 7; + + chunk = src >> 2; + mask = 1 << (src & 3); + + for (value = 0; value < 16; value++) + if (value & mask) +#if ARCH_BITS >= 64 + DES_IP_E[chunk][value] |= + (unsigned ARCH_WORD)1 << dst; +#else + DES_IP_E[chunk][value][dst >> 5] |= + (unsigned ARCH_WORD)1 << (dst & 0x1F); +#endif + } +} + +static void init_C_FP(void) +{ + int src, dst; + int chunk, mask, value; + + memset(DES_C_FP, 0, sizeof(DES_C_FP)); + + for (src = 0; src < 64; src++) { + dst = DES_IP[ARCH_INDEX(DES_C[src])] ^ 7; + + chunk = src >> 2; + mask = 1 << (src & 3); + + for (value = 0; value < 16; value++) + if (value & mask) +#if ARCH_BITS >= 64 + DES_C_FP[chunk][value] |= + (unsigned ARCH_WORD)1 << dst; +#else + DES_C_FP[chunk][value][dst >> 5] |= + (unsigned ARCH_WORD)1 << (dst & 0x1F); +#endif + } +} + +static void init_KS(void) +{ + int pos, chr, round, bit, ofs; + unsigned char block[64]; + ARCH_WORD value[2]; + int k, p, q, r, s; + + memset(block, 0, sizeof(block)); + + for (pos = 0; pos < 8; pos++) + for (chr = 0x7F; chr >= 0; chr--) { + for (bit = 0; bit < 7; bit++) + block[(pos << 3) + bit] = (chr >> (6 - bit)) & 1; + + s = 0; + for (round = 0; round < 16; round++) { + s += DES_ROT[round]; + value[0] = value[1] = 0; + k = 0; + for (ofs = 0; ofs < 64; ofs += 8) + for (bit = 0; bit < 6; bit++) { + p = DES_PC2[k++]; + q = p < 28 ? 0 : 28; + p += s; + while (p >= 28) p -= 28; + r = DES_PC1[p + q]; + value[ofs >> 5] |= (ARCH_WORD)block[r] << + ((ofs & 31) + bit); + } + +#if ARCH_BITS >= 64 + DES_KS_table[pos][chr][round] = + DES_DO_SIZE_FIX(value[0]) | + (DES_DO_SIZE_FIX(value[1]) << 32); +#else + DES_KS_table[pos][chr][round << 1] = + DES_DO_SIZE_FIX(value[0]); + DES_KS_table[pos][chr][(round << 1) + 1] = + DES_DO_SIZE_FIX(value[1]); +#endif + } + } + + DES_KS_updates = 0; + memset(DES_key, 0, sizeof(DES_key)); + memcpy(DES_KS_current, DES_KS_table, sizeof(DES_KS)); +} + +void DES_std_init(void) +{ + init_SPE(); + init_IP_E(); + init_C_FP(); + init_KS(); + + memset(DES_IV, 0, sizeof(DES_IV)); + DES_count = 25; +} + +void DES_std_set_salt(ARCH_WORD salt) +{ + int box, index; + ARCH_WORD xor; +#if ARCH_BITS >= 64 + unsigned ARCH_WORD src; +#else + ARCH_WORD l, h; +#endif + + for (box = 0; box < 8; box++) + for (index = 0; index < 64; index++) { +#if ARCH_BITS >= 64 + src = DES_SPE[box][index]; + xor = (src ^ (src >> 32)) & salt; + + DES_SPE_F[box][index] = src ^ (xor | (xor << 32)); +#else + l = DES_SPE[box][index][0]; + h = DES_SPE[box][index][1]; + xor = (l ^ h) & salt; + +#if DES_X2 + DES_SPE_F[box][index][0] = l ^ xor; + DES_SPE_F[box][index][1] = h ^ xor; +#else + DES_SPE_L[box][index] = l ^ xor; + DES_SPE_H[box][index] = h ^ xor; +#endif +#endif + } + +#if DES_128K + for (box = 0; box < 4; box++) + for (index = 0; index < 64 * 64; index++) { +#if ARCH_BITS >= 64 + DES_SPE_W[box][index] = + DES_SPE_F[box << 1][index & 0x3F] ^ + DES_SPE_F[(box << 1) + 1][index >> 6]; +#else + DES_SPE_W[box][index][0] = + DES_SPE_L[box << 1][index & 0x3F] ^ + DES_SPE_L[(box << 1) + 1][index >> 6]; + DES_SPE_W[box][index][1] = + DES_SPE_H[box << 1][index & 0x3F] ^ + DES_SPE_H[(box << 1) + 1][index >> 6]; +#endif + } +#endif +} + +/* + * The new DES_std_set_key() idea is originally by Roman Rusakov. I extended + * the original idea to detect whether it's faster to calculate from scratch + * or modify the previous key schedule. This code assumes that DES_xor_key1() + * is 1.5 times faster than DES_xor_key2(). + */ + +#if !DES_ASM + +#define DES_xor1_1(ofs) \ + DES_KS_current[ofs] ^= value1[ofs]; +#define DES_xor1_4(ofs) \ + DES_xor1_1(ofs); \ + DES_xor1_1(ofs + 1); \ + DES_xor1_1(ofs + 2); \ + DES_xor1_1(ofs + 3); +#define DES_xor1_16(ofs) \ + DES_xor1_4(ofs); \ + DES_xor1_4(ofs + 4); \ + DES_xor1_4(ofs + 8); \ + DES_xor1_4(ofs + 12); + +#if ARCH_BITS >= 64 +#define DES_xor_key1(_value) { \ + value1 = _value; \ + DES_xor1_16(0); \ +} +#else +#define DES_xor_key1(_value) { \ + value1 = _value; \ + DES_xor1_16(0); \ + DES_xor1_16(16); \ +} +#endif + +#define DES_xor2_1(ofs) \ + DES_KS_current[ofs] ^= value1[ofs] ^ value2[ofs]; +#define DES_xor2_4(ofs) \ + DES_xor2_1(ofs); \ + DES_xor2_1(ofs + 1); \ + DES_xor2_1(ofs + 2); \ + DES_xor2_1(ofs + 3); +#define DES_xor2_16(ofs) \ + DES_xor2_4(ofs); \ + DES_xor2_4(ofs + 4); \ + DES_xor2_4(ofs + 8); \ + DES_xor2_4(ofs + 12); + +#if ARCH_BITS >= 64 +#define DES_xor_key2(_value1, _value2) { \ + value1 = _value1; value2 = _value2; \ + DES_xor2_16(0); \ +} +#else +#define DES_xor_key2(_value1, _value2) { \ + value1 = _value1; value2 = _value2; \ + DES_xor2_16(0); \ + DES_xor2_16(16); \ +} +#endif + +#else + +extern void DES_xor_key1(ARCH_WORD *value); +extern void DES_xor_key2(ARCH_WORD *value1, ARCH_WORD *value2); + +#endif + +void DES_raw_set_key(char *key) +{ + int i; + DES_KS *pos; +#if !DES_ASM + ARCH_WORD *value1; +#endif + + memcpy(DES_KS_current, + DES_KS_table[0][ARCH_INDEX(DES_key[0] = key[0] & 0x7F)], + sizeof(DES_KS)); + + pos = (DES_KS *)DES_KS_table[1][0]; + for (i = 1; i < 8; i++) { + DES_xor_key1(pos[ARCH_INDEX(DES_key[i] = key[i] & 0x7F)]); + pos += 128; + } +} + +void DES_std_set_key(char *key) +{ + int i, j, k, l; +#if !DES_ASM + ARCH_WORD *value1, *value2; +#endif + + j = key[0]; + for (k = i = 0; (l = DES_key[i]) && (j = key[i]); i++) + if (j != l) k += 3; + + if (j) { + while (i < 8 && key[i]) { + i++; k += 2; + } + j = i; + } else { + j = i; + while (DES_key[i++]) k += 2; + } + + if ((k < (j << 1)) && (++DES_KS_updates & 0xFFF)) { + j = 0; l = 1; + for (i = 0; i < 8 && (k = key[i]); i++) { + if (l) + if (k == (l = DES_key[j++])) continue; + + if (l) { + DES_xor_key2(DES_KS_table[i][l], + DES_KS_table[i][k & 0x7F]); + } else + DES_xor_key1(DES_KS_table[i][k & 0x7F]); + } + + if (l) + for (; j < 8 && (l = DES_key[j]); j++) + DES_xor_key1(DES_KS_table[j][l]); + } else { + memcpy(DES_KS_current, DES_KS_table[0][(k = key[0]) & 0x7F], + sizeof(DES_KS)); + + if (k) + for (i = 1; i < 8 && (k = key[i]); i++) + DES_xor_key1(DES_KS_table[i][k & 0x7F]); + } + + DES_key[0] = key[0] & 0x7F; + DES_key[1] = key[1] & 0x7F; + DES_key[2] = key[2] & 0x7F; + DES_key[3] = key[3] & 0x7F; + DES_key[4] = key[4] & 0x7F; + DES_key[5] = key[5] & 0x7F; + DES_key[6] = key[6] & 0x7F; + DES_key[7] = key[7] & 0x7F; +} + +void DES_std_set_block(ARCH_WORD R, ARCH_WORD L) +{ + ARCH_WORD Rl, Rh, Ll, Lh; + unsigned ARCH_WORD C; +#if ARCH_BITS >= 64 + ARCH_WORD mask; +#else + ARCH_WORD *mask; +#endif + int chunk; + + C = (R & 0xAAAAAAAA) | ((L & 0xAAAAAAAA) >> 1); + Rh = Rl = 0; + for (chunk = 0; chunk < 8; chunk++) { + mask = DES_IP_E[chunk][C & 0xF]; +#if ARCH_BITS >= 64 + Rl |= mask & 0xFFFFFFFF; + Rh |= mask >> 32; +#else + Rl |= mask[0]; + Rh |= mask[1]; +#endif + C >>= 4; + } + + C = ((R & 0x55555555) << 1) | (L & 0x55555555); + Lh = Ll = 0; + for (chunk = 0; chunk < 8; chunk++) { + mask = DES_IP_E[chunk][C & 0xF]; +#if ARCH_BITS >= 64 + Ll |= mask & 0xFFFFFFFF; + Lh |= mask >> 32; +#else + Ll |= mask[0]; + Lh |= mask[1]; +#endif + C >>= 4; + } + + Rl = DES_DO_SIZE_FIX(Rl); + Rh = DES_DO_SIZE_FIX(Rh); + Ll = DES_DO_SIZE_FIX(Ll); + Lh = DES_DO_SIZE_FIX(Lh); + +#if ARCH_BITS >= 64 + DES_IV[0] = Rl | (Rh << 32); + DES_IV[1] = Ll | (Lh << 32); +#else + DES_IV[0] = Rl; + DES_IV[1] = Rh; + DES_IV[2] = Ll; + DES_IV[3] = Lh; +#endif +} + +void DES_std_get_block(DES_binary binary, unsigned ARCH_WORD out[2]) +{ + ARCH_WORD Rl, Rh, Ll, Lh; + ARCH_WORD R, L; + unsigned ARCH_WORD C; +#if ARCH_BITS >= 64 + unsigned ARCH_WORD mask; +#else + ARCH_WORD *mask; +#endif + int chunk; + +#if ARCH_BITS >= 64 + Rl = binary[0]; + Rh = binary[0] >> 32; + Ll = binary[1]; + Lh = binary[1] >> 32; +#else + Rl = binary[0]; + Rh = binary[1]; + Ll = binary[2]; + Lh = binary[3]; +#endif + + Rl = DES_UNDO_SIZE_FIX(Rl); + Rh = DES_UNDO_SIZE_FIX(Rh); + Ll = DES_UNDO_SIZE_FIX(Ll); + Lh = DES_UNDO_SIZE_FIX(Lh); + + R = L = 0; + C = ((Ll >> 1) & 0x0F0F0F0F) | ((Lh << 3) & 0xF0F0F0F0); + for (chunk = 0; chunk < 16; chunk++) { + if (chunk == 8) + C = ((Rl >> 1) & 0x0F0F0F0F) | ((Rh << 3) & 0xF0F0F0F0); + mask = DES_C_FP[chunk][C & 0xF]; +#if ARCH_BITS >= 64 + R |= mask & 0xFFFFFFFF; + L |= mask >> 32; +#else + R |= mask[0]; + L |= mask[1]; +#endif + C >>= 4; + } + + out[0] = R; + out[1] = L; +} + +#if !DES_ASM + +#if !DES_MASK +#define DES_D (DES_tmp.w) +#if ARCH_LITTLE_ENDIAN +#define DES_Dl (DES_tmp.w[0]) +#define DES_Dh (DES_tmp.w[1]) +#define DES_B0 (DES_tmp.b[0]) +#define DES_B1 (DES_tmp.b[1]) +#define DES_B2 (DES_tmp.b[2]) +#define DES_B3 (DES_tmp.b[3]) +#define DES_B4 (DES_tmp.b[4]) +#define DES_B5 (DES_tmp.b[5]) +#define DES_B6 (DES_tmp.b[6]) +#define DES_B7 (DES_tmp.b[7]) +#else +#define DES_Dl (DES_tmp.w[1]) +#define DES_Dh (DES_tmp.w[0]) +#if ARCH_BITS > 64 +#define DES_START ARCH_SIZE +#else +#define DES_START 8 +#endif +#define DES_B0 (DES_tmp.b[DES_START - 1]) +#define DES_B1 (DES_tmp.b[DES_START - 2]) +#define DES_B2 (DES_tmp.b[DES_START - 3]) +#define DES_B3 (DES_tmp.b[DES_START - 4]) +#define DES_B4 (DES_tmp.b[DES_START - 5]) +#define DES_B5 (DES_tmp.b[DES_START - 6]) +#define DES_B6 (DES_tmp.b[DES_START - 7]) +#define DES_B7 (DES_tmp.b[DES_START - 8]) +#endif +#endif + +/* + * The code below is heavily optimized, looking at the assembly output for + * several architectures, enjoy the speed. + */ + +#if ARCH_BITS >= 64 +#if !DES_128K +/* + * An extra temporary register is used for better instruction scheduling. + */ +#if DES_MASK +#if DES_SCALE +/* 64-bit, 4K, mask, scale */ +#define DES_ROUND(L, H, B) \ + T = DES_INDEX(DES_SPE_F[0], DES_D & DES_MASK_6); \ + B ^= DES_INDEX(DES_SPE_F[1], (DES_D >> 8) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[2], (DES_D >> 16) & DES_MASK_6); \ + B ^= DES_INDEX(DES_SPE_F[3], (DES_D >> 24) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[4], (DES_D >> 32) & DES_MASK_6); \ + B ^= DES_INDEX(DES_SPE_F[5], (DES_D >> 40) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[6], (DES_D >> 48) & DES_MASK_6); \ + B ^= T ^ DES_INDEX(DES_SPE_F[7], DES_D >> 56); +#else +/* + * This code assumes that the indices are already shifted left by 2, and still + * should be shifted left by 1 more bit. Weird shift counts allow doing this + * with only one extra shift, in the first line. By shifting the mask right + * (which is done at compile time), I moved the extra shift out of the mask, + * which allows doing this with special addressing modes, where possible. + */ +/* 64-bit, 4K, mask, no scale */ +#define DES_ROUND(L, H, B) \ + T = DES_INDEX(DES_SPE_F[0], (DES_D & (DES_MASK_6 >> 1)) << 1); \ + B ^= DES_INDEX(DES_SPE_F[1], (DES_D >> 7) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[2], (DES_D >> 15) & DES_MASK_6); \ + B ^= DES_INDEX(DES_SPE_F[3], (DES_D >> 23) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[4], (DES_D >> 31) & DES_MASK_6); \ + B ^= DES_INDEX(DES_SPE_F[5], (DES_D >> 39) & DES_MASK_6); \ + T ^= DES_INDEX(DES_SPE_F[6], (DES_D >> 47) & DES_MASK_6); \ + B ^= T ^ DES_INDEX(DES_SPE_F[7], (DES_D >> 55) & DES_MASK_6); +#endif +#else +/* 64-bit, 4K, store/load, scale */ +#define DES_ROUND(L, H, B) \ + T = DES_INDEX(DES_SPE_F[0], DES_B0); \ + B ^= DES_INDEX(DES_SPE_F[1], DES_B1); \ + T ^= DES_INDEX(DES_SPE_F[2], DES_B2); \ + B ^= DES_INDEX(DES_SPE_F[3], DES_B3); \ + T ^= DES_INDEX(DES_SPE_F[4], DES_B4); \ + B ^= DES_INDEX(DES_SPE_F[5], DES_B5); \ + T ^= DES_INDEX(DES_SPE_F[6], DES_B6); \ + B ^= T ^ DES_INDEX(DES_SPE_F[7], DES_B7); +#endif +#else +/* 64-bit, 128K, mask, no scale */ +#define DES_ROUND(L, H, B) \ + B ^= DES_INDEX(DES_SPE_W[0], DES_D & 0xFFFF); \ + B ^= DES_INDEX(DES_SPE_W[1], (DES_D >>= 16) & 0xFFFF); \ + B ^= DES_INDEX(DES_SPE_W[2], (DES_D >>= 16) & 0xFFFF); \ + B ^= DES_INDEX(DES_SPE_W[3], DES_D >> 16); +#endif +#else +#if !DES_128K +#if DES_MASK +/* 32-bit, 4K, mask */ +#define DES_ROUND(L, H, B) \ + L ^= DES_INDEX(DES_SPE_L[0], DES_Dl & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[0], DES_Dl & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[1], (DES_Dl >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[1], DES_Dl & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[2], (DES_Dl >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[2], DES_Dl & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[3], (DES_Dl >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[3], DES_Dl & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[4], DES_Dh & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[4], DES_Dh & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[5], (DES_Dh >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[5], DES_Dh & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[6], (DES_Dh >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[6], DES_Dh & DES_MASK_6); \ + L ^= DES_INDEX(DES_SPE_L[7], (DES_Dh >>= 8) & DES_MASK_6); \ + H ^= DES_INDEX(DES_SPE_H[7], DES_Dh & DES_MASK_6); +#else +/* 32-bit, 4K, store/load */ +#define DES_ROUND(L, H, B) \ + L ^= DES_INDEX(DES_SPE_L[0], DES_B0); \ + H ^= DES_INDEX(DES_SPE_H[0], DES_B0); \ + L ^= DES_INDEX(DES_SPE_L[1], DES_B1); \ + H ^= DES_INDEX(DES_SPE_H[1], DES_B1); \ + L ^= DES_INDEX(DES_SPE_L[2], DES_B2); \ + H ^= DES_INDEX(DES_SPE_H[2], DES_B2); \ + L ^= DES_INDEX(DES_SPE_L[3], DES_B3); \ + H ^= DES_INDEX(DES_SPE_H[3], DES_B3); \ + L ^= DES_INDEX(DES_SPE_L[4], DES_B4); \ + H ^= DES_INDEX(DES_SPE_H[4], DES_B4); \ + L ^= DES_INDEX(DES_SPE_L[5], DES_B5); \ + H ^= DES_INDEX(DES_SPE_H[5], DES_B5); \ + L ^= DES_INDEX(DES_SPE_L[6], DES_B6); \ + H ^= DES_INDEX(DES_SPE_H[6], DES_B6); \ + L ^= DES_INDEX(DES_SPE_L[7], DES_B7); \ + H ^= DES_INDEX(DES_SPE_H[7], DES_B7); +#endif +#else +/* 32-bit, 128K, mask */ +#define DES_ROUND(L, H, B) \ + L ^= DES_INDEX_L(DES_SPE_W[0], DES_Dl & 0xFFFF); \ + H ^= DES_INDEX_H(DES_SPE_W[0], DES_Dl & 0xFFFF); \ + L ^= DES_INDEX_L(DES_SPE_W[1], DES_Dl >>= 16); \ + H ^= DES_INDEX_H(DES_SPE_W[1], DES_Dl); \ + L ^= DES_INDEX_L(DES_SPE_W[2], DES_Dh & 0xFFFF); \ + H ^= DES_INDEX_H(DES_SPE_W[2], DES_Dh & 0xFFFF); \ + L ^= DES_INDEX_L(DES_SPE_W[3], DES_Dh >>= 16); \ + H ^= DES_INDEX_H(DES_SPE_W[3], DES_Dh); +#endif +#endif + +#if ARCH_BITS >= 64 +#define DES_2_ROUNDS(KS) \ + DES_D = R ^ KS[0]; \ + DES_ROUND(Ll, Lh, L); \ + DES_D = L ^ KS[1]; \ + DES_ROUND(Rl, Rh, R); +#else +#define DES_2_ROUNDS(KS) \ + DES_Dl = Rl ^ KS[0]; \ + DES_Dh = Rh ^ KS[1]; \ + DES_ROUND(Ll, Lh, L); \ + DES_Dl = Ll ^ KS[2]; \ + DES_Dh = Lh ^ KS[3]; \ + DES_ROUND(Rl, Rh, R); +#endif + +#if DES_COPY +static void crypt_body(void) +#else +void DES_std_crypt(DES_KS KS, DES_binary DES_out) +#endif +{ +#if DES_MASK +#if ARCH_BITS >= 64 + unsigned ARCH_WORD DES_D; +#else + unsigned ARCH_WORD DES_Dl, DES_Dh; +#endif +#else + union { +#if ARCH_BITS >= 64 + ARCH_WORD w; +#else + ARCH_WORD w[2]; +#endif + unsigned char b[8]; + } DES_tmp; +#endif +#if ARCH_BITS >= 64 + ARCH_WORD R, L; +#if !DES_128K + ARCH_WORD T; +#endif +#else + ARCH_WORD Rl, Rh, Ll, Lh; +#endif + int count; + +#if ARCH_BITS >= 64 + R = DES_IV[0]; + L = DES_IV[1]; +#else + Rl = DES_IV[0]; + Rh = DES_IV[1]; + Ll = DES_IV[2]; + Lh = DES_IV[3]; +#endif + count = DES_count; + + do { + DES_2_ROUNDS(DES_KS_INDEX(0)); + DES_2_ROUNDS(DES_KS_INDEX(1)); + DES_2_ROUNDS(DES_KS_INDEX(2)); + DES_2_ROUNDS(DES_KS_INDEX(3)); + DES_2_ROUNDS(DES_KS_INDEX(4)); + DES_2_ROUNDS(DES_KS_INDEX(5)); + DES_2_ROUNDS(DES_KS_INDEX(6)); + DES_2_ROUNDS(DES_KS_INDEX(7)); + +#if ARCH_BITS >= 64 + L ^= R; + R ^= L; + L ^= R; +#else + Ll ^= Rl; + Lh ^= Rh; + Rl ^= Ll; + Rh ^= Lh; + Ll ^= Rl; + Lh ^= Rh; +#endif + } while (--count); + +#if ARCH_BITS >= 64 + DES_out[0] = R; + DES_out[1] = L; +#else + DES_out[0] = Rl; + DES_out[1] = Rh; + DES_out[2] = Ll; + DES_out[3] = Lh; +#endif +} + +#if DES_COPY +void DES_std_crypt(DES_KS KS, DES_binary out) +{ + memcpy(DES_KS_copy, KS, sizeof(DES_KS)); + DES_out = out; + + crypt_body(); +} +#endif + +#endif + +static unsigned char DES_atoi64[0x100] = { + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4 +}; + +ARCH_WORD DES_raw_get_salt(char *ciphertext) +{ + if (ciphertext[13]) return DES_atoi64[ARCH_INDEX(ciphertext[5])] | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[6])] << 6) | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[7])] << 12) | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[8])] << 18); + else return DES_atoi64[ARCH_INDEX(ciphertext[0])] | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[1])] << 6); +} + +ARCH_WORD DES_std_get_salt(char *ciphertext) +{ + unsigned int salt; + + salt = DES_raw_get_salt(ciphertext); + salt = DES_24_TO_32(salt); + return (ARCH_WORD)DES_DO_SIZE_FIX(salt); +} + +ARCH_WORD DES_raw_get_count(char *ciphertext) +{ + if (ciphertext[13]) return DES_atoi64[ARCH_INDEX(ciphertext[1])] | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[2])] << 6) | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[3])] << 12) | + ((ARCH_WORD)DES_atoi64[ARCH_INDEX(ciphertext[4])] << 18); + else return 25; +} + +ARCH_WORD *DES_do_IP(ARCH_WORD in[2]) +{ + static ARCH_WORD out[2]; + int src, dst; + + out[0] = out[1] = 0; + for (dst = 0; dst < 64; dst++) { + src = DES_IP[dst ^ 0x20]; + + if (in[src >> 5] & ((unsigned ARCH_WORD)1 << (src & 0x1F))) + out[dst >> 5] |= (unsigned ARCH_WORD)1 << (dst & 0x1F); + } + + return out; +} + +ARCH_WORD *DES_do_FP(ARCH_WORD in[2]) +{ + static ARCH_WORD out[2]; + int src, dst; + + out[0] = out[1] = 0; + for (src = 0; src < 64; src++) { + dst = DES_IP[src ^ 0x20]; + + if (in[src >> 5] & ((unsigned ARCH_WORD)1 << (src & 0x1F))) + out[dst >> 5] |= (unsigned ARCH_WORD)1 << (dst & 0x1F); + } + + return out; +} + +ARCH_WORD *DES_raw_get_binary(char *ciphertext) +{ + ARCH_WORD block[3]; + ARCH_WORD mask; + int ofs, chr, src, dst, value; + + if (ciphertext[13]) ofs = 9; else ofs = 2; + + block[0] = block[1] = 0; + dst = 0; + for (chr = 0; chr < 11; chr++) { + value = DES_atoi64[ARCH_INDEX(ciphertext[chr + ofs])]; + mask = 0x20; + + for (src = 0; src < 6; src++) { + if (value & mask) + block[dst >> 5] |= (unsigned ARCH_WORD)1 << (dst & 0x1F); + mask >>= 1; + dst++; + } + } + + return DES_do_IP(block); +} + +ARCH_WORD *DES_std_get_binary(char *ciphertext) +{ + static ARCH_WORD out[4]; + ARCH_WORD *raw; + ARCH_WORD salt, mask; + + raw = DES_raw_get_binary(ciphertext); + + out[0] = DES_16_TO_32(raw[0]); + out[1] = DES_16_TO_32(raw[0] >> 16); + out[2] = DES_16_TO_32(raw[1]); + out[3] = DES_16_TO_32(raw[1] >> 16); + + out[0] = DES_DO_SIZE_FIX(out[0]); + out[1] = DES_DO_SIZE_FIX(out[1]); + out[2] = DES_DO_SIZE_FIX(out[2]); + out[3] = DES_DO_SIZE_FIX(out[3]); + + salt = DES_std_get_salt(ciphertext); + + mask = (out[0] ^ out[1]) & salt; + out[0] ^= mask; + out[1] ^= mask; + + mask = (out[2] ^ out[3]) & salt; + out[2] ^= mask; + out[3] ^= mask; + +#if ARCH_BITS >= 64 + out[0] |= out[1] << 32; + out[1] = out[2] | (out[3] << 32); +#endif + + return out; +} diff --git a/src/DES_std.h b/src/DES_std.h new file mode 100644 index 0000000..f6613b5 --- /dev/null +++ b/src/DES_std.h @@ -0,0 +1,206 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * "Standard" (non-bitslice) DES implementation. + */ + +#ifndef _JOHN_DES_STD_H +#define _JOHN_DES_STD_H + +#include "arch.h" + +#if ARCH_BITS >= 64 +#define DES_SIZE 8 +#else +#define DES_SIZE 4 +#endif + +/* + * Various DES tables exported for use by other implementations. + */ +extern unsigned char DES_E[48]; +extern unsigned char DES_PC1[56]; +extern unsigned char DES_ROT[16]; +extern unsigned char DES_PC2[48]; + +/* + * Current key schedule. + */ +typedef ARCH_WORD DES_KS[128 / DES_SIZE]; +extern DES_KS DES_KS_current; + +/* + * Binary ciphertext type. + */ +typedef unsigned ARCH_WORD DES_binary[16 / DES_SIZE]; + +/* + * Initial value for DES_std_crypt(). + */ +extern DES_binary DES_IV; + +/* + * Number of iterations for DES_std_crypt(). + */ +extern ARCH_WORD DES_count; + +/* + * Some extra stuff has to be defined here to calculate DES_BINARY_MASK and + * define the hash functions. + */ +#if DES_128K +#define DES_SIZE_FIX 3 +#else +#if ARCH_BITS >= 64 +/* + * It is not possible to shift by 3 (no free bits), so we have to choose + * between 0 and 2. + */ +#if DES_SCALE +#define DES_SIZE_FIX 0 +#else +#define DES_SIZE_FIX 2 +#endif +#else +#define DES_SIZE_FIX 2 +#endif +#endif + +#if DES_128K +#define DES_DO_SIZE_FIX(x) \ + (((((x) << 2) & 0x00FF00FF) | ((x) & 0xFF00FF00)) << 1) +#else +#define DES_DO_SIZE_FIX(x) \ + ((x) << DES_SIZE_FIX) +#endif + +/* + * Masks used to extract data bits out of binary ciphertexts. + */ +#define DES_MASK_16 DES_DO_SIZE_FIX(0x1E1E1E1E) +#if ARCH_BITS >= 64 +#define DES_BINARY_MASK \ + (DES_MASK_16 | ((ARCH_WORD)DES_MASK_16 << 32)) +#else +#define DES_BINARY_MASK DES_MASK_16 +#endif + +/* + * Binary ciphertext hash functions. + */ +#define DES_STD_HASH_0(x) \ + (((x) >> (DES_SIZE_FIX + 1)) & 0xF) +#if DES_128K +#define DES_STD_HASH_1(x) \ + (DES_STD_HASH_0(x) | \ + (((x) >> (DES_SIZE_FIX + 3)) & 0xF0)) +#else +#define DES_STD_HASH_1(x) \ + (DES_STD_HASH_0(x) | \ + (((x) >> (DES_SIZE_FIX + 5)) & 0xF0)) +#endif +#define DES_STD_HASH_2(x) \ + (DES_STD_HASH_1(x) | \ + (((x) >> (DES_SIZE_FIX + 9)) & 0xF00)) + +#ifndef DES_STD_ALGORITHM_NAME +#if ARCH_BITS >= 64 +#define DES_STD_ALGORITHM_BITS "48/" ARCH_BITS_STR +#else +#define DES_STD_ALGORITHM_BITS "24/32" +#endif +#if DES_128K +#define DES_STD_ALGORITHM_SIZE "128K" +#else +#define DES_STD_ALGORITHM_SIZE "4K" +#endif +#define DES_STD_ALGORITHM_NAME \ + "DES " DES_STD_ALGORITHM_BITS " " DES_STD_ALGORITHM_SIZE +#endif + +/* + * Initializes the internal structures. + */ +extern void DES_std_init(void); + +/* + * Sets a salt for DES_std_crypt(). + */ +extern void DES_std_set_salt(ARCH_WORD salt); + +/* + * Sets a raw 8 character long key for DES_std_crypt(), in DES_KS_current. + */ +extern void DES_raw_set_key(char *key); + +/* + * Sets an ASCIIZ key for DES_std_crypt(), in DES_KS_current. + */ +extern void DES_std_set_key(char *key); + +/* + * Sets an initial value for DES_std_crypt(). + */ +extern void DES_std_set_block(ARCH_WORD R, ARCH_WORD L); + +/* + * Returns the encryption result. + */ +extern void DES_std_get_block(DES_binary binary, unsigned ARCH_WORD out[2]); + +/* + * Main encryption routine. + */ +#if CPU_DETECT && !CPU_REQ +extern void (*DES_std_crypt)(DES_KS KS, DES_binary out); +#else +extern void DES_std_crypt(DES_KS KS, DES_binary out); +#endif + +/* + * Returns the salt. + */ +extern ARCH_WORD DES_raw_get_salt(char *ciphertext); + +/* + * Returns the salt for DES_std_set_salt(). + */ +extern ARCH_WORD DES_std_get_salt(char *ciphertext); + +/* + * Returns the iteration count for DES_std_crypt(). + */ +extern ARCH_WORD DES_raw_get_count(char *ciphertext); + +/* + * Does the Initial Permutation; to be used at startup only (doesn't require + * that DES_std_init() has been called, is by far not as fast as it could be). + */ +extern ARCH_WORD *DES_do_IP(ARCH_WORD in[2]); + +/* + * Ditto for Final Permutation; to be used for reconstruction of source from + * binary ciphertext at startup and when a password is successfully cracked. + */ +extern ARCH_WORD *DES_do_FP(ARCH_WORD in[2]); + +/* + * Converts an ASCII ciphertext to binary. + */ +extern ARCH_WORD *DES_raw_get_binary(char *ciphertext); + +/* + * Converts an ASCII ciphertext to binary to be compared against + * DES_std_crypt() result. + */ +extern ARCH_WORD *DES_std_get_binary(char *ciphertext); + +#endif diff --git a/src/LM_fmt.c b/src/LM_fmt.c new file mode 100644 index 0000000..330af02 --- /dev/null +++ b/src/LM_fmt.c @@ -0,0 +1,254 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2010-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "memory.h" +#include "DES_bs.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "LM" +#define FORMAT_NAME "" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 7 +#define CIPHERTEXT_LENGTH 32 + +#define LM_EMPTY "aad3b435b51404ee" + +static struct fmt_tests tests[] = { + {"$LM$a9c604d244c4e99d", "AAAAAA"}, + {"$LM$cbc501a4d2227783", "AAAAAAA"}, + {"$LM$3466c2b0487fe39a", "CRACKPO"}, + {"$LM$dbc5e5cba8028091", "IMPUNIT"}, + {LM_EMPTY LM_EMPTY, ""}, + {"$LM$73cc402bd3e79175", "SCLEROS"}, + {"$LM$5ecd9236d21095ce", "YOKOHAM"}, + {"$LM$A5E6066DE61C3E35", "ZZZZZZZ"}, /* uppercase encoding */ + {"$LM$1FB363feB834C12D", "ZZZZZZ"}, /* mixed case encoding */ + {NULL} +}; + +#define ALGORITHM_NAME DES_BS_ALGORITHM_NAME + +#define BINARY_SIZE (sizeof(ARCH_WORD_32) * 2) +#define BINARY_ALIGN sizeof(ARCH_WORD_32) +#define SALT_SIZE 0 +#define SALT_ALIGN 1 + +#define MIN_KEYS_PER_CRYPT DES_BS_DEPTH +#define MAX_KEYS_PER_CRYPT DES_BS_DEPTH + +#if DES_bs_mt +struct fmt_main fmt_LM; +#endif + +static void init(struct fmt_main *self) +{ + DES_bs_init(1, DES_bs_cpt); +#if DES_bs_mt + fmt_LM.params.min_keys_per_crypt = DES_bs_min_kpc; + fmt_LM.params.max_keys_per_crypt = DES_bs_max_kpc; +#endif +} + +static char *prepare(char *fields[10], struct fmt_main *self) +{ + if (fields[2] && strlen(fields[2]) == 32) + return fields[2]; + return fields[1]; +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos; + char lower[CIPHERTEXT_LENGTH - 16 + 1]; + + for (pos = ciphertext; atoi16[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (!*pos && pos - ciphertext == CIPHERTEXT_LENGTH) { + strcpy(lower, &ciphertext[16]); + strlwr(lower); + if (strcmp(lower, LM_EMPTY)) + return 2; + else + return 1; + } + + if (strncmp(ciphertext, "$LM$", 4)) return 0; + + for (pos = &ciphertext[4]; atoi16[ARCH_INDEX(*pos)] != 0x7F; pos++); + if (*pos || pos - ciphertext != 20) return 0; + + return 1; +} + +static char *split(char *ciphertext, int index, struct fmt_main *self) +{ + static char out[21]; + +/* We don't just "return ciphertext" for already split hashes since we may + * need to convert hashes stored by older versions of John to all-lowercase. */ + if (!strncmp(ciphertext, "$LM$", 4)) + ciphertext += 4; + + out[0] = '$'; + out[1] = 'L'; + out[2] = 'M'; + out[3] = '$'; + + if (index) + memcpy(&out[4], &ciphertext[16], 16); + else + memcpy(&out[4], ciphertext, 16); + + out[20] = 0; + + strlwr(&out[4]); + + return out; +} + +static void *binary(char *ciphertext) +{ + return DES_bs_get_binary_LM(ciphertext + 4); +} + +static char *source(char *source, void *binary) +{ + return split(DES_bs_get_source_LM(binary), 0, NULL); +} + +static int binary_hash_0(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFF; +} + +static int binary_hash_3(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFF; +} + +static int binary_hash_4(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFF; +} + +static int binary_hash_5(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFFF; +} + +static int binary_hash_6(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0x7FFFFFF; +} + +static int cmp_one(void *binary, int index) +{ + return DES_bs_cmp_one((ARCH_WORD_32 *)binary, 64, index); +} + +static int cmp_exact(char *source, int index) +{ + return 1; +} + +static char *get_key(int index) +{ + static char out[8]; + unsigned char *src; + char *dst; + + init_t(); + + src = DES_bs_all.pxkeys[index]; + dst = out; + while (dst < &out[7] && (*dst = *src)) { + src += sizeof(DES_bs_vector) * 8; + dst++; + } + *dst = 0; + + return out; +} + +struct fmt_main fmt_LM = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if DES_bs_mt + FMT_OMP | FMT_OMP_BAD | +#endif + FMT_8_BIT | FMT_BS | FMT_SPLIT_UNIFIES_CASE, + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + prepare, + valid, + split, + binary, + fmt_default_salt, + source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + fmt_default_salt_hash, + fmt_default_set_salt, + DES_bs_set_key_LM, + get_key, + fmt_default_clear_keys, + DES_bs_crypt_LM, + { + DES_bs_get_hash_0, + DES_bs_get_hash_1, + DES_bs_get_hash_2, + DES_bs_get_hash_3, + DES_bs_get_hash_4, + DES_bs_get_hash_5, + DES_bs_get_hash_6 + }, + (int (*)(void *, int))DES_bs_cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/MD5_fmt.c b/src/MD5_fmt.c new file mode 100644 index 0000000..f6408b6 --- /dev/null +++ b/src/MD5_fmt.c @@ -0,0 +1,298 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2008,2010-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "MD5_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "md5crypt" +#define FORMAT_NAME "" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 15 +#define CIPHERTEXT_LENGTH 22 + +#define BINARY_SIZE 4 +#define BINARY_ALIGN 4 +#define SALT_SIZE 9 +#define SALT_ALIGN 1 + +#define MIN_KEYS_PER_CRYPT MD5_N +#define MAX_KEYS_PER_CRYPT MD5_N + +static struct fmt_tests tests[] = { + {"$1$12345678$aIccj83HRDBo6ux1bVx7D1", "0123456789ABCDE"}, + {"$apr1$Q6ZYh...$RV6ft2bZ8j.NGrxLYaJt9.", "test"}, + {"$1$12345678$f8QoJuo0DpBRfQSD0vglc1", "12345678"}, + {"$1$$qRPK7m23GJusamGpoGLby/", ""}, + {"$apr1$a2Jqm...$grFrwEgiQleDr0zR4Jx1b.", "15 chars is max"}, + {"$1$$AuJCr07mI7DSew03TmBIv/", "no salt"}, + {"$1$`!@#%^&*$E6hD76/pKTS8qToBCkux30", "invalid salt"}, + {"$1$12345678$xek.CpjQUVgdf/P2N9KQf/", ""}, + {"$1$1234$BdIMOAWFOV2AQlLsrN/Sw.", "1234"}, + {"$apr1$rBXqc...$NlXxN9myBOk95T0AyLAsJ0", "john"}, + {"$apr1$Grpld/..$qp5GyjwM2dnA5Cdej9b411", "the"}, + {"$apr1$GBx.D/..$yfVeeYFCIiEXInfRhBRpy/", "ripper"}, + {NULL} +}; + +static char (*saved_key)[PLAINTEXT_LENGTH + 1]; + +struct fmt_main fmt_MD5; + +static void init(struct fmt_main *self) +{ + MD5_std_init(); + +#if MD5_std_mt + fmt_MD5.params.min_keys_per_crypt = MD5_std_min_kpc; + fmt_MD5.params.max_keys_per_crypt = MD5_std_max_kpc; +#endif + + saved_key = mem_alloc_tiny( + sizeof(*saved_key) * fmt_MD5.params.max_keys_per_crypt, + MEM_ALIGN_CACHE); +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos, *start; + + if (strncmp(ciphertext, "$1$", 3)) { + if (strncmp(ciphertext, "$apr1$", 6)) + return 0; + ciphertext += 3; + } + + for (pos = &ciphertext[3]; *pos && *pos != '$'; pos++); + if (!*pos || pos < &ciphertext[3] || pos > &ciphertext[11]) return 0; + + start = ++pos; + while (atoi64[ARCH_INDEX(*pos)] != 0x7F) pos++; + if (*pos || pos - start != CIPHERTEXT_LENGTH) return 0; + + if (atoi64[ARCH_INDEX(*(pos - 1))] & 0x3C) return 0; + + return 1; +} + +static int binary_hash_0(void *binary) +{ + return *(MD5_word *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(MD5_word *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(MD5_word *)binary & 0xFFF; +} + +static int binary_hash_3(void *binary) +{ + return *(MD5_word *)binary & 0xFFFF; +} + +static int binary_hash_4(void *binary) +{ + return *(MD5_word *)binary & 0xFFFFF; +} + +static int binary_hash_5(void *binary) +{ + return *(MD5_word *)binary & 0xFFFFFF; +} + +static int binary_hash_6(void *binary) +{ + return *(MD5_word *)binary & 0x7FFFFFF; +} + +static int get_hash_0(int index) +{ + init_t(); + return MD5_out[index][0] & 0xF; +} + +static int get_hash_1(int index) +{ + init_t(); + return MD5_out[index][0] & 0xFF; +} + +static int get_hash_2(int index) +{ + init_t(); + return MD5_out[index][0] & 0xFFF; +} + +static int get_hash_3(int index) +{ + init_t(); + return MD5_out[index][0] & 0xFFFF; +} + +static int get_hash_4(int index) +{ + init_t(); + return MD5_out[index][0] & 0xFFFFF; +} + +static int get_hash_5(int index) +{ + init_t(); + return MD5_out[index][0] & 0xFFFFFF; +} + +static int get_hash_6(int index) +{ + init_t(); + return MD5_out[index][0] & 0x7FFFFFF; +} + +static int salt_hash(void *salt) +{ + unsigned int i, h, retval; + + retval = 0; + for (i = 0; i <= 6; i += 2) { + h = (unsigned char)atoi64[ARCH_INDEX(((char *)salt)[i])]; + h ^= ((unsigned char *)salt)[i + 1]; + h <<= 6; + h ^= (unsigned char)atoi64[ARCH_INDEX(((char *)salt)[i + 1])]; + h ^= ((unsigned char *)salt)[i]; + retval += h; + } + + retval ^= retval >> SALT_HASH_LOG; + retval &= SALT_HASH_SIZE - 1; + + return retval; +} + +static void set_key(char *key, int index) +{ + MD5_std_set_key(key, index); + + strnfcpy(saved_key[index], key, PLAINTEXT_LENGTH); +} + +static char *get_key(int index) +{ + saved_key[index][PLAINTEXT_LENGTH] = 0; + + return saved_key[index]; +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + MD5_std_crypt(count); + return count; +} + +static int cmp_all(void *binary, int count) +{ +#if MD5_std_mt + int t, n = (count + (MD5_N - 1)) / MD5_N; +#endif + for_each_t(n) { +#if MD5_X2 + if (*(MD5_word *)binary == MD5_out[0][0] || + *(MD5_word *)binary == MD5_out[1][0]) + return 1; +#else + if (*(MD5_word *)binary == MD5_out[0][0]) + return 1; +#endif + } + return 0; +} + +static int cmp_one(void *binary, int index) +{ + init_t(); + return *(MD5_word *)binary == MD5_out[index][0]; +} + +static int cmp_exact(char *source, int index) +{ + init_t(); + return !memcmp(MD5_std_get_binary(source), MD5_out[index], + sizeof(MD5_binary)); +} + +struct fmt_main fmt_MD5 = { + { + FORMAT_LABEL, + FORMAT_NAME, + MD5_ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if MD5_std_mt + FMT_OMP | +#endif + FMT_CASE | FMT_8_BIT, + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + (void *(*)(char *))MD5_std_get_binary, + (void *(*)(char *))MD5_std_get_salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + salt_hash, + (void (*)(void *))MD5_std_set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/MD5_std.c b/src/MD5_std.c new file mode 100644 index 0000000..4f0d6d6 --- /dev/null +++ b/src/MD5_std.c @@ -0,0 +1,1030 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2003,2006,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * This implementation of FreeBSD-style MD5-based crypt(3) password hashing + * supports passwords of up to 15 characters long only since this lets us use a + * significantly faster algorithm. -- SD + */ + +#include + +#include "arch.h" +#include "common.h" +#include "MD5_std.h" + +#if MD5_std_mt +#include +int MD5_std_min_kpc, MD5_std_max_kpc; +int MD5_std_nt; +MD5_std_combined *MD5_std_all_p = NULL; +static char saved_salt[9]; +static int salt_changed; +#else +MD5_std_combined CC_CACHE_ALIGN MD5_std_all; +#endif + +#if !MD5_IMM +static MD5_data MD5_data_init = { + { + 0xd76aa477, 0xf8fa0bcc, 0xbcdb4dd9, 0xb18b7a77, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }, { + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 + }, { + 0x77777777, 0x00ff00ff + } +}; +#endif + +#if !MD5_ASM + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#if MD5_IMM + +/* + * Using immediate values is good for CISC. + */ + +#define AC1 0xd76aa477 +#define AC2pCd 0xf8fa0bcc +#define AC3pCc 0xbcdb4dd9 +#define AC4pCb 0xb18b7a77 +#define AC5 0xf57c0faf +#define AC6 0x4787c62a +#define AC7 0xa8304613 +#define AC8 0xfd469501 +#define AC9 0x698098d8 +#define AC10 0x8b44f7af +#define AC11 0xffff5bb1 +#define AC12 0x895cd7be +#define AC13 0x6b901122 +#define AC14 0xfd987193 +#define AC15 0xa679438e +#define AC16 0x49b40821 +#define AC17 0xf61e2562 +#define AC18 0xc040b340 +#define AC19 0x265e5a51 +#define AC20 0xe9b6c7aa +#define AC21 0xd62f105d +#define AC22 0x02441453 +#define AC23 0xd8a1e681 +#define AC24 0xe7d3fbc8 +#define AC25 0x21e1cde6 +#define AC26 0xc33707d6 +#define AC27 0xf4d50d87 +#define AC28 0x455a14ed +#define AC29 0xa9e3e905 +#define AC30 0xfcefa3f8 +#define AC31 0x676f02d9 +#define AC32 0x8d2a4c8a +#define AC33 0xfffa3942 +#define AC34 0x8771f681 +#define AC35 0x6d9d6122 +#define AC36 0xfde5380c +#define AC37 0xa4beea44 +#define AC38 0x4bdecfa9 +#define AC39 0xf6bb4b60 +#define AC40 0xbebfbc70 +#define AC41 0x289b7ec6 +#define AC42 0xeaa127fa +#define AC43 0xd4ef3085 +#define AC44 0x04881d05 +#define AC45 0xd9d4d039 +#define AC46 0xe6db99e5 +#define AC47 0x1fa27cf8 +#define AC48 0xc4ac5665 +#define AC49 0xf4292244 +#define AC50 0x432aff97 +#define AC51 0xab9423a7 +#define AC52 0xfc93a039 +#define AC53 0x655b59c3 +#define AC54 0x8f0ccc92 +#define AC55 0xffeff47d +#define AC56 0x85845dd1 +#define AC57 0x6fa87e4f +#define AC58 0xfe2ce6e0 +#define AC59 0xa3014314 +#define AC60 0x4e0811a1 +#define AC61 0xf7537e82 +#define AC62 0xbd3af235 +#define AC63 0x2ad7d2bb +#define AC64 0xeb86d391 + +#define Ca 0x67452301 +#define Cb 0xefcdab89 +#define Cc 0x98badcfe +#define Cd 0x10325476 + +#define MASK1 0x77777777 + +#define OOFFOOFF 0x00ff00ff + +#else + +/* + * If we used immediate values on RISC with 32-bit instruction size, it would + * take about twice more instructions to load all the values. + */ + +#define MD5_AC MD5_std_all.data.AC +#define AC1 MD5_AC[0] +#define AC2pCd MD5_AC[1] +#define AC3pCc MD5_AC[2] +#define AC4pCb MD5_AC[3] +#define AC5 MD5_AC[4] +#define AC6 MD5_AC[5] +#define AC7 MD5_AC[6] +#define AC8 MD5_AC[7] +#define AC9 MD5_AC[8] +#define AC10 MD5_AC[9] +#define AC11 MD5_AC[10] +#define AC12 MD5_AC[11] +#define AC13 MD5_AC[12] +#define AC14 MD5_AC[13] +#define AC15 MD5_AC[14] +#define AC16 MD5_AC[15] +#define AC17 MD5_AC[16] +#define AC18 MD5_AC[17] +#define AC19 MD5_AC[18] +#define AC20 MD5_AC[19] +#define AC21 MD5_AC[20] +#define AC22 MD5_AC[21] +#define AC23 MD5_AC[22] +#define AC24 MD5_AC[23] +#define AC25 MD5_AC[24] +#define AC26 MD5_AC[25] +#define AC27 MD5_AC[26] +#define AC28 MD5_AC[27] +#define AC29 MD5_AC[28] +#define AC30 MD5_AC[29] +#define AC31 MD5_AC[30] +#define AC32 MD5_AC[31] +#define AC33 MD5_AC[32] +#define AC34 MD5_AC[33] +#define AC35 MD5_AC[34] +#define AC36 MD5_AC[35] +#define AC37 MD5_AC[36] +#define AC38 MD5_AC[37] +#define AC39 MD5_AC[38] +#define AC40 MD5_AC[39] +#define AC41 MD5_AC[40] +#define AC42 MD5_AC[41] +#define AC43 MD5_AC[42] +#define AC44 MD5_AC[43] +#define AC45 MD5_AC[44] +#define AC46 MD5_AC[45] +#define AC47 MD5_AC[46] +#define AC48 MD5_AC[47] +#define AC49 MD5_AC[48] +#define AC50 MD5_AC[49] +#define AC51 MD5_AC[50] +#define AC52 MD5_AC[51] +#define AC53 MD5_AC[52] +#define AC54 MD5_AC[53] +#define AC55 MD5_AC[54] +#define AC56 MD5_AC[55] +#define AC57 MD5_AC[56] +#define AC58 MD5_AC[57] +#define AC59 MD5_AC[58] +#define AC60 MD5_AC[59] +#define AC61 MD5_AC[60] +#define AC62 MD5_AC[61] +#define AC63 MD5_AC[62] +#define AC64 MD5_AC[63] + +#define MD5_IV MD5_std_all.data.IV +#define Ca MD5_IV[0] +#define Cb MD5_IV[1] +#define Cc MD5_IV[2] +#define Cd MD5_IV[3] + +#define MASK1 MD5_std_all.data.masks[0] + +#define OOFFOOFF MD5_std_all.data.masks[1] + +#endif + +/* + * F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) \ + (x) = (((x) << (n)) | ((MD5_word)(x) >> (32 - (n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ + +#define FF(a, b, c, d, x, s, ac) \ + (a) += F ((b), (c), (d)) + (x) + (ac); \ + ROTATE_LEFT ((a), (s)); \ + (a) += (b); + +#define GG(a, b, c, d, x, s, ac) \ + (a) += G ((b), (c), (d)) + (x) + (ac); \ + ROTATE_LEFT ((a), (s)); \ + (a) += (b); + +#define HH(a, b, c, d, x, s, ac) \ + (a) += H ((b), (c), (d)) + (x) + (ac); \ + ROTATE_LEFT ((a), (s)); \ + (a) += (b); + +#define II(a, b, c, d, x, s, ac) \ + (a) += I ((b), (c), (d)) + (x) + (ac); \ + ROTATE_LEFT ((a), (s)); \ + (a) += (b); + +#endif + +static unsigned char PADDING[56] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#if ARCH_LITTLE_ENDIAN + +#define MD5_swap(dst, src, count) + +#else + +#define MD5_swap(dst, src, count) \ +{ \ + MD5_word *dptr = (dst), *sptr = (src); \ + int loop_count = (count); \ + MD5_word mask = OOFFOOFF; \ + do { \ + MD5_word tmp = *sptr++; \ + ROTATE_LEFT(tmp, 16); \ + *dptr++ = ((tmp & mask) << 8) | ((tmp >> 8) & mask); \ + tmp = *sptr++; \ + ROTATE_LEFT(tmp, 16); \ + *dptr++ = ((tmp & mask) << 8) | ((tmp >> 8) & mask); \ + } while ((loop_count -= 2)); \ +} + +#endif + +#define order MD5_std_all._order +#define pool MD5_std_all._pool +#define block MD5_std_all._block +#define prefix MD5_std_all.prefix +#define prelen MD5_std_all.prelen + +void MD5_std_init(void) +{ + int index; + MD5_pool *current; +#if MD5_std_mt + int t, n; + + if (!MD5_std_all_p) { + n = omp_get_max_threads(); + if (n < 1) + n = 1; + if (n > MD5_std_mt_max) + n = MD5_std_mt_max; + MD5_std_min_kpc = n * MD5_N; + { + int max = n * MD5_std_cpt; + while (max > MD5_std_mt_max) + max -= n; + n = max; + } + MD5_std_max_kpc = n * MD5_N; +/* + * The array of MD5_std_all's is not exactly tiny, but we use mem_alloc_tiny() + * for its alignment support and error checking. We do not need to free() this + * memory anyway. + */ + MD5_std_all_p = mem_alloc_tiny(n * MD5_std_all_size, + MEM_ALIGN_PAGE); + MD5_std_nt = n; + } +#endif + + for_each_t(MD5_std_nt) { +#if !MD5_IMM + MD5_std_all.data = MD5_data_init; +#endif + + current = pool; + for (index = 0; index < MD5_N; index++) { +#define init_line(line, init_even, init_odd) \ + order[line][index].even = init_even; \ + order[line][index].odd = init_odd; + init_line(0, ¤t->e.p, ¤t->o.psp); + init_line(1, ¤t->e.spp, ¤t->o.pp); + init_line(2, ¤t->e.spp, ¤t->o.psp); + init_line(3, ¤t->e.pp, ¤t->o.ps); + init_line(4, ¤t->e.spp, ¤t->o.pp); + init_line(5, ¤t->e.spp, ¤t->o.psp); + init_line(6, ¤t->e.pp, ¤t->o.psp); + init_line(7, ¤t->e.sp, ¤t->o.pp); + init_line(8, ¤t->e.spp, ¤t->o.psp); + init_line(9, ¤t->e.pp, ¤t->o.psp); + init_line(10, ¤t->e.spp, ¤t->o.p); + init_line(11, ¤t->e.spp, ¤t->o.psp); + init_line(12, ¤t->e.pp, ¤t->o.psp); + init_line(13, ¤t->e.spp, ¤t->o.pp); + init_line(14, ¤t->e.sp, ¤t->o.psp); + init_line(15, ¤t->e.pp, ¤t->o.psp); + init_line(16, ¤t->e.spp, ¤t->o.pp); + init_line(17, ¤t->e.spp, ¤t->o.ps); + init_line(18, ¤t->e.pp, ¤t->o.psp); + init_line(19, ¤t->e.spp, ¤t->o.pp); + init_line(20, ¤t->e.spp, ¤t->o.psp); +#undef init_line + current++; + } + } +} + +#if MD5_std_mt +static MAYBE_INLINE void MD5_std_set_salt_for_thread(int t, char *salt) +#else +void MD5_std_set_salt(char *salt) +#endif +{ + int length; + + for (length = 0; length < 8 && salt[length]; length++); + + memcpy(pool[0].s, salt, pool[0].l.s = length); +#if MD5_X2 + memcpy(pool[1].s, salt, pool[1].l.s = length); +#endif + + if (salt[8]) { + prefix = "$apr1$"; + prelen = 6; + } else { + prefix = "$1$"; + prelen = 3; + } +} + +#if MD5_std_mt +void MD5_std_set_salt(char *salt) +{ + memcpy(saved_salt, salt, sizeof(saved_salt)); + salt_changed = 1; +} +#endif + +void MD5_std_set_key(char *key, int index) +{ + int length; + MD5_pool *current; + + init_t(); + + for (length = 0; key[length] && length < 15; length++); + current = &pool[index]; + + memcpy(current->o.p.b, key, current->l.p = length); + memcpy(¤t->o.p.b[length + 16], PADDING, 40 - length); + current->o.p.w[14] = (length + 16) << 3; + + memcpy(current->o.pp.b, key, length); + memcpy(¤t->o.pp.b[length], key, length); + current->l.pp = length << 1; + memcpy(¤t->o.pp.b[current->l.pp + 16], PADDING, + 40 - current->l.pp); + current->o.pp.w[14] = (current->l.pp + 16) << 3; + + memcpy(¤t->e.p.b[16], key, length); + memcpy(¤t->e.p.b[16 + length], PADDING, 40 - length); + current->e.p.w[14] = (length + 16) << 3; + MD5_swap(current->e.p.w, current->e.p.w, 14); + + memcpy(¤t->e.pp.b[16], current->o.pp.b, current->l.pp); + memcpy(¤t->e.pp.b[16 + current->l.pp], PADDING, + 40 - current->l.pp); + current->e.pp.w[14] = (current->l.pp + 16) << 3; + MD5_swap(current->e.pp.w, current->e.pp.w, 14); + + order[1][index].length = current->l.pp; + order[4][index].length = current->l.pp; + order[7][index].length = current->l.pp; + order[10][index].length = length; + order[13][index].length = current->l.pp; + order[16][index].length = current->l.pp; + order[19][index].length = current->l.pp; +} + +#if MD5_ASM +extern void MD5_body(MD5_word x[15], MD5_word out[4]); +#else + +/* + * x86-64 implies a fairly recent CPU, so presumably its L1 instruction cache + * is large enough. + */ +#ifdef __x86_64__ +#define MAYBE_INLINE_BODY MAYBE_INLINE +#else +#define MAYBE_INLINE_BODY +#endif + +#if !MD5_X2 + +#if MD5_std_mt +#define MD5_body(x, out) \ + MD5_body_for_thread(t, x, out) +static MAYBE_INLINE_BODY void MD5_body_for_thread(int t, + MD5_word x[15], MD5_word out[4]) +#else +static MAYBE_INLINE_BODY void MD5_body(MD5_word x[15], MD5_word out[4]) +#endif +{ + MD5_word a, b = Cb, c = Cc, d; + +/* Round 1 */ + a = AC1 + x[0]; + ROTATE_LEFT (a, S11); a += b; /* 1 */ + d = (c ^ (a & MASK1)) + x[1] + AC2pCd; + ROTATE_LEFT (d, S12); d += a; /* 2 */ + c = F(d, a, b) + x[2] + AC3pCc; + ROTATE_LEFT(c, S13); c += d; /* 3 */ + b = F(c, d, a) + x[3] + AC4pCb; + ROTATE_LEFT(b, S14); b += c; /* 4 */ + FF (a, b, c, d, x[ 4], S11, AC5); /* 5 */ + FF (d, a, b, c, x[ 5], S12, AC6); /* 6 */ + FF (c, d, a, b, x[ 6], S13, AC7); /* 7 */ + FF (b, c, d, a, x[ 7], S14, AC8); /* 8 */ + FF (a, b, c, d, x[ 8], S11, AC9); /* 9 */ + FF (d, a, b, c, x[ 9], S12, AC10); /* 10 */ + FF (c, d, a, b, x[10], S13, AC11); /* 11 */ + FF (b, c, d, a, x[11], S14, AC12); /* 12 */ + FF (a, b, c, d, x[12], S11, AC13); /* 13 */ + FF (d, a, b, c, x[13], S12, AC14); /* 14 */ + FF (c, d, a, b, x[14], S13, AC15); /* 15 */ + b += F (c, d, a) + AC16; + ROTATE_LEFT (b, S14); b += c; /* 16 */ + +/* Round 2 */ + GG (a, b, c, d, x[ 1], S21, AC17); /* 17 */ + GG (d, a, b, c, x[ 6], S22, AC18); /* 18 */ + GG (c, d, a, b, x[11], S23, AC19); /* 19 */ + GG (b, c, d, a, x[ 0], S24, AC20); /* 20 */ + GG (a, b, c, d, x[ 5], S21, AC21); /* 21 */ + GG (d, a, b, c, x[10], S22, AC22); /* 22 */ + c += G (d, a, b) + AC23; + ROTATE_LEFT (c, S23); c += d; /* 23 */ + GG (b, c, d, a, x[ 4], S24, AC24); /* 24 */ + GG (a, b, c, d, x[ 9], S21, AC25); /* 25 */ + GG (d, a, b, c, x[14], S22, AC26); /* 26 */ + GG (c, d, a, b, x[ 3], S23, AC27); /* 27 */ + GG (b, c, d, a, x[ 8], S24, AC28); /* 28 */ + GG (a, b, c, d, x[13], S21, AC29); /* 29 */ + GG (d, a, b, c, x[ 2], S22, AC30); /* 30 */ + GG (c, d, a, b, x[ 7], S23, AC31); /* 31 */ + GG (b, c, d, a, x[12], S24, AC32); /* 32 */ + +/* Round 3 */ + HH (a, b, c, d, x[ 5], S31, AC33); /* 33 */ + HH (d, a, b, c, x[ 8], S32, AC34); /* 34 */ + HH (c, d, a, b, x[11], S33, AC35); /* 35 */ + HH (b, c, d, a, x[14], S34, AC36); /* 36 */ + HH (a, b, c, d, x[ 1], S31, AC37); /* 37 */ + HH (d, a, b, c, x[ 4], S32, AC38); /* 38 */ + HH (c, d, a, b, x[ 7], S33, AC39); /* 39 */ + HH (b, c, d, a, x[10], S34, AC40); /* 40 */ + HH (a, b, c, d, x[13], S31, AC41); /* 41 */ + HH (d, a, b, c, x[ 0], S32, AC42); /* 42 */ + HH (c, d, a, b, x[ 3], S33, AC43); /* 43 */ + HH (b, c, d, a, x[ 6], S34, AC44); /* 44 */ + HH (a, b, c, d, x[ 9], S31, AC45); /* 45 */ + HH (d, a, b, c, x[12], S32, AC46); /* 46 */ + c += H (d, a, b) + AC47; + ROTATE_LEFT (c, S33); c += d; /* 47 */ + HH (b, c, d, a, x[ 2], S34, AC48); /* 48 */ + +/* Round 4 */ + II (a, b, c, d, x[ 0], S41, AC49); /* 49 */ + II (d, a, b, c, x[ 7], S42, AC50); /* 50 */ + II (c, d, a, b, x[14], S43, AC51); /* 51 */ + II (b, c, d, a, x[ 5], S44, AC52); /* 52 */ + II (a, b, c, d, x[12], S41, AC53); /* 53 */ + II (d, a, b, c, x[ 3], S42, AC54); /* 54 */ + II (c, d, a, b, x[10], S43, AC55); /* 55 */ + II (b, c, d, a, x[ 1], S44, AC56); /* 56 */ + II (a, b, c, d, x[ 8], S41, AC57); /* 57 */ + d += I (a, b, c) + AC58; + ROTATE_LEFT (d, S42); d += a; /* 58 */ + II (c, d, a, b, x[ 6], S43, AC59); /* 59 */ + II (b, c, d, a, x[13], S44, AC60); /* 60 */ + II (a, b, c, d, x[ 4], S41, AC61); /* 61 */ + II (d, a, b, c, x[11], S42, AC62); /* 62 */ + II (c, d, a, b, x[ 2], S43, AC63); /* 63 */ + II (b, c, d, a, x[ 9], S44, AC64); /* 64 */ + + out[0] = Ca + a; + out[1] = Cb + b; + out[2] = Cc + c; + out[3] = Cd + d; +} + +#else + +#if MD5_std_mt +#define MD5_body(x0, x1, out0, out1) \ + MD5_body_for_thread(t, x0, x1, out0, out1) +static MAYBE_INLINE_BODY void MD5_body_for_thread(int t, + MD5_word x0[15], MD5_word x1[15], + MD5_word out0[4], MD5_word out1[4]) +#else +static MAYBE_INLINE_BODY void MD5_body(MD5_word x0[15], MD5_word x1[15], + MD5_word out0[4], MD5_word out1[4]) +#endif +{ + MD5_word a0, b0 = Cb, c0 = Cc, d0; + MD5_word a1, b1, c1, d1; + MD5_word u, v; + +/* Round 1 */ + a0 = (u = AC1) + x0[0]; + ROTATE_LEFT (a0, S11); a0 += b0; /* 1 */ + a1 = u + x1[0]; + ROTATE_LEFT (a1, S11); a1 += b0; /* 1 */ + d0 = (c0 ^ (a0 & (u = MASK1))) + x0[1] + (v = AC2pCd); + ROTATE_LEFT (d0, S12); d0 += a0; /* 2 */ + d1 = (c0 ^ (a1 & u)) + x1[1] + v; + ROTATE_LEFT (d1, S12); d1 += a1; /* 2 */ + c0 = F(d0, a0, b0) + x0[2] + (u = AC3pCc); + ROTATE_LEFT(c0, S13); c0 += d0; /* 3 */ + c1 = F(d1, a1, b0) + x1[2] + u; + ROTATE_LEFT(c1, S13); c1 += d1; /* 3 */ + b0 = F(c0, d0, a0) + x0[3] + (u = AC4pCb); + ROTATE_LEFT(b0, S14); b0 += c0; /* 4 */ + b1 = F(c1, d1, a1) + x1[3] + u; + ROTATE_LEFT(b1, S14); b1 += c1; /* 4 */ + FF (a0, b0, c0, d0, x0[ 4], S11, (u = AC5)); /* 5 */ + FF (a1, b1, c1, d1, x1[ 4], S11, u); /* 5 */ + FF (d0, a0, b0, c0, x0[ 5], S12, (u = AC6)); /* 6 */ + FF (d1, a1, b1, c1, x1[ 5], S12, u); /* 6 */ + FF (c0, d0, a0, b0, x0[ 6], S13, (u = AC7)); /* 7 */ + FF (c1, d1, a1, b1, x1[ 6], S13, u); /* 7 */ + FF (b0, c0, d0, a0, x0[ 7], S14, (u = AC8)); /* 8 */ + FF (b1, c1, d1, a1, x1[ 7], S14, u); /* 8 */ + FF (a0, b0, c0, d0, x0[ 8], S11, (u = AC9)); /* 9 */ + FF (a1, b1, c1, d1, x1[ 8], S11, u); /* 9 */ + FF (d0, a0, b0, c0, x0[ 9], S12, (u = AC10)); /* 10 */ + FF (d1, a1, b1, c1, x1[ 9], S12, u); /* 10 */ + FF (c0, d0, a0, b0, x0[10], S13, (u = AC11)); /* 11 */ + FF (c1, d1, a1, b1, x1[10], S13, u); /* 11 */ + FF (b0, c0, d0, a0, x0[11], S14, (u = AC12)); /* 12 */ + FF (b1, c1, d1, a1, x1[11], S14, u); /* 12 */ + FF (a0, b0, c0, d0, x0[12], S11, (u = AC13)); /* 13 */ + FF (a1, b1, c1, d1, x1[12], S11, u); /* 13 */ + FF (d0, a0, b0, c0, x0[13], S12, (u = AC14)); /* 14 */ + FF (d1, a1, b1, c1, x1[13], S12, u); /* 14 */ + FF (c0, d0, a0, b0, x0[14], S13, (u = AC15)); /* 15 */ + FF (c1, d1, a1, b1, x1[14], S13, u); /* 15 */ + b0 += F (c0, d0, a0) + (u = AC16); + ROTATE_LEFT (b0, S14); b0 += c0; /* 16 */ + b1 += F (c1, d1, a1) + u; + ROTATE_LEFT (b1, S14); b1 += c1; /* 16 */ + +/* Round 2 */ + GG (a0, b0, c0, d0, x0[ 1], S21, (u = AC17)); /* 17 */ + GG (a1, b1, c1, d1, x1[ 1], S21, u); /* 17 */ + GG (d0, a0, b0, c0, x0[ 6], S22, (u = AC18)); /* 18 */ + GG (d1, a1, b1, c1, x1[ 6], S22, u); /* 18 */ + GG (c0, d0, a0, b0, x0[11], S23, (u = AC19)); /* 19 */ + GG (c1, d1, a1, b1, x1[11], S23, u); /* 19 */ + GG (b0, c0, d0, a0, x0[ 0], S24, (u = AC20)); /* 20 */ + GG (b1, c1, d1, a1, x1[ 0], S24, u); /* 20 */ + GG (a0, b0, c0, d0, x0[ 5], S21, (u = AC21)); /* 21 */ + GG (a1, b1, c1, d1, x1[ 5], S21, u); /* 21 */ + GG (d0, a0, b0, c0, x0[10], S22, (u = AC22)); /* 22 */ + GG (d1, a1, b1, c1, x1[10], S22, u); /* 22 */ + c0 += G (d0, a0, b0) + (u = AC23); + ROTATE_LEFT (c0, S23); c0 += d0; /* 23 */ + c1 += G (d1, a1, b1) + u; + ROTATE_LEFT (c1, S23); c1 += d1; /* 23 */ + GG (b0, c0, d0, a0, x0[ 4], S24, (u = AC24)); /* 24 */ + GG (b1, c1, d1, a1, x1[ 4], S24, u); /* 24 */ + GG (a0, b0, c0, d0, x0[ 9], S21, (u = AC25)); /* 25 */ + GG (a1, b1, c1, d1, x1[ 9], S21, u); /* 25 */ + GG (d0, a0, b0, c0, x0[14], S22, (u = AC26)); /* 26 */ + GG (d1, a1, b1, c1, x1[14], S22, u); /* 26 */ + GG (c0, d0, a0, b0, x0[ 3], S23, (u = AC27)); /* 27 */ + GG (c1, d1, a1, b1, x1[ 3], S23, u); /* 27 */ + GG (b0, c0, d0, a0, x0[ 8], S24, (u = AC28)); /* 28 */ + GG (b1, c1, d1, a1, x1[ 8], S24, u); /* 28 */ + GG (a0, b0, c0, d0, x0[13], S21, (u = AC29)); /* 29 */ + GG (a1, b1, c1, d1, x1[13], S21, u); /* 29 */ + GG (d0, a0, b0, c0, x0[ 2], S22, (u = AC30)); /* 30 */ + GG (d1, a1, b1, c1, x1[ 2], S22, u); /* 30 */ + GG (c0, d0, a0, b0, x0[ 7], S23, (u = AC31)); /* 31 */ + GG (c1, d1, a1, b1, x1[ 7], S23, u); /* 31 */ + GG (b0, c0, d0, a0, x0[12], S24, (u = AC32)); /* 32 */ + GG (b1, c1, d1, a1, x1[12], S24, u); /* 32 */ + +/* Round 3 */ + HH (a0, b0, c0, d0, x0[ 5], S31, (u = AC33)); /* 33 */ + HH (a1, b1, c1, d1, x1[ 5], S31, u); /* 33 */ + HH (d0, a0, b0, c0, x0[ 8], S32, (u = AC34)); /* 34 */ + HH (d1, a1, b1, c1, x1[ 8], S32, u); /* 34 */ + HH (c0, d0, a0, b0, x0[11], S33, (u = AC35)); /* 35 */ + HH (c1, d1, a1, b1, x1[11], S33, u); /* 35 */ + HH (b0, c0, d0, a0, x0[14], S34, (u = AC36)); /* 36 */ + HH (b1, c1, d1, a1, x1[14], S34, u); /* 36 */ + HH (a0, b0, c0, d0, x0[ 1], S31, (u = AC37)); /* 37 */ + HH (a1, b1, c1, d1, x1[ 1], S31, u); /* 37 */ + HH (d0, a0, b0, c0, x0[ 4], S32, (u = AC38)); /* 38 */ + HH (d1, a1, b1, c1, x1[ 4], S32, u); /* 38 */ + HH (c0, d0, a0, b0, x0[ 7], S33, (u = AC39)); /* 39 */ + HH (c1, d1, a1, b1, x1[ 7], S33, u); /* 39 */ + HH (b0, c0, d0, a0, x0[10], S34, (u = AC40)); /* 40 */ + HH (b1, c1, d1, a1, x1[10], S34, u); /* 40 */ + HH (a0, b0, c0, d0, x0[13], S31, (u = AC41)); /* 41 */ + HH (a1, b1, c1, d1, x1[13], S31, u); /* 41 */ + HH (d0, a0, b0, c0, x0[ 0], S32, (u = AC42)); /* 42 */ + HH (d1, a1, b1, c1, x1[ 0], S32, u); /* 42 */ + HH (c0, d0, a0, b0, x0[ 3], S33, (u = AC43)); /* 43 */ + HH (c1, d1, a1, b1, x1[ 3], S33, u); /* 43 */ + HH (b0, c0, d0, a0, x0[ 6], S34, (u = AC44)); /* 44 */ + HH (b1, c1, d1, a1, x1[ 6], S34, u); /* 44 */ + HH (a0, b0, c0, d0, x0[ 9], S31, (u = AC45)); /* 45 */ + HH (a1, b1, c1, d1, x1[ 9], S31, u); /* 45 */ + HH (d0, a0, b0, c0, x0[12], S32, (u = AC46)); /* 46 */ + HH (d1, a1, b1, c1, x1[12], S32, u); /* 46 */ + c0 += H (d0, a0, b0) + (u = AC47); + ROTATE_LEFT (c0, S33); c0 += d0; /* 47 */ + c1 += H (d1, a1, b1) + u; + ROTATE_LEFT (c1, S33); c1 += d1; /* 47 */ + HH (b0, c0, d0, a0, x0[ 2], S34, (u = AC48)); /* 48 */ + HH (b1, c1, d1, a1, x1[ 2], S34, u); /* 48 */ + +/* Round 4 */ + II (a0, b0, c0, d0, x0[ 0], S41, (u = AC49)); /* 49 */ + II (a1, b1, c1, d1, x1[ 0], S41, u); /* 49 */ + II (d0, a0, b0, c0, x0[ 7], S42, (u = AC50)); /* 50 */ + II (d1, a1, b1, c1, x1[ 7], S42, u); /* 50 */ + II (c0, d0, a0, b0, x0[14], S43, (u = AC51)); /* 51 */ + II (c1, d1, a1, b1, x1[14], S43, u); /* 51 */ + II (b0, c0, d0, a0, x0[ 5], S44, (u = AC52)); /* 52 */ + II (b1, c1, d1, a1, x1[ 5], S44, u); /* 52 */ + II (a0, b0, c0, d0, x0[12], S41, (u = AC53)); /* 53 */ + II (a1, b1, c1, d1, x1[12], S41, u); /* 53 */ + II (d0, a0, b0, c0, x0[ 3], S42, (u = AC54)); /* 54 */ + II (d1, a1, b1, c1, x1[ 3], S42, u); /* 54 */ + II (c0, d0, a0, b0, x0[10], S43, (u = AC55)); /* 55 */ + II (c1, d1, a1, b1, x1[10], S43, u); /* 55 */ + II (b0, c0, d0, a0, x0[ 1], S44, (u = AC56)); /* 56 */ + II (b1, c1, d1, a1, x1[ 1], S44, u); /* 56 */ + II (a0, b0, c0, d0, x0[ 8], S41, (u = AC57)); /* 57 */ + II (a1, b1, c1, d1, x1[ 8], S41, u); /* 57 */ + d0 += I (a0, b0, c0) + (u = AC58); + ROTATE_LEFT (d0, S42); d0 += a0; /* 58 */ + d1 += I (a1, b1, c1) + u; + ROTATE_LEFT (d1, S42); d1 += a1; /* 58 */ + II (c0, d0, a0, b0, x0[ 6], S43, (u = AC59)); /* 59 */ + II (c1, d1, a1, b1, x1[ 6], S43, u); /* 59 */ + II (b0, c0, d0, a0, x0[13], S44, (u = AC60)); /* 60 */ + II (b1, c1, d1, a1, x1[13], S44, u); /* 60 */ + II (a0, b0, c0, d0, x0[ 4], S41, (u = AC61)); /* 61 */ + II (a1, b1, c1, d1, x1[ 4], S41, u); /* 61 */ + II (d0, a0, b0, c0, x0[11], S42, (u = AC62)); /* 62 */ + II (d1, a1, b1, c1, x1[11], S42, u); /* 62 */ + II (c0, d0, a0, b0, x0[ 2], S43, (u = AC63)); /* 63 */ + II (c1, d1, a1, b1, x1[ 2], S43, u); /* 63 */ + II (b0, c0, d0, a0, x0[ 9], S44, (u = AC64)); /* 64 */ + II (b1, c1, d1, a1, x1[ 9], S44, u); /* 64 */ + + out1[3] = Cd + d1; + + out0[0] = Ca + a0; + out0[1] = Cb + b0; + out0[2] = Cc + c0; + out0[3] = Cd + d0; + + out1[0] = Ca + a1; + out1[1] = Cb + b1; + out1[2] = Cc + c1; +} + +#endif + +#endif + +#if MD5_std_mt +static MAYBE_INLINE void MD5_std_crypt_for_thread(int t) +#else +void MD5_std_crypt(int count) +#endif +{ + int length, index, mask; + MD5_pattern *line; +#if ARCH_LITTLE_ENDIAN + MD5_word *last0; +#endif +#if MD5_X2 + MD5_pool *key; +#if ARCH_LITTLE_ENDIAN + MD5_word *last1; +#endif +#endif + +#if MD5_X2 + for (index = 0, key = pool; index < MD5_N; index++, key++) { +#else +#define index 0 +#define key pool +#endif + memcpy(key->o.ps.b, key->o.p.b, key->l.p); + memcpy(&key->o.ps.b[key->l.p], key->s, key->l.s); + key->l.ps = key->l.p + key->l.s; + memcpy(&key->o.ps.b[key->l.ps + 16], PADDING, + 40 - key->l.ps); + key->o.ps.w[14] = (key->l.ps + 16) << 3; + + memcpy(key->o.psp.b, key->o.ps.b, key->l.ps); + memcpy(&key->o.psp.b[key->l.ps], key->o.p.b, key->l.p); + key->l.psp = key->l.ps + key->l.p; + memcpy(&key->o.psp.b[key->l.psp + 16], PADDING, + 40 - key->l.psp); + key->o.psp.w[14] = (key->l.psp + 16) << 3; + + memcpy(&key->e.sp.b[16], key->s, key->l.s); + memcpy(&key->e.sp.b[16 + key->l.s], key->o.p.b, + key->l.p); + memcpy(&key->e.sp.b[16 + key->l.ps], PADDING, + 40 - key->l.ps); + key->e.sp.w[14] = (key->l.ps + 16) << 3; + MD5_swap(key->e.sp.w, key->e.sp.w, 14); + + memcpy(&key->e.spp.b[16], key->s, key->l.s); + memcpy(&key->e.spp.b[16 + key->l.s], key->o.pp.b, + key->l.pp); + memcpy(&key->e.spp.b[16 + key->l.psp], PADDING, + 40 - key->l.psp); + key->e.spp.w[14] = (key->l.psp + 16) << 3; + MD5_swap(key->e.spp.w, key->e.spp.w, 14); + + order[0][index].length = key->l.psp; + order[2][index].length = key->l.psp; + order[3][index].length = key->l.ps; + order[5][index].length = key->l.psp; + order[6][index].length = key->l.psp; + order[8][index].length = key->l.psp; + order[9][index].length = key->l.psp; + order[11][index].length = key->l.psp; + order[12][index].length = key->l.psp; + order[14][index].length = key->l.psp; + order[15][index].length = key->l.psp; + order[17][index].length = key->l.ps; + order[18][index].length = key->l.psp; + order[20][index].length = key->l.psp; + + memcpy(&block[index], key->o.psp.b, key->l.psp); + memcpy(&block[index].b[key->l.psp], PADDING, 56 - key->l.psp); + block[index].w[14] = key->l.psp << 3; + MD5_swap(block[index].w, block[index].w, 14); +#if MD5_X2 + } + + MD5_body(block[0].w, block[1].w, MD5_out[0], MD5_out[1]); + MD5_swap(MD5_out[0], MD5_out[0], 8); +#else + MD5_body(block[0].w, MD5_out[0]); + MD5_swap(MD5_out[0], MD5_out[0], 4); +#endif + +#if MD5_X2 + for (index = 0, key = pool; index < MD5_N; index++, key++) { +#endif + memcpy(&block[index], key->o.p.b, key->l.p); + memcpy(&block[index].b[key->l.p], prefix, prelen); + memcpy(&block[index].b[key->l.p + prelen], key->s, key->l.s); + memcpy(&block[index].b[key->l.ps + prelen], + MD5_out[index], key->l.p); + length = key->l.psp + prelen; + if ((mask = key->l.p)) + do { + block[index].b[length++] = + (mask & 1) ? 0 : key->o.p.b[0]; + } while (mask >>= 1); + memcpy(&block[index].b[length], PADDING, 56 - length); + block[index].w[14] = length << 3; + MD5_swap(block[index].w, block[index].w, 14); +#if MD5_X2 + } +#else +#undef index +#undef key +#endif + +#if MD5_X2 + MD5_body(block[0].w, block[1].w, + order[0][0].even->w, order[0][1].even->w); +#else + MD5_body(block[0].w, order[0][0].even->w); +#endif + + index = 500; line = order[0]; + do { +#if ARCH_LITTLE_ENDIAN +#if ARCH_ALLOWS_UNALIGNED +#if MD5_X2 + MD5_body(line[0].even->w, line[1].even->w, + (MD5_word *)&line[0].odd->b[line[0].length], + (MD5_word *)&line[1].odd->b[line[1].length]); +#else + MD5_body(line[0].even->w, + (MD5_word *)&line[0].odd->b[line[0].length]); +#endif +#else +#if MD5_X2 + MD5_body(line[0].even->w, line[1].even->w, + MD5_out[0], MD5_out[1]); + memcpy(&line[0].odd->b[line[0].length], MD5_out[0], 16); + memcpy(&line[1].odd->b[line[1].length], MD5_out[1], 16); +#else + if (((ARCH_WORD)&line[0].odd->b[line[0].length]) & 3) { + MD5_body(line[0].even->w, MD5_out[0]); + memcpy(&line[0].odd->b[line[0].length], + MD5_out[0], 16); + } else { + MD5_body(line[0].even->w, + (MD5_word *)&line[0].odd->b[line[0].length]); + } +#endif +#endif + last0 = line[0].odd->w; +#if MD5_X2 + last1 = line[1].odd->w; + if ((line += 2) > &order[20][MD5_N - 1]) line = order[0]; + MD5_body(last0, last1, line[0].even->w, line[1].even->w); +#else + if (++line > &order[20][0]) line = order[0]; + MD5_body(last0, line[0].even->w); +#endif +#else +#if MD5_X2 + MD5_body(line[0].even->w, line[1].even->w, + MD5_out[0], MD5_out[1]); + MD5_swap(MD5_out[0], MD5_out[0], 8); +#else + MD5_body(line[0].even->w, MD5_out[0]); + MD5_swap(MD5_out[0], MD5_out[0], 4); +#endif + memcpy(&line[0].odd->b[line[0].length], MD5_out[0], 16); +#if MD5_X2 + memcpy(&line[1].odd->b[line[1].length], MD5_out[1], 16); +#endif + MD5_swap(block[0].w, line[0].odd->w, 14); + block[0].w[14] = line[0].odd->w[14]; +#if MD5_X2 + MD5_swap(block[1].w, line[1].odd->w, 14); + block[1].w[14] = line[1].odd->w[14]; + if ((line += 2) > &order[20][MD5_N - 1]) line = order[0]; + MD5_body(block[0].w, block[1].w, + line[0].even->w, line[1].even->w); +#else + if (++line > &order[20][0]) line = order[0]; + MD5_body(block[0].w, line[0].even->w); +#endif +#endif + } while (--index); + + memcpy(MD5_out[0], line[0].even, 16); +#if MD5_X2 + memcpy(MD5_out[1], line[1].even, 16); +#endif +} + +#if MD5_std_mt +void MD5_std_crypt(int count) +{ +#if MD5_std_mt + int t, n = (count + (MD5_N - 1)) / MD5_N; +#endif + +#ifdef _OPENMP +#pragma omp parallel for default(none) private(t) shared(n, salt_changed, saved_salt) +#endif + for_each_t(n) { +/* + * We could move the salt_changed check out of the parallel region (and have + * two specialized parallel regions instead), but MD5_std_crypt_for_thread() + * does so much work that the salt_changed check is negligible. + */ + if (salt_changed) + MD5_std_set_salt_for_thread(t, saved_salt); + MD5_std_crypt_for_thread(t); + } + + salt_changed = 0; +} +#endif + +char *MD5_std_get_salt(char *ciphertext) +{ + static char out[9]; + char *p, *q; + int i; + + p = ciphertext + 3; + if ((out[8] = !strncmp(ciphertext, "$apr1$", 6))) + p = ciphertext + 6; + + q = out; + for (i = 0; *p != '$' && i < 8; i++) + *q++ = *p++; + while (i++ < 8) + *q++ = 0; + + return out; +} + +#define TO_BINARY(b1, b2, b3) \ + value = \ + (MD5_word)atoi64[ARCH_INDEX(pos[0])] | \ + ((MD5_word)atoi64[ARCH_INDEX(pos[1])] << 6) | \ + ((MD5_word)atoi64[ARCH_INDEX(pos[2])] << 12) | \ + ((MD5_word)atoi64[ARCH_INDEX(pos[3])] << 18); \ + pos += 4; \ + out.b[b1] = value >> 16; \ + out.b[b2] = value >> 8; \ + out.b[b3] = value; + +MD5_word *MD5_std_get_binary(char *ciphertext) +{ + static union { + MD5_binary w; + char b[16]; + } out; + char *pos; + MD5_word value; + + pos = ciphertext + 3; + if (!strncmp(ciphertext, "$apr1$", 6)) + pos = ciphertext + 6; + + while (*pos++ != '$'); + + TO_BINARY(0, 6, 12); + TO_BINARY(1, 7, 13); + TO_BINARY(2, 8, 14); + TO_BINARY(3, 9, 15); + TO_BINARY(4, 10, 5); + out.b[11] = + (MD5_word)atoi64[ARCH_INDEX(pos[0])] | + ((MD5_word)atoi64[ARCH_INDEX(pos[1])] << 6); + +#undef OOFFOOFF +#define OOFFOOFF 0x00ff00ff + MD5_swap(out.w, out.w, 4); +#undef OOFFOOFF + + return out.w; +} diff --git a/src/MD5_std.h b/src/MD5_std.h new file mode 100644 index 0000000..a8e1e7f --- /dev/null +++ b/src/MD5_std.h @@ -0,0 +1,165 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2003,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * FreeBSD-style MD5-based password hash implementation. + */ + +#ifndef _JOHN_MD5_STD_H +#define _JOHN_MD5_STD_H + +#include "arch.h" +#include "common.h" + +typedef ARCH_WORD_32 MD5_word; + +/* + * Binary ciphertext type. + */ +typedef MD5_word MD5_binary[4]; + +/* + * Various structures for internal use. + */ + +typedef union { + double dummy; + MD5_word w[15]; + char b[60]; +} MD5_block; + +typedef struct { + int length; + MD5_block *even, *odd; +} MD5_pattern; + +typedef struct { + char s[8]; + struct { + int p, s, ps, pp, psp; + } l; + struct { + MD5_block p, sp, pp, spp; + } e; + struct { + MD5_block p, ps, pp, psp; + } o; +} MD5_pool; + +#if !MD5_IMM +typedef struct { + MD5_word AC[64]; + MD5_word IV[4]; + MD5_word masks[2]; +} MD5_data; +#endif + +#if MD5_X2 +#define MD5_N 2 +#else +#define MD5_N 1 +#endif + +typedef struct { +#if !MD5_IMM + MD5_data data; +#endif + + MD5_binary out[MD5_N]; + + MD5_block _block[MD5_N]; + MD5_pattern _order[21][MD5_N]; + MD5_pool _pool[MD5_N]; + char *prefix; + int prelen; +} MD5_std_combined; + +#if defined(_OPENMP) && !MD5_ASM +#define MD5_std_mt 1 +#define MD5_std_cpt 128 +#define MD5_std_mt_max (MD5_std_cpt * 576) +extern MD5_std_combined *MD5_std_all_p; +extern int MD5_std_min_kpc, MD5_std_max_kpc; +extern int MD5_std_nt; +#define MD5_std_all_align 64 +#define MD5_std_all_size \ + ((sizeof(MD5_std_combined) + (MD5_std_all_align - 1)) & \ + ~(MD5_std_all_align - 1)) +#ifdef __GNUC__ +#define MD5_std_all \ + (*(MD5_std_combined *)((char *)MD5_std_all_p + t)) +#define for_each_t(n) \ + for (t = 0; t < (n) * MD5_std_all_size; t += MD5_std_all_size) +#define init_t() \ + int t = (unsigned int)index / MD5_N * MD5_std_all_size; \ + index = (unsigned int)index % MD5_N; +#else +/* + * For compilers that complain about the above e.g. with "iteration expression + * of omp for loop does not have a canonical shape". + */ +#define MD5_std_all \ + (*(MD5_std_combined *)((char *)MD5_std_all_p + t * MD5_std_all_size)) +#define for_each_t(n) \ + for (t = 0; t < (n); t++) +#define init_t() \ + int t = (unsigned int)index / MD5_N; \ + index = (unsigned int)index % MD5_N; +#endif +#else +#define MD5_std_mt 0 +extern MD5_std_combined MD5_std_all; +#define for_each_t(n) +#define init_t() +#endif + +/* + * MD5_std_crypt() output buffer. + */ +#define MD5_out MD5_std_all.out + +#if MD5_X2 +#define MD5_ALGORITHM_NAME "MD5 32/" ARCH_BITS_STR " X2" +#else +#define MD5_ALGORITHM_NAME "MD5 32/" ARCH_BITS_STR +#endif + +/* + * Initializes the internal structures. + */ +extern void MD5_std_init(void); + +/* + * Sets a salt for MD5_std_crypt(). + */ +extern void MD5_std_set_salt(char *salt); + +/* + * Sets a key for MD5_std_crypt(). + * Currently only supports keys up to 15 characters long. + */ +extern void MD5_std_set_key(char *key, int index); + +/* + * Main hashing routine, sets MD5_out. + */ +extern void MD5_std_crypt(int count); + +/* + * Returns the salt for MD5_std_set_salt(). + */ +extern char *MD5_std_get_salt(char *ciphertext); + +/* + * Converts an ASCII ciphertext to binary. + */ +extern MD5_word *MD5_std_get_binary(char *ciphertext); + +#endif diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..d8ab260 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,917 @@ +# +# This file is part of John the Ripper password cracker, +# Copyright (c) 1996-2013 by Solar Designer +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# +# There's ABSOLUTELY NO WARRANTY, express or implied. +# + +CC = gcc +AS = $(CC) +LD = $(CC) +CPP = $(CC) +CP = cp +LN = ln -sf +RM = rm -f +TR = tr +SED = sed +NULL = /dev/null +CPPFLAGS = -E +OMPFLAGS = +# gcc with OpenMP +#OMPFLAGS = -fopenmp +# gcc with OpenMP on 32-bit x86 with SSE2 +#OMPFLAGS = -fopenmp -msse2 +# Mac OS X (llvm-gcc) with OpenMP +#OMPFLAGS = -fopenmp -D_FORTIFY_SOURCE=0 +# Sun Studio with OpenMP (set the OMP_NUM_THREADS env var at runtime) +#OMPFLAGS = -xopenmp +CFLAGS = -c -Wall -Wdeclaration-after-statement -O2 -fomit-frame-pointer $(OMPFLAGS) +# CFLAGS for use on the main john.c file only +CFLAGS_MAIN = $(CFLAGS) +ASFLAGS = -c $(OMPFLAGS) +LDFLAGS = -s $(OMPFLAGS) +OPT_NORMAL = -funroll-loops +# Remove the "-Os" if you're using an ancient version of gcc +OPT_INLINE = -Os -funroll-loops -finline-functions + +JOHN_OBJS = \ + DES_fmt.o DES_std.o DES_bs.o DES_bs_b.o \ + BSDI_fmt.o \ + MD5_fmt.o MD5_std.o \ + BF_fmt.o BF_std.o \ + AFS_fmt.o \ + LM_fmt.o \ + trip_fmt.o \ + dummy.o \ + batch.o bench.o charset.o common.o compiler.o config.o cracker.o \ + crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \ + loader.o logger.o math.o memory.o misc.o options.o params.o path.o \ + recovery.o rpp.o rules.o signals.o single.o status.o tty.o wordlist.o \ + unshadow.o \ + unafs.o \ + unique.o + +BENCH_DES_OBJS_ORIG = \ + DES_fmt.o DES_std.o + +BENCH_DES_OBJS_DEPEND = \ + $(BENCH_DES_OBJS_ORIG) + +BENCH_DES_BS_OBJS_DEPEND = \ + DES_bs_b.o + +BENCH_MD5_OBJS_DEPEND = \ + MD5_fmt.o MD5_std.o + +BENCH_BF_OBJS_DEPEND = \ + BF_fmt.o BF_std.o + +BENCH_OBJS = \ + $(BENCH_DES_OBJS_DEPEND) \ + DES_bs.o $(BENCH_DES_BS_OBJS_DEPEND) \ + $(BENCH_MD5_OBJS_DEPEND) \ + $(BENCH_BF_OBJS_DEPEND) \ + bench.o best.o common.o config.o formats.o math.o memory.o miscnl.o \ + params.o path.o signals.o tty.o + +PROJ = ../run/john ../run/unshadow ../run/unafs ../run/unique +PROJ_DOS = ../run/john.bin ../run/john.com \ + ../run/unshadow.com ../run/unafs.com ../run/unique.com +PROJ_WIN32 = ../run/john.exe \ + ../run/unshadow.exe ../run/unafs.exe ../run/unique.exe + +default: + @echo "To build John the Ripper, type:" + @echo " make clean SYSTEM" + @echo "where SYSTEM can be one of the following:" + @echo "linux-x86-64-avx Linux, x86-64 with AVX (2011+ Intel CPUs)" + @echo "linux-x86-64-xop Linux, x86-64 with AVX and XOP (2011+ AMD CPUs)" + @echo "linux-x86-64 Linux, x86-64 with SSE2 (most common)" +# @echo "linux-x86-64-32-sse2 Linux, x86-64, 32-bit with SSE2" +# @echo "linux-x86-64-32-mmx Linux, x86-64, 32-bit with MMX" + @echo "linux-x86-avx Linux, x86 32-bit with AVX (2011+ Intel CPUs)" + @echo "linux-x86-xop Linux, x86 32-bit with AVX and XOP (2011+ AMD CPUs)" + @echo "linux-x86-sse2 Linux, x86 32-bit with SSE2 (most common, if 32-bit)" + @echo "linux-x86-mmx Linux, x86 32-bit with MMX (for old computers)" + @echo "linux-x86-any Linux, x86 32-bit (for truly ancient computers)" + @echo "linux-alpha Linux, Alpha" + @echo "linux-sparc Linux, SPARC 32-bit" + @echo "linux-ppc32-altivec Linux, PowerPC w/AltiVec (best)" + @echo "linux-ppc32 Linux, PowerPC 32-bit" +# @echo "linux-ppc64-altivec Linux, PowerPC 64-bit w/AltiVec" + @echo "linux-ppc64 Linux, PowerPC 64-bit" + @echo "linux-ia64 Linux, IA-64" + @echo "freebsd-x86-64 FreeBSD, x86-64 with SSE2 (best)" + @echo "freebsd-x86-sse2 FreeBSD, x86 with SSE2 (best if 32-bit)" + @echo "freebsd-x86-mmx FreeBSD, x86 with MMX" + @echo "freebsd-x86-any FreeBSD, x86" + @echo "freebsd-alpha FreeBSD, Alpha" + @echo "openbsd-x86-64 OpenBSD, x86-64 with SSE2 (best)" + @echo "openbsd-x86-sse2 OpenBSD, x86 with SSE2 (best if 32-bit)" + @echo "openbsd-x86-mmx OpenBSD, x86 with MMX" + @echo "openbsd-x86-any OpenBSD, x86" + @echo "openbsd-alpha OpenBSD, Alpha" + @echo "openbsd-sparc64 OpenBSD, SPARC 64-bit (best)" + @echo "openbsd-sparc OpenBSD, SPARC 32-bit" + @echo "openbsd-ppc32 OpenBSD, PowerPC 32-bit" + @echo "openbsd-ppc64 OpenBSD, PowerPC 64-bit" + @echo "openbsd-pa-risc OpenBSD, PA-RISC" + @echo "openbsd-vax OpenBSD, VAX" + @echo "netbsd-sparc64 NetBSD, SPARC 64-bit" + @echo "netbsd-vax NetBSD, VAX" + @echo "solaris-sparc64-cc Solaris, SPARC V9 64-bit, cc (best)" + @echo "solaris-sparc64-gcc Solaris, SPARC V9 64-bit, gcc" + @echo "solaris-sparcv9-cc Solaris, SPARC V9 32-bit, cc" + @echo "solaris-sparcv8-cc Solaris, SPARC V8 32-bit, cc" + @echo "solaris-sparc-gcc Solaris, SPARC 32-bit, gcc" + @echo "solaris-x86-64-cc Solaris, x86-64 with SSE2, cc (best)" + @echo "solaris-x86-64-gcc Solaris, x86-64 with SSE2, gcc" + @echo "solaris-x86-sse2-cc Solaris 9 4/04+, x86 with SSE2, cc" + @echo "solaris-x86-sse2-gcc Solaris 9 4/04+, x86 with SSE2, gcc" + @echo "solaris-x86-mmx-cc Solaris, x86 with MMX, cc" + @echo "solaris-x86-mmx-gcc Solaris, x86 with MMX, gcc" + @echo "solaris-x86-any-cc Solaris, x86, cc" + @echo "solaris-x86-any-gcc Solaris, x86, gcc" + @echo "sco-x86-any-gcc SCO, x86, gcc" + @echo "sco-x86-any-cc SCO, x86, cc" + @echo "tru64-alpha Tru64 (Digital UNIX, OSF/1), Alpha" + @echo "aix-ppc32 AIX, PowerPC 32-bit" + @echo "macosx-x86-64 Mac OS X 10.5+, Xcode 3.0+, x86-64 with SSE2 (best)" + @echo "macosx-x86-sse2 Mac OS X, x86 with SSE2" + @echo "macosx-ppc32-altivec Mac OS X, PowerPC w/AltiVec (best)" + @echo "macosx-ppc32 Mac OS X, PowerPC 32-bit" +# @echo "macosx-ppc64-altivec Mac OS X, PowerPC 64-bit w/AltiVec" + @echo "macosx-ppc64 Mac OS X 10.4+, PowerPC 64-bit" + @echo "macosx-universal Mac OS X, Universal Binary (x86 + x86-64 + PPC)" + @echo "hpux-pa-risc-gcc HP-UX, PA-RISC, gcc" + @echo "hpux-pa-risc-cc HP-UX, PA-RISC, ANSI cc" + @echo "irix-mips64-r10k IRIX, MIPS 64-bit (R10K) (best)" + @echo "irix-mips64 IRIX, MIPS 64-bit" + @echo "irix-mips32 IRIX, MIPS 32-bit" + @echo "dos-djgpp-x86-mmx DOS, DJGPP, x86 with MMX" + @echo "dos-djgpp-x86-any DOS, DJGPP, x86" + @echo "win32-cygwin-x86-sse2 Win32, Cygwin, x86 with SSE2 (best)" + @echo "win32-cygwin-x86-mmx Win32, Cygwin, x86 with MMX" + @echo "win32-cygwin-x86-any Win32, Cygwin, x86" + @echo "beos-x86-sse2 BeOS, x86 with SSE2 (best)" + @echo "beos-x86-mmx BeOS, x86 with MMX" + @echo "beos-x86-any BeOS, x86" + @echo "generic Any other Unix-like system with gcc" + +linux-x86-64-avx: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" \ + CFLAGS_MAIN="$(CFLAGS) -DJOHN_AVX -DHAVE_CRYPT" \ + CFLAGS="$(CFLAGS) -mavx -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -mavx" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-x86-64-xop: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" \ + CFLAGS_MAIN="$(CFLAGS) -DJOHN_XOP -DHAVE_CRYPT" \ + CFLAGS="$(CFLAGS) -mxop -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -mxop" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-x86-64: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-x86-64-32-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-sse.o" \ + CFLAGS="$(CFLAGS) -m32 -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -m32" \ + LDFLAGS="$(LDFLAGS) -m32 -lcrypt" + +linux-x86-64-32-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-mmx.o" \ + CFLAGS="$(CFLAGS) -m32 -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -m32" \ + LDFLAGS="$(LDFLAGS) -m32 -lcrypt" + +linux-x86-avx: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o" \ + CFLAGS_MAIN="$(CFLAGS) -m32 -DJOHN_AVX -DHAVE_CRYPT" \ + CFLAGS="$(CFLAGS) -m32 -mavx -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -m32 -mavx" \ + LDFLAGS="$(LDFLAGS) -m32 -lcrypt" + +linux-x86-xop: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o" \ + CFLAGS_MAIN="$(CFLAGS) -m32 -DJOHN_XOP -DHAVE_CRYPT" \ + CFLAGS="$(CFLAGS) -m32 -mxop -DHAVE_CRYPT" \ + ASFLAGS="$(ASFLAGS) -m32 -mxop" \ + LDFLAGS="$(LDFLAGS) -m32 -lcrypt" + +linux-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-sse.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o x86-mmx.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-x86-any: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-alpha: + $(LN) alpha.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o alpha.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +# This target is currently "undocumented" as ccc generates much slower +# code for the large unrolled loops in John; let's hope it gets fixed. +linux-alpha-ccc: + $(LN) alpha.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o alpha.o" \ + CC=ccc \ + CFLAGS="-c -Wf,-switch,noil_schedule -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" \ + OPT_NORMAL="-fast" \ + OPT_INLINE="-O2 -arch host" + +linux-sparc: + $(LN) sparc32.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +linux-ppc32-altivec: + $(LN) ppc32alt.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" \ + OPT_INLINE="-finline-functions -finline-limit=4000 -maltivec" + +linux-ppc32: + $(LN) ppc32.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +# This is slightly slower than linux-ppc32-altivec for most hash types. +linux-ppc64-altivec: + $(LN) ppc64alt.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -m64 -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -m64 -lcrypt" \ + OPT_INLINE="-finline-functions -finline-limit=4000 -maltivec" + +linux-ppc64: + $(LN) ppc64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -m64 -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -m64 -lcrypt" \ + OPT_INLINE="-finline-functions -finline-limit=4000" + +linux-ia64: + $(LN) ia64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lcrypt" + +freebsd-x86-64: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86-64.o" + +freebsd-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +freebsd-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +freebsd-x86-any: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +freebsd-x86-any-a.out: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES -DALIGN_LOG -DBSD" + +freebsd-alpha: + $(LN) alpha.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) alpha.o" + +openbsd-x86-64: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86-64.o" + +openbsd-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +openbsd-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +openbsd-x86-any: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + ASFLAGS="$(ASFLAGS) -DBSD" + +openbsd-x86-any-a.out: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES -DALIGN_LOG -DBSD" + +openbsd-alpha: + $(LN) alpha.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) alpha.o" + +openbsd-sparc64: + $(LN) sparc64.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="$(CFLAGS) -m64 -mcpu=ultrasparc" \ + LDFLAGS="$(LDFLAGS) -m64" + +openbsd-sparc: + $(LN) sparc32.h arch.h + $(MAKE) $(PROJ) + +openbsd-ppc32: + $(LN) ppc32.h arch.h + $(MAKE) $(PROJ) + +openbsd-ppc64: + $(LN) ppc64.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="$(CFLAGS) -m64" \ + LDFLAGS="$(LDFLAGS) -m64" \ + OPT_INLINE="-finline-functions -finline-limit=4000" + +openbsd-pa-risc: + $(LN) pa-risc.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="-c -Wall -O3 -fomit-frame-pointer" + +openbsd-vax: + $(LN) vax.h arch.h + $(MAKE) $(PROJ) + +netbsd-sparc64: + $(LN) sparc64.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="$(CFLAGS) -m64 -mcpu=ultrasparc" \ + LDFLAGS="$(LDFLAGS) -m64" + +netbsd-vax: + $(LN) vax.h arch.h + $(MAKE) $(PROJ) + +solaris-sparc64-cc: + $(LN) sparc64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CC=cc \ + CFLAGS="-c -fast -xarch=native64 -DHAVE_CRYPT $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -xarch=native64 -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-sparc64-gcc: + $(LN) sparc64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -m64 -mcpu=ultrasparc -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -m64 -lrt" + +solaris-sparcv9-cc: + $(LN) sparc32.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CC=cc \ + CFLAGS="-c -xO4 -xarch=v8plusa -xchip=ultra -DHAVE_CRYPT $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-sparcv8-cc: + $(LN) sparc32.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CC=cc \ + CFLAGS="-c -xO4 -xarch=v8 -DHAVE_CRYPT $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-sparc-gcc: + $(LN) sparc32.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lrt" + +solaris-x86-64-cc: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" \ + CC=cc \ + CFLAGS="-c -fast -xarch=native64 -DHAVE_CRYPT $(OMPFLAGS)" \ + ASFLAGS="-c -xarch=native64 $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -xarch=native64 -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-x86-64-gcc: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o x86-64.o" \ + CFLAGS="$(CFLAGS) -m64 -DHAVE_CRYPT" \ + ASFLAGS="$(CFLAGS) -m64" \ + LDFLAGS="$(LDFLAGS) -m64 -lrt" + +solaris-x86-sse2-cc: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o x86-sse.o" \ + CC=cc \ + CFLAGS="-c -fast -xarch=native -DHAVE_CRYPT $(OMPFLAGS)" \ + ASFLAGS="-c -xarch=native $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -xarch=native -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-x86-sse2-gcc: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o x86-sse.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lrt" + +solaris-x86-mmx-cc: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o x86-mmx.o" \ + CC=cc \ + CFLAGS="-c -fast -xarch=native -DHAVE_CRYPT $(OMPFLAGS)" \ + ASFLAGS="-c -xarch=native $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -xarch=native -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-x86-mmx-gcc: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o x86-mmx.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lrt" + +solaris-x86-any-cc: + $(RM) arch.h + ln -s x86-any.h arch.h + $(MAKE) $(PROJ) \ + SHELL=/bin/sh \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o" \ + CC=cc \ + CFLAGS="-c -xO4 -DHAVE_CRYPT $(OMPFLAGS)" \ + ASFLAGS="-c $(OMPFLAGS)" \ + LDFLAGS="$(LDFLAGS) -lrt" \ + OPT_NORMAL="" \ + OPT_INLINE="-xinline=s1,s2,s3,s4,s5,s6,s7,s8" + +solaris-x86-any-gcc: + $(RM) arch.h + ln -s x86-any.h arch.h + $(MAKE) $(PROJ) \ + SHELL=/bin/sh \ + JOHN_OBJS="$(JOHN_OBJS) c3_fmt.o solaris-x86.o" \ + CFLAGS="$(CFLAGS) -DHAVE_CRYPT" \ + LDFLAGS="$(LDFLAGS) -lrt" + +# Older versions of Sun's assembler had a line length restriction (and some +# other problems, which affect newer versions as well and which are worked +# around in x86.S). +solaris-x86.o: x86.S + $(CPP) $(CPPFLAGS) -P -DDUMBAS x86.S | $(TR) \; \\n > tmp.s + $(AS) $(ASFLAGS) tmp.s -o solaris-x86.o + $(RM) tmp.s + +sco-x86-any-gcc: + $(RM) arch.h + ln -s x86-any.h arch.h + $(MAKE) $(PROJ) \ + SHELL=/bin/sh \ + JOHN_OBJS="$(JOHN_OBJS) sco-x86.o" + +sco-x86-any-cc: + $(RM) arch.h + ln -s x86-any.h arch.h + $(MAKE) $(PROJ) \ + SHELL=/bin/sh \ + JOHN_OBJS="$(JOHN_OBJS) sco-x86.o" \ + CC=cc \ + CFLAGS="-c -b elf -O3" \ + ASFLAGS="-c -b elf" \ + OPT_NORMAL="-K loop_unroll,no_inline" \ + OPT_INLINE="-K inline" + +# SCO is even worse than Solaris x86 +sco-x86.o: x86.S + $(CPP) $(CPPFLAGS) -DDUMBAS x86.S | \ + $(TR) \; \\n | $(SED) 's/\([%.]\) /\1/g' > tmp.s + $(AS) $(ASFLAGS) tmp.s -o sco-x86.o + $(RM) tmp.s + +tru64-alpha: + $(LN) alpha.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) digipaq-alpha.o" \ + CC=cc \ + CFLAGS="-c -O4 -arch host" \ + OPT_NORMAL="" \ + OPT_INLINE="-inline all" + +# Digital/Compaq's cc and make use the .S suffix for a different purpose... +digipaq-alpha.o: alpha.S + $(CPP) $(CPPFLAGS) alpha.S > tmp.s + $(AS) $(ASFLAGS) tmp.s -o digipaq-alpha.o + $(RM) tmp.s + +aix-ppc32: + $(LN) ppc32.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -qunroll=2 -qarch=ppc -qchars=signed" \ + LDFLAGS="$(LDFLAGS) -lbsd" \ + OPT_NORMAL="-O2" \ + OPT_INLINE="-O3 -Q=99 -w" + +macosx-x86-64: + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86-64.o" \ + ASFLAGS="$(ASFLAGS) -m64 -DUNDERSCORES -DBSD -DALIGN_LOG" \ + CFLAGS="$(CFLAGS) -m64" \ + LDFLAGS="$(LDFLAGS) -m64" + +macosx-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -m32 -DUNDERSCORES -DBSD -DALIGN_LOG" \ + CFLAGS="$(CFLAGS) -m32" \ + LDFLAGS="$(LDFLAGS) -m32" + +macosx-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ + ASFLAGS="$(ASFLAGS) -m32 -DUNDERSCORES -DBSD -DALIGN_LOG" \ + CFLAGS="$(CFLAGS) -m32" \ + LDFLAGS="$(LDFLAGS) -m32" + +macosx-ppc32-altivec: + $(LN) ppc32alt.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="-c -Wall -fomit-frame-pointer" \ + OPT_NORMAL="-fast -mcpu=7450" \ + OPT_INLINE="-fast -mcpu=7450 -finline-limit=4000 -faltivec -maltivec" + +# The -cross targets can be used to compile PowerPC binaries on x86. +macosx-ppc32-altivec-cross: + $(LN) ppc32alt.h arch.h + $(MAKE) $(PROJ) \ + ASFLAGS="$(ASFLAGS) -arch ppc" \ + CFLAGS="-c -Wall -arch ppc -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -arch ppc" \ + OPT_NORMAL="-fast -mcpu=7450" \ + OPT_INLINE="-fast -mcpu=7450 -finline-limit=4000 -faltivec -maltivec" + +# "cc -traditional-cpp" was needed on older versions of Mac OS X; it might +# actually be problematic on current ones, but those will hopefully use other +# make targets anyway (e.g., macosx-ppc32-altivec above). +macosx-ppc32: + $(LN) ppc32.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -traditional-cpp" \ + OPT_NORMAL="-O2" \ + OPT_INLINE="-O3" + +macosx-ppc32-cross: + $(LN) ppc32.h arch.h + $(MAKE) $(PROJ) \ + ASFLAGS="$(ASFLAGS) -arch ppc" \ + CFLAGS="-c -Wall -arch ppc -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -arch ppc" \ + OPT_NORMAL="-O2" \ + OPT_INLINE="-O3 -finline-limit=4000" + +# This is slightly slower than macosx-ppc32-altivec for most hash types. +macosx-ppc64-altivec: + $(LN) ppc64alt.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="-c -m64 -Wall -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -m64" \ + OPT_NORMAL="-fast" \ + OPT_INLINE="-fast -finline-limit=4000 -faltivec -maltivec" + +macosx-ppc64-altivec-cross: + $(LN) ppc64alt.h arch.h + $(MAKE) $(PROJ) \ + ASFLAGS="$(ASFLAGS) -arch ppc" \ + CFLAGS="-c -arch ppc -m64 -Wall -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -arch ppc -m64" \ + OPT_NORMAL="-fast" \ + OPT_INLINE="-fast -finline-limit=4000 -faltivec -maltivec" + +macosx-ppc64: + $(LN) ppc64.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="-c -m64 -Wall -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -m64" \ + OPT_NORMAL="-fast" \ + OPT_INLINE="-fast -finline-limit=4000" + +macosx-ppc64-cross: + $(LN) ppc64.h arch.h + $(MAKE) $(PROJ) \ + ASFLAGS="$(ASFLAGS) -arch ppc" \ + CFLAGS="-c -arch ppc -m64 -Wall -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -arch ppc -m64" \ + OPT_NORMAL="-fast" \ + OPT_INLINE="-fast -finline-limit=4000" + +john-macosx-x86-64: + $(RM) *.o + $(LN) x86-64.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86-64.o" \ + ASFLAGS="$(ASFLAGS) -arch x86_64 -m64 -DUNDERSCORES -DBSD -DALIGN_LOG" \ + CFLAGS="$(CFLAGS) -arch x86_64 -m64" \ + LDFLAGS="$(LDFLAGS) -arch x86_64 -m64" + mv ../run/john john-macosx-x86-64 + +john-macosx-x86: + $(RM) *.o + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -arch i386 -m32 -DUNDERSCORES -DBSD -DALIGN_LOG" \ + CFLAGS="$(CFLAGS) -arch i386 -m32" \ + LDFLAGS="$(LDFLAGS) -arch i386 -m32" + mv ../run/john john-macosx-x86 + +john-macosx-ppc: + $(RM) *.o + $(LN) ppc32alt.h arch.h + $(MAKE) $(PROJ) \ + ASFLAGS="$(ASFLAGS) -arch ppc" \ + CFLAGS="-c -Wall -arch ppc -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -arch ppc" \ + OPT_NORMAL="-fast -mcpu=7450" \ + OPT_INLINE="-fast -mcpu=7450 -finline-limit=4000 -faltivec -maltivec" + mv ../run/john john-macosx-ppc + +macosx-universal: john-macosx-x86-64 john-macosx-x86 john-macosx-ppc + lipo -create john-macosx-x86-64 john-macosx-x86 john-macosx-ppc \ + -output ../run/john + +hpux-pa-risc-gcc: + $(LN) pa-risc.h arch.h + $(MAKE) $(PROJ) \ + CFLAGS="-c -Wall -O3 -fomit-frame-pointer" + +hpux-pa-risc-cc: + $(LN) pa-risc.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -Aa -D_HPUX_SOURCE -DANSI_CPP" \ + OPT_NORMAL="+O2" \ + OPT_INLINE="+O3 +Oinline" + +irix-mips64-r10k: + $(LN) mips64.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -O2 -64 -mips4 -r10000 -signed" \ + LDFLAGS="$(LDFLAGS) -64 -mips4 -r10000" \ + OPT_NORMAL="-LNO:opt=1 -OPT:Olimit=2194" \ + OPT_INLINE="-INLINE:all" + +irix-mips64: + $(LN) mips64.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -O2 -64 -mips3 -signed" \ + LDFLAGS="$(LDFLAGS) -64 -mips3" \ + OPT_NORMAL="-LNO:opt=1 -OPT:Olimit=2194" \ + OPT_INLINE="-INLINE:all" + +irix-mips32: + $(LN) mips32.h arch.h + $(MAKE) $(PROJ) \ + CC=cc \ + CFLAGS="-c -O2 -32 -signed" \ + LDFLAGS="$(LDFLAGS) -32" \ + OPT_NORMAL="-LNO:opt=1 -OPT:Olimit=2194" \ + OPT_INLINE="-INLINE:all" + +dos-djgpp-x86-mmx: + copy x86-mmx.h arch.h + $(MAKE) $(PROJ_DOS) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ + CFLAGS="$(CFLAGS) -mpreferred-stack-boundary=2" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES -DALIGN_LOG" + +dos-djgpp-x86-any: + copy x86-any.h arch.h + $(MAKE) $(PROJ_DOS) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + CFLAGS="$(CFLAGS) -mpreferred-stack-boundary=2" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES -DALIGN_LOG" + +win32-cygwin-x86-sse2: + $(CP) x86-sse.h arch.h + $(MAKE) $(PROJ_WIN32) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES" + +win32-cygwin-x86-mmx: + $(CP) x86-mmx.h arch.h + $(MAKE) $(PROJ_WIN32) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" \ + CFLAGS="$(CFLAGS) -mpreferred-stack-boundary=3" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES" + +win32-cygwin-x86-any: + $(CP) x86-any.h arch.h + $(MAKE) $(PROJ_WIN32) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" \ + CFLAGS="$(CFLAGS) -mpreferred-stack-boundary=2" \ + ASFLAGS="$(ASFLAGS) -DUNDERSCORES" + +beos-x86-sse2: + $(LN) x86-sse.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-sse.o" + +beos-x86-mmx: + $(LN) x86-mmx.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o x86-mmx.o" + +beos-x86-any: + $(LN) x86-any.h arch.h + $(MAKE) $(PROJ) \ + JOHN_OBJS="$(JOHN_OBJS) x86.o" + +generic: generic.h + $(RM) arch.h + ln -s generic.h arch.h + $(MAKE) $(PROJ) + +generic.h: + $(RM) arch.h + $(CC) $(CFLAGS) detect.c + $(LD) detect.o $(LDFLAGS) -o detect + ./best.sh "$(MAKE)" \ + "$(BENCH_DES_OBJS_DEPEND)" \ + "$(BENCH_DES_BS_OBJS_DEPEND)" \ + "$(BENCH_MD5_OBJS_DEPEND)" \ + "$(BENCH_BF_OBJS_DEPEND)" + +bench: $(BENCH_OBJS) + $(LD) $(BENCH_OBJS) $(LDFLAGS) -o bench + +../run/john: $(JOHN_OBJS) + $(LD) $(JOHN_OBJS) $(LDFLAGS) -o ../run/john + +../run/unshadow: ../run/john + $(RM) ../run/unshadow + ln -s john ../run/unshadow + +../run/unafs: ../run/john + $(RM) ../run/unafs + ln -s john ../run/unafs + +../run/unique: ../run/john + $(RM) ../run/unique + ln -s john ../run/unique + +../run/john.bin: $(JOHN_OBJS) + $(LD) $(JOHN_OBJS) $(LDFLAGS) -o ../run/john.exe + if exist ..\run\john.bin del ..\run\john.bin + ren ..\run\john.exe john.bin + +../run/john.com: john.com + copy john.com ..\run\john.com + +../run/unshadow.com: john.com + copy john.com ..\run\unshadow.com + +../run/unafs.com: john.com + copy john.com ..\run\unafs.com + +../run/unique.com: john.com + copy john.com ..\run\unique.com + +john.com: john.asm + @echo Use Borland TASM/TLINK to make JOHN.COM + +../run/john.exe: $(JOHN_OBJS) + $(LD) $(JOHN_OBJS) $(LDFLAGS) -lkernel32 -o ../run/john.exe + strip ../run/john.exe + +../run/unshadow.exe: symlink.c + $(CC) symlink.c -o ../run/unshadow.exe + strip ../run/unshadow.exe + +../run/unafs.exe: symlink.c + $(CC) symlink.c -o ../run/unafs.exe + strip ../run/unafs.exe + +../run/unique.exe: symlink.c + $(CC) symlink.c -o ../run/unique.exe + strip ../run/unique.exe + +# Inlining the S-boxes produces faster code as long as they fit in the cache. +DES_bs_b.o: DES_bs_b.c sboxes.c nonstd.c sboxes-s.c + $(CC) $(CFLAGS) $(OPT_INLINE) DES_bs_b.c + +miscnl.o: misc.c + $(CC) $(CFLAGS) $(OPT_NORMAL) -D_JOHN_MISC_NO_LOG misc.c -o miscnl.o + +john.o: john.c + $(CC) $(CFLAGS_MAIN) $(OPT_NORMAL) $*.c + +.c.o: + $(CC) $(CFLAGS) $(OPT_NORMAL) $*.c + +.S.o: + $(AS) $(ASFLAGS) $*.S + +# We don't have any files with .s suffix, this is for compiling in DOS only +.s.o: + $(AS) $(ASFLAGS) $*.S + +check: + ../run/john --make_check + +depend: + makedepend -fMakefile.dep -Y *.c 2>> /dev/null + +clean: + $(RM) $(PROJ) $(PROJ_DOS) $(PROJ_WIN32) + $(RM) ../run/john.exe john-macosx-* *.o *.bak core + $(RM) detect bench generic.h arch.h tmp.s + $(CP) $(NULL) Makefile.dep + +include Makefile.dep diff --git a/src/Makefile.dep b/src/Makefile.dep new file mode 100644 index 0000000..e69de29 diff --git a/src/alpha.S b/src/alpha.S new file mode 100644 index 0000000..8694c64 --- /dev/null +++ b/src/alpha.S @@ -0,0 +1,329 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Alpha assembly routines. + * + * These are optimized for EV4 (21064, 21066), not EV5 (21164), since on + * a 21164 bitslice DES is always faster anyway. However, I tried to make + * them have reasonable performance on EV5 too, in places where it didn't + * affect EV4. + * + * In reality, bitslice DES turned out to be faster almost everywhere, so + * these routines are now only used for BSDI setkey() and AFS by default. + * + * The following things were kept in mind while coding: + * + * 1. Huge instruction latencies: + * 3 cycles LDQ to XOR, + * 2 cycles S8ADDQ to LDQ, + * 2 cycles EXTBL to S8ADDQ + * => schedule the instructions accordingly; + * => allocate some extra temporary registers; + * AND has better latency than EXTBL + * => use it where possible. + * + * 2. Dual issue rules: + * only one LD/ST with one other instruction can dual issue (simplified) + * => keep in mind for latency calculations; + * => mix LD/ST with other instructions where possible; + * => no need to avoid dependencies if the two instructions are + * _both_ from _one_ of these two classes anyway, unless can be + * done with no extra cost at all (better for EV5); + * the pair has to be qword aligned + * => surround each LD/ST instruction with others, so that it can + * dual issue either with the preceding, or the following one. + * + * 3. Direct-mapped L1 cache: + * => the entire key schedule (128 bytes) is loaded into 16 registers at + * startup, so there's no risk of it overlapping with SPE tables in the + * cache, while in the inner loop. + */ + +/* + * DES stuff. + */ + +#define D $0 +#define tmp1 $1 +#define tmp2 $2 +#define tmp3 $3 +#define tmp4 $4 +#define R $5 +#define L $6 +#define count $7 +#define SPE $8 +#define kp $16 +#define out $17 +#define K1 $18 +#define K2 $19 +#define K3 $20 +#define K4 $21 +#define K5 $22 +#define K6 $23 +#define K7 $24 +#define K8 $25 +#define K9 $9 +#define K10 $10 +#define K11 $11 +#define K12 $12 +#define K13 $13 +#define K14 $14 +#define K15 $15 +#define K16 $16 + +.text + +#define DES_2_ROUNDS_START(K) \ + and D,0xFF,tmp1; \ + extbl D,1,tmp2; \ + s8addq tmp1,SPE,tmp1; \ + s8addq tmp2,SPE,tmp2; \ + extbl D,2,tmp3; \ + ldq tmp1,0(tmp1); \ + extbl D,3,tmp4; \ + s8addq tmp3,SPE,tmp3; \ + ldq tmp2,0x200(tmp2); \ + s8addq tmp4,SPE,tmp4; \ + ldq tmp3,0x400(tmp3); \ + xor L,tmp1,L; \ + ldq tmp4,0x600(tmp4); \ + extbl D,4,tmp1; \ + xor L,tmp2,L; \ + s8addq tmp1,SPE,tmp1; \ + extbl D,5,tmp2; \ + xor L,tmp3,L; \ + ldq tmp1,0x800(tmp1); \ + s8addq tmp2,SPE,tmp2; \ + xor L,tmp4,L; \ + extbl D,6,tmp3; \ + extbl D,7,tmp4; \ + ldq tmp2,0xA00(tmp2); \ + s8addq tmp3,SPE,tmp3; \ + s8addq tmp4,SPE,tmp4; \ + ldq tmp3,0xC00(tmp3); \ + xor L,tmp1,L; \ + ldq tmp4,0xE00(tmp4); \ + xor L,tmp2,L; \ + xor L,tmp3,L; \ + xor L,tmp4,L; \ + xor K,L,D; \ + and D,0xFF,tmp1; \ + extbl D,1,tmp2; \ + s8addq tmp1,SPE,tmp1; \ + s8addq tmp2,SPE,tmp2; \ + extbl D,2,tmp3; \ + ldq tmp1,0(tmp1); \ + extbl D,3,tmp4; \ + s8addq tmp3,SPE,tmp3; \ + ldq tmp2,0x200(tmp2); \ + s8addq tmp4,SPE,tmp4; \ + ldq tmp3,0x400(tmp3); \ + xor R,tmp1,R; \ + ldq tmp4,0x600(tmp4); \ + extbl D,4,tmp1; \ + xor R,tmp2,R; \ + s8addq tmp1,SPE,tmp1; \ + extbl D,5,tmp2; \ + xor R,tmp3,R; \ + ldq tmp1,0x800(tmp1); \ + s8addq tmp2,SPE,tmp2; \ + xor R,tmp4,R; \ + extbl D,6,tmp3; \ + extbl D,7,tmp4; \ + ldq tmp2,0xA00(tmp2); \ + s8addq tmp3,SPE,tmp3; \ + s8addq tmp4,SPE,tmp4; \ + ldq tmp3,0xC00(tmp3); \ + xor R,tmp1,R; \ + ldq tmp4,0xE00(tmp4); \ + xor R,tmp2,R + +#define DES_2_ROUNDS(K1, K2) \ + DES_2_ROUNDS_START(K1); \ + xor R,tmp3,R; \ + xor R,tmp4,R; \ + xor K2,R,D + +.align 7 +.globl DES_std_crypt +.ent DES_std_crypt +DES_std_crypt: + ldgp $29,0($27) +DES_std_crypt..ng: + subq $30,56,$30 + lda tmp1,DES_IV + lda tmp2,DES_count + lda SPE,DES_SPE_F + ldq R,0(tmp1) + ldq L,8(tmp1) + ldq count,0(tmp2) + ldq K1,0(kp) + ldq K2,8(kp) + ldq K3,16(kp) + ldq K4,24(kp) + xor K1,R,D + ldq K5,32(kp) + ldq K6,40(kp) + ldq K7,48(kp) + ldq K8,56(kp) + stq K9,0($30) + stq K10,8($30) + stq K11,16($30) + stq K12,24($30) + stq K13,32($30) + stq K14,40($30) + stq K15,48($30) + ldq K9,64(kp) + ldq K10,72(kp) + ldq K11,80(kp) + ldq K12,88(kp) + ldq K13,96(kp) + ldq K14,104(kp) + ldq K15,112(kp) + ldq K16,120(kp) +DES_loop: + DES_2_ROUNDS(K2, K3) + DES_2_ROUNDS(K4, K5) + DES_2_ROUNDS(K6, K7) + DES_2_ROUNDS(K8, K9) + DES_2_ROUNDS(K10, K11) + DES_2_ROUNDS(K12, K13) + DES_2_ROUNDS(K14, K15) + DES_2_ROUNDS_START(K16) + subq count,1,count + xor R,tmp3,tmp3 + bis L,L,R + xor tmp3,tmp4,L + xor K1,R,D + bne count,DES_loop + ldq K9,0($30) + ldq K10,8($30) + ldq K11,16($30) + ldq K12,24($30) + ldq K13,32($30) + ldq K14,40($30) + ldq K15,48($30) + stq R,0(out) + addq $30,56,$30 + stq L,8(out) + ret $31,($26),1 +.end DES_std_crypt + +#undef kp +#define kp $0 +#define key1 $16 +#define key2 $17 +#define tmp5 $5 +#define tmp6 $6 +#define tmp7 $7 +#define tmp8 $8 +#define tmp9 $18 +#define tmp10 $19 +#define tmp11 $20 +#define tmp12 $21 + +#define DES_xor1(ofs) \ + ldq tmp1,ofs(key1); \ + ldq tmp2,ofs(kp); \ + ldq tmp3,ofs+8(key1); \ + ldq tmp4,ofs+8(kp); \ + ldq tmp5,ofs+16(key1); \ + ldq tmp6,ofs+16(kp); \ + xor tmp1,tmp2,tmp1; \ + ldq tmp7,ofs+24(key1); \ + xor tmp3,tmp4,tmp2; \ + ldq tmp8,ofs+24(kp); \ + stq tmp1,ofs(kp); \ + xor tmp5,tmp6,tmp3; \ + stq tmp2,ofs+8(kp); \ + xor tmp7,tmp8,tmp4; \ + stq tmp3,ofs+16(kp); \ + stq tmp4,ofs+24(kp) + +.align 3 +.globl DES_xor_key1 +.ent DES_xor_key1 +DES_xor_key1: + ldgp $29,0($27) +DES_xor_key1..ng: + lda kp,DES_KS_current + DES_xor1(0) + DES_xor1(32) + DES_xor1(64) + DES_xor1(96) + ret $31,($26),1 +.end DES_xor_key1 + +#define DES_xor2(ofs) \ + ldq tmp1,ofs(key1); \ + ldq tmp2,ofs(key2); \ + ldq tmp3,ofs(kp); \ + ldq tmp4,ofs+8(key1); \ + ldq tmp5,ofs+8(key2); \ + xor tmp1,tmp2,tmp1; \ + ldq tmp6,ofs+8(kp); \ + xor tmp1,tmp3,tmp1; \ + ldq tmp7,ofs+16(key1); \ + ldq tmp8,ofs+16(key2); \ + xor tmp4,tmp5,tmp2; \ + ldq tmp9,ofs+16(kp); \ + xor tmp2,tmp6,tmp2; \ + ldq tmp10,ofs+24(key1); \ + ldq tmp11,ofs+24(key2); \ + xor tmp7,tmp8,tmp3; \ + ldq tmp12,ofs+24(kp); \ + xor tmp3,tmp9,tmp3; \ + stq tmp1,ofs(kp); \ + xor tmp10,tmp11,tmp4; \ + stq tmp2,ofs+8(kp); \ + xor tmp4,tmp12,tmp4; \ + stq tmp3,ofs+16(kp); \ + stq tmp4,ofs+24(kp) + +.align 3 +.globl DES_xor_key2 +.ent DES_xor_key2 +DES_xor_key2: + ldgp $29,0($27) +DES_xor_key2..ng: + lda kp,DES_KS_current + DES_xor2(0) + DES_xor2(32) + DES_xor2(64) + DES_xor2(96) + ret $31,($26),1 +.end DES_xor_key2 + +.data + +.align 7 +.globl DES_SPE_F +DES_SPE_F: +.space 0x1000 + +.globl DES_IV +DES_IV: +.space 16 + +.globl DES_count +DES_count: +.space 8 + +.align 7 +.globl DES_KS_current +DES_KS_current: +.space 128 + +.comm DES_KS_table, (8 * 128 * 16 * 8), 128 + +#if defined(__ELF__) && defined(__linux__) +.section .note.GNU-stack,"",@progbits +#endif diff --git a/src/alpha.h b/src/alpha.h new file mode 100644 index 0000000..5ab04d7 --- /dev/null +++ b/src/alpha.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for Alpha. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned long)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 1 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 1 +#define BF_X2 0 + +#endif diff --git a/src/batch.c b/src/batch.c new file mode 100644 index 0000000..f26541f --- /dev/null +++ b/src/batch.c @@ -0,0 +1,61 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2003,2004 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "params.h" +#include "signals.h" +#include "loader.h" +#include "status.h" +#include "config.h" +#include "single.h" +#include "wordlist.h" +#include "inc.h" + +static void do_single_pass(struct db_main *db) +{ + do_single_crack(db); +} + +static void do_wordlist_pass(struct db_main *db) +{ + char *name; + + if (!(name = cfg_get_param(SECTION_OPTIONS, NULL, "Wordlist"))) + if (!(name = cfg_get_param(SECTION_OPTIONS, NULL, "Wordfile"))) + name = WORDLIST_NAME; + + do_wordlist_crack(db, name, 1); +} + +static void do_incremental_pass(struct db_main *db) +{ + do_incremental_crack(db, NULL); +} + +void do_batch_crack(struct db_main *db) +{ + switch (status.pass) { + case 0: + case 1: + status.pass = 1; + do_single_pass(db); + if (event_abort || !db->salts) break; + + case 2: + status.pass = 2; + do_wordlist_pass(db); + if (event_abort || !db->salts) break; + + case 3: + status.pass = 3; + do_incremental_pass(db); + } +} diff --git a/src/batch.h b/src/batch.h new file mode 100644 index 0000000..0d0adb5 --- /dev/null +++ b/src/batch.h @@ -0,0 +1,25 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Batch cracker. + */ + +#ifndef _JOHN_BATCH_H +#define _JOHN_BATCH_H + +#include "loader.h" + +/* + * Runs the cracker. + */ +extern void do_batch_crack(struct db_main *db); + +#endif diff --git a/src/bench.c b/src/bench.c new file mode 100644 index 0000000..b6f5d35 --- /dev/null +++ b/src/bench.c @@ -0,0 +1,328 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2003,2004,2006,2008-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#ifdef __ultrix__ +#define __POSIX +#define _POSIX_SOURCE +#endif + +#define NEED_OS_TIMER +#include "os.h" + +#ifdef _SCO_C_DIALECT +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "times.h" + +#include "arch.h" +#include "misc.h" +#include "math.h" +#include "params.h" +#include "memory.h" +#include "signals.h" +#include "formats.h" +#include "bench.h" + +long clk_tck = 0; + +void clk_tck_init(void) +{ + if (clk_tck) return; + +#if defined(_SC_CLK_TCK) || !defined(CLK_TCK) + clk_tck = sysconf(_SC_CLK_TCK); +#else + clk_tck = CLK_TCK; +#endif +} + +unsigned int benchmark_time = BENCHMARK_TIME; + +static volatile int bench_running; + +static void bench_handle_timer(int signum) +{ + bench_running = 0; +} + +static void bench_set_keys(struct fmt_main *format, + struct fmt_tests *current, int cond) +{ + char *plaintext; + int index, length; + + format->methods.clear_keys(); + + length = format->params.benchmark_length; + for (index = 0; index < format->params.max_keys_per_crypt; index++) { + do { + if (!current->ciphertext) + current = format->params.tests; + plaintext = current->plaintext; + current++; + + if (cond > 0) { + if ((int)strlen(plaintext) > length) break; + } else + if (cond < 0) { + if ((int)strlen(plaintext) <= length) break; + } else + break; + } while (1); + + format->methods.set_key(plaintext, index); + } +} + +char *benchmark_format(struct fmt_main *format, int salts, + struct bench_results *results) +{ + static void *binary = NULL; + static int binary_size = 0; + static char s_error[64]; + char *where; + struct fmt_tests *current; + int cond; +#if OS_TIMER + struct itimerval it; +#endif + struct tms buf; + clock_t start_real, start_virtual, end_real, end_virtual; + int64 crypts; + char *ciphertext; + void *salt, *two_salts[2]; + int index, max; + + clk_tck_init(); + + if (!(current = format->params.tests)) return "FAILED (no data)"; + if ((where = fmt_self_test(format))) { + sprintf(s_error, "FAILED (%s)", where); + return s_error; + } + + if (format->params.binary_size > binary_size) { + binary_size = format->params.binary_size; + binary = mem_alloc_tiny(binary_size, MEM_ALIGN_WORD); + memset(binary, 0x55, binary_size); + } + + for (index = 0; index < 2; index++) { + two_salts[index] = mem_alloc(format->params.salt_size); + + if ((ciphertext = format->params.tests[index].ciphertext)) { + char **fields = format->params.tests[index].fields; + if (!fields[1]) + fields[1] = ciphertext; + ciphertext = format->methods.split( + format->methods.prepare(fields, format), 0, format); + salt = format->methods.salt(ciphertext); + } else + salt = two_salts[0]; + + memcpy(two_salts[index], salt, format->params.salt_size); + } + + if (format->params.benchmark_length > 0) { + cond = (salts == 1) ? 1 : -1; + salts = 1; + } else + cond = 0; + + bench_set_keys(format, current, cond); + +#if OS_TIMER + memset(&it, 0, sizeof(it)); + if (setitimer(ITIMER_REAL, &it, NULL)) pexit("setitimer"); +#endif + + bench_running = 1; + signal(SIGALRM, bench_handle_timer); + +/* Cap it at a sane value to hopefully avoid integer overflows below */ + if (benchmark_time > 3600) + benchmark_time = 3600; + +#if OS_TIMER + if (!(it.it_value.tv_sec = benchmark_time)) { +/* Use exactly one tick for reasonable precision, but no less than 1 ms */ + if ((it.it_value.tv_usec = 1000000 / clk_tck) < 1000) + it.it_value.tv_usec = 1000; /* 1 ms */ + } + if (setitimer(ITIMER_REAL, &it, NULL)) pexit("setitimer"); +#else + sig_timer_emu_init(benchmark_time * clk_tck); +#endif + + start_real = times(&buf); + start_virtual = buf.tms_utime + buf.tms_stime; + start_virtual += buf.tms_cutime + buf.tms_cstime; + crypts.lo = crypts.hi = 0; + + index = salts; + max = format->params.max_keys_per_crypt; + do { + int count = max; + + if (!--index) { + index = salts; + if (!(++current)->ciphertext) + current = format->params.tests; + bench_set_keys(format, current, cond); + } + + if (salts > 1) format->methods.set_salt(two_salts[index & 1]); + format->methods.cmp_all(binary, + format->methods.crypt_all(&count, NULL)); + + add32to64(&crypts, count); +#if !OS_TIMER + sig_timer_emu_tick(); +#endif + } while (bench_running && !event_abort); + + end_real = times(&buf); + if (end_real == start_real) end_real++; + + end_virtual = buf.tms_utime + buf.tms_stime; + end_virtual += buf.tms_cutime + buf.tms_cstime; + if (end_virtual == start_virtual) end_virtual++; + + results->real = end_real - start_real; + results->virtual = end_virtual - start_virtual; + results->crypts = crypts; + + for (index = 0; index < 2; index++) + MEM_FREE(two_salts[index]); + + return event_abort ? "" : NULL; +} + +void benchmark_cps(int64 *crypts, clock_t time, char *buffer) +{ + unsigned int cps_hi, cps_lo; + int64 tmp; + + tmp = *crypts; + mul64by32(&tmp, clk_tck); + cps_hi = div64by32lo(&tmp, time); + + if (cps_hi >= 1000000) + sprintf(buffer, "%uK", cps_hi / 1000); + else + if (cps_hi >= 100) + sprintf(buffer, "%u", cps_hi); + else { + mul64by32(&tmp, 10); + cps_lo = div64by32lo(&tmp, time) % 10; + sprintf(buffer, "%u.%u", cps_hi, cps_lo); + } +} + +int benchmark_all(void) +{ + struct fmt_main *format; + char *result, *msg_1, *msg_m; + struct bench_results results_1, results_m; + char s_real[64], s_virtual[64]; + unsigned int total, failed; + + if (!benchmark_time) + puts("Warning: doing quick benchmarking - " + "the performance numbers will be inaccurate"); + + total = failed = 0; + if ((format = fmt_list)) + do { + printf("Benchmarking: %s%s%s%s [%s]... ", + format->params.label, + format->params.format_name[0] ? ", " : "", + format->params.format_name, + format->params.benchmark_comment, + format->params.algorithm_name); + fflush(stdout); + + switch (format->params.benchmark_length) { + case -1: + msg_m = "Raw"; + msg_1 = NULL; + break; + + case 0: + msg_m = "Many salts"; + msg_1 = "Only one salt"; + break; + + default: + msg_m = "Short"; + msg_1 = "Long"; + } + + total++; + + if ((result = benchmark_format(format, + format->params.salt_size ? BENCHMARK_MANY : 1, + &results_m))) { + puts(result); + failed++; + goto next; + } + + if (msg_1) + if ((result = benchmark_format(format, 1, &results_1))) { + puts(result); + failed++; + goto next; + } + + puts("DONE"); + + benchmark_cps(&results_m.crypts, results_m.real, s_real); + benchmark_cps(&results_m.crypts, results_m.virtual, s_virtual); +#if !defined(__DJGPP__) && !defined(__BEOS__) + printf("%s:\t%s c/s real, %s c/s virtual\n", + msg_m, s_real, s_virtual); +#else + printf("%s:\t%s c/s\n", + msg_m, s_real); +#endif + + if (!msg_1) { + putchar('\n'); + goto next; + } + + benchmark_cps(&results_1.crypts, results_1.real, s_real); + benchmark_cps(&results_1.crypts, results_1.virtual, s_virtual); +#if !defined(__DJGPP__) && !defined(__BEOS__) + printf("%s:\t%s c/s real, %s c/s virtual\n\n", + msg_1, s_real, s_virtual); +#else + printf("%s:\t%s c/s\n\n", + msg_1, s_real); +#endif + +next: + fmt_done(format); + } while ((format = format->next) && !event_abort); + + if (failed && total > 1 && !event_abort) + printf("%u out of %u tests have FAILED\n", failed, total); + + return failed || event_abort; +} diff --git a/src/bench.h b/src/bench.h new file mode 100644 index 0000000..f99149f --- /dev/null +++ b/src/bench.h @@ -0,0 +1,71 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2006,2009,2011,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Cracking algorithm benchmark. + */ + +#ifndef _JOHN_BENCH_H +#define _JOHN_BENCH_H + +#include + +#include "arch.h" +#include "math.h" +#include "formats.h" + +/* + * Structure used to return benchmark results. + */ +struct bench_results { +/* Elapsed real and processor time */ + clock_t real, virtual; + +/* Number of ciphertexts computed */ + int64 crypts; +}; + +/* + * Clock ticks per second - either as obtained via sysconf(_SC_CLK_TCK) + * or the constant CLK_TCK. + */ +extern long clk_tck; + +/* + * Initializes clk_tck on the first invocation; does nothing afterwards. + */ +extern void clk_tck_init(void); + +/* + * Benchmark time in seconds (per cracking algorithm). + */ +extern unsigned int benchmark_time; + +/* + * Benchmarks the supplied cracking algorithm. Returns NULL on success, + * an error message if the self-test fails or there are no test vectors + * for this algorithm, or an empty string if aborted. + */ +extern char *benchmark_format(struct fmt_main *format, int salts, + struct bench_results *results); + +/* + * Converts benchmarked c/s into an ASCII string. + */ +extern void benchmark_cps(int64 *crypts, clock_t time, char *buffer); + +/* + * Benchmarks all the registered cracking algorithms and prints the results + * to stdout. Returns zero on success, non-zero if any tests failed or were + * aborted. + */ +extern int benchmark_all(void); + +#endif diff --git a/src/best.c b/src/best.c new file mode 100644 index 0000000..9164ee0 --- /dev/null +++ b/src/best.c @@ -0,0 +1,104 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2006,2011-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Benchmark to detect the best algorithm for a particular architecture. + */ + +#ifdef __ultrix__ +#define __POSIX +#define _POSIX_SOURCE +#endif + +#define NEED_OS_FORK +#include "os.h" + +#ifdef _SCO_C_DIALECT +#include +#endif +#include +#include + +#include "math.h" +#include "params.h" +#include "common.h" +#include "formats.h" +#include "bench.h" + +extern struct fmt_main fmt_DES, fmt_MD5, fmt_BF; + +int john_main_process = 0; +#if OS_FORK +int john_child_count = 0; +int *john_child_pids = NULL; +#endif + +int main(int argc, char **argv) +{ + struct fmt_main *format; + struct bench_results results; + unsigned long virtual; + int64 tmp; + char s_real[64], s_virtual[64]; + + if (argc != 2) return 1; + + switch (argv[1][0]) { + case '1': + format = &fmt_DES; + break; + + case '2': + format = &fmt_MD5; + break; + + case '3': + format = &fmt_BF; + break; + + default: + return 1; + } + + fprintf(stderr, "Benchmarking: %s%s%s%s [%s]... ", + format->params.label, + format->params.format_name[0] ? ", " : "", + format->params.format_name, + format->params.benchmark_comment, + format->params.algorithm_name); + + common_init(); + + if (benchmark_format(format, BENCHMARK_MANY, &results)) { + virtual = 0; + + fprintf(stderr, "FAILED\n"); + } else { + tmp = results.crypts; + mul64by32(&tmp, clk_tck * 10); +#ifdef _OPENMP + virtual = div64by32lo(&tmp, results.real); +#else + virtual = div64by32lo(&tmp, results.virtual); +#endif + + benchmark_cps(&results.crypts, results.real, s_real); + benchmark_cps(&results.crypts, results.virtual, s_virtual); + + fprintf(stderr, "%s c/s real, %s c/s virtual\n", + s_real, s_virtual); + } + + fmt_done(format); + + printf("%lu\n", virtual); + + return virtual ? 0 : 1; +} diff --git a/src/best.sh b/src/best.sh new file mode 100755 index 0000000..5e671b1 --- /dev/null +++ b/src/best.sh @@ -0,0 +1,136 @@ +#!/bin/sh +# +# This file is part of John the Ripper password cracker, +# Copyright (c) 1996-2000,2003,2005,2008,2011 by Solar Designer +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted. +# +# There's ABSOLUTELY NO WARRANTY, express or implied. +# + +[ $# -eq 5 ] || exit 1 + +MAKE=$1 +DES_DEPEND=$2 +DES_BS_DEPEND=$3 +MD5_DEPEND=$4 +BF_DEPEND=$5 + +# Detect the best non-bitslice DES algorithm + +MAX=0 +DES_BEST=1 + +for MODE in 1 2 3 4 5; do + if ./detect $MODE 1 0 0 0 0 0 > arch.h; then + rm -f $DES_DEPEND bench + echo "Compiling: DES benchmark (code version #$MODE)" + $MAKE bench || exit 1 + RES=`./bench 1` || exit 1 + if [ $RES -gt $MAX ]; then + MAX=$RES + DES_BEST=$MODE + fi + fi +done + +./detect $DES_BEST 0 0 0 0 0 0 > arch.h +rm -f $DES_DEPEND bench + +echo "Compiling: DES benchmark (code version #$DES_BEST, no key copying)" +$MAKE bench || exit 1 +RES=`./bench 1` || exit 1 +if [ $RES -gt $MAX ]; then + MAX=$RES + DES_COPY=0 +else + DES_COPY=1 +fi + +# Check if bitslice DES is faster + +DES_BS=0 + +rm -f $DES_DEPEND bench + +for MODE in 1 2 3; do + if ./detect $DES_BEST $DES_COPY $MODE 0 0 0 0 > arch.h; then + echo "Compiling: DES benchmark (bitslice, code version #$MODE)" + if [ $MODE -gt 1 ]; then + rm -f $DES_BS_DEPEND bench + fi + $MAKE bench || exit 1 + RES=`./bench 1` || exit 1 + if [ $RES -gt $MAX ]; then + MAX=$RES + DES_BS=$MODE + fi + fi +done + +# Detect the best MD5 algorithm + +MAX=`./bench 2` || exit 1 + +./detect $DES_BEST $DES_COPY $DES_BS 1 0 0 0 > arch.h +rm -f $MD5_DEPEND bench + +echo "Compiling: MD5 benchmark (two hashes at a time)" +$MAKE bench || exit 1 +RES=`./bench 2` || exit 1 +if [ $RES -gt $MAX ]; then + MAX=$RES + MD5_X2=1 +else + MD5_X2=0 +fi + +./detect $DES_BEST $DES_COPY $DES_BS $MD5_X2 1 0 0 > arch.h +rm -f $MD5_DEPEND bench + +echo "Compiling: MD5 benchmark (immediate values)" +$MAKE bench || exit 1 +RES=`./bench 2` || exit 1 +if [ $RES -gt $MAX ]; then + MD5_IMM=1 +else + MD5_IMM=0 +fi + +# Detect the best Blowfish algorithm + +MAX=`./bench 3` || exit 1 + +./detect $DES_BEST $DES_COPY $DES_BS $MD5_X2 $MD5_IMM 1 0 > arch.h +rm -f $BF_DEPEND bench + +echo "Compiling: Blowfish benchmark (scale)" +$MAKE bench || exit 1 +RES=`./bench 3` || exit 1 +if [ $RES -gt $MAX ]; then + MAX=$RES + BF_SCALE=1 +else + BF_SCALE=0 +fi + +./detect $DES_BEST $DES_COPY $DES_BS $MD5_X2 $MD5_IMM $BF_SCALE 1 > arch.h +rm -f $BF_DEPEND bench + +echo "Compiling: Blowfish benchmark (two hashes at a time)" +$MAKE bench || exit 1 +RES=`./bench 3` || exit 1 +if [ $RES -gt $MAX ]; then + BF_X2=1 +else + BF_X2=0 +fi + +# Produce generic.h, make sure everything is rebuilt with detected options, +# and do some cleanup + +./detect $DES_BEST $DES_COPY $DES_BS $MD5_X2 $MD5_IMM $BF_SCALE $BF_X2 \ + > generic.h +rm -f $DES_DEPEND $DES_BS_DEPEND $MD5_DEPEND $BF_DEPEND \ + bench detect best.o detect.o arch.h diff --git a/src/c3_fmt.c b/src/c3_fmt.c new file mode 100644 index 0000000..eea2f54 --- /dev/null +++ b/src/c3_fmt.c @@ -0,0 +1,504 @@ +/* + * Generic crypt(3) support, as well as support for glibc's crypt_r(3) and + * Solaris' MT-safe crypt(3C) with OpenMP parallelization. + * + * This file is part of John the Ripper password cracker, + * Copyright (c) 2009-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _XOPEN_SOURCE 4 /* for crypt(3) */ +#define _XOPEN_SOURCE_EXTENDED +#define _XOPEN_VERSION 4 +#define _XPG4_2 +#define _GNU_SOURCE /* for crypt_r(3) */ +#include +#include +#if defined(_OPENMP) && defined(__GLIBC__) +#include +#include /* for omp_get_thread_num() */ +#else +#include +#endif + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "memory.h" +#include "common.h" +#include "formats.h" +#include "loader.h" + +#define FORMAT_LABEL "crypt" +#define FORMAT_NAME "generic crypt(3)" +#define ALGORITHM_NAME "?/" ARCH_BITS_STR + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH 0 + +#define PLAINTEXT_LENGTH 72 + +#define BINARY_SIZE 128 +#define BINARY_ALIGN 1 +#define SALT_SIZE BINARY_SIZE +#define SALT_ALIGN 1 + +#define MIN_KEYS_PER_CRYPT 96 +#define MAX_KEYS_PER_CRYPT 96 + +static struct fmt_tests tests[] = { + {"CCNf8Sbh3HDfQ", "U*U*U*U*"}, + {"CCX.K.MFy4Ois", "U*U***U"}, + {"CC4rMpbg9AMZ.", "U*U***U*"}, + {"XXxzOu6maQKqQ", "*U*U*U*U"}, + {"SDbsugeBiC58A", ""}, + {NULL} +}; + +static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1]; +static char saved_salt[SALT_SIZE]; +static char crypt_out[MAX_KEYS_PER_CRYPT][BINARY_SIZE]; + +#if defined(_OPENMP) && defined(__GLIBC__) +#define MAX_THREADS MAX_KEYS_PER_CRYPT + +/* We assume that this is zero-initialized (all NULL pointers) */ +static struct crypt_data *crypt_data[MAX_THREADS]; +#endif + +static int valid(char *ciphertext, struct fmt_main *self) +{ + int length, count_base64, id, pw_length; + char pw[PLAINTEXT_LENGTH + 1], *new_ciphertext; +/* We assume that these are zero-initialized */ + static char sup_length[BINARY_SIZE], sup_id[0x80]; + + length = count_base64 = 0; + while (ciphertext[length]) { + if (atoi64[ARCH_INDEX(ciphertext[length])] != 0x7F && + (ciphertext[0] == '_' || length >= 2)) + count_base64++; + length++; + } + + if (length < 13 || length >= BINARY_SIZE) + return 0; + + id = 0; + if (length == 13 && count_base64 == 11) + id = 1; + else + if (length >= 13 && + count_base64 >= length - 2 && /* allow for invalid salt */ + (length - 2) % 11 == 0) + id = 2; + else + if (length == 20 && count_base64 == 19 && ciphertext[0] == '_') + id = 3; + else + if (ciphertext[0] == '$') { + id = (unsigned char)ciphertext[1]; + if (id <= 0x20 || id >= 0x80) + id = 9; + } else + if (ciphertext[0] == '*' || ciphertext[0] == '!') /* likely locked */ + id = 10; + +/* Previously detected as supported */ + if (sup_length[length] > 0 && sup_id[id] > 0) + return 1; + +/* Previously detected as unsupported */ + if (sup_length[length] < 0 && sup_id[id] < 0) + return 0; + + pw_length = ((length - 2) / 11) << 3; + if (pw_length >= sizeof(pw)) + pw_length = sizeof(pw) - 1; + memcpy(pw, ciphertext, pw_length); /* reuse the string, why not? */ + pw[pw_length] = 0; + +#if defined(_OPENMP) && defined(__GLIBC__) +/* + * Let's use crypt_r(3) just like we will in crypt_all() below. + * It is possible that crypt(3) and crypt_r(3) differ in their supported hash + * types on a given system. + */ + { + struct crypt_data **data = &crypt_data[0]; + if (!*data) { +/* + * **data is not exactly tiny, but we use mem_alloc_tiny() for its alignment + * support and error checking. We do not need to free() this memory anyway. + * + * The page alignment is to keep different threads' data on different pages. + */ + *data = mem_alloc_tiny(sizeof(**data), MEM_ALIGN_PAGE); + memset(*data, 0, sizeof(**data)); + } + new_ciphertext = crypt_r(pw, ciphertext, *data); + } +#else + new_ciphertext = crypt(pw, ciphertext); +#endif + + if (new_ciphertext && strlen(new_ciphertext) == length && + !strncmp(new_ciphertext, ciphertext, 2)) { + sup_length[length] = 1; + sup_id[id] = 1; + return 1; + } + + if (id != 10 && !ldr_in_pot) + fprintf(stderr, "Warning: " + "hash encoding string length %d, type id %c%c\n" + "appears to be unsupported on this system; " + "will not load such hashes.\n", + length, id > 0x20 ? '$' : '#', id > 0x20 ? id : '0' + id); + + if (!sup_length[length]) + sup_length[length] = -1; + if (!sup_id[id]) + sup_id[id] = -1; + return 0; +} + +static void *binary(char *ciphertext) +{ + static char out[BINARY_SIZE]; + strncpy(out, ciphertext, sizeof(out)); /* NUL padding is required */ + return out; +} + +static void *salt(char *ciphertext) +{ + static char out[SALT_SIZE]; + int cut = sizeof(out); + +#if 1 +/* This piece is optional, but matching salts are not detected without it */ + int length = strlen(ciphertext); + + switch (length) { + case 13: + case 24: + cut = 2; + break; + + case 20: + if (ciphertext[0] == '_') cut = 9; + break; + + case 35: + case 46: + case 57: + if (ciphertext[0] != '$') cut = 2; + /* fall through */ + + default: + if ((length >= 26 && length <= 34 && + !strncmp(ciphertext, "$1$", 3)) || + (length >= 47 && !strncmp(ciphertext, "$5$", 3)) || + (length >= 90 && !strncmp(ciphertext, "$6$", 3))) { + char *p = strrchr(ciphertext + 3, '$'); + if (p) cut = p - ciphertext; + } else + if (length == 59 && !strncmp(ciphertext, "$2$", 3)) + cut = 28; + else + if (length == 60 && + (!strncmp(ciphertext, "$2a$", 4) || + !strncmp(ciphertext, "$2x$", 4) || + !strncmp(ciphertext, "$2y$", 4))) + cut = 29; + else + if (length >= 27 && + (!strncmp(ciphertext, "$md5$", 5) || + !strncmp(ciphertext, "$md5,", 5))) { + char *p = strrchr(ciphertext + 4, '$'); + if (p) { + /* NUL padding is required */ + memset(out, 0, sizeof(out)); + memcpy(out, ciphertext, ++p - ciphertext); +/* + * Workaround what looks like a bug in sunmd5.c: crypt_genhash_impl() where it + * takes a different substring as salt depending on whether the optional + * existing hash encoding is present after the salt or not. Specifically, the + * last '$' delimiter is included into the salt when there's no existing hash + * encoding after it, but is omitted from the salt otherwise. + */ + out[p - ciphertext] = 'x'; + return out; + } + } + } +#endif + + /* NUL padding is required */ + memset(out, 0, sizeof(out)); + memcpy(out, ciphertext, cut); + + return out; +} + +#define H(s, i) \ + ((int)(unsigned char)(atoi64[ARCH_INDEX((s)[(i)])] ^ (s)[(i) - 1])) + +#define H0(s) \ + int i = strlen(s) - 2; \ + return i > 0 ? H((s), i) & 0xF : 0 +#define H1(s) \ + int i = strlen(s) - 2; \ + return i > 2 ? (H((s), i) ^ (H((s), i - 2) << 4)) & 0xFF : 0 +#define H2(s) \ + int i = strlen(s) - 2; \ + return i > 2 ? (H((s), i) ^ (H((s), i - 2) << 6)) & 0xFFF : 0 +#define H3(s) \ + int i = strlen(s) - 2; \ + return i > 4 ? (H((s), i) ^ (H((s), i - 2) << 5) ^ \ + (H((s), i - 4) << 10)) & 0xFFFF : 0 +#define H4(s) \ + int i = strlen(s) - 2; \ + return i > 6 ? (H((s), i) ^ (H((s), i - 2) << 5) ^ \ + (H((s), i - 4) << 10) ^ (H((s), i - 6) << 15)) & 0xFFFFF : 0 + +static int binary_hash_0(void *binary) +{ + H0((char *)binary); +} + +static int binary_hash_1(void *binary) +{ + H1((char *)binary); +} + +static int binary_hash_2(void *binary) +{ + H2((char *)binary); +} + +static int binary_hash_3(void *binary) +{ + H3((char *)binary); +} + +static int binary_hash_4(void *binary) +{ + H4((char *)binary); +} + +static int get_hash_0(int index) +{ + H0(crypt_out[index]); +} + +static int get_hash_1(int index) +{ + H1(crypt_out[index]); +} + +static int get_hash_2(int index) +{ + H2(crypt_out[index]); +} + +static int get_hash_3(int index) +{ + H3(crypt_out[index]); +} + +static int get_hash_4(int index) +{ + H4(crypt_out[index]); +} + +static int salt_hash(void *salt) +{ + int i, h; + + i = strlen((char *)salt) - 1; + if (i > 1) i--; + + h = (unsigned char)atoi64[ARCH_INDEX(((char *)salt)[i])]; + h ^= ((unsigned char *)salt)[i - 1]; + h <<= 6; + h ^= (unsigned char)atoi64[ARCH_INDEX(((char *)salt)[i - 1])]; + h ^= ((unsigned char *)salt)[i]; + + return h & (SALT_HASH_SIZE - 1); +} + +static void set_salt(void *salt) +{ + strcpy(saved_salt, salt); +} + +static void set_key(char *key, int index) +{ + strnzcpy(saved_key[index], key, PLAINTEXT_LENGTH + 1); +} + +static char *get_key(int index) +{ + return saved_key[index]; +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + static int warned = 0; + int count = *pcount; + int index; + +#if defined(_OPENMP) && defined(__GLIBC__) +#pragma omp parallel for default(none) private(index) shared(warned, count, crypt_out, saved_key, saved_salt, crypt_data, stderr) + for (index = 0; index < count; index++) { + char *hash; + int t = omp_get_thread_num(); + if (t < MAX_THREADS) { + struct crypt_data **data = &crypt_data[t]; + if (!*data) { +/* Stagger the structs to reduce their competition for the same cache lines */ + size_t mask = MEM_ALIGN_PAGE, shift = 0; + while (t) { + mask >>= 1; + if (mask < MEM_ALIGN_CACHE) + break; + if (t & 1) + shift += mask; + t >>= 1; + } + *data = (void *)((char *) + mem_alloc_tiny(sizeof(**data) + + shift, MEM_ALIGN_PAGE) + shift); + memset(*data, 0, sizeof(**data)); + } + hash = crypt_r(saved_key[index], saved_salt, *data); + } else { /* should not happen */ + struct crypt_data data; + memset(&data, 0, sizeof(data)); + hash = crypt_r(saved_key[index], saved_salt, &data); + } + if (!hash) { +#pragma omp critical + if (!warned) { + fprintf(stderr, + "Warning: crypt_r() returned NULL\n"); + warned = 1; + } + hash = ""; + } + strnzcpy(crypt_out[index], hash, BINARY_SIZE); + } +#else +#if defined(_OPENMP) && defined(__sun) +/* + * crypt(3C) is MT-safe on Solaris. For traditional DES-based hashes, this is + * implemented with locking (hence there's no speedup from the use of multiple + * threads, and the per-thread performance is extremely poor anyway). For + * modern hash types, the function is actually able to compute multiple hashes + * in parallel by different threads (and the performance for some hash types is + * reasonable). Overall, this code is reasonable to use for SHA-crypt and + * SunMD5 hashes, which are not yet supported by non-jumbo John natively. + */ +#pragma omp parallel for default(none) private(index) shared(warned, count, crypt_out, saved_key, saved_salt, stderr) +#endif + for (index = 0; index < count; index++) { + char *hash = crypt(saved_key[index], saved_salt); + if (!hash) { +#if defined(_OPENMP) && defined(__sun) +#pragma omp critical +#endif + if (!warned) { + fprintf(stderr, + "Warning: crypt() returned NULL\n"); + warned = 1; + } + hash = ""; + } + strnzcpy(crypt_out[index], hash, BINARY_SIZE); + } +#endif + + return count; +} + +static int cmp_all(void *binary, int count) +{ + int index; + + for (index = 0; index < count; index++) + if (!strcmp((char *)binary, crypt_out[index])) + return 1; + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + return !strcmp((char *)binary, crypt_out[index]); +} + +static int cmp_exact(char *source, int index) +{ + return 1; +} + +struct fmt_main fmt_crypt = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT | FMT_OMP, + tests + }, { + fmt_default_init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + binary, + salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + NULL, + NULL + }, + salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + NULL, + NULL + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/charset.c b/src/charset.c new file mode 100644 index 0000000..df045a9 --- /dev/null +++ b/src/charset.c @@ -0,0 +1,716 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2005,2008,2010-2013 by Solar Designer + */ + +#include +#include +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "list.h" +#include "crc32.h" +#include "signals.h" +#include "loader.h" +#include "external.h" +#include "charset.h" + +typedef unsigned int (*char_counters) + [CHARSET_SIZE + 1][CHARSET_SIZE + 1][CHARSET_SIZE]; + +typedef unsigned int (*crack_counters) + [CHARSET_LENGTH][CHARSET_LENGTH][CHARSET_SIZE]; + +static CRC32_t checksum; + +static unsigned long charset_filter_plaintexts(struct db_main *db, + struct list_main **lists) +{ + int length, old_length; + unsigned long count; + struct list_entry *current, *next; + char *ptr, key[PLAINTEXT_BUFFER_SIZE]; + + for (length = 0; length <= CHARSET_LENGTH; length++) + list_init(&lists[length]); + + count = 0; + + if ((current = db->plaintexts->head)) + do { + next = current->next; + + if (!current->data[0]) + continue; + + old_length = 0; + ptr = current->data; + if (f_filter) { + old_length = strlen(current->data); +/* + * The current->data string might happen to end near page boundary and the next + * page might not be mapped, whereas ext_filter_body() may pre-read a few chars + * beyond NUL for greater speed in uses during cracking. Also, the external + * filter() may make the string longer. Finally, ext_filter_body() assumes + * that the string passed to it fits in PLAINTEXT_BUFFER_SIZE. Hence, we copy + * the string here. + */ + if (old_length < sizeof(key)) { + memcpy(key, current->data, old_length + 1); + } else { + memcpy(key, current->data, sizeof(key) - 1); + key[sizeof(key) - 1] = 0; + } + if (!ext_filter_body(key, key)) + continue; + ptr = key; + } + + length = 0; + while (*ptr) { + int c = *(unsigned char *)ptr; + if (c < CHARSET_MIN || c > CHARSET_MAX) + break; + length++; + ptr++; + } + + if (!*ptr) { + struct list_main *list; +/* + * lists[CHARSET_LENGTH] is a catch-all for excessive length strings that + * nevertheless consist exclusively of characters in the CHARSET_MIN to + * CHARSET_MAX range (including in their portion beyond CHARSET_LENGTH). + */ + if (length > CHARSET_LENGTH) + list = lists[CHARSET_LENGTH]; + else + list = lists[length - 1]; + if (old_length) { + if (length > old_length) { + list_add(list, key); + } else { + memcpy(current->data, key, length + 1); + list_add_link(list, current); + } + } else { +/* + * Truncate very long strings at PLAINTEXT_BUFFER_SIZE for consistency with + * what would happen if we applied a dummy filter(), as well as for easy + * testing against older revisions of this code. + */ + if (length >= PLAINTEXT_BUFFER_SIZE) + current->data + [PLAINTEXT_BUFFER_SIZE - 1] = 0; + list_add_link(list, current); + } + count++; + } + } while ((current = next)); + + return count; +} + +static int cfputc(int c, FILE *stream) +{ + unsigned char ch; + + ch = c; + CRC32_Update(&checksum, &ch, 1); + + return fputc(c, stream); +} + +static void charset_checksum_header(struct charset_header *header) +{ + CRC32_Update(&checksum, header->version, sizeof(header->version)); + CRC32_Update(&checksum, &header->min, 1); + CRC32_Update(&checksum, &header->max, 1); + CRC32_Update(&checksum, &header->length, 1); + CRC32_Update(&checksum, &header->count, 1); + CRC32_Update(&checksum, header->offsets, sizeof(header->offsets)); + CRC32_Update(&checksum, header->order, sizeof(header->order)); + CRC32_Final(header->check, checksum); +} + +static void charset_write_header(FILE *file, struct charset_header *header) +{ + fwrite(header->version, sizeof(header->version), 1, file); + fwrite(header->check, sizeof(header->check), 1, file); + fputc(header->min, file); + fputc(header->max, file); + fputc(header->length, file); + fputc(header->count, file); + fwrite(header->offsets, sizeof(header->offsets), 1, file); + fwrite(header->order, sizeof(header->order), 1, file); +} + +int charset_read_header(FILE *file, struct charset_header *header) +{ + if (fread(header->version, sizeof(header->version), 1, file) != 1 || + fread(header->check, sizeof(header->check), 1, file) != 1) + return -1; + { + unsigned char values[4]; + if (fread(values, sizeof(values), 1, file) != 1) + return -1; + header->min = values[0]; + header->max = values[1]; + header->length = values[2]; + header->count = values[3]; + } + return + fread(header->offsets, sizeof(header->offsets), 1, file) != 1 || + fread(header->order, sizeof(header->order), 1, file) != 1; +} + +static int charset_new_length(int length, + struct charset_header *header, FILE *file) +{ + int result; + long offset; + + if ((result = length < CHARSET_LENGTH)) { + putchar('.'); + fflush(stdout); + + if ((offset = ftell(file)) < 0) pexit("ftell"); + header->offsets[length][0] = offset; + header->offsets[length][1] = offset >> 8; + header->offsets[length][2] = offset >> 16; + header->offsets[length][3] = offset >> 24; + } + + return result; +} + +typedef struct { + int index; + unsigned int value; +} count_sort_t; + +static int cmp_count(const void *p1, const void *p2) +{ + const count_sort_t *c1 = (const count_sort_t *)p1; + const count_sort_t *c2 = (const count_sort_t *)p2; + int diff = (int)c2->value - (int)c1->value; + if (diff) + return diff; + return c1->index - c2->index; +} + +static void charset_generate_chars(struct list_main **lists, + FILE *file, struct charset_header *header, + char_counters chars, crack_counters cracks) +{ + struct list_entry *current; + unsigned char buffer[CHARSET_SIZE]; + count_sort_t iv[CHARSET_SIZE]; + int length, pos, count; + int i, j, k; + + memset(cracks, 0, sizeof(*cracks)); + +/* Zeroize the same portion of "chars" as is used by the loop below */ + memset((*chars)[0][0], 0, sizeof((*chars)[0][0])); + + for (length = 0; length <= CHARSET_LENGTH; length++) { + if ((current = lists[length]->head)) + do { + char *ptr; + for (ptr = current->data; *ptr; ptr++) { + int c = *(unsigned char *)ptr; + (*chars)[0][0][ARCH_INDEX(c - CHARSET_MIN)]++; + } + } while ((current = current->next)); + } + + count = 0; + for (k = 0; k < CHARSET_SIZE; k++) { + unsigned int value = (*chars)[0][0][k]; + if (value) { + iv[count].index = k; + iv[count++].value = value; + } + } + + if (count > 1) + qsort(iv, count, sizeof(iv[0]), cmp_count); + + for (k = 0; k < count; k++) + buffer[k] = CHARSET_MIN + iv[k].index; + + header->count = count; + fwrite(buffer, 1, count, file); + CRC32_Update(&checksum, buffer, count); + + for (length = 0; charset_new_length(length, header, file); length++) + for (pos = 0; pos <= length; pos++) { + if (event_abort) + return; + + if (!(current = lists[length]->head)) + continue; + + switch (pos) { + case 0: + memset((*chars)[CHARSET_SIZE][CHARSET_SIZE], 0, + sizeof((*chars)[CHARSET_SIZE][CHARSET_SIZE])); + do { + unsigned char *ptr = + (unsigned char *)current->data; + int c = ARCH_INDEX(ptr[0] - CHARSET_MIN); + (*chars)[CHARSET_SIZE][CHARSET_SIZE][c]++; + } while ((current = current->next)); + break; + case 1: + memset((*chars)[CHARSET_SIZE], 0, + sizeof((*chars)[CHARSET_SIZE])); + do { + unsigned char *ptr = + (unsigned char *)current->data; + int b = ARCH_INDEX(ptr[0] - CHARSET_MIN); + int c = ARCH_INDEX(ptr[1] - CHARSET_MIN); + (*chars)[CHARSET_SIZE][b][c]++; + (*chars)[CHARSET_SIZE][CHARSET_SIZE][c]++; + } while ((current = current->next)); + break; + default: + memset(chars, 0, sizeof(*chars)); + do { + unsigned char *ptr = + (unsigned char *)current->data; + int a = ARCH_INDEX(ptr[pos - 2] - CHARSET_MIN); + int b = ARCH_INDEX(ptr[pos - 1] - CHARSET_MIN); + int c = ARCH_INDEX(ptr[pos] - CHARSET_MIN); + (*chars)[a][b][c]++; + (*chars)[CHARSET_SIZE][b][c]++; + (*chars)[CHARSET_SIZE][CHARSET_SIZE][c]++; + } while ((current = current->next)); + } + + cfputc(CHARSET_ESC, file); cfputc(CHARSET_NEW, file); + cfputc(length, file); cfputc(pos, file); + + for (i = (pos > 1 ? 0 : CHARSET_SIZE); i <= CHARSET_SIZE; i++) + for (j = (pos ? 0 : CHARSET_SIZE); j <= CHARSET_SIZE; j++) { + count = 0; + for (k = 0; k < CHARSET_SIZE; k++) { + unsigned int value = (*chars)[i][j][k]; + if (value) { + iv[count].index = k; + iv[count++].value = value; + } + } + + if (!count) + continue; + + if (count > 1) + qsort(iv, count, sizeof(iv[0]), cmp_count); + + if (i == CHARSET_SIZE && j == CHARSET_SIZE) + for (k = 0; k < count; k++) + (*cracks)[length][pos][k] = iv[k].value; + + for (k = 0; k < count; k++) + buffer[k] = CHARSET_MIN + iv[k].index; + + cfputc(CHARSET_ESC, file); cfputc(CHARSET_LINE, file); + cfputc(i, file); cfputc(j, file); + fwrite(buffer, 1, count, file); + CRC32_Update(&checksum, buffer, count); + } + } + + cfputc(CHARSET_ESC, file); cfputc(CHARSET_NEW, file); + cfputc(CHARSET_LENGTH, file); +} + +static double powi(int x, unsigned int y) +{ + double a = 1.0; + if (y) { + double b = x; + do { + if (y & 1) + a *= b; + if (!(y >>= 1)) + break; + b *= b; + } while (1); + } + return a; +} + +typedef struct { + int length, pos, count; + double value; +} ratio_sort_t; + +static int cmp_ratio(const void *p1, const void *p2) +{ + const ratio_sort_t *r1 = (const ratio_sort_t *)p1; + const ratio_sort_t *r2 = (const ratio_sort_t *)p2; + int diff; + if (r1->value < r2->value) + return -1; + if (r1->value > r2->value) + return 1; + diff = r1->length - r2->length; + if (diff) + return diff; +#if 1 + diff = r1->count - r2->count; + if (diff) + return diff; + return r1->pos - r2->pos; +#else +/* + * Stabilize the sorting order differently for testing against older revisions + * of the code. This kind of stabilization is arguably illogical and it tends + * to require many more recalculations. + */ + diff = r1->pos - r2->pos; + if (diff) + return diff; + return r1->count - r2->count; +#endif +} + +/* + * This generates the "cracking order" (please see the comment in charset.h) + * based on the number of candidate passwords for each {length, fixed index + * position, character count} combination, and on the number of cracked + * passwords for that combination. The idea is to start with combinations for + * which the ratio between the number of candidates and the number of + * successful cracks is the smallest. This way, the expected number of + * successful cracks per unit of time will be monotonically non-increasing + * over time. Of course, this applies to the expectation only (based on + * available statistics) - actual behavior (on a yet unknown set of passwords + * to be cracked) may and likely will differ. Additionally, there are some + * algorithmic constraints, which may force us to deviate from the perfect + * monotonically non-decreasing sequence of ratios. + * + * The cracks[] array is used as input (containing the number of successful + * cracks for each combination). + */ +static void charset_generate_order(crack_counters cracks, + unsigned char *order, int size) +{ + int length, pos, count; /* zero-based */ + int nratios, taken; + double total; + unsigned char *ptr, *end; + ratio_sort_t (*ratios) + [CHARSET_LENGTH * (CHARSET_LENGTH + 1) / 2 * CHARSET_SIZE]; + int counts[CHARSET_LENGTH][CHARSET_LENGTH]; + int recalcs, diff, prev_diff, same_diff, best_diff; + unsigned char *best_order; + + ratios = mem_alloc(sizeof(*ratios)); + +/* Calculate the ratios */ + + nratios = 0; + for (length = 0; length < CHARSET_LENGTH; length++) + for (count = 0; count < CHARSET_SIZE; count++) { +/* First, calculate the number of candidate passwords for this combination of + * length and count (number of different character indices). We subtract the + * number of candidates for the previous count (at the same length) because + * those are to be tried as a part of another combination. */ + total = powi(count + 1, length + 1) - powi(count, length + 1); + +/* Calculate the number of candidates for a {length, fixed index position, + * character count} combination, for the specific values of length and count. + * Obviously, this value is the same for each position in which the character + * index is fixed - it only depends on the length and count - which is why we + * calculate it out of the inner loop. */ + if (count) + total /= length + 1; + +/* Finally, for each fixed index position separately, calculate the candidates + * to successful cracks ratio. We treat combinations with no successful cracks + * (so far) the same as those with exactly one successful crack. */ + for (pos = 0; pos <= length; pos++) { + double ratio = total; + unsigned int div = (*cracks)[length][pos][count]; + if (div) + ratio /= div; + (*ratios)[nratios].length = length; + (*ratios)[nratios].pos = pos; + (*ratios)[nratios].count = count; + (*ratios)[nratios++].value = ratio; + } + } + + recalcs = prev_diff = same_diff = 0; + best_diff = 0x7fffffff; + best_order = NULL; + +again: + + assert(nratios == sizeof(*ratios) / sizeof((*ratios)[0])); + +/* + * Fill out the order[] with combinations sorted for (mostly) non-decreasing + * ratios (except as we may have to deviate from this to meet the + * "count == counts[length][pos]" constraint). + */ + + qsort(ratios, nratios, sizeof((*ratios)[0]), cmp_ratio); + + memset(counts, 0, sizeof(counts)); + + diff = 0; + taken = 0; + ptr = order; + do { +/* Find the minimum non-taken ratio and its corresponding combination */ + int found = 0, alltaken = 1; + int i; + + for (i = taken; i < nratios; i++) { + if ((*ratios)[i].value < 0.0) { + if (alltaken && taken < i) + taken = i; + continue; + } + alltaken = 0; + length = (*ratios)[i].length; + pos = (*ratios)[i].pos; + count = (*ratios)[i].count; + if (count == counts[length][pos]) { + found = 1; + break; + } + } + + if (!found) + break; + + counts[length][pos]++; + +/* Record the combination and "take" it out of the input array */ + (*ratios)[i].value = -1.0; /* taken */ + assert(ptr <= order + size - 3); + if (recalcs && + (ptr[0] != length || ptr[1] != pos || ptr[2] != count)) + diff++; + *ptr++ = length; + *ptr++ = pos; + *ptr++ = count; + } while (!event_abort); + + if (event_abort) + goto out; + + assert(ptr == order + size); + + end = ptr; + + recalcs++; + putchar(recalcs < 3 ? '.' : + (diff == prev_diff ? '=' : (diff > prev_diff ? '+' : '-'))); + fflush(stdout); + if (recalcs >= 3) { + if (diff == prev_diff) + same_diff++; + else + same_diff = 0; + } + if ((recalcs >= 2 && !diff) || + (diff == best_diff && !memcmp(order, best_order, end - order)) || + same_diff >= 50 || + (recalcs >= 200 && diff == best_diff) || + recalcs >= 300) { + if (diff > best_diff) { + memcpy(order, best_order, end - order); + diff = best_diff; + } + if (diff) + printf(" Unstable order (%d recalculations, " + "%d differences remain)\n", recalcs, diff); + else + printf(" Stable order (%d recalculations)\n", recalcs); + goto out; + } + prev_diff = diff; + if (recalcs >= 2 && diff < best_diff) { + if (!best_order) + best_order = mem_alloc(end - order); + memcpy(best_order, order, end - order); + best_diff = diff; + } + +/* Recalculate the ratios */ + + memset(counts, 0, sizeof(counts)); + ptr = order; + nratios = 0; + do { + double est; /* estimated cracks for this portion */ + + length = *ptr++; + pos = *ptr++; + count = *ptr++; + counts[length][pos] = count; + +/* First calculate the number of candidate passwords */ + total = 1.0; + { + int i; + for (i = 0; i <= length; i++) + if (i != pos) + total *= counts[length][i] + 1; + } + +/* Then calculate the candidates to successful cracks ratio */ + { + int i, j, relcount; + + relcount = count + 2 + (count < 4); /* tunable */ + if (relcount > CHARSET_SIZE - 1) + relcount = CHARSET_SIZE - 1; + + est = 1.0; + for (i = 0; i <= length; i++) + if (i != pos) { + unsigned int relsum = 0; + double cursum; + int curcount = counts[length][i]; + int mincount = curcount; + if (mincount > relcount) + mincount = relcount; + for (j = 0; j <= mincount; j++) + relsum += (*cracks)[length][i][j]; + cursum = relsum; + for (; j <= relcount; j++) + relsum += (*cracks)[length][i][j]; + for (j = mincount + 1; j <= curcount; j++) + cursum += (*cracks)[length][i][j]; + if (!relsum) + relsum = 1; + est *= cursum / relsum; + } + est *= (*cracks)[length][pos][count]; + { + double min_est = + length ? 0.001 : 0.9; /* tunable */ + if (est < min_est) + est = min_est; + } + } + + (*ratios)[nratios].length = length; + (*ratios)[nratios].pos = pos; + (*ratios)[nratios].count = count; + (*ratios)[nratios++].value = total / est; + } while (ptr < end); + + if (!event_abort) + goto again; + +out: + MEM_FREE(best_order); + MEM_FREE(ratios); +} + +static void charset_generate_all(struct list_main **lists, char *charset) +{ + FILE *file; + int was_error; + struct charset_header *header; + char_counters chars; + crack_counters cracks; + + header = (struct charset_header *)mem_alloc(sizeof(*header)); + memset(header, 0, sizeof(*header)); + + chars = (char_counters)mem_alloc(sizeof(*chars)); + cracks = (crack_counters)mem_alloc(sizeof(*cracks)); + + if (!(file = fopen(path_expand(charset), "wb"))) + pexit("fopen: %s", path_expand(charset)); + + charset_write_header(file, header); + + printf("Generating charsets"); + fflush(stdout); + + charset_generate_chars(lists, file, header, chars, cracks); + if (event_abort) { + fclose(file); + unlink(charset); + putchar('\n'); check_abort(0); + } + + printf(" DONE\nGenerating cracking order"); + fflush(stdout); + + charset_generate_order(cracks, header->order, sizeof(header->order)); + if (event_abort) { + fclose(file); + unlink(charset); + putchar('\n'); check_abort(0); + } + + fflush(file); + if (!ferror(file) && !fseek(file, 0, SEEK_SET)) { + strncpy(header->version, CHARSET_V, sizeof(header->version)); + header->min = CHARSET_MIN; + header->max = CHARSET_MAX; + header->length = CHARSET_LENGTH; + charset_checksum_header(header); + charset_write_header(file, header); + } + + MEM_FREE(cracks); + MEM_FREE(chars); + + was_error = ferror(file); + if (fclose(file) || was_error) { + unlink(charset); + fprintf(stderr, "Failed to write charset file: %s\n", charset); + error(); + } + + printf("Successfully wrote charset file: %s (%d character%s)\n", + charset, header->count, header->count != 1 ? "s" : ""); + + MEM_FREE(header); +} + +void do_makechars(struct db_main *db, char *charset) +{ + struct list_main *lists[CHARSET_LENGTH + 1]; + unsigned long total, remaining; + + total = db->plaintexts->count; + + printf("Loaded %lu plaintext%s%s\n", + total, + total != 1 ? "s" : "", + total ? "" : ", exiting..."); + + remaining = charset_filter_plaintexts(db, lists); + + if (remaining < total) + printf("Remaining %lu plaintext%s%s\n", + remaining, + remaining != 1 ? "s" : "", + remaining ? "" : ", exiting..."); + + if (!remaining) + return; + + CRC32_Init(&checksum); + + charset_generate_all(lists, charset); +} diff --git a/src/charset.h b/src/charset.h new file mode 100644 index 0000000..b1e2701 --- /dev/null +++ b/src/charset.h @@ -0,0 +1,79 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2008,2013 by Solar Designer + */ + +/* + * Charset file generation. + */ + +#ifndef _JOHN_CHARSET_H +#define _JOHN_CHARSET_H + +#include "params.h" +#include "loader.h" + +/* + * While CHARSET_MIN and CHARSET_MAX are configurable in params.h, CHARSET_SIZE + * is expected (by declarations and code in charset.c and inc.c) to be exactly + * (CHARSET_MAX - CHARSET_MIN + 1). So let's define it that way in here. + */ +#define CHARSET_SIZE (CHARSET_MAX - CHARSET_MIN + 1) + +/* + * Charset file control char codes (only CHARSET_ESC is reserved, and can't + * be used in a charset). + */ +#define CHARSET_ESC 0 +#define CHARSET_NEW 1 +#define CHARSET_LINE 2 + +/* + * Charset file header. + */ +struct charset_header { +/* CHARSET_V* */ + char version[4]; + +/* A checksum of the file or equivalent plus some space for future extensions + * (only 4 bytes are used currently) */ + unsigned char check[24]; + +/* CHARSET_MIN, CHARSET_MAX */ + unsigned char min, max; + +/* CHARSET_LENGTH */ + unsigned char length; + +/* Number of different characters, up to (max - min + 1) */ + unsigned char count; + +/* File offsets for each length, 32-bit little endian */ + unsigned char offsets[CHARSET_LENGTH][4]; + +/* + * Cracking order. + * + * This is a list of current {length, fixed index position, character count}. + * There are CHARSET_LENGTH different lengths, and fixed index position is up + * to the current length, which means that we have exactly (CHARSET_LENGTH * + * (CHARSET_LENGTH + 1) / 2) different {length, fixed index position} pairs; + * for each such pair we need to try all charsets from 1 character and up to + * CHARSET_SIZE characters large. + */ + unsigned char order + [CHARSET_LENGTH * (CHARSET_LENGTH + 1) / 2 * CHARSET_SIZE * 3]; +}; + +/* + * Reads a charset file header. + * Returns zero on success, non-zero on error. + */ +extern int charset_read_header(FILE *file, struct charset_header *header); + +/* + * Generates a charset file, based on plaintexts in the database. + */ +extern void do_makechars(struct db_main *db, char *charset); + +#endif diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..b462b29 --- /dev/null +++ b/src/common.c @@ -0,0 +1,48 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "arch.h" +#include "common.h" + +char itoa64[64] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +char atoi64[0x100]; + +char itoa16[16] = + "0123456789abcdef"; +char atoi16[0x100]; + +static int initialized = 0; + +void common_init(void) +{ + char *pos; + + if (initialized) return; + + memset(atoi64, 0x7F, sizeof(atoi64)); + for (pos = itoa64; pos <= &itoa64[63]; pos++) + atoi64[ARCH_INDEX(*pos)] = pos - itoa64; + + memset(atoi16, 0x7F, sizeof(atoi16)); + for (pos = itoa16; pos <= &itoa16[15]; pos++) + atoi16[ARCH_INDEX(*pos)] = pos - itoa16; + + atoi16['A'] = atoi16['a']; + atoi16['B'] = atoi16['b']; + atoi16['C'] = atoi16['c']; + atoi16['D'] = atoi16['d']; + atoi16['E'] = atoi16['e']; + atoi16['F'] = atoi16['f']; + + initialized = 1; +} diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..a0f4b2d --- /dev/null +++ b/src/common.h @@ -0,0 +1,67 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2005,2009,2011,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Things common to many ciphertext formats. + */ + +#ifndef _JOHN_COMMON_H +#define _JOHN_COMMON_H + +#include "arch.h" +#include "memory.h" + +#if ARCH_INT_GT_32 +typedef unsigned short ARCH_WORD_32; +#else +typedef unsigned int ARCH_WORD_32; +#endif + +#ifdef __GNUC__ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define MAYBE_INLINE __attribute__((always_inline)) __inline__ +#else +#define MAYBE_INLINE __inline__ +#endif +#elif __STDC_VERSION__ >= 199901L +#define MAYBE_INLINE inline +#else +#define MAYBE_INLINE +#endif + +#if ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 2) +#define CC_CACHE_ALIGN \ + __attribute__ ((aligned (MEM_ALIGN_CACHE))) +#else +#define CC_CACHE_ALIGN /* nothing */ +#endif + +/* + * This "shift" is the number of bytes that may be inserted between arrays the + * size of which would be a multiple of cache line size (some power of two) and + * that might be accessed simultaneously. The purpose of the shift is to avoid + * cache bank conflicts with such accesses, actually allowing them to proceed + * simultaneously. This number should be a multiple of the machine's word size + * but smaller than cache line size. + */ +#define CACHE_BANK_SHIFT ARCH_SIZE + +/* + * ASCII <-> binary conversion tables. + */ +extern char itoa64[64], atoi64[0x100]; +extern char itoa16[16], atoi16[0x100]; + +/* + * Initializes the tables. + */ +extern void common_init(void); + +#endif diff --git a/src/compiler.c b/src/compiler.c new file mode 100644 index 0000000..9bf6f75 --- /dev/null +++ b/src/compiler.c @@ -0,0 +1,1639 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2003,2005,2011-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include +#include +#include +#include +#include + +#include "arch.h" +#include "params.h" +#include "memory.h" +#include "compiler.h" + +#undef PRINT_INSNS + +char *c_errors[] = { + NULL, /* No error */ + "Unknown identifier", + "Unexpected character", + "Error in expression", + "Identifier is too long", + "Expression is too complex", + "Invalid array size", + "Data section is too large", + "Integer constant out of range", + "Duplicate identifier", + "Keyword is used as an identifier", + "Not in a function", + "Nested functions are not supported", + "Not in an if statement", + "Not in a loop", + "Unexpected end of source", + "Internal compiler error" +}; + +int c_errno; + +union c_insn { + void (*op)(void); + c_int *mem; + c_int imm; + union c_insn *pc; +}; + +struct c_fixup { + struct c_fixup *next; + union c_insn *pc; +}; + +static int c_pass; + +static union c_insn *c_code_start; +static union c_insn *c_code_ptr; +static union c_insn *c_pc; + +static c_int *c_data_start; +static c_int *c_data_ptr; + +static union c_insn c_stack[C_STACK_SIZE]; +static union c_insn *c_sp; + +static union c_insn *c_loop_start; +static struct c_fixup *c_break_fixups; + +static struct c_ident *c_funcs; + +static char c_unget_buffer[C_UNGET_SIZE]; +static int c_unget_count; + +static char c_isident[0x100]; +#define c_isstart(c) \ + (c_isident[ARCH_INDEX(c)] && ((c) < '0' || (c) > '9')) + +static int c_EOF; + +static int (*c_ext_getchar)(void); +static void (*c_ext_rewind)(void); + +static char *c_reserved[] = { + "void", + "int", + "if", + "else", + "while", + "continue", + "break", + "return", + NULL +}; + +#define C_LEFT_TO_RIGHT 0 +#define C_RIGHT_TO_LEFT 1 + +#define C_CLASS_BINARY 0 +#define C_CLASS_LEFT 1 +#define C_CLASS_RIGHT 2 + +struct c_op { + int prec; + int dir; + int class; + char *name; + void (*op)(void); +}; + +#ifdef __GNUC__ +static struct c_op c_ops[]; +#else +#ifdef PRINT_INSNS +static struct c_op c_ops[52]; +#else +static struct c_op c_ops[38]; +#endif +#endif + +static void c_init(void) +{ + int c; + + for (c = 0; c < 0x100; c++) + if (c < 0x80) + c_isident[c] = (isalpha(c) || isdigit(c) || c == '_') ? 1 : 0; + else + c_isident[c] = 0; + + c_code_ptr = c_code_start; + c_data_ptr = c_data_start; + + c_loop_start = NULL; + c_break_fixups = NULL; + + c_funcs = NULL; + + c_unget_count = 0; + + c_EOF = 0; + c_errno = 0; + + c_ext_rewind(); +} + +static void c_ungetchar(char c) +{ + if (c_unget_count >= C_UNGET_SIZE) + c_errno = C_ERROR_INTERNAL; + else + c_unget_buffer[c_unget_count++] = c; +} + +static char c_buffer_getchar(void) +{ + int c; + + if (c_unget_count) return c_unget_buffer[--c_unget_count]; + if ((c = c_ext_getchar()) > 0) return c; + + c_EOF = 1; + c_errno = C_ERROR_EOF; + return ' '; +} + +static char c_getchar(int quote) +{ + int c; + int space = 0; + + do { + c = (unsigned char)c_buffer_getchar(); + if (quote || c_EOF) return c; + + if (c <= ' ') space = 1; else + if (c == '/') + switch ((c = c_buffer_getchar())) { + case '/': + do { + c = c_buffer_getchar(); + } while (!c_EOF && c != '\n' && c != '\r'); + c = ' '; space = 1; + break; + + case '*': + do { + if ((c = c_buffer_getchar()) == '*') + if ((c = c_buffer_getchar()) == '/') + break; + } while (!c_EOF); + c = ' '; space = 1; + break; + + default: + c_ungetchar(c); + c = '/'; + } + } while (c <= ' '); + + if (space) { + c_ungetchar(c); + c = ' '; + } + + return c; +} + +static char *c_gettoken(void) +{ + static char token[C_TOKEN_SIZE]; + int pos = 0; + + while (c_isident[ARCH_INDEX(token[pos++] = c_getchar(0))]) + if (pos >= C_TOKEN_SIZE) { + c_errno = C_ERROR_TOOLONG; + break; + } + + if (pos != 1) c_ungetchar(token[--pos]); + token[pos] = 0; + + return token; +} + +static c_int c_getint(char *token) +{ + c_int value; + long l_value; + char *error; + + if (token[0] == '\'') { + if ((value = (unsigned char)c_getchar(1)) == '\'') + c_errno = C_ERROR_UNEXPECTED; + else + if (value == '\\') + value = (unsigned char)c_getchar(1); + if (c_getchar(1) != '\'') + c_errno = C_ERROR_UNEXPECTED; + } else { + errno = 0; + l_value = strtol(token, &error, 0); + value = (c_int)l_value; + if (errno == ERANGE || (long)value != l_value) + c_errno = C_ERROR_RANGE; + else + if (!*token || *error || errno) + c_errno = C_ERROR_UNEXPECTED; + } + + return value; +} + +static char c_skip_space(void) +{ + char c; + + if ((c = c_getchar(0)) == ' ') c = c_getchar(0); + + return c; +} + +static int c_expect(char expected) +{ + char c; + + if ((c = c_getchar(0)) == ' ') + if (expected != ' ') c = c_getchar(0); + + if (c != expected) c_errno = C_ERROR_UNEXPECTED; + + return c_errno; +} + +static struct c_ident *c_find_ident(struct c_ident *list, + struct c_ident *globals, char *name) +{ + struct c_ident *current; + + if ((current = list) != globals) + do { + if (!strcmp(name, current->name)) break; + } while ((current = current->next) != globals); + + if (current != globals) + return current; + else + return NULL; +} + +static int c_alloc_ident(struct c_ident **list, struct c_ident *globals, + char *name, void *addr) +{ + char **current; + struct c_ident *last; + + current = c_reserved; + do { + if (!strcmp(name, *current)) return c_errno = C_ERROR_RESERVED; + } while (*++current); + + if (c_find_ident(*list, globals, name)) return c_errno = C_ERROR_DUPE; + + last = *list; + *list = (struct c_ident *)mem_alloc(sizeof(struct c_ident)); + (*list)->next = last; + strcpy((*list)->name = (char *)mem_alloc(strlen(name) + 1), name); + (*list)->addr = addr; + + return c_errno; +} + +static void c_free_ident(struct c_ident *list, struct c_ident *globals) +{ + struct c_ident *current; + + while ((current = list) != globals) { + list = list->next; + MEM_FREE(current->name); + MEM_FREE(current); + } +} + +static int c_find_op(char *token, int left) +{ + int best = -1; + int op = 0; + + do { + if ((c_ops[op].class != C_CLASS_LEFT && left) || + (c_ops[op].class == C_CLASS_LEFT && !left)) + if (!memcmp(c_ops[op].name, token, strlen(c_ops[op].name))) + if (best < 0 || + strlen(c_ops[op].name) > strlen(c_ops[best].name)) + best = op; + } while (c_ops[++op].prec); + + return best; +} + +static void c_free_fixup(struct c_fixup *list, union c_insn *pc) +{ + struct c_fixup *current; + + while ((current = list)) { + if (c_pass) + current->pc->pc = pc; + + list = list->next; + MEM_FREE(current); + } +} + +static void (*c_op_return)(void); +static void (*c_op_bz)(void); +static void (*c_op_ba)(void); +static void (*c_op_push_imm)(void); +static void (*c_op_push_mem)(void); +static void (*c_op_pop)(void); + +static void (*c_op_push_imm_imm)(void); +static void (*c_op_push_imm_mem)(void); +static void (*c_op_push_mem_imm)(void); +static void (*c_op_push_mem_mem)(void); +static void (*c_op_push_mem_mem_mem)(void); +static void (*c_op_push_mem_mem_mem_imm)(void); +static void (*c_op_push_mem_mem_mem_mem)(void); + +static void (*c_op_assign)(void); +static void (*c_op_assign_pop)(void); + +static void (*c_push + (void (*last)(void), void (*op)(void), union c_insn *value))(void) +{ + if (last == c_op_push_imm || last == c_op_push_mem) { + if (last == c_op_push_imm) { + if (op == c_op_push_imm) + last = c_op_push_imm_imm; + else + last = c_op_push_imm_mem; + } else { + if (op == c_op_push_imm) + last = c_op_push_mem_imm; + else + last = c_op_push_mem_mem; + } + + if (c_pass) { + (c_code_ptr - 2)->op = last; + *c_code_ptr = *value; + } + c_code_ptr++; + } else if (last == c_op_push_mem_mem && op == c_op_push_mem) { + last = c_op_push_mem_mem_mem; + if (c_pass) { + (c_code_ptr - 3)->op = last; + *c_code_ptr = *value; + } + c_code_ptr++; + } else if (last == c_op_push_mem_mem_mem) { + if (op == c_op_push_imm) + last = c_op_push_mem_mem_mem_imm; + else + last = c_op_push_mem_mem_mem_mem; + if (c_pass) { + (c_code_ptr - 4)->op = last; + *c_code_ptr = *value; + } + c_code_ptr++; + } else { + last = op; + + if (c_pass) { + (c_code_ptr++)->op = op; + *c_code_ptr++ = *value; + } else + c_code_ptr += 2; + } + + return last; +} + +static int c_block(char term, struct c_ident *vars); + +static int c_define(char term, struct c_ident **vars, struct c_ident *globals) +{ + char *token; + char c; + c_int size; + + c_expect(' '); + token = c_gettoken(); + if (!c_isstart(*token)) c_errno = C_ERROR_UNEXPECTED; + + do + if (*token != ' ') { + if (!c_isstart(*token)) c_errno = C_ERROR_UNEXPECTED; + if (c_errno) return c_errno; + + if ((c = c_skip_space()) == '(') { + if (term) return c_errno = C_ERROR_NESTEDFUNC; + + if (c_alloc_ident(&c_funcs, NULL, token, c_code_ptr)) + return c_errno; + + c_expect(')'); + if (c_expect('{')) return c_errno; + + c_block('}', *vars); + + if (c_pass) + c_code_ptr->op = c_op_return; + c_code_ptr++; + + break; + } else { + if (c_alloc_ident(vars, globals, token, c_data_ptr++)) + return c_errno; + + if (c == '[') { + size = c_getint(c_gettoken()); + if (c_errno) return c_errno; + + if (size < 1 || size > C_ARRAY_SIZE) + return c_errno = C_ERROR_ARRAYSIZE; + + c_data_ptr += size - 1; + + if (c_data_ptr - c_data_start > C_DATA_SIZE) + return c_errno = C_ERROR_DATASIZE; + + c_expect(']'); + c = c_skip_space(); + } + + if (c == ';') break; + if (c != ',') c_errno = C_ERROR_UNEXPECTED; + } + } while (!c_errno && *(token = c_gettoken()) != ';'); + + return c_errno; +} + +static int c_expr(char term, struct c_ident *vars, char *token, int pop) +{ + char c; + struct c_ident *var; + int lookahead, op; + struct c_op *op1, *op2; + union c_insn value; + int stack[C_EXPR_SIZE]; + int sp = 0; + int balance = -1; + int left = 0; + void (*last)(void) = (void (*)(void))0; + + if (term == ')') stack[sp++] = -1; + do { + c = *token; + + if (c == ')' || c == ']' || c == ';' || c == term) { + while (sp) { + if (stack[--sp] < 0) break; + if (c_ops[stack[sp]].class == C_CLASS_BINARY) + balance--; + + last = c_ops[stack[sp]].op; + if (c_pass) + c_code_ptr->op = last; + c_code_ptr++; + + if (!stack[sp]) break; + } + + if ((c == ')' && stack[sp] >= 0) || + (c == ']' && stack[sp]) || + ((c == ';' || (term != ')' && c == term)) && sp)) + c_errno = C_ERROR_COUNT; + if (c_errno || (!sp && c == term)) break; + + left = 1; + } else + if ((c >= '0' && c <= '9') || c == '\'') { + value.imm = c_getint(token); + last = c_push(last, c_op_push_imm, &value); + + left = 1; balance++; + } else + if (c == '(' || c == '[') { + if (sp >= C_EXPR_SIZE) + c_errno = C_ERROR_TOOCOMPLEX; + else + stack[sp++] = (c == '(') ? -1 : 0; + + left = 0; + } else + if (c != ' ') { + if (c_isident[ARCH_INDEX(c)]) + var = c_find_ident(vars, NULL, token); + else + var = NULL; + + if (var) { + value.mem = var->addr; + last = c_push(last, c_op_push_mem, &value); + + left = 1; balance++; + } else { + if ((lookahead = !token[1])) { + token[1] = c_getchar(0); + token[2] = c_getchar(0); + token[3] = 0; + } + + if ((op = c_find_op(token, left)) < 0) { + if (c_isident[ARCH_INDEX(c)]) + c_errno = C_ERROR_UNKNOWN; + else + c_errno = C_ERROR_UNEXPECTED; + return c_errno; + } + + if (lookahead) + if (strlen(c_ops[op].name) < 3) { + c_ungetchar(token[2]); + if (!c_ops[op].name[1]) + c_ungetchar(token[1]); + } + + op1 = &c_ops[op]; + while (sp && stack[sp - 1] >= 0) { + op2 = &c_ops[stack[sp - 1]]; + + if (op2->dir == C_RIGHT_TO_LEFT) + if (op2->prec <= op1->prec) break; + + if (op2->dir == C_LEFT_TO_RIGHT) + if (op2->prec < op1->prec) break; + + if (op2->class == C_CLASS_BINARY) + balance--; + + last = op2->op; + if (c_pass) + c_code_ptr->op = last; + c_code_ptr++; + + sp--; + } + + if (sp >= C_EXPR_SIZE) + c_errno = C_ERROR_TOOCOMPLEX; + else { + stack[sp++] = op; + + left = op1->class == C_CLASS_RIGHT; + } + } + } + + if (c_errno || c == ';' || (c == term && c != ')')) break; + token = c_gettoken(); + } while (!c_errno); + + if (c_errno) return c_errno; + + if (sp || balance) c_errno = C_ERROR_COUNT; + + if (pop) { + if (last == c_op_assign) { + if (c_pass) + (c_code_ptr - 1)->op = c_op_assign_pop; + } else { + if (c_pass) + c_code_ptr->op = c_op_pop; + c_code_ptr++; + } + } + + if (!term && !c_errno) c_errno = C_ERROR_NOTINFUNC; + if (*token == term) return -1; + + return c_errno; +} + +static int c_cond(char term, struct c_ident *vars, char *token) +{ + char c; + char *pos; + union c_insn *start, *outer_loop_start, *fixup; + struct c_fixup *outer_loop_break_fixups; + + if (!term) return c_errno = C_ERROR_NOTINFUNC; + + c = *token; + start = c_code_ptr; + + if (c_expect('(')) return c_errno; + switch (c_expr(')', vars, c_gettoken(), 0)) { + case -1: + break; + + case 0: + c_errno = C_ERROR_UNEXPECTED; + + default: + return c_errno; + } + + if (c_pass) + c_code_ptr->op = c_op_bz; + c_code_ptr++; + fixup = c_code_ptr++; + + outer_loop_start = c_loop_start; + outer_loop_break_fixups = c_break_fixups; + if (c == 'w') { + c_loop_start = start; + c_break_fixups = NULL; + } + + if (c_block(';', vars)) { + if (c == 'w') { + c_free_fixup(c_break_fixups, NULL); + c_break_fixups = outer_loop_break_fixups; + } + return c_errno; + } + + if (c == 'w') { + c_loop_start = outer_loop_start; + + if (c_pass) { + (c_code_ptr++)->op = c_op_ba; + (c_code_ptr++)->pc = start; + } else + c_code_ptr += 2; + + c_free_fixup(c_break_fixups, c_code_ptr); + c_break_fixups = outer_loop_break_fixups; + } else { + while (*(token = c_gettoken()) == ' ') + if (c_errno) return c_errno; + + if (!strcmp(token, "else")) { + if (c_pass) { + (c_code_ptr++)->op = c_op_ba; + fixup->pc = c_code_ptr + 1; + fixup = c_code_ptr++; + } else + c_code_ptr += 2; + + if (c_block(';', vars)) return c_errno; + } else { + pos = token + strlen(token); + while (pos > token) c_ungetchar(*--pos); + } + } + + if (c_pass) + fixup->pc = c_code_ptr; + c_ungetchar(';'); + + return c_errno; +} + +static int c_continue(void) +{ + if (!c_loop_start) return c_errno = C_ERROR_NOTINLOOP; + + if (c_pass) { + (c_code_ptr++)->op = c_op_ba; + (c_code_ptr++)->pc = c_loop_start; + } else + c_code_ptr += 2; + + c_expect(';'); + c_ungetchar(';'); + + return c_errno; +} + +static int c_break(void) +{ + struct c_fixup *fixup; + + if (!c_loop_start) return c_errno = C_ERROR_NOTINLOOP; + + c_expect(';'); + c_ungetchar(';'); + + fixup = c_break_fixups; + c_break_fixups = + (struct c_fixup *)mem_alloc(sizeof(struct c_fixup)); + c_break_fixups->next = fixup; + + if (c_pass) + c_code_ptr->op = c_op_ba; + c_break_fixups->pc = c_code_ptr + 1; + c_code_ptr += 2; + + return c_errno; +} + +static int c_return(char term) +{ + if (!term) return c_errno = C_ERROR_NOTINFUNC; + + if (c_pass) + c_code_ptr->op = c_op_return; + c_code_ptr++; + + c_expect(';'); + c_ungetchar(';'); + + return c_errno; +} + +static int c_block(char term, struct c_ident *vars) +{ + struct c_ident *locals = vars; + char *token; + + while (*(token = c_gettoken()) != term) { + if (c_errno) { + if (!term && c_errno == C_ERROR_EOF) + c_errno = C_ERROR_NONE; + break; + } + if (*token == ' ') continue; + + if (*token == '{') { + if (!term) return c_errno = C_ERROR_NOTINFUNC; + + if (term == ';') term = '}'; else + if (c_block('}', locals)) break; else continue; + } else + + if (!strcmp(token, "void") || !strcmp(token, "int")) { + if (c_define(term, &locals, vars)) break; + } else + + if (!strcmp(token, "if") || !strcmp(token, "while")) { + if (c_cond(term, locals, token)) break; + } else + + if (!strcmp(token, "else")) + return c_errno = C_ERROR_NOTINIF; + else + + if (!strcmp(token, "continue")) { + if (c_continue()) break; + } else + + if (!strcmp(token, "break")) { + if (c_break()) break; + } else + + if (!strcmp(token, "return")) { + if (c_return(term)) break; + } else + + if (*token != ';') + if (c_expr(term, locals, token, 1)) break; + + if (c_errno) break; + } + + c_free_ident(locals, vars); + + if (c_errno && c_EOF) c_errno = C_ERROR_EOF; + + return c_errno; +} + +int c_compile(int (*ext_getchar)(void), void (*ext_rewind)(void), + struct c_ident *externs) +{ +#if defined(__GNUC__) && !defined(PRINT_INSNS) + c_execute_fast(NULL); +#endif + + c_ext_getchar = ext_getchar; + c_ext_rewind = ext_rewind; + + c_code_start = NULL; + c_data_start = NULL; + + for (c_pass = 0; c_pass < 2; c_pass++) { + c_init(); + c_block(0, externs); +#ifdef PRINT_INSNS + fprintf(stderr, "Code size: %u\n", + (unsigned int)(c_code_ptr - c_code_start)); +#endif + + if (!c_pass) { + c_free_ident(c_funcs, NULL); + c_free_fixup(c_break_fixups, NULL); + } + + if (c_errno || c_pass) break; + + c_code_start = mem_alloc((size_t)c_code_ptr); + c_data_start = mem_alloc((size_t)c_data_ptr); + memset(c_data_start, 0, (size_t)c_data_ptr); + } + + return c_errno; +} + +void *c_lookup(char *name) +{ + struct c_ident *f = c_find_ident(c_funcs, NULL, name); + if (f) + return f->addr; + return NULL; +} + +#if !defined(__GNUC__) || defined(PRINT_INSNS) + +void c_execute_fast(void *addr) +{ + c_stack[0].pc = NULL; + c_sp = &c_stack[2]; + + c_pc = addr; + do { +#ifdef PRINT_INSNS + void (*op)(void) = (c_pc++)->op; + int i = 0; + while (c_ops[i].op != op && c_ops[i].prec >= 0) + i++; + fprintf(stderr, "op: %s\n", c_ops[i].name); + op(); +#else + (c_pc++)->op(); + if (!c_pc) + break; + (c_pc++)->op(); + if (!c_pc) + break; + (c_pc++)->op(); + if (!c_pc) + break; + (c_pc++)->op(); +#endif + } while (c_pc); +} + +#else + +void c_execute_fast(void *addr) +{ + union c_insn *pc = addr; + union c_insn *sp = c_stack; + c_int imm = 0; + + static void *ops[] = { + &&op_index, + &&op_assign, + &&op_add_a, + &&op_sub_a, + &&op_mul_a, + &&op_div_a, + &&op_mod_a, + &&op_or_a, + &&op_xor_a, + &&op_and_a, + &&op_shl_a, + &&op_shr_a, + &&op_or_i, + &&op_and_b, + &&op_not_b, + &&op_eq, + &&op_sub, + &&op_gt, + &&op_lt, + &&op_ge, + &&op_le, + &&op_or_i, + &&op_xor_i, + &&op_and_i, + &&op_shl, + &&op_shr, + &&op_add, + &&op_sub, + &&op_mul, + &&op_div, + &&op_mod, + &&op_not_i, + &&op_neg, + &&op_inc_l, + &&op_dec_l, + &&op_inc_r, + &&op_dec_r + }; + +#if __GNUC__ >= 3 + if (__builtin_expect(addr == NULL, 0)) { +#else + if (!addr) { +#endif + int op = 0; + + assert(c_op_return != &&op_return); /* Don't do this twice */ + + c_op_return = &&op_return; + c_op_bz = &&op_bz; + c_op_ba = &&op_ba; + c_op_push_imm = &&op_push_imm; + c_op_push_mem = &&op_push_mem; + c_op_pop = &&op_pop; + + c_op_push_imm_imm = &&op_push_imm_imm; + c_op_push_imm_mem = &&op_push_imm_mem; + c_op_push_mem_imm = &&op_push_mem_imm; + c_op_push_mem_mem = &&op_push_mem_mem; + c_op_push_mem_mem_mem = &&op_push_mem_mem_mem; + c_op_push_mem_mem_mem_imm = &&op_push_mem_mem_mem_imm; + c_op_push_mem_mem_mem_mem = &&op_push_mem_mem_mem_mem; + + c_op_assign = &&op_assign; + c_op_assign_pop = &&op_assign_pop; + + do { + c_ops[op].op = ops[op]; + } while (c_ops[++op].prec); + + return; + } + + goto *(pc++)->op; + +op_return: + return; + +op_bz: + sp -= 2; +#if __GNUC__ >= 3 + if (__builtin_expect(imm != 0, 1)) { +#else + if (imm) { +#endif + pc += 2; + goto *(pc - 1)->op; + } + +op_ba: + pc = pc->pc; + goto *(pc++)->op; + +op_push_imm: + (sp - 2)->imm = imm; + imm = pc->imm; + pc += 2; + sp += 2; + goto *(pc - 1)->op; + +op_push_mem: + (sp - 2)->imm = imm; + imm = *((sp + 1)->mem = pc->mem); + pc += 2; + sp += 2; + goto *(pc - 1)->op; + +op_pop: + sp -= 2; + goto *(pc++)->op; + +op_push_imm_imm: + (sp - 2)->imm = imm; + sp->imm = pc->imm; + imm = (pc + 1)->imm; + pc += 3; + sp += 4; + goto *(pc - 1)->op; + +op_push_imm_mem: + (sp - 2)->imm = imm; + sp->imm = pc->imm; + imm = *((sp + 3)->mem = (pc + 1)->mem); + pc += 3; + sp += 4; + goto *(pc - 1)->op; + +op_push_mem_imm: + (sp - 2)->imm = imm; + sp->imm = *((sp + 1)->mem = pc->mem); + imm = (pc + 1)->imm; + pc += 3; + sp += 4; + goto *(pc - 1)->op; + +op_push_mem_mem: + (sp - 2)->imm = imm; + sp->imm = *((sp + 1)->mem = pc->mem); + imm = *((sp + 3)->mem = (pc + 1)->mem); + pc += 3; + sp += 4; + goto *(pc - 1)->op; + +op_push_mem_mem_mem: + (sp - 2)->imm = imm; + sp->imm = *((sp + 1)->mem = pc->mem); + (sp + 2)->imm = *((sp + 3)->mem = (pc + 1)->mem); + imm = *((sp + 5)->mem = (pc + 2)->mem); + pc += 4; + sp += 6; + goto *(pc - 1)->op; + +op_push_mem_mem_mem_imm: + (sp - 2)->imm = imm; + sp->imm = *((sp + 1)->mem = pc->mem); + (sp + 2)->imm = *((sp + 3)->mem = (pc + 1)->mem); + (sp + 4)->imm = *((sp + 5)->mem = (pc + 2)->mem); + imm = (pc + 3)->imm; + pc += 5; + sp += 8; + goto *(pc - 1)->op; + +op_push_mem_mem_mem_mem: + (sp - 2)->imm = imm; + sp->imm = *((sp + 1)->mem = pc->mem); + (sp + 2)->imm = *((sp + 3)->mem = (pc + 1)->mem); + (sp + 4)->imm = *((sp + 5)->mem = (pc + 2)->mem); + imm = *((sp + 7)->mem = (pc + 3)->mem); + pc += 5; + sp += 8; + goto *(pc - 1)->op; + +op_index: + imm = *((sp - 3)->mem += imm); + sp -= 2; + goto *(pc++)->op; + +op_assign: + *(sp - 3)->mem = imm; + sp -= 2; + goto *(pc++)->op; + +op_assign_pop: + *(sp - 3)->mem = imm; + sp -= 4; + goto *(pc++)->op; + +op_add_a: + imm = *(sp - 3)->mem += imm; + sp -= 2; + goto *(pc++)->op; + +op_sub_a: + imm = *(sp - 3)->mem -= imm; + sp -= 2; + goto *(pc++)->op; + +op_mul_a: + imm = *(sp - 3)->mem *= imm; + sp -= 2; + goto *(pc++)->op; + +op_div_a: + imm = *(sp - 3)->mem /= imm; + sp -= 2; + goto *(pc++)->op; + +op_mod_a: + imm = *(sp - 3)->mem %= imm; + sp -= 2; + goto *(pc++)->op; + +op_or_a: + imm = *(sp - 3)->mem |= imm; + sp -= 2; + goto *(pc++)->op; + +op_xor_a: + imm = *(sp - 3)->mem ^= imm; + sp -= 2; + goto *(pc++)->op; + +op_and_a: + imm = *(sp - 3)->mem &= imm; + sp -= 2; + goto *(pc++)->op; + +op_shl_a: + imm = *(sp - 3)->mem <<= imm; + sp -= 2; + goto *(pc++)->op; + +op_shr_a: + imm = *(sp - 3)->mem >>= imm; + sp -= 2; + goto *(pc++)->op; + +op_or_i: + imm |= (sp - 4)->imm; + sp -= 2; + goto *(pc++)->op; + +op_and_b: + imm = (sp - 4)->imm && imm; + sp -= 2; + goto *(pc++)->op; + +op_not_b: + imm = !imm; + goto *(pc++)->op; + +op_eq: + imm = (sp - 4)->imm == imm; + sp -= 2; + goto *(pc++)->op; + +op_gt: + imm = (sp - 4)->imm > imm; + sp -= 2; + goto *(pc++)->op; + +op_lt: + imm = (sp - 4)->imm < imm; + sp -= 2; + goto *(pc++)->op; + +op_ge: + imm = (sp - 4)->imm >= imm; + sp -= 2; + goto *(pc++)->op; + +op_le: + imm = (sp - 4)->imm <= imm; + sp -= 2; + goto *(pc++)->op; + +op_xor_i: + imm ^= (sp - 4)->imm; + sp -= 2; + goto *(pc++)->op; + +op_and_i: + imm &= (sp - 4)->imm; + sp -= 2; + goto *(pc++)->op; + +op_shl: + imm = (sp - 4)->imm << imm; + sp -= 2; + goto *(pc++)->op; + +op_shr: + imm = (sp - 4)->imm >> imm; + sp -= 2; + goto *(pc++)->op; + +op_add: + imm += (sp - 4)->imm; + sp -= 2; + goto *(pc++)->op; + +op_sub: + imm = (sp - 4)->imm - imm; + sp -= 2; + goto *(pc++)->op; + +op_mul: + imm *= (sp - 4)->imm; + sp -= 2; + goto *(pc++)->op; + +op_div: + imm = (sp - 4)->imm / imm; + sp -= 2; + goto *(pc++)->op; + +op_mod: + imm = (sp - 4)->imm % imm; + sp -= 2; + goto *(pc++)->op; + +op_not_i: + imm = ~imm; + goto *(pc++)->op; + +op_neg: + imm = -imm; + goto *(pc++)->op; + +op_inc_l: + *(sp - 1)->mem = ++imm; + goto *(pc++)->op; + +op_dec_l: + *(sp - 1)->mem = --imm; + goto *(pc++)->op; + +op_inc_r: + *(sp - 1)->mem = imm + 1; + goto *(pc++)->op; + +op_dec_r: + *(sp - 1)->mem = imm - 1; + goto *(pc++)->op; +} + +#endif + +static void c_f_op_return(void) +{ + c_pc = (c_sp -= 2)->pc; +} + +static void c_f_op_bz(void) +{ + if ((c_sp -= 2)->imm) + c_pc++; + else + c_pc = c_pc->pc; +} + +static void c_f_op_ba(void) +{ + c_pc = c_pc->pc; +} + +static void c_f_op_push_imm(void) +{ + c_sp->imm = (c_pc++)->imm; + c_sp += 2; +} + +static void c_f_op_push_mem(void) +{ + (c_sp++)->imm = *c_pc->mem; + (c_sp++)->mem = (c_pc++)->mem; +} + +static void c_f_op_pop(void) +{ + c_sp -= 2; +} + +static void c_f_op_push_imm_imm(void) +{ + c_sp->imm = (c_pc++)->imm; + (c_sp + 2)->imm = (c_pc++)->imm; + c_sp += 4; +} + +static void c_f_op_push_imm_mem(void) +{ + c_sp->imm = (c_pc++)->imm; + (c_sp + 2)->imm = *c_pc->mem; + (c_sp + 3)->mem = (c_pc++)->mem; + c_sp += 4; +} + +static void c_f_op_push_mem_imm(void) +{ + c_sp->imm = *c_pc->mem; + (c_sp + 1)->mem = (c_pc++)->mem; + (c_sp + 2)->imm = (c_pc++)->imm; + c_sp += 4; +} + +static void c_f_op_push_mem_mem(void) +{ + c_sp->imm = *c_pc->mem; + (c_sp + 1)->mem = (c_pc++)->mem; + (c_sp + 2)->imm = *c_pc->mem; + (c_sp + 3)->mem = (c_pc++)->mem; + c_sp += 4; +} + +static void c_f_op_push_mem_mem_mem(void) +{ + c_sp->imm = *c_pc->mem; + (c_sp + 1)->mem = (c_pc++)->mem; + (c_sp + 2)->imm = *c_pc->mem; + (c_sp + 3)->mem = (c_pc++)->mem; + (c_sp + 4)->imm = *c_pc->mem; + (c_sp + 5)->mem = (c_pc++)->mem; + c_sp += 6; +} + +static void c_f_op_push_mem_mem_mem_imm(void) +{ + c_sp->imm = *c_pc->mem; + (c_sp + 1)->mem = (c_pc++)->mem; + (c_sp + 2)->imm = *c_pc->mem; + (c_sp + 3)->mem = (c_pc++)->mem; + (c_sp + 4)->imm = *c_pc->mem; + (c_sp + 5)->mem = (c_pc++)->mem; + (c_sp + 6)->imm = (c_pc++)->imm; + c_sp += 8; +} + +static void c_f_op_push_mem_mem_mem_mem(void) +{ + c_sp->imm = *c_pc->mem; + (c_sp + 1)->mem = (c_pc++)->mem; + (c_sp + 2)->imm = *c_pc->mem; + (c_sp + 3)->mem = (c_pc++)->mem; + (c_sp + 4)->imm = *c_pc->mem; + (c_sp + 5)->mem = (c_pc++)->mem; + (c_sp + 6)->imm = *c_pc->mem; + (c_sp + 7)->mem = (c_pc++)->mem; + c_sp += 8; +} + +static void c_op_index(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *((c_sp - 1)->mem += c_sp->imm); +} + +static void c_f_op_assign(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem = c_sp->imm; +} + +static void c_f_op_assign_pop(void) +{ + c_sp -= 4; + *(c_sp + 1)->mem = (c_sp + 2)->imm; +} + +static void c_op_add_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem += c_sp->imm; +} + +static void c_op_sub_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem -= c_sp->imm; +} + +static void c_op_mul_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem *= c_sp->imm; +} + +static void c_op_div_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem /= c_sp->imm; +} + +static void c_op_mod_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem %= c_sp->imm; +} + +static void c_op_or_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem |= c_sp->imm; +} + +static void c_op_xor_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem ^= c_sp->imm; +} + +static void c_op_and_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem &= c_sp->imm; +} + +static void c_op_shl_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem <<= c_sp->imm; +} + +static void c_op_shr_a(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = *(c_sp - 1)->mem >>= c_sp->imm; +} + +static void c_op_or_i(void) +{ + c_sp -= 2; + (c_sp - 2)->imm |= c_sp->imm; +} + +static void c_op_and_b(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm && c_sp->imm; +} + +static void c_op_not_b(void) +{ + (c_sp - 2)->imm = !(c_sp - 2)->imm; +} + +static void c_op_eq(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm == c_sp->imm; +} + +static void c_op_gt(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm > c_sp->imm; +} + +static void c_op_lt(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm < c_sp->imm; +} + +static void c_op_ge(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm >= c_sp->imm; +} + +static void c_op_le(void) +{ + c_sp -= 2; + (c_sp - 2)->imm = (c_sp - 2)->imm <= c_sp->imm; +} + +static void c_op_xor_i(void) +{ + c_sp -= 2; + (c_sp - 2)->imm ^= c_sp->imm; +} + +static void c_op_and_i(void) +{ + c_sp -= 2; + (c_sp - 2)->imm &= c_sp->imm; +} + +static void c_op_shl(void) +{ + c_sp -= 2; + (c_sp - 2)->imm <<= c_sp->imm; +} + +static void c_op_shr(void) +{ + c_sp -= 2; + (c_sp - 2)->imm >>= c_sp->imm; +} + +static void c_op_add(void) +{ + c_sp -= 2; + (c_sp - 2)->imm += c_sp->imm; +} + +static void c_op_sub(void) +{ + c_sp -= 2; + (c_sp - 2)->imm -= c_sp->imm; +} + +static void c_op_mul(void) +{ + c_sp -= 2; + (c_sp - 2)->imm *= c_sp->imm; +} + +static void c_op_div(void) +{ + c_sp -= 2; + (c_sp - 2)->imm /= c_sp->imm; +} + +static void c_op_mod(void) +{ + c_sp -= 2; + (c_sp - 2)->imm %= c_sp->imm; +} + +static void c_op_not_i(void) +{ + (c_sp - 2)->imm = ~(c_sp - 2)->imm; +} + +static void c_op_neg(void) +{ + (c_sp - 2)->imm = -(c_sp - 2)->imm; +} + +static void c_op_inc_l(void) +{ + *(c_sp - 1)->mem = ++(c_sp - 2)->imm; +} + +static void c_op_dec_l(void) +{ + *(c_sp - 1)->mem = --(c_sp - 2)->imm; +} + +static void c_op_inc_r(void) +{ + *(c_sp - 1)->mem = (c_sp - 2)->imm + 1; +} + +static void c_op_dec_r(void) +{ + *(c_sp - 1)->mem = (c_sp - 2)->imm - 1; +} + +static void (*c_op_return)(void) = c_f_op_return; +static void (*c_op_bz)(void) = c_f_op_bz; +static void (*c_op_ba)(void) = c_f_op_ba; +static void (*c_op_push_imm)(void) = c_f_op_push_imm; +static void (*c_op_push_mem)(void) = c_f_op_push_mem; +static void (*c_op_pop)(void) = c_f_op_pop; + +static void (*c_op_push_imm_imm)(void) = c_f_op_push_imm_imm; +static void (*c_op_push_imm_mem)(void) = c_f_op_push_imm_mem; +static void (*c_op_push_mem_imm)(void) = c_f_op_push_mem_imm; +static void (*c_op_push_mem_mem)(void) = c_f_op_push_mem_mem; +static void (*c_op_push_mem_mem_mem)(void) = c_f_op_push_mem_mem_mem; +static void (*c_op_push_mem_mem_mem_imm)(void) = c_f_op_push_mem_mem_mem_imm; +static void (*c_op_push_mem_mem_mem_mem)(void) = c_f_op_push_mem_mem_mem_mem; + +static void (*c_op_assign)(void) = c_f_op_assign; +static void (*c_op_assign_pop)(void) = c_f_op_assign_pop; + +static struct c_op c_ops[] = { + {1, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "[", c_op_index}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "=", c_f_op_assign}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "+=", c_op_add_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "-=", c_op_sub_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "*=", c_op_mul_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "/=", c_op_div_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "%=", c_op_mod_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "|=", c_op_or_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "^=", c_op_xor_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "&=", c_op_and_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, "<<=", c_op_shl_a}, + {2, C_RIGHT_TO_LEFT, C_CLASS_BINARY, ">>=", c_op_shr_a}, + {3, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "||", c_op_or_i}, + {4, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "&&", c_op_and_b}, + {5, C_RIGHT_TO_LEFT, C_CLASS_LEFT, "!", c_op_not_b}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "==", c_op_eq}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "!=", c_op_sub}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, ">", c_op_gt}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "<", c_op_lt}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, ">=", c_op_ge}, + {6, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "<=", c_op_le}, + {7, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "|", c_op_or_i}, + {7, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "^", c_op_xor_i}, + {8, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "&", c_op_and_i}, + {9, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "<<", c_op_shl}, + {9, C_LEFT_TO_RIGHT, C_CLASS_BINARY, ">>", c_op_shr}, + {10, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "+", c_op_add}, + {10, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "-", c_op_sub}, + {11, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "*", c_op_mul}, + {11, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "/", c_op_div}, + {11, C_LEFT_TO_RIGHT, C_CLASS_BINARY, "%", c_op_mod}, + {12, C_RIGHT_TO_LEFT, C_CLASS_LEFT, "~", c_op_not_i}, + {12, C_RIGHT_TO_LEFT, C_CLASS_LEFT, "-", c_op_neg}, + {12, C_LEFT_TO_RIGHT, C_CLASS_LEFT, "++", c_op_inc_l}, + {12, C_LEFT_TO_RIGHT, C_CLASS_LEFT, "--", c_op_dec_l}, + {12, C_LEFT_TO_RIGHT, C_CLASS_RIGHT, "++", c_op_inc_r}, + {12, C_LEFT_TO_RIGHT, C_CLASS_RIGHT, "--", c_op_dec_r}, +#ifdef PRINT_INSNS + {0, 0, 0, "return", c_f_op_return}, + {0, 0, 0, "bz", c_f_op_bz}, + {0, 0, 0, "ba", c_f_op_ba}, + {0, 0, 0, "push_imm", c_f_op_push_imm}, + {0, 0, 0, "push_mem", c_f_op_push_mem}, + {0, 0, 0, "pop", c_f_op_pop}, + {0, 0, 0, "push_imm_imm", c_f_op_push_imm_imm}, + {0, 0, 0, "push_imm_mem", c_f_op_push_imm_mem}, + {0, 0, 0, "push_mem_imm", c_f_op_push_mem_imm}, + {0, 0, 0, "push_mem_mem", c_f_op_push_mem_mem}, + {0, 0, 0, "push_mem_mem_mem", c_f_op_push_mem_mem_mem}, + {0, 0, 0, "push_mem_mem_mem_imm", c_f_op_push_mem_mem_mem_imm}, + {0, 0, 0, "push_mem_mem_mem_mem", c_f_op_push_mem_mem_mem_mem}, + {0, 0, 0, "assign_pop", c_f_op_assign_pop}, + {-1} +#else + {0} +#endif +}; diff --git a/src/compiler.h b/src/compiler.h new file mode 100644 index 0000000..8c51f84 --- /dev/null +++ b/src/compiler.h @@ -0,0 +1,88 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Simple C compiler. + */ + +#ifndef _JOHN_COMPILER_H +#define _JOHN_COMPILER_H + +/* + * Error codes. + */ +#define C_ERROR_NONE 0 +#define C_ERROR_UNKNOWN 1 +#define C_ERROR_UNEXPECTED 2 +#define C_ERROR_COUNT 3 +#define C_ERROR_TOOLONG 4 +#define C_ERROR_TOOCOMPLEX 5 +#define C_ERROR_ARRAYSIZE 6 +#define C_ERROR_DATASIZE 7 +#define C_ERROR_RANGE 8 +#define C_ERROR_DUPE 9 +#define C_ERROR_RESERVED 10 +#define C_ERROR_NOTINFUNC 11 +#define C_ERROR_NESTEDFUNC 12 +#define C_ERROR_NOTINIF 13 +#define C_ERROR_NOTINLOOP 14 +#define C_ERROR_EOF 15 +#define C_ERROR_INTERNAL 16 + +/* + * Error names. + */ +extern char *c_errors[]; + +/* + * Last error code. + */ +extern int c_errno; + +/* + * Data type used by compiled programs. + */ +typedef int c_int; + +/* + * Identifier list entry. + */ +struct c_ident { +/* Pointer to next entry */ + struct c_ident *next; + +/* This identifier */ + char *name; + +/* Its address */ + void *addr; +}; + +/* + * Runs the compiler, and allocates some memory for its output and the + * program's data. Returns one of the error codes. + */ +extern int c_compile(int (*ext_getchar)(void), void (*ext_rewind)(void), + struct c_ident *externs); + +/* + * Returns the function's address or NULL if not found. + */ +extern void *c_lookup(char *name); + +/* + * Executes a function previously compiled with c_compile(). + */ +#define c_execute(addr) \ + if (addr) \ + c_execute_fast(addr) +extern void c_execute_fast(void *addr); + +#endif diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..4a9fadb --- /dev/null +++ b/src/config.c @@ -0,0 +1,237 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2002,2009,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include +#include +#include +#include + +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "config.h" +#include "john.h" + +char *cfg_name = NULL; +static struct cfg_section *cfg_database = NULL; + +static char *trim(char *s) +{ + char *e; + + while (*s && (*s == ' ' || *s == '\t')) s++; + if (!*s) return s; + + e = s + strlen(s) - 1; + while (e >= s && (*e == ' ' || *e == '\t')) e--; + *++e = 0; + return s; +} + +static void cfg_add_section(char *name) +{ + struct cfg_section *last; + + last = cfg_database; + cfg_database = mem_alloc_tiny( + sizeof(struct cfg_section), MEM_ALIGN_WORD); + cfg_database->next = last; + + cfg_database->name = str_alloc_copy(name); + cfg_database->params = NULL; + + if (!strncmp(name, "list.", 5)) { + cfg_database->list = mem_alloc_tiny( + sizeof(struct cfg_list), MEM_ALIGN_WORD); + cfg_database->list->head = cfg_database->list->tail = NULL; + } else { + cfg_database->list = NULL; + } +} + +static void cfg_add_line(char *line, int number) +{ + struct cfg_list *list; + struct cfg_line *entry; + + entry = mem_alloc_tiny(sizeof(struct cfg_line), MEM_ALIGN_WORD); + entry->next = NULL; + + entry->data = str_alloc_copy(line); + entry->number = number; + + list = cfg_database->list; + if (list->tail) + list->tail = list->tail->next = entry; + else + list->tail = list->head = entry; +} + +static void cfg_add_param(char *name, char *value) +{ + struct cfg_param *current, *last; + + last = cfg_database->params; + current = cfg_database->params = mem_alloc_tiny( + sizeof(struct cfg_param), MEM_ALIGN_WORD); + current->next = last; + + current->name = str_alloc_copy(name); + current->value = str_alloc_copy(value); +} + +static int cfg_process_line(char *line, int number) +{ + char *p; + + line = trim(line); + if (!*line || *line == '#' || *line == ';') return 0; + + if (*line == '[') { + if ((p = strchr(line, ']'))) *p = 0; else return 1; + cfg_add_section(strlwr(trim(line + 1))); + } else + if (cfg_database && cfg_database->list) { + cfg_add_line(line, number); + } else + if (cfg_database && (p = strchr(line, '='))) { + *p++ = 0; + cfg_add_param(strlwr(trim(line)), trim(p)); + } else { + return 1; + } + + return 0; +} + +static void cfg_error(char *name, int number) +{ + if (john_main_process) + fprintf(stderr, "Error in %s at line %d\n", + path_expand(name), number); + error(); +} + +void cfg_init(char *name, int allow_missing) +{ + FILE *file; + char line[LINE_BUFFER_SIZE]; + int number; + + if (cfg_database) return; + + if (!(file = fopen(path_expand(name), "r"))) { + if (allow_missing && errno == ENOENT) return; + pexit("fopen: %s", path_expand(name)); + } + + number = 0; + while (fgetl(line, sizeof(line), file)) + if (cfg_process_line(line, ++number)) cfg_error(name, number); + + if (ferror(file)) pexit("fgets"); + + if (fclose(file)) pexit("fclose"); + + cfg_name = str_alloc_copy(path_expand(name)); +} + +static struct cfg_section *cfg_get_section(char *section, char *subsection) +{ + struct cfg_section *current; + char *p1, *p2; + + if ((current = cfg_database)) + do { + p1 = current->name; p2 = section; + while (*p1 && *p1 == tolower((int)(unsigned char)*p2)) { + p1++; p2++; + } + if (*p2) continue; + + if ((p2 = subsection)) + while (*p1 && *p1 == tolower((int)(unsigned char)*p2)) { + p1++; p2++; + } + if (*p1) continue; + if (p2) if (*p2) continue; + + return current; + } while ((current = current->next)); + + return NULL; +} + +struct cfg_list *cfg_get_list(char *section, char *subsection) +{ + struct cfg_section *current; + + if ((current = cfg_get_section(section, subsection))) + return current->list; + + return NULL; +} + +char *cfg_get_param(char *section, char *subsection, char *param) +{ + struct cfg_section *current_section; + struct cfg_param *current_param; + char *p1, *p2; + + if ((current_section = cfg_get_section(section, subsection))) + if ((current_param = current_section->params)) + do { + p1 = current_param->name; p2 = param; + while (*p1 && *p1 == tolower((int)(unsigned char)*p2)) { + p1++; p2++; + } + if (*p1 || *p2) continue; + + return current_param->value; + } while ((current_param = current_param->next)); + + return NULL; +} + +int cfg_get_int(char *section, char *subsection, char *param) +{ + char *s_value, *error; + long l_value; + + if ((s_value = cfg_get_param(section, subsection, param))) { + l_value = strtol(s_value, &error, 10); + if (!*s_value || *error || (l_value & ~0x3FFFFFFFL)) + return -1; + return (int)l_value; + } + + return -1; +} + +int cfg_get_bool(char *section, char *subsection, char *param, int def) +{ + char *value; + + if (!(value = cfg_get_param(section, subsection, param))) + return def; + + switch (*value) { + case 'y': + case 'Y': + case 't': + case 'T': + case '1': + return 1; + } + + return 0; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..a2c55ad --- /dev/null +++ b/src/config.h @@ -0,0 +1,85 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2009 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Configuration file loader. + */ + +#ifndef _JOHN_CONFIG_H +#define _JOHN_CONFIG_H + +/* + * Parameter list entry. + */ +struct cfg_param { + struct cfg_param *next; + char *name, *value; +}; + +/* + * Line list entry. + */ +struct cfg_line { + struct cfg_line *next; + char *data; + int number; +}; + +/* + * Main line list structure, head is used to start scanning the list, while + * tail is used to add new entries. + */ +struct cfg_list { + struct cfg_line *head, *tail; +}; + +/* + * Section list entry. + */ +struct cfg_section { + struct cfg_section *next; + char *name; + struct cfg_param *params; + struct cfg_list *list; +}; + +/* + * Name of the currently loaded configuration file, or NULL for none. + */ +extern char *cfg_name; + +/* + * Loads a configuration file, or does nothing if one is already loaded. + */ +extern void cfg_init(char *name, int allow_missing); + +/* + * Searches for a section with the supplied name, and returns its line list + * structure, or NULL if the search fails. + */ +extern struct cfg_list *cfg_get_list(char *section, char *subsection); + +/* + * Searches for a section with the supplied name and a parameter within the + * section, and returns the parameter's value, or NULL if not found. + */ +extern char *cfg_get_param(char *section, char *subsection, char *param); + +/* + * Similar to the above, but does an atoi(). Returns -1 if not found. + */ +extern int cfg_get_int(char *section, char *subsection, char *param); + +/* + * Converts the value to boolean. Returns def if not found. + */ +extern int cfg_get_bool(char *section, char *subsection, char *param, int def); + +#endif diff --git a/src/cracker.c b/src/cracker.c new file mode 100644 index 0000000..4976759 --- /dev/null +++ b/src/cracker.c @@ -0,0 +1,467 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2003,2006,2010-2013 by Solar Designer + */ + +#define NEED_OS_TIMER +#include "os.h" + +#include +#include + +#include "arch.h" +#include "misc.h" +#include "math.h" +#include "params.h" +#include "memory.h" +#include "signals.h" +#include "idle.h" +#include "formats.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "external.h" +#include "john.h" + +#ifdef index +#undef index +#endif + +static struct db_main *crk_db; +static struct fmt_params crk_params; +static struct fmt_methods crk_methods; +static int crk_key_index, crk_last_key; +static void *crk_last_salt; +static void (*crk_fix_state)(void); +static struct db_keys *crk_guesses; +static int64 *crk_timestamps; +static char crk_stdout_key[PLAINTEXT_BUFFER_SIZE]; + +static void crk_dummy_set_salt(void *salt) +{ +} + +static void crk_dummy_fix_state(void) +{ +} + +static void crk_init_salt(void) +{ + if (!crk_db->salts->next) { + crk_methods.set_salt(crk_db->salts->salt); + crk_methods.set_salt = crk_dummy_set_salt; + } +} + +static void crk_help(void) +{ + static int printed = 0; + if (!john_main_process || printed) + return; + fprintf(stderr, "Press 'q' or Ctrl-C to abort, " + "almost any other key for status\n"); + printed = 1; +} + +void crk_init(struct db_main *db, void (*fix_state)(void), + struct db_keys *guesses) +{ + char *where; + size_t size; + +/* + * We should have already called fmt_self_test() from john.c. This redundant + * self-test is only to catch some more obscure bugs in debugging builds (it + * is a no-op in normal builds). Additionally, we skip it even in debugging + * builds if we're running in --stdout mode (there's no format involved then) + * or if the format has a custom reset() method (we've already called reset(db) + * from john.c, and we don't want to mess with the format's state). + */ + if (db->loaded && db->format->methods.reset == fmt_default_reset) + if ((where = fmt_self_test(db->format))) { + log_event("! Self test failed (%s)", where); + fprintf(stderr, "Self test failed (%s)\n", where); + error(); + } + + crk_db = db; + memcpy(&crk_params, &db->format->params, sizeof(struct fmt_params)); + memcpy(&crk_methods, &db->format->methods, sizeof(struct fmt_methods)); + + if (db->loaded) crk_init_salt(); + crk_last_key = crk_key_index = 0; + crk_last_salt = NULL; + + if (fix_state) + (crk_fix_state = fix_state)(); + else + crk_fix_state = crk_dummy_fix_state; + + crk_guesses = guesses; + + if (db->loaded) { + size = crk_params.max_keys_per_crypt * sizeof(int64); + memset(crk_timestamps = mem_alloc(size), -1, size); + } else + crk_stdout_key[0] = 0; + + rec_save(); + + crk_help(); + + idle_init(db->format); +} + +/* + * crk_remove_salt() is called by crk_remove_hash() when it happens to remove + * the last password hash for a salt. + */ +static void crk_remove_salt(struct db_salt *salt) +{ + struct db_salt **current; + + crk_db->salt_count--; + + current = &crk_db->salts; + while (*current != salt) + current = &(*current)->next; + *current = salt->next; +} + +/* + * Updates the database after a password has been cracked. + */ +static void crk_remove_hash(struct db_salt *salt, struct db_password *pw) +{ + struct db_password **current; + int hash, count; + + crk_db->password_count--; + + if (!--salt->count) { + salt->list = NULL; /* "single crack" mode might care */ + crk_remove_salt(salt); + return; + } + +/* + * If there's no bitmap for this salt, assume that next_hash fields are unused + * and don't need to be updated. Only bother with the list. + */ + if (!salt->bitmap) { + current = &salt->list; + while (*current != pw) + current = &(*current)->next; + *current = pw->next; + pw->binary = NULL; + return; + } + + hash = crk_db->format->methods.binary_hash[salt->hash_size](pw->binary); + count = 0; + current = &salt->hash[hash >> PASSWORD_HASH_SHR]; + do { + if (crk_db->format->methods.binary_hash[salt->hash_size] + ((*current)->binary) == hash) + count++; + if (*current == pw) + *current = pw->next_hash; + else + current = &(*current)->next_hash; + } while (*current); + + assert(count >= 1); + +/* + * If we have removed the last entry with the exact hash value from this hash + * bucket (which could also contain entries with nearby hash values in case + * PASSWORD_HASH_SHR is non-zero), we must also reset the corresponding bit. + */ + if (count == 1) + salt->bitmap[hash / (sizeof(*salt->bitmap) * 8)] &= + ~(1U << (hash % (sizeof(*salt->bitmap) * 8))); + +/* + * If there's a hash table for this salt, assume that the list is only used by + * "single crack" mode, so mark the entry for removal by "single crack" mode + * code in case that's what we're running, instead of traversing the list here. + */ + pw->binary = NULL; +} + +static int crk_process_guess(struct db_salt *salt, struct db_password *pw, + int index) +{ + int dupe; + char *key; + + dupe = !memcmp(&crk_timestamps[index], &status.crypts, sizeof(int64)); + crk_timestamps[index] = status.crypts; + + key = crk_methods.get_key(index); + + log_guess(crk_db->options->flags & DB_LOGIN ? pw->login : "?", + dupe ? NULL : + crk_methods.source(pw->source, pw->binary), key); + + crk_db->guess_count++; + status.guess_count++; + + if (crk_guesses && !dupe) { + strnfcpy(crk_guesses->ptr, key, crk_params.plaintext_length); + crk_guesses->ptr += crk_params.plaintext_length; + crk_guesses->count++; + } + + crk_remove_hash(salt, pw); + + if (!crk_db->salts) + return 1; + + crk_init_salt(); + + return 0; +} + +static int crk_process_event(void) +{ + event_pending = 0; + + if (event_save) { + event_save = 0; + rec_save(); + } + + if (event_status) { + event_status = 0; + status_print(); + } + + if (event_ticksafety) { + event_ticksafety = 0; + status_ticks_overflow_safety(); + } + + return event_abort; +} + +static int crk_password_loop(struct db_salt *salt) +{ + struct db_password *pw; + int count, match, index; + +#if !OS_TIMER + sig_timer_emu_tick(); +#endif + + idle_yield(); + + if (event_pending && crk_process_event()) + return -1; + + count = crk_key_index; + match = crk_methods.crypt_all(&count, salt); + crk_last_key = count; + + { + int64 effective_count; + mul32by32(&effective_count, salt->count, count); + status_update_crypts(&effective_count, count); + } + + if (!match) + return 0; + + if (!salt->bitmap) { + pw = salt->list; + do { + if (crk_methods.cmp_all(pw->binary, match)) + for (index = 0; index < match; index++) + if (crk_methods.cmp_one(pw->binary, index)) + if (crk_methods.cmp_exact(crk_methods.source( + pw->source, pw->binary), index)) { + if (crk_process_guess(salt, pw, index)) + return 1; + else + break; + } + } while ((pw = pw->next)); + } else + for (index = 0; index < match; index++) { + int hash = salt->index(index); + if (salt->bitmap[hash / (sizeof(*salt->bitmap) * 8)] & + (1U << (hash % (sizeof(*salt->bitmap) * 8)))) { + pw = salt->hash[hash >> PASSWORD_HASH_SHR]; + do { + if (crk_methods.cmp_one(pw->binary, index)) + if (crk_methods.cmp_exact(crk_methods.source( + pw->source, pw->binary), index)) + if (crk_process_guess(salt, pw, index)) + return 1; + } while ((pw = pw->next_hash)); + } + } + + return 0; +} + +static int crk_salt_loop(void) +{ + int done; + struct db_salt *salt; + + salt = crk_db->salts; + do { + crk_methods.set_salt(salt->salt); + if ((done = crk_password_loop(salt))) + break; + } while ((salt = salt->next)); + + if (done >= 0) + add32to64(&status.cands, crk_key_index); + + if (salt) + return 1; + + crk_key_index = 0; + crk_last_salt = NULL; + crk_fix_state(); + + crk_methods.clear_keys(); + + if (ext_abort) + event_abort = 1; + + if (ext_status && !event_abort) { + ext_status = 0; + event_status = 0; + status_print(); + } + + return ext_abort; +} + +int crk_process_key(char *key) +{ + if (crk_db->loaded) { + crk_methods.set_key(key, crk_key_index++); + + if (crk_key_index >= crk_params.max_keys_per_crypt) + return crk_salt_loop(); + + return 0; + } + +#if !OS_TIMER + sig_timer_emu_tick(); +#endif + + if (event_pending) + if (crk_process_event()) return 1; + + puts(strnzcpy(crk_stdout_key, key, crk_params.plaintext_length + 1)); + + status_update_cands(1); + + crk_fix_state(); + + if (ext_abort) + event_abort = 1; + + if (ext_status && !event_abort) { + ext_status = 0; + event_status = 0; + status_print(); + } + + return ext_abort; +} + +/* This function is used by single.c only */ +int crk_process_salt(struct db_salt *salt) +{ + char *ptr; + char key[PLAINTEXT_BUFFER_SIZE]; + int count, count_from_guesses, index; + + if (crk_guesses) { + crk_guesses->count = 0; + crk_guesses->ptr = crk_guesses->buffer; + } + + if (crk_last_salt != salt->salt) + crk_methods.set_salt(crk_last_salt = salt->salt); + + ptr = salt->keys->buffer; + count = salt->keys->count; + count_from_guesses = salt->keys->count_from_guesses; + index = 0; + + crk_methods.clear_keys(); + + while (count--) { + strnzcpy(key, ptr, crk_params.plaintext_length + 1); + ptr += crk_params.plaintext_length; + + crk_methods.set_key(key, index++); + if (index >= crk_params.max_keys_per_crypt || !count) { + int done; + crk_key_index = index; + if ((done = crk_password_loop(salt)) >= 0) { +/* + * The approach we use here results in status.cands growing slower than it + * ideally should until this loop completes (at which point status.cands has + * the correct value). If cracking is interrupted (and then possibly + * restored), status.cands may be left with a value lower than it should have. + * An alternative would have been storing per-candidate flags indicating where + * each candidate came from, but it'd cost. + */ + int not_from_guesses = + index - count_from_guesses; + if (not_from_guesses > 0) { + add32to64(&status.cands, + not_from_guesses); + count_from_guesses = 0; + } else + count_from_guesses -= index; + } + if (done) + return 1; + if (!salt->list) + return 0; + index = 0; + } + } + + return 0; +} + +char *crk_get_key1(void) +{ + if (crk_db->loaded) + return crk_methods.get_key(0); + else + return crk_stdout_key; +} + +char *crk_get_key2(void) +{ + if (crk_key_index > 1 && crk_key_index < crk_last_key) + return crk_methods.get_key(crk_key_index - 1); + else + if (crk_last_key > 1) + return crk_methods.get_key(crk_last_key - 1); + else + return NULL; +} + +void crk_done(void) +{ + if (crk_db->loaded) { + if (crk_key_index && crk_db->salts && !event_abort) + crk_salt_loop(); + + MEM_FREE(crk_timestamps); + } +} diff --git a/src/cracker.h b/src/cracker.h new file mode 100644 index 0000000..896aeae --- /dev/null +++ b/src/cracker.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99 by Solar Designer + */ + +/* + * Cracking routines. + */ + +#ifndef _JOHN_CRACKER_H +#define _JOHN_CRACKER_H + +#include "loader.h" + +/* + * Initializes the cracker for a password database (should not be empty). + * If fix_state() is not NULL, it will be called when key buffer becomes + * empty, its purpose is to save current state for possible recovery in + * the future. If guesses is not NULL, the cracker will save guessed keys + * in there (the caller must make sure there's room). + */ +extern void crk_init(struct db_main *db, void (*fix_state)(void), + struct db_keys *guesses); + +/* + * Tries the key against all passwords in the database (should not be empty). + * The return value is non-zero if aborted or everything got cracked (the + * event_abort flag can be used to find out which of these has happened). + */ +extern int crk_process_key(char *key); + +/* + * Resets the guessed keys buffer and processes all the buffered keys for + * this salt. The return value is the same as for crk_process_key(). + */ +extern int crk_process_salt(struct db_salt *salt); + +/* + * Return current keys range, crk_get_key2() may return NULL if there's only + * one key. Note: these functions may share a static result buffer. + */ +extern char *crk_get_key1(void); +extern char *crk_get_key2(void); + +/* + * Processes all the buffered keys (unless aborted). + */ +extern void crk_done(void); + +#endif diff --git a/src/crc32.c b/src/crc32.c new file mode 100644 index 0000000..dd53480 --- /dev/null +++ b/src/crc32.c @@ -0,0 +1,81 @@ +/* + * This is a tiny implementation of CRC-32. + * + * This software was written by Solar Designer in 1998 and revised in 2005. + * No copyright is claimed, and the software is hereby placed in the public + * domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 1998,2005 by Solar Designer and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + */ + +#include + +#include "memory.h" +#include "crc32.h" + +#define POLY 0xEDB88320 +#define ALL1 0xFFFFFFFF + +static CRC32_t *table = NULL; + +void CRC32_Init(CRC32_t *value) +{ + unsigned int index, bit; + CRC32_t entry; + + *value = ALL1; + + if (table) return; +/* mem_alloc() doesn't return on failure. If replacing this with plain + * malloc(3), error checking would need to be added. */ + table = mem_alloc(sizeof(*table) * 0x100); + + for (index = 0; index < 0x100; index++) { + entry = index; + + for (bit = 0; bit < 8; bit++) + if (entry & 1) { + entry >>= 1; + entry ^= POLY; + } else + entry >>= 1; + + table[index] = entry; + } +} + +void CRC32_Update(CRC32_t *value, void *data, unsigned int size) +{ + unsigned char *ptr; + unsigned int count; + CRC32_t result; + + result = *value; + ptr = data; + count = size; + + if (count) + do { + result = (result >> 8) ^ table[(result ^ *ptr++) & 0xFF]; + } while (--count); + + *value = result; +} + +void CRC32_Final(unsigned char *out, CRC32_t value) +{ + value = ~value; + out[0] = value; + out[1] = value >> 8; + out[2] = value >> 16; + out[3] = value >> 24; +} diff --git a/src/crc32.h b/src/crc32.h new file mode 100644 index 0000000..9dd9751 --- /dev/null +++ b/src/crc32.h @@ -0,0 +1,42 @@ +/* + * This is a tiny implementation of CRC-32. + * + * This software was written by Solar Designer in 1998 and revised in 2005. + * No copyright is claimed, and the software is hereby placed in the public + * domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 1998,2005 by Solar Designer and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + */ + +#ifndef _JOHN_CRC32_H +#define _JOHN_CRC32_H + +typedef unsigned int CRC32_t; + +/* + * When called for the first time, allocates memory for and initializes + * the internal table. Always initializes the CRC-32 value to all 1's. + */ +extern void CRC32_Init(CRC32_t *value); + +/* + * Updates the current CRC-32 value with the supplied data block. + */ +extern void CRC32_Update(CRC32_t *value, void *data, unsigned int size); + +/* + * Finalizes the CRC-32 value by inverting all bits and saving it as + * little-endian. + */ +extern void CRC32_Final(unsigned char *out, CRC32_t value); + +#endif diff --git a/src/detect.c b/src/detect.c new file mode 100644 index 0000000..fdc657b --- /dev/null +++ b/src/detect.c @@ -0,0 +1,137 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters detection program. + */ + +#include + +int main(int argc, char **argv) +{ + int value = 1; + int size_log; + + if (argc != 8) return 1; + + size_log = 0; + while (sizeof(long) * 8 != 1 << size_log) size_log++; + + puts( +"/*\n" +" * Architecture specific parameters. This is a generated file, do not edit.\n" +" */\n" +"\n" +"#ifndef _JOHN_ARCH_H\n" +"#define _JOHN_ARCH_H\n"); + + printf( +"#define ARCH_WORD\t\t\tlong\n" +"#define ARCH_SIZE\t\t\t%d\n" +"#define ARCH_BITS\t\t\t%d\n" +"#define ARCH_BITS_LOG\t\t\t%d\n" +"#define ARCH_BITS_STR\t\t\t\"%d\"\n" +"#define ARCH_LITTLE_ENDIAN\t\t%d\n" +"#define ARCH_INT_GT_32\t\t\t%d\n" +"#define ARCH_ALLOWS_UNALIGNED\t\t0\n" +#ifdef __alpha__ +"#define ARCH_INDEX(x)\t\t\t((unsigned long)(unsigned char)(x))\n" +#else +"#define ARCH_INDEX(x)\t\t\t((unsigned int)(unsigned char)(x))\n" +#endif +"\n", + (int)sizeof(long), + (int)(sizeof(long) * 8), + size_log, + (int)(sizeof(long) * 8), + (int)(*(char *)&value), + (sizeof(int) > 4) ? 1 : 0); + + puts( +"#define CPU_DETECT\t\t\t0\n\n" +"#define DES_ASM\t\t\t\t0"); + + switch (argv[1][0]) { + case '1': + puts( +"#define DES_128K\t\t\t0\n" +"#define DES_X2\t\t\t\t0\n" +"#define DES_MASK\t\t\t0\n" +"#define DES_SCALE\t\t\t1\n" +"#define DES_EXTB\t\t\t0"); + break; + + case '2': + puts( +"#define DES_128K\t\t\t1\n" +"#define DES_X2\t\t\t\t0\n" +"#define DES_MASK\t\t\t1\n" +"#define DES_SCALE\t\t\t1\n" +"#define DES_EXTB\t\t\t1"); + break; + + case '3': + puts( +"#define DES_128K\t\t\t0\n" +"#define DES_X2\t\t\t\t0\n" +"#define DES_MASK\t\t\t1\n" +"#define DES_SCALE\t\t\t1\n" +"#define DES_EXTB\t\t\t0"); + break; + + case '4': + puts( +"#define DES_128K\t\t\t0\n" +"#define DES_X2\t\t\t\t0\n" +"#define DES_MASK\t\t\t1\n" +"#define DES_SCALE\t\t\t1\n" +"#define DES_EXTB\t\t\t1"); + break; + + case '5': + if (sizeof(long) >= 8) { + puts( +"#define DES_128K\t\t\t0\n" +"#define DES_X2\t\t\t\t0\n" +"#define DES_MASK\t\t\t1\n" +"#define DES_SCALE\t\t\t0\n" +"#define DES_EXTB\t\t\t0"); + break; + } + + default: + return 1; + } + + printf( +"#define DES_COPY\t\t\t%c\n" +"#define DES_BS_ASM\t\t\t0\n" +"#define DES_BS\t\t\t\t%c\n" +"#define DES_BS_VECTOR\t\t\t0\n" +"#define DES_BS_EXPAND\t\t\t1\n" +"\n" +"#define MD5_ASM\t\t\t\t0\n" +"#define MD5_X2\t\t\t\t%c\n" +"#define MD5_IMM\t\t\t\t%c\n" +"\n" +"#define BF_ASM\t\t\t\t0\n" +"#define BF_SCALE\t\t\t%c\n" +"#define BF_X2\t\t\t\t%c\n" +"\n" +"#endif\n", + argv[2][0], + argv[3][0], + argv[4][0], + argv[5][0], + argv[6][0], + argv[7][0]); + + return 0; +} diff --git a/src/dummy.c b/src/dummy.c new file mode 100644 index 0000000..c334fb2 --- /dev/null +++ b/src/dummy.c @@ -0,0 +1,321 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2011,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "dummy" +#define FORMAT_NAME "" +#define ALGORITHM_NAME "N/A" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +/* Max 125, but 95 typically produces fewer L1 data cache tag collisions */ +#define PLAINTEXT_LENGTH 95 + +typedef struct { + ARCH_WORD_32 hash; + char c0; +} dummy_binary; + +#define BINARY_SIZE sizeof(dummy_binary) +#define BINARY_ALIGN sizeof(ARCH_WORD_32) +#define SALT_SIZE 0 +#define SALT_ALIGN 1 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT (0x4000 / (PLAINTEXT_LENGTH + 1)) + +static struct fmt_tests tests[] = { + {"$dummy$64756d6d79", "dummy"}, + {"$dummy$", ""}, + {"$dummy$70617373776f7264", "password"}, + {NULL} +}; + +static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1]; + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *p, *q, c; + + if (strncmp(ciphertext, "$dummy$", 7)) + return 0; + + p = strrchr(ciphertext, '$'); + +/* Support saltless hashes only for now */ + if (p - ciphertext != 6) + return 0; + + q = ++p; + while ((c = *q)) { + q++; + if (atoi16[ARCH_INDEX(c)] == 0x7F) + return 0; + if (c >= 'A' && c <= 'F') /* support lowercase only */ + return 0; + } + +/* Must be an even number of hex chars (zero is OK) */ + if ((q - p) & 1) + return 0; + +/* We won't be able to crack passwords longer than PLAINTEXT_LENGTH. + * Also, we rely on this check having been performed before decode(). */ + if (((q - p) >> 1) > PLAINTEXT_LENGTH) + return 0; + + return 1; +} + +static char *decode(char *ciphertext) +{ + static char out[PLAINTEXT_LENGTH + 1]; + char *p, *q, c; + + p = strrchr(ciphertext, '$') + 1; + q = out; + while ((c = *p)) { + p++; + *q++ = (atoi16[ARCH_INDEX(c)] << 4) | atoi16[ARCH_INDEX(*p++)]; + } + *q = 0; + + return out; +} + +static MAYBE_INLINE ARCH_WORD_32 string_hash(char *s) +{ + ARCH_WORD_32 hash, extra; + char *p; + + p = s + 2; + hash = (unsigned char)s[0]; + if (!hash) + goto out; + extra = (unsigned char)s[1]; + if (!extra) + goto out; + + while (*p) { + hash <<= 3; extra <<= 2; + hash += (unsigned char)p[0]; + if (!p[1]) break; + extra += (unsigned char)p[1]; + p += 2; + if (hash & 0xe0000000) { + hash ^= hash >> 20; + extra ^= extra >> 20; + hash &= 0xfffff; + } + } + + hash -= extra; + hash ^= extra << 10; + + hash ^= hash >> 16; + +out: + return hash; +} + +static void *binary(char *ciphertext) +{ + static dummy_binary out; + char *decoded; + + decoded = decode(ciphertext); + + out.hash = string_hash(decoded); + out.c0 = decoded[0]; + + return &out; +} + +static int binary_hash_0(void *binary) +{ + ARCH_WORD_32 hash = ((dummy_binary *)binary)->hash; + hash ^= hash >> 8; + return (hash ^ (hash >> 4)) & 0xf; +} + +static int binary_hash_1(void *binary) +{ + ARCH_WORD_32 hash = ((dummy_binary *)binary)->hash; + return (hash ^ (hash >> 8)) & 0xff; +} + +static int binary_hash_2(void *binary) +{ + ARCH_WORD_32 hash = ((dummy_binary *)binary)->hash; + return (hash ^ (hash >> 12)) & 0xfff; +} + +static int binary_hash_3(void *binary) +{ + return ((dummy_binary *)binary)->hash & 0xffff; +} + +static int binary_hash_4(void *binary) +{ + return ((dummy_binary *)binary)->hash & 0xfffff; +} + +static int binary_hash_5(void *binary) +{ + return ((dummy_binary *)binary)->hash & 0xffffff; +} + +static int binary_hash_6(void *binary) +{ + return ((dummy_binary *)binary)->hash & 0x7ffffff; +} + +static int get_hash_0(int index) +{ + ARCH_WORD_32 hash = string_hash(saved_key[index]); + hash ^= hash >> 8; + return (hash ^ (hash >> 4)) & 0xf; +} + +static int get_hash_1(int index) +{ + ARCH_WORD_32 hash = string_hash(saved_key[index]); + return (hash ^ (hash >> 8)) & 0xff; +} + +static int get_hash_2(int index) +{ + ARCH_WORD_32 hash = string_hash(saved_key[index]); + return (hash ^ (hash >> 12)) & 0xfff; +} + +static int get_hash_3(int index) +{ + return string_hash(saved_key[index]) & 0xffff; +} + +static int get_hash_4(int index) +{ + return string_hash(saved_key[index]) & 0xfffff; +} + +static int get_hash_5(int index) +{ + return string_hash(saved_key[index]) & 0xffffff; +} + +static int get_hash_6(int index) +{ + return string_hash(saved_key[index]) & 0x7ffffff; +} + +static void set_key(char *key, int index) +{ + char *p = saved_key[index]; + *p = 0; + strncat(p, key, PLAINTEXT_LENGTH); +} + +static char *get_key(int index) +{ + return saved_key[index]; +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + return *pcount; +} + +static int cmp_all(void *binary, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (((dummy_binary *)binary)->c0 != saved_key[i][0]) + continue; + if (((dummy_binary *)binary)->hash == string_hash(saved_key[i])) + return 1; + } + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + return + ((dummy_binary *)binary)->c0 == saved_key[index][0] && + ((dummy_binary *)binary)->hash == string_hash(saved_key[index]); +} + +static int cmp_exact(char *source, int index) +{ + return !strcmp(decode(source), saved_key[index]); +} + +struct fmt_main fmt_dummy = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + fmt_default_init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + binary, + fmt_default_salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + fmt_default_salt_hash, + fmt_default_set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/external.c b/src/external.c new file mode 100644 index 0000000..cf1b395 --- /dev/null +++ b/src/external.c @@ -0,0 +1,293 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2003,2004,2006,2011,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "misc.h" +#include "params.h" +#include "signals.h" +#include "compiler.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "config.h" +#include "cracker.h" +#include "john.h" +#include "external.h" + +static char int_word[PLAINTEXT_BUFFER_SIZE]; +static char rec_word[PLAINTEXT_BUFFER_SIZE]; + +/* + * A "sequence number" for distributing the candidate passwords across nodes. + * It is OK if this number overflows once in a while, as long as this happens + * in the same way for all nodes (must be same size unsigned integer type). + */ +static unsigned int seq, rec_seq; + +unsigned int ext_flags = 0; +static char *ext_mode; + +static c_int ext_word[PLAINTEXT_BUFFER_SIZE]; +c_int ext_abort, ext_status; + +static struct c_ident ext_ident_status = { + NULL, + "status", + &ext_status +}; + +static struct c_ident ext_ident_abort = { + &ext_ident_status, + "abort", + &ext_abort +}; + +static struct c_ident ext_globals = { + &ext_ident_abort, + "word", + ext_word +}; + +static void *f_generate; +void *f_filter = NULL; + +static struct cfg_list *ext_source; +static struct cfg_line *ext_line; +static int ext_pos; + +static int ext_getchar(void) +{ + unsigned char c; + + if (!ext_line || !ext_line->data) return -1; + + if ((c = (unsigned char)ext_line->data[ext_pos++])) return c; + + ext_line = ext_line->next; + ext_pos = 0; + return '\n'; +} + +static void ext_rewind(void) +{ + ext_line = ext_source->head; + ext_pos = 0; +} + +void ext_init(char *mode) +{ + if (!(ext_source = cfg_get_list(SECTION_EXT, mode))) { + if (john_main_process) + fprintf(stderr, "Unknown external mode: %s\n", mode); + error(); + } + + if (c_compile(ext_getchar, ext_rewind, &ext_globals)) { + if (!ext_line) ext_line = ext_source->tail; + + if (john_main_process) + fprintf(stderr, + "Compiler error in %s at line %d: %s\n", + cfg_name, ext_line->number, + c_errors[c_errno]); + error(); + } + + ext_word[0] = 0; + c_execute(c_lookup("init")); + + f_generate = c_lookup("generate"); + f_filter = c_lookup("filter"); + + if ((ext_flags & EXT_REQ_GENERATE) && !f_generate) { + if (john_main_process) + fprintf(stderr, + "No generate() for external mode: %s\n", mode); + error(); + } + if ((ext_flags & EXT_REQ_FILTER) && !f_filter) { + if (john_main_process) + fprintf(stderr, + "No filter() for external mode: %s\n", mode); + error(); + } + if (john_main_process && + (ext_flags & (EXT_USES_GENERATE | EXT_USES_FILTER)) == + EXT_USES_FILTER && f_generate) + fprintf(stderr, "Warning: external mode defines generate(), " + "but is only used for filter()\n"); + + ext_mode = mode; +} + +int ext_filter_body(char *in, char *out) +{ + unsigned char *internal; + c_int *external; + + internal = (unsigned char *)in; + external = ext_word; + external[0] = internal[0]; + external[1] = internal[1]; + external[2] = internal[2]; + external[3] = internal[3]; + if (external[0] && external[1] && external[2] && external[3]) + do { + if (!(external[4] = internal[4])) + break; + if (!(external[5] = internal[5])) + break; + if (!(external[6] = internal[6])) + break; + if (!(external[7] = internal[7])) + break; + internal += 4; + external += 4; + } while (1); + + c_execute_fast(f_filter); + + if (!ext_word[0] && in[0]) return 0; + + internal = (unsigned char *)out; + external = ext_word; + internal[0] = external[0]; + internal[1] = external[1]; + internal[2] = external[2]; + internal[3] = external[3]; + if (external[0] && external[1] && external[2] && external[3]) + do { + if (!(internal[4] = external[4])) + break; + if (!(internal[5] = external[5])) + break; + if (!(internal[6] = external[6])) + break; + if (!(internal[7] = external[7])) + break; + internal += 4; + external += 4; + } while (1); + + return 1; +} + +static void save_state(FILE *file) +{ + unsigned char *ptr; + + fprintf(file, "%u\n", rec_seq); + ptr = (unsigned char *)rec_word; + do { + fprintf(file, "%d\n", (int)*ptr); + } while (*ptr++); +} + +static int restore_state(FILE *file) +{ + int c; + unsigned char *internal; + c_int *external; + int count; + + if (rec_version >= 4 && fscanf(file, "%u\n", &seq) != 1) + return 1; + + internal = (unsigned char *)int_word; + external = ext_word; + count = 0; + do { + if (fscanf(file, "%d\n", &c) != 1) return 1; + if (++count >= PLAINTEXT_BUFFER_SIZE) return 1; + } while ((*internal++ = *external++ = c)); + + c_execute(c_lookup("restore")); + + return 0; +} + +static void fix_state(void) +{ + strcpy(rec_word, int_word); + rec_seq = seq; +} + +void do_external_crack(struct db_main *db) +{ + unsigned char *internal; + c_int *external; + + log_event("Proceeding with external mode: %.100s", ext_mode); + + internal = (unsigned char *)int_word; + external = ext_word; + while (*external) + *internal++ = *external++; + *internal = 0; + + seq = 0; + + status_init(NULL, 0); + + rec_restore_mode(restore_state); + rec_init(db, save_state); + + crk_init(db, fix_state, NULL); + + do { + c_execute_fast(f_generate); + if (!ext_word[0]) + break; + +/* + * The skipping of other nodes' candidate passwords can be optimized, such as + * to avoid the modulo division like it's done for dist_words in wordlist.c. + */ + if (options.node_count) { + int for_node = seq++ % options.node_count + 1; + if (for_node < options.node_min || + for_node > options.node_max) + continue; + } + + if (f_filter) { + c_execute_fast(f_filter); + if (!ext_word[0]) + continue; + } + + int_word[0] = ext_word[0]; + if ((int_word[1] = ext_word[1])) { + internal = (unsigned char *)&int_word[2]; + external = &ext_word[2]; + do { + if (!(internal[0] = external[0])) + break; + if (!(internal[1] = external[1])) + break; + if (!(internal[2] = external[2])) + break; + if (!(internal[3] = external[3])) + break; + internal += 4; + external += 4; + } while (1); + } + + if (crk_process_key(int_word)) break; + } while (1); + + crk_done(); + rec_done(event_abort); +} diff --git a/src/external.h b/src/external.h new file mode 100644 index 0000000..2551ebc --- /dev/null +++ b/src/external.h @@ -0,0 +1,56 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * External mode support. + */ + +#ifndef _JOHN_EXTERNAL_H +#define _JOHN_EXTERNAL_H + +#include "compiler.h" +#include "loader.h" + +#define EXT_REQ_GENERATE 0x00000001 +#define EXT_REQ_FILTER 0x00000002 +#define EXT_USES_GENERATE 0x00010000 +#define EXT_USES_FILTER 0x00020000 + +extern unsigned int ext_flags; + +extern c_int ext_abort, ext_status; + +/* + * Defined for use in the ext_filter() macro, below. + */ +extern void *f_filter; + +/* + * Initializes an external mode. + */ +extern void ext_init(char *mode); + +/* + * Calls an external word filter. Returns 0 if the word is rejected. + */ +#define ext_filter(word) \ + (!f_filter || ext_filter_body(word, word)) + +/* + * The actual implementation of ext_filter(); use the macro instead. + */ +extern int ext_filter_body(char *in, char *out); + +/* + * Runs the external mode cracker. + */ +extern void do_external_crack(struct db_main *db); + +#endif diff --git a/src/formats.c b/src/formats.c new file mode 100644 index 0000000..bacd0e8 --- /dev/null +++ b/src/formats.c @@ -0,0 +1,298 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2006,2008,2010-2013 by Solar Designer + */ + +#include +#include + +#include "params.h" +#include "memory.h" +#include "formats.h" + +struct fmt_main *fmt_list = NULL; +static struct fmt_main **fmt_tail = &fmt_list; + +void fmt_register(struct fmt_main *format) +{ + format->private.initialized = 0; + format->next = NULL; + *fmt_tail = format; + fmt_tail = &format->next; +} + +void fmt_init(struct fmt_main *format) +{ + if (!format->private.initialized) { + format->methods.init(format); + format->private.initialized = 1; + } +} + +void fmt_done(struct fmt_main *format) +{ + if (format->private.initialized) { + format->methods.done(); + format->private.initialized = 0; + } +} + +static int is_poweroftwo(size_t align) +{ + return align != 0 && (align & (align - 1)) == 0; +} + +static int is_aligned(void *p, size_t align) +{ + return ((size_t)p & (align - 1)) == 0; +} + +static char *fmt_self_test_body(struct fmt_main *format, + void *binary_copy, void *salt_copy) +{ + static char s_size[32]; + struct fmt_tests *current; + char *ciphertext, *plaintext; + int ntests, done, index, max, size; + void *binary, *salt; + int binary_align_warned = 0, salt_align_warned = 0; + +/* + * Test each format just once unless we're debugging. + */ +#ifndef DEBUG + if (format->private.initialized == 2) + return NULL; +#endif + + if (format->params.plaintext_length < 1 || + format->params.plaintext_length > PLAINTEXT_BUFFER_SIZE - 3) + return "plaintext_length"; + + if (!is_poweroftwo(format->params.binary_align)) + return "binary_align"; + + if (!is_poweroftwo(format->params.salt_align)) + return "salt_align"; + + if (format->methods.valid("*", format)) + return "valid"; + + fmt_init(format); + + format->methods.reset(NULL); + + if (!(current = format->params.tests)) return NULL; + ntests = 0; + while ((current++)->ciphertext) + ntests++; + current = format->params.tests; + + done = 0; + index = 0; max = format->params.max_keys_per_crypt; + do { + if (!current->fields[1]) + current->fields[1] = current->ciphertext; + ciphertext = format->methods.prepare(current->fields, format); + if (!ciphertext || strlen(ciphertext) < 7) + return "prepare"; + if (format->methods.valid(ciphertext, format) != 1) + return "valid"; + ciphertext = format->methods.split(ciphertext, 0, format); + plaintext = current->plaintext; + +/* + * Make sure the declared binary_size and salt_size are sufficient to actually + * hold the binary ciphertexts and salts. We do this by copying the values + * returned by binary() and salt() only to the declared sizes. + */ + binary = format->methods.binary(ciphertext); + if (!is_aligned(binary, format->params.binary_align) && + !binary_align_warned) { + puts("Warning: binary() returned misaligned pointer"); + binary_align_warned = 1; + } + memcpy(binary_copy, binary, format->params.binary_size); + binary = binary_copy; + + salt = format->methods.salt(ciphertext); + if (!is_aligned(salt, format->params.salt_align) && + !salt_align_warned) { + puts("Warning: salt() returned misaligned pointer"); + salt_align_warned = 1; + } + memcpy(salt_copy, salt, format->params.salt_size); + salt = salt_copy; + + if (strcmp(ciphertext, + format->methods.source(ciphertext, binary))) + return "source"; + + if ((unsigned int)format->methods.salt_hash(salt) >= + SALT_HASH_SIZE) + return "salt_hash"; + + format->methods.set_salt(salt); + format->methods.set_key(current->plaintext, index); + + { + int count = index + 1; + int match = format->methods.crypt_all(&count, NULL); +/* If salt is NULL, the return value must always match *count the way it is + * after the crypt_all() call. */ + if (match != count) + return "crypt_all"; + } + + for (size = 0; size < PASSWORD_HASH_SIZES; size++) + if (format->methods.binary_hash[size] && + format->methods.get_hash[size](index) != + format->methods.binary_hash[size](binary)) { + sprintf(s_size, "get_hash[%d](%d)", size, index); + return s_size; + } + + if (!format->methods.cmp_all(binary, index + 1)) + return "cmp_all"; + if (!format->methods.cmp_one(binary, index)) + return "cmp_one"; + if (!format->methods.cmp_exact(ciphertext, index)) + return "cmp_exact"; + + if (strncmp(format->methods.get_key(index), plaintext, + format->params.plaintext_length)) + return "get_key"; + +/* Remove some old keys to better test cmp_all() */ + if (index & 1) + format->methods.set_key("", index); + +/* 0 1 2 3 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 ... */ + if (index >= 2 && max > ntests) + index += index >> 1; + else + index++; + + if (index >= max) { + index = (max > 5 && max > ntests && done != 1) ? 5 : 0; + done |= 1; + } + + if (!(++current)->ciphertext) { +/* Jump straight to last index for non-bitslice DES */ + if (!(format->params.flags & FMT_BS) && + (!strcmp(format->params.label, "des") || + !strcmp(format->params.label, "bsdi") || + !strcmp(format->params.label, "afs"))) + index = max - 1; + + current = format->params.tests; + done |= 2; + } + } while (done != 3); + + format->private.initialized = 2; + + return NULL; +} + +/* + * Allocate memory for a copy of a binary ciphertext or salt with only the + * minimum guaranteed alignment. We do this to test that binary_hash*(), + * cmp_*(), and salt_hash() do accept such pointers. + */ +static void *alloc_binary(void **alloc, size_t size, size_t align) +{ + size_t mask = align - 1; + char *p; + +/* Ensure minimum required alignment and leave room for "align" bytes more */ + p = *alloc = mem_alloc(size + mask + align); + p += mask; + p -= (size_t)p & mask; + +/* If the alignment is too great, reduce it to the minimum */ + if (!((size_t)p & align)) + p += align; + + return p; +} + +char *fmt_self_test(struct fmt_main *format) +{ + char *retval; + void *binary_alloc, *salt_alloc; + void *binary_copy, *salt_copy; + + binary_copy = alloc_binary(&binary_alloc, + format->params.binary_size, format->params.binary_align); + salt_copy = alloc_binary(&salt_alloc, + format->params.salt_size, format->params.salt_align); + + retval = fmt_self_test_body(format, binary_copy, salt_copy); + + MEM_FREE(salt_alloc); + MEM_FREE(binary_alloc); + + return retval; +} + +void fmt_default_init(struct fmt_main *self) +{ +} + +void fmt_default_done(void) +{ +} + +void fmt_default_reset(struct db_main *db) +{ +} + +char *fmt_default_prepare(char *fields[10], struct fmt_main *self) +{ + return fields[1]; +} + +char *fmt_default_split(char *ciphertext, int index, struct fmt_main *self) +{ + return ciphertext; +} + +void *fmt_default_binary(char *ciphertext) +{ + return ciphertext; +} + +void *fmt_default_salt(char *ciphertext) +{ + return ciphertext; +} + +char *fmt_default_source(char *source, void *binary) +{ + return source; +} + +int fmt_default_binary_hash(void *binary) +{ + return 0; +} + +int fmt_default_salt_hash(void *salt) +{ + return 0; +} + +void fmt_default_set_salt(void *salt) +{ +} + +void fmt_default_clear_keys(void) +{ +} + +int fmt_default_get_hash(int index) +{ + return 0; +} diff --git a/src/formats.h b/src/formats.h new file mode 100644 index 0000000..0eee7b9 --- /dev/null +++ b/src/formats.h @@ -0,0 +1,289 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2010-2013 by Solar Designer + */ + +/* + * Supported ciphertext formats management. + */ + +#ifndef _JOHN_FORMATS_H +#define _JOHN_FORMATS_H + +#include "params.h" + +/* + * Some format methods accept pointers to these, yet we can't just include + * loader.h here because that would be a circular dependency. + */ +struct db_main; +struct db_salt; + +/* + * Format property flags. + */ +/* Uses case-sensitive passwords */ +#define FMT_CASE 0x00000001 +/* Supports 8-bit characters in passwords (does not ignore the 8th bit) */ +#define FMT_8_BIT 0x00000002 +/* Uses a bitslice implementation */ +#define FMT_BS 0x00010000 +/* The split() method unifies the case of characters in hash encodings */ +#define FMT_SPLIT_UNIFIES_CASE 0x00020000 +#ifdef _OPENMP +/* Parallelized with OpenMP */ +#define FMT_OMP 0x01000000 +/* Poor OpenMP scalability */ +#define FMT_OMP_BAD 0x02000000 +#else +#define FMT_OMP 0 +#define FMT_OMP_BAD 0 +#endif +/* We've already warned the user about hashes of this type being present */ +#define FMT_WARNED 0x80000000 + +/* + * A password to test the methods for correct operation. + */ +struct fmt_tests { + char *ciphertext, *plaintext; + char *fields[10]; +}; + +/* + * Parameters of a hash function and its cracking algorithm. + */ +struct fmt_params { +/* Label to refer to this format (any alphabetical characters in it must be + * lowercase). */ + char *label; + +/* Ciphertext format name */ + char *format_name; + +/* Cracking algorithm name */ + char *algorithm_name; + +/* Comment about the benchmark (can be empty) */ + char *benchmark_comment; + +/* Benchmark for short/long passwords instead of for one/many salts */ + int benchmark_length; + +/* Maximum length of a plaintext password */ + int plaintext_length; + +/* Size and alignment of binary ciphertext, in bytes */ + int binary_size; + int binary_align; + +/* Size and alignment of internal salt representation, in bytes */ + int salt_size; + int salt_align; + +/* Number of plaintexts hashed by a single crypt_all() method call */ + int min_keys_per_crypt; + int max_keys_per_crypt; + +/* Properties of this format */ + unsigned int flags; + +/* Some passwords to test the methods for correct operation (or NULL for no + * self test, and no benchmark), terminated with a NULL ciphertext. */ + struct fmt_tests *tests; +}; + +/* + * fmt_main is declared for real further down this file, but we refer to it in + * function prototypes in fmt_methods. + */ +struct fmt_main; + +/* + * Functions to implement a cracking algorithm. + */ +struct fmt_methods { +/* Initializes the algorithm's internal structures. + * prepare(), valid(), and split() are the only methods that are allowed to be + * called before a call to init(). + * Note that initializing an algorithm might de-initialize some others (if a + * shared underlying resource is used). */ + void (*init)(struct fmt_main *self); + +/* De-initializes this format, which must have been previously initialized */ + void (*done)(void); + +/* Called whenever the set of password hashes being cracked changes, such as + * after self-test, but before actual cracking starts. When called before a + * self-test or benchmark rather than before actual cracking, db may be NULL. + * Normally, this is a no-op since a format implementation shouldn't mess with + * the database unnecessarily. However, when there is a good reason to do so + * this may e.g. transfer the salts and hashes onto a GPU card. */ + void (*reset)(struct db_main *db); + +/* Extracts the ciphertext string out of the input file fields. Normally, this + * will simply return field[1], but in some special cases it may use another + * field (e.g., when the hash type is commonly used with PWDUMP rather than + * /etc/passwd format files) or/and it may also extract and include the + * username, etc. */ + char *(*prepare)(char *fields[10], struct fmt_main *self); + +/* Checks if an ASCII ciphertext is valid for this format. Returns zero for + * invalid ciphertexts, or the number of parts the ciphertext should be split + * into (up to 9, will usually be 1). */ + int (*valid)(char *ciphertext, struct fmt_main *self); + +/* Splits a ciphertext into several pieces and returns the piece with given + * index, starting from 0 (will usually return the ciphertext unchanged). + * For hex-encoded hashes which are compared by the target system/application + * irrespective of the case of characters (upper/lower/mixed) used in their + * encoding, split() must unify the case (e.g., convert to all-lowercase) + * and FMT_SPLIT_UNIFIES_CASE must be set. */ + char *(*split)(char *ciphertext, int index, struct fmt_main *self); + +/* Converts an ASCII ciphertext to binary, possibly using the salt */ + void *(*binary)(char *ciphertext); + +/* Converts an ASCII salt to its internal representation */ + void *(*salt)(char *ciphertext); + +/* Reconstructs the ASCII ciphertext from its binary (saltless only). + * Alternatively, in the simplest case simply returns "source" as-is. */ + char *(*source)(char *source, void *binary); + +/* These functions calculate a hash out of a binary ciphertext. To be used + * for hash table initialization. One of them should be selected depending + * on the hash table size. */ + int (*binary_hash[PASSWORD_HASH_SIZES])(void *binary); + +/* Calculates a hash out of a salt (given in internal representation). To be + * used by the password file loader. */ + int (*salt_hash)(void *salt); + +/* Sets a salt for the crypt_all() method */ + void (*set_salt)(void *salt); + +/* Sets a plaintext, with index from 0 to fmt_params.max_keys_per_crypt - 1 */ + void (*set_key)(char *key, int index); + +/* Returns a plaintext previously set with and potentially altered by + * set_key() (e.g., converted to all-uppercase and truncated at 7 for LM + * hashes). The plaintext may also have been generated or altered by + * crypt_all(). Depending on crypt_all() implementation, the index used here + * does not have to match an index previously used with set_key(), although + * for most formats it does. See the description of crypt_all() below. */ + char *(*get_key)(int index); + +/* Allow the previously set keys to be dropped if that would help improve + * performance and/or reduce the impact of certain hardware faults. After + * a call to clear_keys() the keys are undefined. */ + void (*clear_keys)(void); + +/* Computes the ciphertexts for given salt and plaintexts. + * For implementation reasons, this may happen to always compute at least + * min_keys_per_crypt ciphertexts even if the requested count is lower, + * although it is preferable for implementations to obey the count whenever + * practical and also for callers not to call crypt_all() with fewer than + * min_keys_per_crypt keys whenever practical. + * Returns the last output index for which there might be a match (against the + * supplied salt's hashes) plus 1. A return value of zero indicates no match. + * Note that output indices don't have to match input indices (although they + * may and usually do). The indices passed to get_key(), get_hash[](), + * cmp_one(), and cmp_exact() must be in the 0 to crypt_all() return value + * minus 1 range, although for infrequent status reporting get_key() may also + * be called on indices previously supplied to set_key() as well as on indices + * up to the updated *count minus 1 even if they're beyond this range. + * The count passed to cmp_all() must be equal to crypt_all()'s return value. + * If an implementation does not use the salt parameter or if salt is NULL + * (as it may be during self-test and benchmark), the return value must always + * match *count the way it is after the crypt_all() call. + * The count is passed by reference and must be updated by crypt_all() if it + * computes other than the requested count (such as if it generates additional + * candidate passwords on its own). The updated count is used for c/s rate + * calculation. The return value is thus in the 0 to updated *count range. */ + int (*crypt_all)(int *count, struct db_salt *salt); + +/* These functions calculate a hash out of a ciphertext that has just been + * generated with the crypt_all() method. To be used while cracking. */ + int (*get_hash[PASSWORD_HASH_SIZES])(int index); + +/* Compares a given ciphertext against all the crypt_all() method outputs and + * returns zero if no matches detected. A non-zero return value means that + * there might be matches, and more checks are needed. */ + int (*cmp_all)(void *binary, int count); + +/* Same as the above, except the comparison is done against only one of the + * crypt_all() method outputs. */ + int (*cmp_one)(void *binary, int index); + +/* Compares an ASCII ciphertext against a particular crypt_all() output */ + int (*cmp_exact)(char *source, int index); +}; + +/* + * Private fields for formats management. + */ +struct fmt_private { + int initialized; +}; + +/* + * A structure to keep a list of supported ciphertext formats. + */ +struct fmt_main { + struct fmt_params params; + struct fmt_methods methods; + struct fmt_private private; + struct fmt_main *next; +}; + +/* + * Linked list of registered formats. + */ +extern struct fmt_main *fmt_list; + +/* + * Format registration function. + */ +extern void fmt_register(struct fmt_main *format); + +/* + * Initializes the format's internal structures unless already initialized. + */ +extern void fmt_init(struct fmt_main *format); + +/* + * De-initializes this format if it was previously initialized. + */ +extern void fmt_done(struct fmt_main *format); + +/* + * Tests the format's methods for correct operation. Returns NULL on + * success, method name on error. + */ +extern char *fmt_self_test(struct fmt_main *format); + +/* + * Default methods. + */ +extern void fmt_default_init(struct fmt_main *self); +extern void fmt_default_done(void); +extern void fmt_default_reset(struct db_main *db); +extern char *fmt_default_prepare(char *fields[10], struct fmt_main *self); +extern char *fmt_default_split(char *ciphertext, int index, + struct fmt_main *self); +extern void *fmt_default_binary(char *ciphertext); +extern void *fmt_default_salt(char *ciphertext); +extern char *fmt_default_source(char *source, void *binary); +extern int fmt_default_binary_hash(void *binary); +extern int fmt_default_salt_hash(void *salt); +extern void fmt_default_set_salt(void *salt); +extern void fmt_default_clear_keys(void); +extern int fmt_default_get_hash(int index); + +/* + * Dummy hash function to use for salts with no hash table. + */ +#define fmt_dummy_hash fmt_default_get_hash + +#endif diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..6c960d9 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,148 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2003 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "misc.h" +#include "memory.h" +#include "list.h" +#include "getopt.h" + +static char *opt_errors[] = { + NULL, /* No error */ + "Unknown option", + "Option requires a parameter", + "Invalid option parameter", + "Extra parameter for option", + "Invalid options combination or duplicate option" +}; + +static char *opt_find(struct opt_entry *list, char *opt, + struct opt_entry **entry) +{ + char *name, *param; + size_t length; + struct opt_entry *found; + + if (opt[0] == '-') { + if (*(name = opt + 1) == '-') name++; + if (!(param = strchr(name, '='))) + param = strchr(name, ':'); + if (param) { + length = param - name; + if (!*++param) param = NULL; + } else + length = strlen(name); + + found = NULL; + do { + if (length <= strlen(list->name)) + if (!strncmp(name, list->name, length)) { + if (!found) + found = list; + else { + *entry = NULL; + return NULL; + } + } + } while ((++list)->name); + + if ((*entry = found)) + return param; + else + return NULL; + } else { + *entry = list; + return opt; + } +} + +static int opt_process_param(char *param, char *format, void *buffer) +{ + if (format[0] == OPT_FMT_STR_ALLOC[0]) { + *(char **)buffer = str_alloc_copy(param); + return 0; + } else + if (format[0] == OPT_FMT_ADD_LIST[0]) { + list_add(*(struct list_main **)buffer, param); + return 0; + } else + if (format[0] == OPT_FMT_ADD_LIST_MULTI[0]) { + list_add_multi(*(struct list_main **)buffer, param); + return 0; + } else + return sscanf(param, format, buffer) != 1; +} + +static int opt_process_one(struct opt_entry *list, opt_flags *flg, char *opt) +{ + char *param; + struct opt_entry *entry; + + param = opt_find(list, opt, &entry); + if (!entry) return OPT_ERROR_UNKNOWN; + + if (*flg & entry->flg_set & entry->flg_clr) return OPT_ERROR_COMB; + + *flg &= ~entry->flg_clr; + *flg |= entry->flg_set; + + if (entry->format) { + if (!param) { + if (entry->req_clr & OPT_REQ_PARAM) + return OPT_ERROR_PARAM_REQ; + } else + if (opt_process_param(param, entry->format, entry->param)) + return OPT_ERROR_PARAM_INV; + } else + if (param) return OPT_ERROR_PARAM_EXT; + + return OPT_ERROR_NONE; +} + +static int opt_check_one(struct opt_entry *list, opt_flags flg, char *opt) +{ + struct opt_entry *entry; + + opt_find(list, opt, &entry); + if (!entry) return OPT_ERROR_UNKNOWN; + + if ((flg & entry->req_set) != entry->req_set || (flg & entry->req_clr)) + return OPT_ERROR_COMB; + + return OPT_ERROR_NONE; +} + +void opt_process(struct opt_entry *list, opt_flags *flg, char **argv) +{ + char **opt; + int res; + + if (*(opt = argv)) + while (*++opt) + if ((res = opt_process_one(list, flg, *opt))) { + fprintf(stderr, "%s: \"%s\"\n", opt_errors[res], *opt); + error(); + } +} + +void opt_check(struct opt_entry *list, opt_flags flg, char **argv) +{ + char **opt; + int res; + + if (*(opt = argv)) + while (*++opt) + if ((res = opt_check_one(list, flg, *opt))) { + fprintf(stderr, "%s: \"%s\"\n", opt_errors[res], *opt); + error(); + } +} diff --git a/src/getopt.h b/src/getopt.h new file mode 100644 index 0000000..14dafac --- /dev/null +++ b/src/getopt.h @@ -0,0 +1,82 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Command line option processing. + */ + +#ifndef _JOHN_GETOPT_H +#define _JOHN_GETOPT_H + +/* + * Option flags bitmask type. + */ +typedef unsigned int opt_flags; + +/* + * Supported options list entry, the list ends with a NULL name field. + * First list entry should have an empty name, and is used for non-options. + */ +struct opt_entry { +/* Option name, as specified on the command line */ + char *name; + +/* Option flags to set and clear, respectively. If a bit is set in both + * flg_set and flg_clr, that flag is set, and required not to be set by + * the time the option appeared (used to detect duplicate options). */ + opt_flags flg_set, flg_clr; + +/* Required option flags to be set and clear, respectively. In req_clr, if + * OPT_REQ_PARAM is set, the option's parameter is required (by default + * the parameters are optional). */ + opt_flags req_set, req_clr; + +/* Parameter format for sscanf(), should contain one conversion specifier. + * Some additional formats are supported, see OPT_FMT_* defines below. */ + char *format; + +/* Pointer to buffer where the parameter is to be stored */ + void *param; +}; + +/* + * Special flag for req_clr. + */ +#define OPT_REQ_PARAM 0x80000000 + +/* + * Additional parameter formats. + */ +#define OPT_FMT_STR_ALLOC "S" /* str_alloc_copy() */ +#define OPT_FMT_ADD_LIST "L" /* add_list() */ +#define OPT_FMT_ADD_LIST_MULTI "M" /* add_list_multi() */ + +/* + * Error codes. + */ +#define OPT_ERROR_NONE 0 /* No error */ +#define OPT_ERROR_UNKNOWN 1 /* Unknown option */ +#define OPT_ERROR_PARAM_REQ 2 /* Parameter required */ +#define OPT_ERROR_PARAM_INV 3 /* Invalid parameter */ +#define OPT_ERROR_PARAM_EXT 4 /* Extra parameter */ +#define OPT_ERROR_COMB 5 /* Invalid combination */ + +/* + * Processes all the command line options. Updates the supplied flags and + * parameters specified in the options list. + */ +extern void opt_process(struct opt_entry *list, opt_flags *flg, char **argv); + +/* + * Checks option dependencies. + */ +extern void opt_check(struct opt_entry *list, opt_flags flg, char **argv); + +#endif diff --git a/src/ia64.h b/src/ia64.h new file mode 100644 index 0000000..0f9b40f --- /dev/null +++ b/src/ia64.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2006,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for IA-64. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 0 +#define DES_SCALE 1 +#define DES_EXTB 0 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 1 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 1 + +#endif diff --git a/src/idle.c b/src/idle.c new file mode 100644 index 0000000..fa4758b --- /dev/null +++ b/src/idle.c @@ -0,0 +1,144 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2006,2009,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _XOPEN_SOURCE /* for nice(2) */ +#include +#include + +#ifdef _POSIX_PRIORITY_SCHEDULING +#include +#include +#include + +static int use_yield = 0; +#endif + +#ifdef __CYGWIN32__ +extern int nice(int); +#endif + +#ifdef __BEOS__ +#include +#endif + +#ifdef _OPENMP +#include +#endif + +#include "params.h" +#include "config.h" +#include "options.h" +#include "signals.h" +#include "bench.h" +#include "formats.h" + +int idle_requested(struct fmt_main *format) +{ + if (!cfg_get_bool(SECTION_OPTIONS, NULL, "Idle", 1)) + return 0; + +#ifdef _OPENMP + if ((format->params.flags & FMT_OMP) && omp_get_max_threads() > 1) + return 0; +#endif + + return 1; +} + +void idle_init(struct fmt_main *format) +{ +#if defined(_POSIX_PRIORITY_SCHEDULING) && defined(SCHED_IDLE) + struct sched_param param = {0}; +#endif + + if (!idle_requested(format) || (options.flags & FLG_STDOUT)) + return; + + clk_tck_init(); + +#ifndef __BEOS__ +/* + * Normally, the range is -20 to 19, but some systems can do 20 as well (at + * least some versions of Linux on Alpha), so we try 20. We assume that we're + * started with a non-negative nice value (so no need to increment it by more + * than 20). + */ + if (nice(20) == -1) + perror("nice"); +#else + set_thread_priority(getpid(), 1); +#endif + +#if defined(_POSIX_PRIORITY_SCHEDULING) && defined(SCHED_IDLE) + use_yield = sched_setscheduler(getpid(), SCHED_IDLE, ¶m) != 0; +#elif defined(_POSIX_PRIORITY_SCHEDULING) + use_yield = 1; +#endif +} + +void idle_yield(void) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + static unsigned int calls_to_skip = 0; + static unsigned int calls_per_tick = 0; + static unsigned int calls_since_tick = 0; + static unsigned int calls_since_adj = 0; + static int calls_per_tick_known = 0; + static clock_t last_adj = 0; + clock_t last_check; + clock_t current; + int yield_calls; + struct tms buf; + + if (!use_yield) return; + + if (++calls_since_tick < calls_to_skip) return; + calls_since_adj += calls_since_tick; + calls_since_tick = 0; + + current = times(&buf); + if (!last_adj) last_adj = current; + + if (current - last_adj >= clk_tck) { + calls_per_tick = calls_since_adj / (current - last_adj); + calls_since_adj = 0; + calls_per_tick_known = 2; + last_adj = current; + } else if (calls_per_tick_known < 2) { + if (current > last_adj) { + calls_per_tick = calls_since_adj / (current - last_adj); + calls_per_tick_known = 1; + } else if (!calls_per_tick_known) + calls_per_tick++; + } + + yield_calls = 0; + do { + if (event_pending) break; + last_check = current; + sched_yield(); + yield_calls++; + current = times(&buf); + } while (current - last_check > 1 && current - last_adj < clk_tck); + + if (yield_calls != 1) + calls_to_skip = 0; + calls_to_skip += calls_per_tick; + + { + /* 1/16th of a second */ + unsigned int max_calls_to_skip = calls_per_tick * clk_tck >> 4; + if (max_calls_to_skip < calls_per_tick) + max_calls_to_skip = calls_per_tick; + if (calls_to_skip > max_calls_to_skip) + calls_to_skip = max_calls_to_skip; + } +#endif +} diff --git a/src/idle.h b/src/idle.h new file mode 100644 index 0000000..c5d49cd --- /dev/null +++ b/src/idle.h @@ -0,0 +1,37 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Idle priority support routines. + */ + +#ifndef _JOHN_IDLE_H +#define _JOHN_IDLE_H + +#include "formats.h" + +/* + * Returns non-zero if idle priority is requested in the configuration file and + * is actually to be enabled for the supplied "format". + */ +extern int idle_requested(struct fmt_main *format); + +/* + * Sets this process to idle priority if requested and supported. + */ +extern void idle_init(struct fmt_main *format); + +/* + * If the idle_init() call was unable to "fully" set the idle priority, yet it + * was requested, this will yield a timeslice if there's something else to do. + */ +extern void idle_yield(void); + +#endif diff --git a/src/inc.c b/src/inc.c new file mode 100644 index 0000000..e50f17e --- /dev/null +++ b/src/inc.c @@ -0,0 +1,705 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2006,2010-2013 by Solar Designer + */ + +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "signals.h" +#include "formats.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "config.h" +#include "charset.h" +#include "external.h" +#include "cracker.h" +#include "john.h" + +extern struct fmt_main fmt_LM; + +typedef char (*char2_table) + [CHARSET_SIZE + 1][CHARSET_SIZE + 1]; +typedef char (*chars_table) + [CHARSET_SIZE + 1][CHARSET_SIZE + 1][CHARSET_SIZE + 1]; + +static unsigned int rec_entry, rec_length; +static unsigned char rec_numbers[CHARSET_LENGTH]; + +static unsigned int entry, length; +static unsigned char numbers[CHARSET_LENGTH]; +static int counts[CHARSET_LENGTH][CHARSET_LENGTH]; + +static unsigned int real_count, real_minc, real_min, real_max, real_size; +static unsigned char real_chars[CHARSET_SIZE]; + +static void save_state(FILE *file) +{ + unsigned int pos; + + fprintf(file, "%u\n2\n%u\n", rec_entry, rec_length + 1); + for (pos = 0; pos <= rec_length; pos++) + fprintf(file, "%u\n", (unsigned int)rec_numbers[pos]); +} + +static int restore_state(FILE *file) +{ + unsigned int compat, pos; + + if (rec_version < 2) + return 1; + + if (fscanf(file, "%u\n%u\n%u\n", &rec_entry, &compat, &rec_length) != 3) + return 1; + rec_length--; /* zero-based */ + if (compat != 2 || rec_length >= CHARSET_LENGTH) + return 1; + for (pos = 0; pos <= rec_length; pos++) { + unsigned int number; + if (fscanf(file, "%u\n", &number) != 1) + return 1; + if (number >= CHARSET_SIZE) + return 1; + rec_numbers[pos] = number; + } + + return 0; +} + +static void fix_state(void) +{ + rec_entry = entry; + rec_length = length; + memcpy(rec_numbers, numbers, length); +} + +static void inc_format_error(char *charset) +{ + log_event("! Incorrect charset file format: %.100s", charset); + if (john_main_process) + fprintf(stderr, "Incorrect charset file format: %s\n", charset); + error(); +} + +static int is_mixedcase(char *chars) +{ + char present[0x100]; + char *ptr, c; + + memset(present, 0, sizeof(present)); + ptr = chars; + while ((c = *ptr++)) + present[ARCH_INDEX(c)] = 1; + + ptr = chars; + while ((c = *ptr++)) { + /* assume ASCII */ + if (c >= 'A' && c <= 'Z' && present[ARCH_INDEX(c) | 0x20]) + return 1; + } + + return 0; +} + +static void inc_new_length(unsigned int length, + struct charset_header *header, FILE *file, char *charset, + char *char1, char2_table char2, chars_table *chars) +{ + long offset; + int value, pos, i, j; + char *buffer; + int count; + + log_event("- Switching to length %d", length + 1); + + char1[0] = 0; + if (length) { + for (i = real_min; i <= real_max; i++) + (*char2)[i][0] = 0; + (*char2)[CHARSET_SIZE][0] = 0; + } + for (pos = 0; pos <= (int)length - 2; pos++) { + for (i = real_min; i <= real_max; i++) + for (j = real_min; j <= real_max; j++) + (*chars[pos])[i][j][0] = 0; + for (j = real_min; j <= real_max; j++) + (*chars[pos])[CHARSET_SIZE][j][0] = 0; + (*chars[pos])[CHARSET_SIZE][CHARSET_SIZE][0] = 0; + } + + offset = + (long)header->offsets[length][0] | + ((long)header->offsets[length][1] << 8) | + ((long)header->offsets[length][2] << 16) | + ((long)header->offsets[length][3] << 24); + if (fseek(file, offset, SEEK_SET)) + pexit("fseek"); + + i = j = pos = -1; + if ((value = getc(file)) != EOF) + do { + if (value != CHARSET_ESC) { + switch (pos) { + case -1: + inc_format_error(charset); + + case 0: + buffer = char1; + break; + + case 1: + if (j < 0) + inc_format_error(charset); + buffer = (*char2)[j]; + break; + + default: + if (i < 0 || j < 0) + inc_format_error(charset); + buffer = (*chars[pos - 2])[i][j]; + } + + buffer[count = 0] = value; + while ((value = getc(file)) != EOF) { + buffer[++count] = value; + if (value == CHARSET_ESC) + break; + if (count >= CHARSET_SIZE) + inc_format_error(charset); + } + buffer[count] = 0; + + continue; + } + + if ((value = getc(file)) == EOF) + break; + else + if (value == CHARSET_NEW) { + if ((value = getc(file)) != (int)length) + break; + if ((value = getc(file)) == EOF) + break; + if (value < 0 || value > (int)length) + inc_format_error(charset); + pos = value; + } else + if (value == CHARSET_LINE) { + if (pos < 0) + inc_format_error(charset); + if ((value = getc(file)) == EOF) + break; + i = value; + if (i < 0 || i > CHARSET_SIZE) + inc_format_error(charset); + if ((value = getc(file)) == EOF) + break; + j = value; + if (j < 0 || j > CHARSET_SIZE) + inc_format_error(charset); + } else + inc_format_error(charset); + + value = getc(file); + } while (value != EOF); + + if (value == EOF) { + if (ferror(file)) + pexit("getc"); + else + inc_format_error(charset); + } +} + +static int expand(char *dst, char *src, int size) +{ + char present[CHARSET_SIZE]; + char *dptr = dst, *sptr = src; + int count = size; + unsigned int i; + + memset(present, 0, real_size); + while (*dptr) { + if (--count <= 1) + return 0; + i = ARCH_INDEX(*dptr++) - real_minc; + if (i >= real_size) + return -1; + present[i] = 1; + } + + while (*sptr) { + i = ARCH_INDEX(*sptr) - real_minc; + if (i >= real_size) + return -1; + if (!present[i]) { + *dptr++ = *sptr++; + if (--count <= 1) + break; + } else + sptr++; + } + *dptr = 0; + + return 0; +} + +static void inc_new_count(unsigned int length, int count, char *charset, + char *allchars, char *char1, char2_table char2, chars_table *chars) +{ + int pos, ci; + int size; + int error; + + log_event("- Expanding tables for length %d to character count %d", + length + 1, count + 1); + + size = count + 2; + + error = expand(char1, allchars, size); + if (length) + error |= expand((*char2)[CHARSET_SIZE], allchars, size); + for (pos = 0; pos <= (int)length - 2; pos++) + error |= expand((*chars[pos])[CHARSET_SIZE][CHARSET_SIZE], + allchars, size); + + for (ci = 0; ci < real_count; ci++) { + int i = real_chars[ci]; + int cj; + + if (length) + error |= + expand((*char2)[i], (*char2)[CHARSET_SIZE], size); + + for (cj = 0; cj < real_count; cj++) { + int j = real_chars[cj]; + for (pos = 0; pos <= (int)length - 2; pos++) { + error |= expand((*chars[pos])[i][j], + (*chars[pos])[CHARSET_SIZE][j], size); + error |= expand((*chars[pos])[i][j], + (*chars[pos])[CHARSET_SIZE][CHARSET_SIZE], + size); + } + } + } + + if (error) + inc_format_error(charset); +} + +static int inc_key_loop(int length, int fixed, int count, + char *char1, char2_table char2, chars_table *chars) +{ + char key_i[PLAINTEXT_BUFFER_SIZE]; + char key_e[PLAINTEXT_BUFFER_SIZE]; + char *key; + char *chars_cache; + int *counts_length; + int counts_cache; + int numbers_cache; + int pos; + + key_i[length + 1] = 0; + numbers[fixed] = count; + + chars_cache = NULL; + + counts_length = counts[length]; + counts_cache = counts_length[length]; + + pos = 0; +update_ending: + if (pos < 2) { + if (pos == 0) + key_i[0] = char1[numbers[0]]; + if (length) + key_i[1] = (*char2)[ARCH_INDEX(key_i[0]) - CHARSET_MIN] + [numbers[1]]; + pos = 2; + } + while (pos < length) { + key_i[pos] = (*chars[pos - 2]) + [ARCH_INDEX(key_i[pos - 2]) - CHARSET_MIN] + [ARCH_INDEX(key_i[pos - 1]) - CHARSET_MIN] + [numbers[pos]]; + pos++; + } + numbers_cache = numbers[length]; + if (pos == length) { + chars_cache = (*chars[pos - 2]) + [ARCH_INDEX(key_i[pos - 2]) - CHARSET_MIN] + [ARCH_INDEX(key_i[pos - 1]) - CHARSET_MIN]; +update_last: + key_i[length] = chars_cache[numbers_cache]; + } + + key = key_i; + if (!f_filter || ext_filter_body(key_i, key = key_e)) + if (crk_process_key(key)) + return 1; + + pos = length; + if (fixed < length) { + if (++numbers_cache <= counts_cache) { + if (length >= 2) + goto update_last; + numbers[length] = numbers_cache; + goto update_ending; + } + numbers[pos--] = 0; + while (pos > fixed) { + if (++numbers[pos] <= counts_length[pos]) + goto update_ending; + numbers[pos--] = 0; + } + } + while (pos-- > 0) { + if (++numbers[pos] <= counts_length[pos]) + goto update_ending; + numbers[pos] = 0; + } + + return 0; +} + +void do_incremental_crack(struct db_main *db, char *mode) +{ + char *charset; + int min_length, max_length, max_count; + char *extra; + FILE *file; + struct charset_header *header; + unsigned int check; + char allchars[CHARSET_SIZE + 1]; + char char1[CHARSET_SIZE + 1]; + char2_table char2; + chars_table chars[CHARSET_LENGTH - 2]; + unsigned char *ptr; + unsigned int fixed, count; + int last_length, last_count; + int pos; + + if (!mode) { + if (db->format == &fmt_LM) + mode = "LM_ASCII"; + else + mode = "ASCII"; + } + + log_event("Proceeding with \"incremental\" mode: %.100s", mode); + + if (!(charset = cfg_get_param(SECTION_INC, mode, "File"))) { + log_event("! No charset defined"); + if (john_main_process) + fprintf(stderr, "No charset defined for mode: %s\n", + mode); + error(); + } + + extra = cfg_get_param(SECTION_INC, mode, "Extra"); + + if ((min_length = cfg_get_int(SECTION_INC, mode, "MinLen")) < 0) + min_length = 0; + if ((max_length = cfg_get_int(SECTION_INC, mode, "MaxLen")) < 0) + max_length = CHARSET_LENGTH; + max_count = cfg_get_int(SECTION_INC, mode, "CharCount"); + + if (min_length > max_length) { + log_event("! MinLen = %d exceeds MaxLen = %d", + min_length, max_length); + if (john_main_process) + fprintf(stderr, "MinLen = %d exceeds MaxLen = %d\n", + min_length, max_length); + error(); + } + + if (min_length > db->format->params.plaintext_length) { + log_event("! MinLen = %d is too large for this hash type", + min_length); + if (john_main_process) + fprintf(stderr, + "MinLen = %d exceeds the maximum possible " + "length for the current hash type (%d)\n", + min_length, db->format->params.plaintext_length); + error(); + } + + if (max_length > db->format->params.plaintext_length) { + log_event("! MaxLen = %d is too large for this hash type", + max_length); + if (john_main_process) + fprintf(stderr, "Warning: MaxLen = %d is too large " + "for the current hash type, reduced to %d\n", + max_length, db->format->params.plaintext_length); + max_length = db->format->params.plaintext_length; + } + + if (max_length > CHARSET_LENGTH) { + log_event("! MaxLen = %d exceeds the compile-time limit of %d", + max_length, CHARSET_LENGTH); + if (john_main_process) + fprintf(stderr, "MaxLen = %d exceeds the compile-time " + "limit of %d\n", max_length, CHARSET_LENGTH); + error(); + } + + if (!(file = fopen(path_expand(charset), "rb"))) + pexit("fopen: %s", path_expand(charset)); + + header = (struct charset_header *)mem_alloc(sizeof(*header)); + + if (charset_read_header(file, header) && !ferror(file)) + inc_format_error(charset); + if (ferror(file)) + pexit("fread"); + + if (feof(file) || + memcmp(header->version, CHARSET_V, sizeof(header->version)) || + !header->count) + inc_format_error(charset); + + if (header->min != CHARSET_MIN || header->max != CHARSET_MAX || + header->length != CHARSET_LENGTH) { + log_event("! Incompatible charset file: %.100s", charset); + if (john_main_process) + fprintf(stderr, "Incompatible charset file: %s\n", + charset); + error(); + } + +#if CHARSET_SIZE < 0xff + if (header->count > CHARSET_SIZE) + inc_format_error(charset); +#endif + + check = + (unsigned int)header->check[0] | + ((unsigned int)header->check[1] << 8) | + ((unsigned int)header->check[2] << 16) | + ((unsigned int)header->check[3] << 24); + if (!rec_restoring_now) + rec_check = check; + if (rec_check != check) { + log_event("! Charset file has changed: %.100s", charset); + if (john_main_process) + fprintf(stderr, "Charset file has changed: %s\n", + charset); + error(); + } + + if (fread(allchars, header->count, 1, file) != 1) { + if (ferror(file)) + pexit("fread"); + inc_format_error(charset); + } + +/* Sanity-check and expand allchars */ + real_minc = CHARSET_MIN; real_size = CHARSET_SIZE; + allchars[header->count] = 0; + if (expand(allchars, "", sizeof(allchars))) + inc_format_error(charset); + if (extra && expand(allchars, extra, sizeof(allchars))) { + log_event("! Extra characters not in compile-time " + "specified range ('\\x%02x' to '\\x%02x')", + CHARSET_MIN, CHARSET_MAX); + if (john_main_process) + fprintf(stderr, "Extra characters not in compile-time " + "specified range ('\\x%02x' to '\\x%02x')\n", + CHARSET_MIN, CHARSET_MAX); + error(); + } + +/* Calculate the actual real_* based on sanitized and expanded allchars */ + { + unsigned char c; + real_min = 0xff; + real_count = real_max = 0; + while ((c = allchars[real_count])) { + c -= CHARSET_MIN; + if (c < real_min) + real_min = c; + if (c > real_max) + real_max = c; + real_chars[real_count++] = c; + } + real_minc = CHARSET_MIN + real_min; + real_size = real_max - real_min + 1; + if (real_size < real_count) + inc_format_error(charset); + } + + if (max_count < 0) + max_count = CHARSET_SIZE; + + if (min_length != max_length) + log_event("- Lengths %d to %d, up to %d different characters", + min_length, max_length, max_count); + else + log_event("- Length %d, up to %d different characters", + min_length, max_count); + + if ((unsigned int)max_count > real_count) { + log_event("! Only %u characters available", real_count); + if (john_main_process) + fprintf(stderr, + "Warning: only %u characters available\n", + real_count); + } + + if (!(db->format->params.flags & FMT_CASE) && is_mixedcase(allchars)) { + log_event("! Mixed-case charset, " + "but the hash type is case-insensitive"); + if (john_main_process) + fprintf(stderr, "Warning: mixed-case charset, " + "but the current hash type is case-insensitive;\n" + "some candidate passwords may be unnecessarily " + "tried more than once.\n"); + } + + char2 = NULL; + for (pos = 0; pos < CHARSET_LENGTH - 2; pos++) + chars[pos] = NULL; + if (max_length >= 2) { + char2 = (char2_table)mem_alloc(sizeof(*char2)); + for (pos = 0; pos < max_length - 2; pos++) + chars[pos] = (chars_table)mem_alloc(sizeof(*chars[0])); + } + + rec_entry = 0; + memset(rec_numbers, 0, sizeof(rec_numbers)); + + status_init(NULL, 0); + + rec_restore_mode(restore_state); + rec_init(db, save_state); + + ptr = header->order; + entry = 0; + while (entry < rec_entry && + ptr < &header->order[sizeof(header->order) - 1]) { + entry++; + length = *ptr++; fixed = *ptr++; count = *ptr++; + + if (length >= CHARSET_LENGTH || + fixed > length || + count >= CHARSET_SIZE) + inc_format_error(charset); + + if (count >= real_count || (fixed && !count)) + continue; + + if ((int)length + 1 < min_length || + (int)length >= max_length || + (int)count >= max_count) + continue; + + if (count) + counts[length][fixed]++; + + if (counts[length][fixed] != count) { + log_event("! Unexpected count: %d != %d", + counts[length][fixed] + 1, count + 1); + fprintf(stderr, "Unexpected count: %d != %d\n", + counts[length][fixed] + 1, count + 1); + error(); + } + } + + memcpy(numbers, rec_numbers, sizeof(numbers)); + + crk_init(db, fix_state, NULL); + + last_count = last_length = -1; + + entry--; + while (ptr < &header->order[sizeof(header->order) - 1]) { + int skip = 0; + if (options.node_count) { + int for_node = entry % options.node_count + 1; + skip = for_node < options.node_min || + for_node > options.node_max; + } + + entry++; + length = *ptr++; fixed = *ptr++; count = *ptr++; + + if (length >= CHARSET_LENGTH || + fixed > length || + count >= CHARSET_SIZE) + inc_format_error(charset); + + if (entry != rec_entry) + memset(numbers, 0, sizeof(numbers)); + + if (count >= real_count || (fixed && !count)) + continue; + + if ((int)length + 1 < min_length || + (int)length >= max_length || + (int)count >= max_count) + continue; + + if (!skip) { + int i, max_count = 0; + if ((int)length != last_length) { + inc_new_length(last_length = length, + header, file, charset, char1, char2, chars); + last_count = -1; + } + for (i = 0; i <= length; i++) + if (counts[length][i] > max_count) + max_count = counts[length][i]; + if (count > max_count) + max_count = count; + if (max_count > last_count) { + last_count = max_count; + inc_new_count(length, max_count, charset, + allchars, char1, char2, chars); + } + } + + if (!length && !min_length) { + min_length = 1; + if (!skip && crk_process_key("")) + break; + } + + if (count) + counts[length][fixed]++; + + if (counts[length][fixed] != count) { + log_event("! Unexpected count: %d != %d", + counts[length][fixed] + 1, count + 1); + fprintf(stderr, "Unexpected count: %d != %d\n", + counts[length][fixed] + 1, count + 1); + error(); + } + + if (skip) + continue; + + log_event("- Trying length %d, fixed @%d, character count %d", + length + 1, fixed + 1, counts[length][fixed] + 1); + + if (inc_key_loop(length, fixed, count, char1, char2, chars)) + break; + } + + crk_done(); + rec_done(event_abort); + + for (pos = 0; pos < max_length - 2; pos++) + MEM_FREE(chars[pos]); + MEM_FREE(char2); + MEM_FREE(header); + + fclose(file); +} diff --git a/src/inc.h b/src/inc.h new file mode 100644 index 0000000..9b88013 --- /dev/null +++ b/src/inc.h @@ -0,0 +1,20 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + */ + +/* + * Incremental mode cracker. + */ + +#ifndef _JOHN_INC_H +#define _JOHN_INC_H + +#include "loader.h" + +/* + * Runs the incremental mode cracker. + */ +extern void do_incremental_crack(struct db_main *db, char *mode); + +#endif diff --git a/src/john.asm b/src/john.asm new file mode 100644 index 0000000..53f0628 --- /dev/null +++ b/src/john.asm @@ -0,0 +1,202 @@ +; +; This file is part of John the Ripper password cracker, +; Copyright (c) 1996-98 by Solar Designer +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted. +; +; There's ABSOLUTELY NO WARRANTY, express or implied. +; + +.model tiny +.code +.startup +.8086 + + mov sp,400h + + push sp + pop ax + cmp ax,sp + jne No386 + +.186 + push 0F200h + popf + pushf + pop ax + test ax,0F000h + jnz Is386 + +No386: + mov dx,offset MsgNo386 +ShowMsg: + push cs + pop ds + mov ah,9 + int 21h + int 20h + +Error: + mov dx,offset MsgError + jmp short ShowMsg + +Is386: +.386 + mov ah,4Ah + mov bx,es + mov bh,-43h + neg bx + int 21h + jc Error + + mov ah,48h + mov bx,112*1024/16 + int 21h + jc Error + mov es,ax +FillHoles: + mov ah,48h + int 21h + jnc FillHoles + shr bx,1 + jnz FillHoles + mov ah,49h + int 21h + jc Error + + mov es,word ptr ds:[2Ch] + push es + pop ds + xor di,di + xor ax,ax + mov cx,0FFFCh +Search1: + repne scasb + cmp word ptr [di],100h + loopne Search1 + jne Error + lea dx,[di+3] + mov al,'.' +Search2: + repne scasb + cmp dword ptr [di],'MOC' + loopne Search2 + jne Error + mov al,'\' + lea cx,[di+2] + sub cx,dx + lea bx,[di-2] + std + repne scasb + mov cx,bx + sub cx,di + cmp cx,5 + jb Error + lea bx,[di+2] + push cx + push cs + pop es + mov di,0FFh + mov si,di + sub si,cx + add cs:[80h],cl + sub cx,7Fh + neg cx + segcs + rep movsb + pop cx + mov si,bx + mov di,81h + cld +LinkName: + lodsb + or al,20h + stosb + loop LinkName + mov al,' ' + dec di + stosb + mov di,bx + mov dword ptr [di],'NHOJ' + mov dword ptr [di+4],'NIB.' + mov byte ptr [di+8],cl + + mov ax,3D00h + int 21h + jc Error2 + xchg ax,bx + + xor cx,cx + mov dx,14h + mov ax,4200h + int 21h + jc Error2 + + mov cl,2 + mov dx,EntryOfs + push cs + pop ds + mov ah,3Fh + int 21h + jc Error2 + xor cx,ax + jnz Error2 + + mov dx,200h + mov ax,4200h + int 21h + jc Error2 + + mov ax,cs + add ax,50h + mov al,0F0h + mov es,ax + mov cl,80h + xor si,si + xor di,di + segcs + rep movsw + + add ax,10h + mov ds,ax + xor dx,dx + mov ch,8 + mov ah,3Fh + int 21h + jc Error2 + cmp ax,cx + jne Error2 + + mov ah,3Eh + int 21h + jc Error2 + + xor di,di + mov al,0EBh + push es + push ds + pop es +Search3: + repne scasb + cmp dword ptr [di],21CD4AB4h + loopne Search3 + pop es + jne Error2 + + mov byte ptr ds:[di+2],0Ch + push ds +EntryOfs = offset $ + 1 + push 8000h + retf + +Error2: + jmp Error + +MsgNo386: + db 'At least a 386 CPU is required', 13, 10, '$' + +MsgError: + db 'Unable to load main program', 13, 10, '$' + + end diff --git a/src/john.c b/src/john.c new file mode 100644 index 0000000..c3b81bf --- /dev/null +++ b/src/john.c @@ -0,0 +1,707 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2004,2006,2009-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * Please note that although this main john.c file is under the cut-down BSD + * license above (so that you may reuse sufficiently generic pieces of code + * from this file under these relaxed terms), some other source files that it + * uses are under GPLv2. For licensing terms for John the Ripper as a whole, + * see doc/LICENSE. + */ + +#define NEED_OS_FORK +#include "os.h" + +#include +#include +#include +#include +#include +#include +#include +#if OS_FORK +#include +#endif + +#include "params.h" + +#ifdef _OPENMP +#include +static int john_omp_threads_orig = 0; +static int john_omp_threads_new; +#endif + +#include "arch.h" +#include "misc.h" +#include "path.h" +#include "memory.h" +#include "list.h" +#include "tty.h" +#include "signals.h" +#include "common.h" +#include "idle.h" +#include "formats.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "config.h" +#include "bench.h" +#include "charset.h" +#include "single.h" +#include "wordlist.h" +#include "inc.h" +#include "external.h" +#include "batch.h" + +#if CPU_DETECT +extern int CPU_detect(void); +#endif + +extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF; +extern struct fmt_main fmt_AFS, fmt_LM; +#ifdef HAVE_CRYPT +extern struct fmt_main fmt_crypt; +#endif +extern struct fmt_main fmt_trip; +extern struct fmt_main fmt_dummy; + +extern int unshadow(int argc, char **argv); +extern int unafs(int argc, char **argv); +extern int unique(int argc, char **argv); + +int john_main_process = 1; +#if OS_FORK +int john_child_count = 0; +int *john_child_pids = NULL; +#endif +static int children_ok = 1; + +static struct db_main database; +static struct fmt_main dummy_format; + +static int exit_status = 0; + +static void john_register_one(struct fmt_main *format) +{ + if (options.format && strcasecmp(options.format, format->params.label)) + return; + + fmt_register(format); +} + +static void john_register_all(void) +{ + john_register_one(&fmt_DES); + john_register_one(&fmt_BSDI); + john_register_one(&fmt_MD5); + john_register_one(&fmt_BF); + john_register_one(&fmt_LM); + john_register_one(&fmt_AFS); + john_register_one(&fmt_trip); + john_register_one(&fmt_dummy); +#ifdef HAVE_CRYPT + john_register_one(&fmt_crypt); +#endif + + if (!fmt_list) { + fprintf(stderr, "Unknown ciphertext format name requested\n"); + error(); + } +} + +static void john_log_format(void) +{ + int min_chunk, chunk; + + log_event("- Hash type: %.100s%s%.100s (lengths up to %d%s)", + database.format->params.label, + database.format->params.format_name[0] ? ", " : "", + database.format->params.format_name, + database.format->params.plaintext_length, + database.format->methods.split != fmt_default_split ? + ", longer passwords split" : ""); + + log_event("- Algorithm: %.100s", + database.format->params.algorithm_name); + + chunk = min_chunk = database.format->params.max_keys_per_crypt; + if (options.flags & (FLG_SINGLE_CHK | FLG_BATCH_CHK) && + chunk < SINGLE_HASH_MIN) + chunk = SINGLE_HASH_MIN; + if (chunk > 1) + log_event("- Candidate passwords %s be buffered and " + "tried in chunks of %d", + min_chunk > 1 ? "will" : "may", + chunk); +} + +#ifdef _OPENMP +static void john_omp_init(void) +{ + john_omp_threads_new = omp_get_max_threads(); + if (!john_omp_threads_orig) + john_omp_threads_orig = john_omp_threads_new; +} + +#if OMP_FALLBACK +#if defined(__DJGPP__) || defined(__CYGWIN32__) +#error OMP_FALLBACK is incompatible with the current DOS and Win32 code +#endif +#define HAVE_JOHN_OMP_FALLBACK +static void john_omp_fallback(char **argv) { + if (!getenv("JOHN_NO_OMP_FALLBACK") && john_omp_threads_new <= 1) { + rec_done(-2); +#define OMP_FALLBACK_PATHNAME JOHN_SYSTEMWIDE_EXEC "/" OMP_FALLBACK_BINARY + execv(OMP_FALLBACK_PATHNAME, argv); + perror("execv: " OMP_FALLBACK_PATHNAME); + } +} +#endif + +static void john_omp_maybe_adjust_or_fallback(char **argv) +{ + if (options.fork && !getenv("OMP_NUM_THREADS")) { + john_omp_threads_new /= options.fork; + if (john_omp_threads_new < 1) + john_omp_threads_new = 1; + omp_set_num_threads(john_omp_threads_new); + john_omp_init(); +#ifdef HAVE_JOHN_OMP_FALLBACK + john_omp_fallback(argv); +#endif + } +} + +static void john_omp_show_info(void) +{ + if (!options.fork && john_omp_threads_orig > 1 && + database.format && !rec_restoring_now) { + const char *msg = NULL; + if (!(database.format->params.flags & FMT_OMP)) + msg = "no OpenMP support"; + else if ((database.format->params.flags & FMT_OMP_BAD)) + msg = "poor OpenMP scalability"; + if (msg) +#if OS_FORK + fprintf(stderr, "Warning: %s for this hash type, " + "consider --fork=%d\n", + msg, john_omp_threads_orig); +#else + fprintf(stderr, "Warning: %s for this hash type\n", + msg); +#endif + } + +/* + * Only show OpenMP info if one of the following is true: + * - we have a format detected for the loaded hashes and it is OpenMP-enabled; + * - we're doing --test and no format is specified (so we will test all, + * including some that are presumably OpenMP-enabled); + * - we're doing --test and the specified format is OpenMP-enabled. + */ + { + int show = 0; + if (database.format && + (database.format->params.flags & FMT_OMP)) + show = 1; + else if ((options.flags & (FLG_TEST_CHK | FLG_FORMAT)) == + FLG_TEST_CHK) + show = 1; + else if ((options.flags & FLG_TEST_CHK) && + (fmt_list->params.flags & FMT_OMP)) + show = 1; + + if (!show) + return; + } + + if (options.fork) { +#if OS_FORK + if (john_omp_threads_new > 1) + fprintf(stderr, + "Will run %d OpenMP threads per process " + "(%u total across %u processes)\n", + john_omp_threads_new, + john_omp_threads_new * options.fork, options.fork); + else if (john_omp_threads_orig > 1) + fputs("Warning: OpenMP was disabled due to --fork; " + "a non-OpenMP build may be faster\n", stderr); +#endif + } else { + if (john_omp_threads_new > 1) + fprintf(stderr, + "Will run %d OpenMP threads\n", + john_omp_threads_new); + } + + if (john_omp_threads_orig == 1) + fputs("Warning: OpenMP is disabled; " + "a non-OpenMP build may be faster\n", stderr); +} +#endif + +#if OS_FORK +static void john_fork(void) +{ + int i, pid; + int *pids; + + fflush(stdout); + fflush(stderr); + +/* + * It may cost less memory to reset john_main_process to 0 before fork()'ing + * the children than to do it in every child process individually (triggering + * copy-on-write of the entire page). We then reset john_main_process back to + * 1 in the parent, but this only costs one page, not one page per child. + */ + john_main_process = 0; + + pids = mem_alloc_tiny((options.fork - 1) * sizeof(*pids), + sizeof(*pids)); + + for (i = 1; i < options.fork; i++) { + switch ((pid = fork())) { + case -1: + pexit("fork"); + + case 0: + options.node_min += i; + options.node_max = options.node_min; + if (rec_restoring_now) { + unsigned int node_id = options.node_min; + rec_done(-2); + rec_restore_args(1); + if (node_id != options.node_min + i) + fprintf(stderr, + "Inconsistent crash recovery file:" + " %s\n", rec_name); + options.node_min = options.node_max = node_id; + } + sig_init_child(); + return; + + default: + pids[i - 1] = pid; + } + } + + john_main_process = 1; + john_child_pids = pids; + john_child_count = options.fork - 1; + + options.node_max = options.node_min; +} + +static void john_wait(void) +{ + int waiting_for = john_child_count; + + log_event("Waiting for %d child%s to terminate", + waiting_for, waiting_for == 1 ? "" : "ren"); + fprintf(stderr, "Waiting for %d child%s to terminate\n", + waiting_for, waiting_for == 1 ? "" : "ren"); + +/* + * Although we may block on wait(2), we still have signal handlers and a timer + * in place, so we're relaying keypresses to child processes via signals. + */ + while (waiting_for) { + int i, status; + int pid = wait(&status); + if (pid == -1) { + if (errno != EINTR) + perror("wait"); + } else + for (i = 0; i < john_child_count; i++) { + if (john_child_pids[i] == pid) { + john_child_pids[i] = 0; + waiting_for--; + children_ok = children_ok && + WIFEXITED(status) && !WEXITSTATUS(status); + break; + } + } + } + +/* Close and possibly remove our .rec file now */ + rec_done((children_ok && !event_abort) ? -1 : -2); +} +#endif + +static char *john_loaded_counts(void) +{ + static char s_loaded_counts[80]; + + if (database.password_count == 1) + return "1 password hash"; + + sprintf(s_loaded_counts, + database.salt_count > 1 ? + "%d password hashes with %d different salts" : + "%d password hashes with no different salts", + database.password_count, + database.salt_count); + + return s_loaded_counts; +} + +static void john_load(void) +{ + struct list_entry *current; + + umask(077); + + if (options.flags & FLG_EXTERNAL_CHK) + ext_init(options.external); + + if (options.flags & FLG_MAKECHR_CHK) { + options.loader.flags |= DB_CRACKED; + ldr_init_database(&database, &options.loader); + + if (options.flags & FLG_PASSWD) { + ldr_show_pot_file(&database, POT_NAME); + + database.options->flags |= DB_PLAINTEXTS; + if ((current = options.passwd->head)) + do { + ldr_show_pw_file(&database, current->data); + } while ((current = current->next)); + } else { + database.options->flags |= DB_PLAINTEXTS; + ldr_show_pot_file(&database, POT_NAME); + } + + return; + } + + if (options.flags & FLG_STDOUT) { + ldr_init_database(&database, &options.loader); + database.format = &dummy_format; + memset(&dummy_format, 0, sizeof(dummy_format)); + dummy_format.params.plaintext_length = options.length; + dummy_format.params.flags = FMT_CASE | FMT_8_BIT; + } + + if (options.flags & FLG_PASSWD) { + int total; + + if (options.flags & FLG_SHOW_CHK) { + options.loader.flags |= DB_CRACKED; + ldr_init_database(&database, &options.loader); + + ldr_show_pot_file(&database, POT_NAME); + + if ((current = options.passwd->head)) + do { + ldr_show_pw_file(&database, current->data); + } while ((current = current->next)); + + printf("%s%d password hash%s cracked, %d left\n", + database.guess_count ? "\n" : "", + database.guess_count, + database.guess_count != 1 ? "es" : "", + database.password_count - + database.guess_count); + + return; + } + + if (options.flags & (FLG_SINGLE_CHK | FLG_BATCH_CHK) && + status.pass <= 1) + options.loader.flags |= DB_WORDS; + else + if (mem_saving_level) + options.loader.flags &= ~DB_LOGIN; + ldr_init_database(&database, &options.loader); + + if ((current = options.passwd->head)) + do { + ldr_load_pw_file(&database, current->data); + } while ((current = current->next)); + + if ((options.flags & FLG_CRACKING_CHK) && + database.password_count) { + log_init(LOG_NAME, NULL, options.session); + if (status_restored_time) + log_event("Continuing an interrupted session"); + else + log_event("Starting a new session"); + log_event("Loaded a total of %s", john_loaded_counts()); + printf("Loaded %s (%s%s%s [%s])\n", + john_loaded_counts(), + database.format->params.label, + database.format->params.format_name[0] ? ", " : "", + database.format->params.format_name, + database.format->params.algorithm_name); + } + + total = database.password_count; + ldr_load_pot_file(&database, POT_NAME); + ldr_fix_database(&database); + + if (!database.password_count) { + log_discard(); + printf("No password hashes %s (see FAQ)\n", + total ? "left to crack" : "loaded"); + } else + if (database.password_count < total) { + log_event("Remaining %s", john_loaded_counts()); + printf("Remaining %s\n", john_loaded_counts()); + } + + if ((options.flags & FLG_PWD_REQ) && !database.salts) exit(0); + } + +#ifdef _OPENMP + john_omp_show_info(); +#endif + + if (options.node_count) { + if (options.node_min != options.node_max) { + log_event("- Node numbers %u-%u of %u%s", + options.node_min, options.node_max, + options.node_count, options.fork ? " (fork)" : ""); + fprintf(stderr, "Node numbers %u-%u of %u%s\n", + options.node_min, options.node_max, + options.node_count, options.fork ? " (fork)" : ""); + } else { + log_event("- Node number %u of %u", + options.node_min, options.node_count); + fprintf(stderr, "Node number %u of %u\n", + options.node_min, options.node_count); + } + +#if OS_FORK + if (options.fork) + john_fork(); +#endif + } +} + +#if CPU_DETECT +static void CPU_detect_or_fallback(char **argv, int make_check) +{ + if (!CPU_detect()) { +#if CPU_REQ +#if CPU_FALLBACK +#if defined(__DJGPP__) || defined(__CYGWIN32__) +#error CPU_FALLBACK is incompatible with the current DOS and Win32 code +#endif + if (!make_check) { +#define CPU_FALLBACK_PATHNAME JOHN_SYSTEMWIDE_EXEC "/" CPU_FALLBACK_BINARY + execv(CPU_FALLBACK_PATHNAME, argv); + perror("execv: " CPU_FALLBACK_PATHNAME); + } +#endif + fprintf(stderr, "Sorry, %s is required for this build\n", + CPU_NAME); + if (make_check) + exit(0); + error(); +#endif + } +} +#else +#define CPU_detect_or_fallback(argv, make_check) +#endif + +static void john_init(char *name, int argc, char **argv) +{ + int make_check = (argc == 2 && !strcmp(argv[1], "--make_check")); + if (make_check) + argv[1] = "--test=0"; + + CPU_detect_or_fallback(argv, make_check); + +#ifdef _OPENMP + john_omp_init(); +#endif + + if (!make_check) { +#ifdef HAVE_JOHN_OMP_FALLBACK + john_omp_fallback(argv); +#endif + + path_init(argv); + +#if JOHN_SYSTEMWIDE + cfg_init(CFG_PRIVATE_FULL_NAME, 1); + cfg_init(CFG_PRIVATE_ALT_NAME, 1); +#endif + cfg_init(CFG_FULL_NAME, 1); + cfg_init(CFG_ALT_NAME, 0); + } + + status_init(NULL, 1); + if (argc < 2) + john_register_all(); /* for printing by opt_init() */ + opt_init(name, argc, argv); +#ifdef _OPENMP + john_omp_maybe_adjust_or_fallback(argv); +#endif + john_register_all(); /* maybe restricted to one format by options */ + common_init(); + sig_init(); + + john_load(); +} + +static void john_run(void) +{ + if (options.flags & FLG_TEST_CHK) + exit_status = benchmark_all() ? 1 : 0; + else + if (options.flags & FLG_MAKECHR_CHK) + do_makechars(&database, options.charset); + else + if (options.flags & FLG_CRACKING_CHK) { + int remaining = database.password_count; + + if (!(options.flags & FLG_STDOUT)) { + char *where = fmt_self_test(database.format); + if (where) { + fprintf(stderr, "Self test failed (%s)\n", + where); + error(); + } + database.format->methods.reset(&database); + log_init(LOG_NAME, POT_NAME, options.session); + status_init(NULL, 1); + john_log_format(); + if (idle_requested(database.format)) + log_event("- Configured to use otherwise idle " + "processor cycles only"); + } + tty_init(options.flags & FLG_STDIN_CHK); + + if (options.flags & FLG_SINGLE_CHK) + do_single_crack(&database); + else + if (options.flags & FLG_WORDLIST_CHK) + do_wordlist_crack(&database, options.wordlist, + (options.flags & FLG_RULES) != 0); + else + if (options.flags & FLG_INC_CHK) + do_incremental_crack(&database, options.charset); + else + if (options.flags & FLG_EXTERNAL_CHK) + do_external_crack(&database); + else + if (options.flags & FLG_BATCH_CHK) + do_batch_crack(&database); + + status_print(); + +#if OS_FORK + if (options.fork && john_main_process) + john_wait(); +#endif + + tty_done(); + + if (john_main_process && database.password_count < remaining) { + char *might = "Warning: passwords printed above might"; + char *partial = " be partial"; + char *not_all = " not be all those cracked"; + switch (database.options->flags & + (DB_SPLIT | DB_NODUP)) { + case DB_SPLIT: + fprintf(stderr, "%s%s\n", might, partial); + break; + case DB_NODUP: + fprintf(stderr, "%s%s\n", might, not_all); + break; + case (DB_SPLIT | DB_NODUP): + fprintf(stderr, "%s%s and%s\n", + might, partial, not_all); + } + fputs("Use the \"--show\" option to display all of " + "the cracked passwords reliably\n", stderr); + } + } +} + +static void john_done(void) +{ + if ((options.flags & (FLG_CRACKING_CHK | FLG_STDOUT)) == + FLG_CRACKING_CHK) { + if (event_abort) { + log_event("Session aborted"); + /* We have already printed to stderr from signals.c */ + } else if (children_ok) { + log_event("Session completed"); + if (john_main_process) + fprintf(stderr, "Session completed\n"); + } else { + const char *msg = + "Main process session completed, " + "but some child processes failed"; + log_event("%s", msg); + fprintf(stderr, "%s\n", msg); + exit_status = 1; + } + fmt_done(database.format); + } + log_done(); + + path_done(); + + check_abort(0); +} + +int main(int argc, char **argv) +{ + char *name; + +#ifdef __DJGPP__ + if (--argc <= 0) return 1; + if ((name = strrchr(argv[0], '/'))) + strcpy(name + 1, argv[1]); + name = argv[1]; + argv[1] = argv[0]; + argv++; +#else + if (!argv[0]) + name = "john"; + else + if ((name = strrchr(argv[0], '/'))) + name++; + else + name = argv[0]; +#endif + +#ifdef __CYGWIN32__ + strlwr(name); + if (strlen(name) > 4 && !strcmp(name + strlen(name) - 4, ".exe")) + name[strlen(name) - 4] = 0; +#endif + + if (!strcmp(name, "unshadow")) { + CPU_detect_or_fallback(argv, 0); + return unshadow(argc, argv); + } + + if (!strcmp(name, "unafs")) { + CPU_detect_or_fallback(argv, 0); + return unafs(argc, argv); + } + + if (!strcmp(name, "unique")) { + CPU_detect_or_fallback(argv, 0); + return unique(argc, argv); + } + + john_init(name, argc, argv); + john_run(); + john_done(); + + return exit_status; +} diff --git a/src/john.com b/src/john.com new file mode 100644 index 0000000..7b02054 Binary files /dev/null and b/src/john.com differ diff --git a/src/john.h b/src/john.h new file mode 100644 index 0000000..05cd7ae --- /dev/null +++ b/src/john.h @@ -0,0 +1,38 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2013 by Solar Designer + */ + +/* + * John's global variables exported from john.c to other source files. + */ + +#ifndef _JOHN_JOHN_H +#define _JOHN_JOHN_H + +/* + * Are we the main process? (The only process or the parent of a group of + * child processes.) + */ +extern int john_main_process; + +#ifndef NEED_OS_FORK +#define NEED_OS_FORK +#include "os.h" +#endif + +#if OS_FORK +/* + * Number of child processes, if any (or zero otherwise). + */ +extern int john_child_count; + +/* + * Child process PIDs array, element 0 corresponds to node 2, array size is + * john_child_count elements. (This is only used when options.fork is set, + * otherwise the pointer is NULL.) + */ +extern int *john_child_pids; +#endif + +#endif diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..e67bb85 --- /dev/null +++ b/src/list.c @@ -0,0 +1,82 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "memory.h" +#include "list.h" + +void list_init(struct list_main **list) +{ + *list = mem_alloc_tiny(sizeof(struct list_main), MEM_ALIGN_WORD); + (*list)->tail = (*list)->head = NULL; + (*list)->count = 0; +} + +void list_add(struct list_main *list, char *data) +{ + struct list_entry *entry; + + entry = mem_alloc_tiny(sizeof(struct list_entry) + strlen(data), + MEM_ALIGN_WORD); + strcpy(entry->data, data); + + list_add_link(list, entry); +} + +void list_add_link(struct list_main *list, struct list_entry *entry) +{ + entry->next = NULL; + + if (list->tail) + list->tail = list->tail->next = entry; + else + list->tail = list->head = entry; + + list->count++; +} + +void list_add_multi(struct list_main *list, char *data) +{ + char *comma; + + do { + if ((comma = strchr(data, ','))) *comma = 0; + + list_add(list, data); + + data = comma + 1; + if (comma) *comma = ','; + } while (comma); +} + +void list_add_unique(struct list_main *list, char *data) +{ + struct list_entry *current; + + if ((current = list->head)) + do { + if (!strcmp(current->data, data)) return; + } while ((current = current->next)); + + list_add(list, data); +} + +#if 0 +void list_del_next(struct list_main *list, struct list_entry *prev) +{ + if (prev) { + if (!(prev->next = prev->next->next)) list->tail = prev; + } else + if (!(list->head = list->head->next)) list->tail = NULL; + list->count--; +} +#endif diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..dc806ee --- /dev/null +++ b/src/list.h @@ -0,0 +1,70 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * String list management routines. + */ + +#ifndef _JOHN_LIST_H +#define _JOHN_LIST_H + +/* + * String list entry, allocated as (sizeof(struct list_entry) + strlen(data)). + */ +struct list_entry { + struct list_entry *next; + + char data[1]; +}; + +/* + * Main string list structure, head is used to start scanning the list, while + * tail is used to add new entries. + */ +struct list_main { + struct list_entry *head, *tail; + + int count; +}; + +/* + * Initializes an empty string list. + */ +extern void list_init(struct list_main **list); + +/* + * Adds an entry to the list. + */ +extern void list_add(struct list_main *list, char *data); + +/* + * Adds a previously allocated entry to the list. + */ +extern void list_add_link(struct list_main *list, struct list_entry *entry); + +/* + * Adds multiple entries to the list from a comma-separated string. + */ +extern void list_add_multi(struct list_main *list, char *data); + +/* + * Adds an entry to the list checking for dupes. This is slow, and should + * only be used on tiny lists. + */ +extern void list_add_unique(struct list_main *list, char *data); + +#if 0 +/* + * Deletes the entry following prev from the list. + */ +extern void list_del_next(struct list_main *list, struct list_entry *prev); +#endif + +#endif diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 0000000..ed93c6a --- /dev/null +++ b/src/loader.c @@ -0,0 +1,1048 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2003,2005,2010-2012 by Solar Designer + */ + +#include +#include +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "list.h" +#include "signals.h" +#include "formats.h" +#include "loader.h" + +#ifdef HAVE_CRYPT +extern struct fmt_main fmt_crypt; +int ldr_in_pot = 0; +#endif + +/* + * Flags for read_file(). + */ +#define RF_ALLOW_MISSING 1 +#define RF_ALLOW_DIR 2 + +/* + * Word separator characters for ldr_split_words(), used on GECOS fields. + */ +#define issep \ + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\177" + +static char issep_map[0x100]; +static int issep_initialized = 0; + +static char *no_username = "?"; + +static void read_file(struct db_main *db, char *name, int flags, + void (*process_line)(struct db_main *db, char *line)) +{ + struct stat file_stat; + FILE *file; + char line[LINE_BUFFER_SIZE]; + + if (flags & RF_ALLOW_DIR) { + if (stat(name, &file_stat)) { + if (flags & RF_ALLOW_MISSING) + if (errno == ENOENT) return; + pexit("stat: %s", path_expand(name)); + } else + if (S_ISDIR(file_stat.st_mode)) return; + } + + if (!(file = fopen(path_expand(name), "r"))) { + if ((flags & RF_ALLOW_MISSING) && errno == ENOENT) return; + pexit("fopen: %s", path_expand(name)); + } + + while (fgets(line, sizeof(line), file)) { + process_line(db, line); + check_abort(0); + } + + if (ferror(file)) pexit("fgets"); + + if (fclose(file)) pexit("fclose"); +} + +static void ldr_init_issep(void) +{ + char *pos; + + if (issep_initialized) return; + + memset(issep_map, 0, sizeof(issep_map)); + + memset(issep_map, 1, 33); + for (pos = issep; *pos; pos++) + issep_map[ARCH_INDEX(*pos)] = 1; + + issep_initialized = 1; +} + +void ldr_init_database(struct db_main *db, struct db_options *options) +{ + db->loaded = 0; + + db->options = mem_alloc_copy(options, + sizeof(struct db_options), MEM_ALIGN_WORD); + + db->salts = NULL; + + db->password_hash = NULL; + db->password_hash_func = NULL; + + if (options->flags & DB_CRACKED) { + db->salt_hash = NULL; + + db->cracked_hash = mem_alloc( + CRACKED_HASH_SIZE * sizeof(struct db_cracked *)); + memset(db->cracked_hash, 0, + CRACKED_HASH_SIZE * sizeof(struct db_cracked *)); + } else { + db->salt_hash = mem_alloc( + SALT_HASH_SIZE * sizeof(struct db_salt *)); + memset(db->salt_hash, 0, + SALT_HASH_SIZE * sizeof(struct db_salt *)); + + db->cracked_hash = NULL; + + if (options->flags & DB_WORDS) { + options->flags |= DB_LOGIN; + + ldr_init_issep(); + } + } + + list_init(&db->plaintexts); + + db->salt_count = db->password_count = db->guess_count = 0; + + db->format = NULL; +} + +/* + * Allocate a hash table for use by the loader itself. We use this for two + * purposes: to detect and avoid loading of duplicate hashes when DB_WORDS is + * not set, and to remove previously-cracked hashes (found in john.pot). We + * allocate, use, and free this hash table prior to deciding on the sizes of + * and allocating the per-salt hash tables to be used while cracking. + */ +static void ldr_init_password_hash(struct db_main *db) +{ + int (*func)(void *binary); + int size = PASSWORD_HASH_SIZE_FOR_LDR; + + if (size > 0 && mem_saving_level >= 2) + size--; + + do { + func = db->format->methods.binary_hash[size]; + if (func && func != fmt_default_binary_hash) + break; + } while (--size >= 0); + if (size < 0) + size = 0; + db->password_hash_func = func; + size = password_hash_sizes[size] * sizeof(struct db_password *); + db->password_hash = mem_alloc(size); + memset(db->password_hash, 0, size); +} + +static char *ldr_get_field(char **ptr) +{ + char *res, *pos; + + if (!*ptr) return ""; + + if ((pos = strchr(res = *ptr, ':'))) { + *pos++ = 0; *ptr = pos; + } else { + pos = res; + do { + if (*pos == '\r' || *pos == '\n') *pos = 0; + } while (*pos++); + *ptr = NULL; + } + + return res; +} + +static int ldr_check_list(struct list_main *list, char *s1, char *s2) +{ + struct list_entry *current; + char *data; + + if (!(current = list->head)) return 0; + + if (*current->data == '-') { + data = current->data + 1; + do { + if (!strcmp(s1, data) || !strcmp(s2, data)) return 1; + if ((current = current->next)) data = current->data; + } while (current); + } else { + do { + data = current->data; + if (!strcmp(s1, data) || !strcmp(s2, data)) return 0; + } while ((current = current->next)); + return 1; + } + + return 0; +} + +static int ldr_check_shells(struct list_main *list, char *shell) +{ + char *name; + + if (list->head) { + if ((name = strrchr(shell, '/'))) name++; else name = shell; + return ldr_check_list(list, shell, name); + } + + return 0; +} + +static int ldr_split_line(char **login, char **ciphertext, + char **gecos, char **home, + char *source, struct fmt_main **format, + struct db_options *options, char *line) +{ + struct fmt_main *alt; + char *fields[10], *uid, *gid, *shell; + int i, retval; + + fields[0] = *login = ldr_get_field(&line); + fields[1] = *ciphertext = ldr_get_field(&line); + +/* Check for NIS stuff */ + if ((!strcmp(*login, "+") || !strncmp(*login, "+@", 2)) && + strlen(*ciphertext) < 10 && strncmp(*ciphertext, "$dummy$", 7)) + return 0; + + if (!**ciphertext && !line) { +/* Possible hash on a line on its own (no colons) */ + char *p = *login; +/* Skip leading and trailing whitespace */ + while (*p == ' ' || *p == '\t') p++; + *ciphertext = p; + p += strlen(p) - 1; + while (p > *ciphertext && (*p == ' ' || *p == '\t')) p--; + p++; +/* Some valid dummy hashes may be shorter than 10 characters, so don't subject + * them to the length checks. */ + if (strncmp(*ciphertext, "$dummy$", 7) && + p - *ciphertext != 10 /* not tripcode */) { +/* Check for a special case: possibly a traditional crypt(3) hash with + * whitespace in its invalid salt. Only support such hashes at the very start + * of a line (no leading whitespace other than the invalid salt). */ + if (p - *ciphertext == 11 && *ciphertext - *login == 2) + (*ciphertext)--; + if (p - *ciphertext == 12 && *ciphertext - *login == 1) + (*ciphertext)--; + if (p - *ciphertext < 13) + return 0; + } + *p = 0; + fields[0] = *login = no_username; + fields[1] = *ciphertext; + } + + if (source) + strcpy(source, line ? line : ""); + +/* + * This check is just a loader performance optimization, so that we can parse + * fewer fields when we know we won't need the rest. It should be revised or + * removed when there are formats that use higher-numbered fields in prepare(). + */ + if ((options->flags & DB_WORDS) || options->shells->head) { + /* Parse all fields */ + for (i = 2; i < 10; i++) + fields[i] = ldr_get_field(&line); + } else { + /* Parse some fields only */ + for (i = 2; i < 4; i++) + fields[i] = ldr_get_field(&line); + for (; i < 10; i++) + fields[i] = "/"; + } + + /* /etc/passwd */ + uid = fields[2]; + gid = fields[3]; + *gecos = fields[4]; + *home = fields[5]; + shell = fields[6]; + + if (fields[5][0] != '/' && + ((!strcmp(fields[5], "0") && !strcmp(fields[6], "0")) || + fields[8][0] == '/' || + fields[9][0] == '/')) { + /* /etc/master.passwd */ + *gecos = fields[7]; + *home = fields[8]; + shell = fields[9]; + } else if (fields[3] - fields[2] == 32 + 1) { + /* PWDUMP */ + uid = fields[1]; + *ciphertext = fields[2]; + if (!strncmp(*ciphertext, "NO PASSWORD", 11)) + *ciphertext = ""; + gid = shell = ""; + *gecos = fields[4]; + *home = fields[5]; + + /* Re-introduce the previously removed uid field */ + if (source) { + int shift = strlen(uid); + memmove(source + shift + 1, source, strlen(source) + 1); + memcpy(source, uid, shift); + source[shift] = ':'; + } + } + + if (ldr_check_list(options->users, *login, uid)) return 0; + if (ldr_check_list(options->groups, gid, gid)) return 0; + if (ldr_check_shells(options->shells, shell)) return 0; + + if (*format) { + char *prepared; + int valid; + + prepared = (*format)->methods.prepare(fields, *format); + if (prepared) + valid = (*format)->methods.valid(prepared, *format); + else + valid = 0; + + if (valid) { + *ciphertext = prepared; + return valid; + } + + alt = fmt_list; + do { + if (alt == *format) + continue; + if (alt->params.flags & FMT_WARNED) + continue; +#ifdef HAVE_CRYPT + if (alt == &fmt_crypt && +#ifdef __sun + strncmp(*ciphertext, "$md5$", 5) && + strncmp(*ciphertext, "$md5,", 5) && +#endif + strncmp(*ciphertext, "$5$", 3) && + strncmp(*ciphertext, "$6$", 3)) + continue; +#endif + prepared = alt->methods.prepare(fields, alt); + if (alt->methods.valid(prepared, alt)) { + alt->params.flags |= FMT_WARNED; + fprintf(stderr, + "Warning: only loading hashes of type " + "\"%s\", but also saw type \"%s\"\n" + "Use the \"--format=%s\" option to force " + "loading hashes of that type instead\n", + (*format)->params.label, + alt->params.label, + alt->params.label); + break; + } + } while ((alt = alt->next)); + + return 0; + } + + retval = -1; + if ((alt = fmt_list)) + do { + char *prepared; + int valid; + +#ifdef HAVE_CRYPT +/* + * Only probe for support by the current system's crypt(3) if this is forced + * from the command-line or/and if the hash encoding string looks like one of + * those that are only supported in that way. Avoid the probe in other cases + * because it may be slow and undesirable (false detection is possible). + */ + if (alt == &fmt_crypt && + fmt_list != &fmt_crypt /* not forced */ && +#ifdef __sun + strncmp(*ciphertext, "$md5$", 5) && + strncmp(*ciphertext, "$md5,", 5) && +#endif + strncmp(*ciphertext, "$5$", 3) && + strncmp(*ciphertext, "$6$", 3)) + continue; +#endif + + prepared = alt->methods.prepare(fields, alt); + if (!prepared) + continue; + valid = alt->methods.valid(prepared, alt); + if (!valid) + continue; + + if (retval < 0) { + retval = valid; + *ciphertext = prepared; + fmt_init(*format = alt); +#ifdef LDR_WARN_AMBIGUOUS + if (!source) /* not --show */ + continue; +#endif + break; + } +#ifdef LDR_WARN_AMBIGUOUS + fprintf(stderr, + "Warning: detected hash type \"%s\", but the string is " + "also recognized as \"%s\"\n" + "Use the \"--format=%s\" option to force loading these " + "as that type instead\n", + (*format)->params.label, alt->params.label, + alt->params.label); +#endif + } while ((alt = alt->next)); + + return retval; +} + +static void ldr_split_string(struct list_main *dst, char *src) +{ + char *word, *pos; + char c; + + pos = src; + do { + word = pos; + while (*word && issep_map[ARCH_INDEX(*word)]) word++; + if (!*word) break; + + pos = word; + while (!issep_map[ARCH_INDEX(*pos)]) pos++; + c = *pos; + *pos = 0; + list_add_unique(dst, word); + *pos++ = c; + } while (c && dst->count < LDR_WORDS_MAX); +} + +static struct list_main *ldr_init_words(char *login, char *gecos, char *home) +{ + struct list_main *words; + char *pos; + + list_init(&words); + + if (*login && login != no_username) + list_add(words, login); + ldr_split_string(words, gecos); + if (login != no_username) + ldr_split_string(words, login); + + if ((pos = strrchr(home, '/')) && pos[1]) + list_add_unique(words, pos + 1); + + return words; +} + +static void ldr_load_pw_line(struct db_main *db, char *line) +{ + static int skip_dupe_checking = 0; + struct fmt_main *format; + int index, count; + char *login, *ciphertext, *gecos, *home; + char *piece; + void *binary, *salt; + int salt_hash, pw_hash; + struct db_salt *current_salt, *last_salt; + struct db_password *current_pw, *last_pw; + struct list_main *words; + size_t pw_size, salt_size; + + count = ldr_split_line(&login, &ciphertext, &gecos, &home, + NULL, &db->format, db->options, line); + if (count <= 0) return; + if (count >= 2) db->options->flags |= DB_SPLIT; + + format = db->format; + + words = NULL; + + if (db->options->flags & DB_WORDS) { + pw_size = sizeof(struct db_password); + salt_size = sizeof(struct db_salt); + } else { + if (db->options->flags & DB_LOGIN) + pw_size = sizeof(struct db_password) - + sizeof(struct list_main *); + else + pw_size = sizeof(struct db_password) - + (sizeof(char *) + sizeof(struct list_main *)); + salt_size = sizeof(struct db_salt) - + sizeof(struct db_keys *); + } + + if (!db->password_hash) + ldr_init_password_hash(db); + + for (index = 0; index < count; index++) { + piece = format->methods.split(ciphertext, index, format); + + binary = format->methods.binary(piece); + pw_hash = db->password_hash_func(binary); + + if (!(db->options->flags & DB_WORDS) && !skip_dupe_checking) { + int collisions = 0; + if ((current_pw = db->password_hash[pw_hash])) + do { + if (!memcmp(binary, current_pw->binary, + format->params.binary_size) && + !strcmp(piece, format->methods.source( + current_pw->source, current_pw->binary))) { + db->options->flags |= DB_NODUP; + break; + } + if (++collisions <= LDR_HASH_COLLISIONS_MAX) + continue; + if (format->params.binary_size) + fprintf(stderr, "Warning: " + "excessive partial hash " + "collisions detected\n%s", + db->password_hash_func != + fmt_default_binary_hash ? "" : + "(cause: the \"format\" lacks " + "proper binary_hash() function " + "definitions)\n"); + else + fprintf(stderr, "Warning: " + "check for duplicates partially " + "bypassed to speedup loading\n"); + skip_dupe_checking = 1; + current_pw = NULL; /* no match */ + break; + } while ((current_pw = current_pw->next_hash)); + + if (current_pw) continue; + } + + salt = format->methods.salt(piece); + salt_hash = format->methods.salt_hash(salt); + + if ((current_salt = db->salt_hash[salt_hash])) + do { + if (!memcmp(current_salt->salt, salt, + format->params.salt_size)) + break; + } while ((current_salt = current_salt->next)); + + if (!current_salt) { + last_salt = db->salt_hash[salt_hash]; + current_salt = db->salt_hash[salt_hash] = + mem_alloc_tiny(salt_size, MEM_ALIGN_WORD); + current_salt->next = last_salt; + + current_salt->salt = mem_alloc_copy(salt, + format->params.salt_size, + format->params.salt_align); + + current_salt->index = fmt_dummy_hash; + current_salt->bitmap = NULL; + current_salt->list = NULL; + current_salt->hash = ¤t_salt->list; + current_salt->hash_size = -1; + + current_salt->count = 0; + + if (db->options->flags & DB_WORDS) + current_salt->keys = NULL; + + db->salt_count++; + } + + current_salt->count++; + db->password_count++; + + last_pw = current_salt->list; + current_pw = current_salt->list = mem_alloc_tiny( + pw_size, MEM_ALIGN_WORD); + current_pw->next = last_pw; + + last_pw = db->password_hash[pw_hash]; + db->password_hash[pw_hash] = current_pw; + current_pw->next_hash = last_pw; + +/* If we're not going to use the source field for its usual purpose, see if we + * can pack the binary value in it. */ + if (format->methods.source != fmt_default_source && + sizeof(current_pw->source) >= format->params.binary_size) + current_pw->binary = memcpy(¤t_pw->source, + binary, format->params.binary_size); + else + current_pw->binary = mem_alloc_copy(binary, + format->params.binary_size, + format->params.binary_align); + + if (format->methods.source == fmt_default_source) + current_pw->source = str_alloc_copy(piece); + + if (db->options->flags & DB_WORDS) { + if (!words) + words = ldr_init_words(login, gecos, home); + current_pw->words = words; + } + + if (db->options->flags & DB_LOGIN) { + if (count >= 2 && count <= 9) { + current_pw->login = mem_alloc_tiny( + strlen(login) + 3, MEM_ALIGN_NONE); + sprintf(current_pw->login, "%s:%d", + login, index + 1); + } else + if (login == no_username) + current_pw->login = login; + else + if (words && *login) + current_pw->login = words->head->data; + else + current_pw->login = str_alloc_copy(login); + } + } +} + +void ldr_load_pw_file(struct db_main *db, char *name) +{ + read_file(db, name, RF_ALLOW_DIR, ldr_load_pw_line); +} + +static void ldr_load_pot_line(struct db_main *db, char *line) +{ + struct fmt_main *format = db->format; + char *ciphertext; + void *binary; + int hash; + struct db_password *current; + + ciphertext = ldr_get_field(&line); + if (format->methods.valid(ciphertext, format) != 1) return; + + ciphertext = format->methods.split(ciphertext, 0, format); + binary = format->methods.binary(ciphertext); + hash = db->password_hash_func(binary); + + if ((current = db->password_hash[hash])) + do { + if (!current->binary) /* already marked for removal */ + continue; + if (memcmp(binary, current->binary, format->params.binary_size)) + continue; + if (strcmp(ciphertext, + format->methods.source(current->source, current->binary))) + continue; + current->binary = NULL; /* mark for removal */ + } while ((current = current->next_hash)); +} + +void ldr_load_pot_file(struct db_main *db, char *name) +{ + if (db->format) { +#ifdef HAVE_CRYPT + ldr_in_pot = 1; +#endif + read_file(db, name, RF_ALLOW_MISSING, ldr_load_pot_line); +#ifdef HAVE_CRYPT + ldr_in_pot = 0; +#endif + } +} + +/* + * The following are several functions called by ldr_fix_database(). + * They assume that the per-salt hash tables have not yet been initialized. + */ + +/* + * Glue the salt_hash[] buckets together and into the salts list. The loader + * needs the hash table, but then we free it and the cracker uses the list. + */ +static void ldr_init_salts(struct db_main *db) +{ + struct db_salt **tail, *current; + int hash; + + for (hash = 0, tail = &db->salts; hash < SALT_HASH_SIZE; hash++) + if ((current = db->salt_hash[hash])) { + *tail = current; + do { + tail = ¤t->next; + } while ((current = current->next)); + } +} + +/* + * Remove the previously-cracked hashes marked with "binary = NULL" by + * ldr_load_pot_line(). + */ +static void ldr_remove_marked(struct db_main *db) +{ + struct db_salt *current_salt, *last_salt; + struct db_password *current_pw, *last_pw; + + last_salt = NULL; + if ((current_salt = db->salts)) + do { + last_pw = NULL; + if ((current_pw = current_salt->list)) + do { + if (!current_pw->binary) { + db->password_count--; + current_salt->count--; + + if (last_pw) + last_pw->next = current_pw->next; + else + current_salt->list = current_pw->next; + } else + last_pw = current_pw; + } while ((current_pw = current_pw->next)); + + if (!current_salt->list) { + db->salt_count--; + + if (last_salt) + last_salt->next = current_salt->next; + else + db->salts = current_salt->next; + } else + last_salt = current_salt; + } while ((current_salt = current_salt->next)); +} + +/* + * Remove salts with too few or too many password hashes. + */ +static void ldr_filter_salts(struct db_main *db) +{ + struct db_salt *current, *last; + int min = db->options->min_pps; + int max = db->options->max_pps; + + if (!max) { + if (!min) return; + max = ~(unsigned int)0 >> 1; + } + + last = NULL; + if ((current = db->salts)) + do { + if (current->count < min || current->count > max) { + if (last) + last->next = current->next; + else + db->salts = current->next; + + db->salt_count--; + db->password_count -= current->count; + } else + last = current; + } while ((current = current->next)); +} + +/* + * Allocate memory for and initialize the hash table for this salt if needed. + * Also initialize salt->count (the number of password hashes for this salt). + */ +static void ldr_init_hash_for_salt(struct db_main *db, struct db_salt *salt) +{ + struct db_password *current; + int (*hash_func)(void *binary); + int bitmap_size, hash_size; + int hash; + + if (salt->hash_size < 0) { + salt->count = 0; + if ((current = salt->list)) + do { + current->next_hash = NULL; /* unused */ + salt->count++; + } while ((current = current->next)); + + return; + } + + bitmap_size = password_hash_sizes[salt->hash_size]; + { + size_t size = (bitmap_size + + sizeof(*salt->bitmap) * 8 - 1) / + (sizeof(*salt->bitmap) * 8) * sizeof(*salt->bitmap); + salt->bitmap = mem_alloc_tiny(size, sizeof(*salt->bitmap)); + memset(salt->bitmap, 0, size); + } + + hash_size = bitmap_size >> PASSWORD_HASH_SHR; + if (hash_size > 1) { + size_t size = hash_size * sizeof(struct db_password *); + salt->hash = mem_alloc_tiny(size, MEM_ALIGN_WORD); + memset(salt->hash, 0, size); + } + + salt->index = db->format->methods.get_hash[salt->hash_size]; + + hash_func = db->format->methods.binary_hash[salt->hash_size]; + + salt->count = 0; + if ((current = salt->list)) + do { + hash = hash_func(current->binary); + salt->bitmap[hash / (sizeof(*salt->bitmap) * 8)] |= + 1U << (hash % (sizeof(*salt->bitmap) * 8)); + if (hash_size > 1) { + hash >>= PASSWORD_HASH_SHR; + current->next_hash = salt->hash[hash]; + salt->hash[hash] = current; + } else + current->next_hash = current->next; + salt->count++; + } while ((current = current->next)); +} + +/* + * Decide on whether to use a hash table and on its size for each salt, call + * ldr_init_hash_for_salt() to allocate and initialize the hash tables. + */ +static void ldr_init_hash(struct db_main *db) +{ + struct db_salt *current; + int threshold, size; + + threshold = password_hash_thresholds[0]; + if (db->format && (db->format->params.flags & FMT_BS)) { +/* + * Estimate the complexity of DES_bs_get_hash() for each computed hash (but + * comparing it against less than 1 loaded hash on average due to the use of a + * hash table) vs. the complexity of DES_bs_cmp_all() for all computed hashes + * at once (but calling it for each loaded hash individually). + */ + threshold = 5 * ARCH_BITS / ARCH_BITS_LOG + 1; + } + + if ((current = db->salts)) + do { + size = -1; + if (current->count >= threshold && mem_saving_level < 3) + for (size = PASSWORD_HASH_SIZES - 1; size >= 0; size--) + if (current->count >= + password_hash_thresholds[size] && + db->format->methods.binary_hash[size] && + db->format->methods.binary_hash[size] != + fmt_default_binary_hash) + break; + + if (mem_saving_level >= 2) + size--; + + current->hash_size = size; + ldr_init_hash_for_salt(db, current); + } while ((current = current->next)); +} + +void ldr_fix_database(struct db_main *db) +{ + ldr_init_salts(db); + MEM_FREE(db->password_hash); + MEM_FREE(db->salt_hash); + + ldr_filter_salts(db); + ldr_remove_marked(db); + + ldr_init_hash(db); + + db->loaded = 1; +} + +static int ldr_cracked_hash(char *ciphertext) +{ + unsigned int hash = 0; + char *p = ciphertext; + + while (*p) { + hash <<= 1; + hash += (unsigned char)*p++ | 0x20; /* ASCII case insensitive */ + if (hash >> (2 * CRACKED_HASH_LOG - 1)) { + hash ^= hash >> CRACKED_HASH_LOG; + hash &= CRACKED_HASH_SIZE - 1; + } + } + + hash ^= hash >> CRACKED_HASH_LOG; + hash &= CRACKED_HASH_SIZE - 1; + + return hash; +} + +static void ldr_show_pot_line(struct db_main *db, char *line) +{ + char *ciphertext, *pos; + int hash; + struct db_cracked *current, *last; + + ciphertext = ldr_get_field(&line); + + if (line) { +/* If just one format was forced on the command line, insist on it */ + if (!fmt_list->next && + !fmt_list->methods.valid(ciphertext, fmt_list)) + return; + + pos = line; + do { + if (*pos == '\r' || *pos == '\n') *pos = 0; + } while (*pos++); + + if (db->options->flags & DB_PLAINTEXTS) { + list_add(db->plaintexts, line); + return; + } + + hash = ldr_cracked_hash(ciphertext); + + last = db->cracked_hash[hash]; + current = db->cracked_hash[hash] = + mem_alloc_tiny(sizeof(struct db_cracked), + MEM_ALIGN_WORD); + current->next = last; + + current->ciphertext = str_alloc_copy(ciphertext); + current->plaintext = str_alloc_copy(line); + } +} + +void ldr_show_pot_file(struct db_main *db, char *name) +{ +#ifdef HAVE_CRYPT + ldr_in_pot = 1; +#endif + read_file(db, name, RF_ALLOW_MISSING, ldr_show_pot_line); +#ifdef HAVE_CRYPT + ldr_in_pot = 0; +#endif +} + +static void ldr_show_pw_line(struct db_main *db, char *line) +{ + int show; + char source[LINE_BUFFER_SIZE]; + struct fmt_main *format; + char *(*split)(char *ciphertext, int index, struct fmt_main *self); + int index, count, unify; + char *login, *ciphertext, *gecos, *home; + char *piece; + int pass, found, chars; + int hash; + struct db_cracked *current; + + format = NULL; + count = ldr_split_line(&login, &ciphertext, &gecos, &home, + source, &format, db->options, line); + if (!count) return; + +/* If just one format was forced on the command line, insist on it */ + if (!fmt_list->next && !format) return; + + show = !(db->options->flags & DB_PLAINTEXTS); + + if (format) { + split = format->methods.split; + unify = format->params.flags & FMT_SPLIT_UNIFIES_CASE; + } else { + split = fmt_default_split; + count = 1; + unify = 0; + } + + if (!*ciphertext) { + found = 1; + if (show) printf("%s:NO PASSWORD", login); + + db->guess_count++; + } else + for (found = pass = 0; pass == 0 || (pass == 1 && found); pass++) + for (index = 0; index < count; index++) { + piece = split(ciphertext, index, format); + if (unify) + piece = strcpy(mem_alloc(strlen(piece) + 1), piece); + + hash = ldr_cracked_hash(piece); + + if ((current = db->cracked_hash[hash])) + do { + char *pot = current->ciphertext; + if (!strcmp(pot, piece)) + break; +/* This extra check, along with ldr_cracked_hash() being case-insensitive, + * is only needed for matching some pot file records produced by older + * versions of John and contributed patches where split() didn't unify the + * case of hex-encoded hashes. */ + if (unify && + format->methods.valid(pot, format) == 1 && + !strcmp(split(pot, 0, format), piece)) + break; + } while ((current = current->next)); + + if (unify) + MEM_FREE(piece); + + if (pass) { + chars = 0; + if (show) { + if (format) + chars = format->params.plaintext_length; + if (index < count - 1 && current && + (int)strlen(current->plaintext) != chars) + current = NULL; + } + + if (current) { + if (show) { + printf("%s", current->plaintext); + } else + list_add(db->plaintexts, + current->plaintext); + + db->guess_count++; + } else + while (chars--) + putchar('?'); + } else + if (current) { + found = 1; + if (show) printf("%s:", login); + break; + } + } + + if (found && show) { + if (source[0]) + printf(":%s", source); + else + putchar('\n'); + } + + if (format || found) db->password_count += count; +} + +void ldr_show_pw_file(struct db_main *db, char *name) +{ + read_file(db, name, RF_ALLOW_DIR, ldr_show_pw_line); +} diff --git a/src/loader.h b/src/loader.h new file mode 100644 index 0000000..7230c9f --- /dev/null +++ b/src/loader.h @@ -0,0 +1,244 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2010-2013 by Solar Designer + */ + +/* + * Password database management. + */ + +#ifndef _JOHN_LOADER_H +#define _JOHN_LOADER_H + +#include "params.h" +#include "list.h" +#include "formats.h" + +/* + * Password hash list entry (with a fixed salt). + */ +struct db_password { +/* Pointer to next password hash with the same salt */ + struct db_password *next; + +/* After loading is completed: pointer to next password hash with the same salt + * and hash-of-hash. + * While loading: pointer to next password hash with the same hash-of-hash. */ + struct db_password *next_hash; + +/* Hot portion of or full binary ciphertext for fast comparison (aligned) */ + void *binary; + +/* ASCII ciphertext for exact comparison and saving with cracked passwords. + * Alternatively, when the source() method is non-default this field is either + * unused or this pointer may be reused to hold the binary value above. */ + char *source; + +/* Login field from the password file, with ":1" or ":2" appended if the + * ciphertext was split into two parts. */ + char *login; + +/* Words from the GECOS field (loaded for "single crack" mode only) */ + struct list_main *words; +}; + +/* + * Buffered keys hash table entry. + */ +struct db_keys_hash_entry { +/* Index of next key with the same hash, or -1 if none */ + short next; + +/* Byte offset of this key in the buffer */ + unsigned short offset; +}; + +/* + * Buffered keys hash. + */ +struct db_keys_hash { +/* The hash table, maps to indices for the list below; -1 means empty bucket */ + short hash[SINGLE_HASH_SIZE]; + +/* List of keys with the same hash, allocated as min_keys_per_crypt entries */ + struct db_keys_hash_entry list[1]; +}; + +/* + * Buffered keys. + */ +struct db_keys { +/* Keys hash table, for fast dupe checking */ + struct db_keys_hash *hash; + +/* &buffer[count * plaintext_length] */ + char *ptr; + +/* Number of keys currently in the buffer */ + int count; + +/* Number of keys currently in the buffer that came from successful guesses + * for other salts and thus are being tried for all salts */ + int count_from_guesses; + +/* Whether we have words to base candidate passwords on or not. + * Even if not, we need this keys buffer anyway to hold other salts' successful + * guesses for testing against this salt's hashes. */ + int have_words; + +/* Number of last processed rule */ + int rule; + +/* Number of recursive calls for this salt */ + int lock; + +/* The keys, allocated as (plaintext_length * min_keys_per_crypt) bytes */ + char buffer[1]; +}; + +/* + * Salt list entry. + */ +struct db_salt { +/* Pointer to next salt in the list */ + struct db_salt *next; + +/* Salt in internal representation */ + void *salt; + +/* Bitmap indicating whether a computed hash is potentially present in the list + * and hash table below. Normally, the bitmap is large enough that most of its + * bits are zero. */ + unsigned int *bitmap; + +/* Pointer to a hash function to get the bit index into the bitmap above for + * the crypt_all() method output with given index. The function always returns + * zero if there's no bitmap for this salt. */ + int (*index)(int index); + +/* List of passwords with this salt */ + struct db_password *list; + +/* Password hash table for this salt, or a pointer to the list field */ + struct db_password **hash; + +/* Hash table size code, negative for none */ + int hash_size; + +/* Number of passwords with this salt */ + int count; + +/* Buffered keys, allocated for "single crack" mode only */ + struct db_keys *keys; +}; + +/* + * Structure to hold a cracked password. + */ +struct db_cracked { +/* Pointer to next password with the same hash */ + struct db_cracked *next; + +/* Data from the pot file */ + char *ciphertext, *plaintext; +}; + +/* + * Password database contents flags. + */ +/* Login fields loaded */ +#define DB_LOGIN 0x00000001 +/* Words from GECOS fields loaded */ +#define DB_WORDS 0x00000002 +/* Some hashed passwords were split into several entries */ +#define DB_SPLIT 0x00000010 +/* Duplicate hashes were seen and excluded */ +#define DB_NODUP 0x00000020 +/* Cracked passwords only (ciphertext, plaintext) */ +#define DB_CRACKED 0x00000100 +/* Cracked plaintexts list */ +#define DB_PLAINTEXTS 0x00000200 + +/* + * Password database options. + */ +struct db_options { +/* Contents flags bitmask */ + unsigned int flags; + +/* Filters to use while loading */ + struct list_main *users, *groups, *shells; + +/* Requested passwords per salt */ + int min_pps, max_pps; +}; + +/* + * Main password database. + */ +struct db_main { +/* Are hashed passwords loaded into this database? */ + int loaded; + +/* Options */ + struct db_options *options; + +/* Salt list */ + struct db_salt *salts; + +/* Salt and password hash tables, used while loading */ + struct db_salt **salt_hash; + struct db_password **password_hash; + +/* binary_hash function used by the loader itself */ + int (*password_hash_func)(void *binary); + +/* Cracked passwords */ + struct db_cracked **cracked_hash; + +/* Cracked plaintexts list */ + struct list_main *plaintexts; + +/* Number of salts, passwords and guesses */ + int salt_count, password_count, guess_count; + +/* Ciphertext format */ + struct fmt_main *format; +}; + +#ifdef HAVE_CRYPT +/* Non-zero while the loader is processing the pot file */ +extern int ldr_in_pot; +#endif + +/* + * Initializes the database before loading. + */ +extern void ldr_init_database(struct db_main *db, struct db_options *options); + +/* + * Loads a password file into the database. + */ +extern void ldr_load_pw_file(struct db_main *db, char *name); + +/* + * Removes passwords cracked in previous sessions from the database. + */ +extern void ldr_load_pot_file(struct db_main *db, char *name); + +/* + * Fixes the database after loading. + */ +extern void ldr_fix_database(struct db_main *db); + +/* + * Loads cracked passwords into the database. + */ +extern void ldr_show_pot_file(struct db_main *db, char *name); + +/* + * Shows cracked passwords. + */ +extern void ldr_show_pw_file(struct db_main *db, char *name); + +#endif diff --git a/src/logger.c b/src/logger.c new file mode 100644 index 0000000..e2022b3 --- /dev/null +++ b/src/logger.c @@ -0,0 +1,280 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2004,2010,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _XOPEN_SOURCE /* for fileno(3) and fsync(2) */ + +#define NEED_OS_FLOCK +#include "os.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "status.h" +#include "options.h" +#include "config.h" + +static int cfg_beep; + +/* + * Note: the file buffer is allocated as (size + LINE_BUFFER_SIZE) bytes + * and (ptr - buffer) may actually exceed size by up to LINE_BUFFER_SIZE. + * As long as log_file_write() is called after every write to the buffer, + * there's always room for at least LINE_BUFFER_SIZE bytes to be added. + */ +struct log_file { + char *name; + char *buffer, *ptr; + int size; + int fd; +}; + +static struct log_file log = {NULL, NULL, NULL, 0, -1}; +static struct log_file pot = {NULL, NULL, NULL, 0, -1}; + +static int in_logger = 0; + +static void log_file_init(struct log_file *f, char *name, int size) +{ + f->name = name; + + if (chmod(path_expand(name), S_IRUSR | S_IWUSR)) + if (errno != ENOENT) + pexit("chmod: %s", path_expand(name)); + + if ((f->fd = open(path_expand(name), + O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) + pexit("open: %s", path_expand(name)); + + f->ptr = f->buffer = mem_alloc(size + LINE_BUFFER_SIZE); + f->size = size; +} + +static void log_file_flush(struct log_file *f) +{ + int count; + + if (f->fd < 0) return; + + count = f->ptr - f->buffer; + if (count <= 0) return; + +#if OS_FLOCK + while (flock(f->fd, LOCK_EX)) { + if (errno != EINTR) + pexit("flock(LOCK_EX)"); + } +#endif + if (write_loop(f->fd, f->buffer, count) < 0) pexit("write"); + f->ptr = f->buffer; +#if OS_FLOCK + if (flock(f->fd, LOCK_UN)) + pexit("flock(LOCK_UN)"); +#endif +} + +static int log_file_write(struct log_file *f) +{ + if (f->ptr - f->buffer > f->size) { + log_file_flush(f); + return 1; + } + + return 0; +} + +static void log_file_fsync(struct log_file *f) +{ + if (f->fd < 0) return; + + log_file_flush(f); +#ifndef __CYGWIN32__ + if (fsync(f->fd)) pexit("fsync"); +#endif +} + +static void log_file_done(struct log_file *f, int do_sync) +{ + if (f->fd < 0) return; + + if (do_sync) + log_file_fsync(f); + else + log_file_flush(f); + if (close(f->fd)) pexit("close"); + f->fd = -1; + + MEM_FREE(f->buffer); +} + +static int log_time(void) +{ + int count1, count2; + unsigned int time; + + count1 = 0; + if (options.fork) { + count1 = (int)sprintf(log.ptr, "%u ", options.node_min); + if (count1 < 0) + return count1; + } + + time = pot.fd >= 0 ? status_get_time() : status_restored_time; + + count2 = (int)sprintf(log.ptr + count1, "%u:%02u:%02u:%02u ", + time / 86400, time % 86400 / 3600, + time % 3600 / 60, time % 60); + if (count2 < 0) + return count2; + + return count1 + count2; +} + +void log_init(char *log_name, char *pot_name, char *session) +{ + in_logger = 1; + + if (log_name && log.fd < 0) { + if (session) + log_name = path_session(session, LOG_SUFFIX); + + log_file_init(&log, log_name, LOG_BUFFER_SIZE); + } + + if (pot_name && pot.fd < 0) { + log_file_init(&pot, pot_name, POT_BUFFER_SIZE); + + cfg_beep = cfg_get_bool(SECTION_OPTIONS, NULL, "Beep", 0); + } + + in_logger = 0; +} + +void log_guess(char *login, char *ciphertext, char *plaintext) +{ + int count1, count2; + + printf("%-16s (%s)\n", plaintext, login); + + in_logger = 1; + + if (pot.fd >= 0 && ciphertext && + strlen(ciphertext) + strlen(plaintext) <= LINE_BUFFER_SIZE - 3) { + count1 = (int)sprintf(pot.ptr, + "%s:%s\n", ciphertext, plaintext); + if (count1 > 0) pot.ptr += count1; + } + + if (log.fd >= 0 && + strlen(login) < LINE_BUFFER_SIZE - 64) { + count1 = log_time(); + if (count1 > 0) { + log.ptr += count1; + count2 = (int)sprintf(log.ptr, + "+ Cracked %s\n", login); + if (count2 > 0) + log.ptr += count2; + else + log.ptr -= count1; + } + } + +/* Try to keep the two files in sync */ + if (log_file_write(&pot)) + log_file_flush(&log); + else + if (log_file_write(&log)) + log_file_flush(&pot); + + in_logger = 0; + + if (cfg_beep) + write_loop(fileno(stderr), "\007", 1); +} + +void log_event(const char *format, ...) +{ + va_list args; + int count1, count2; + + if (log.fd < 0) return; + +/* + * Handle possible recursion: + * log_*() -> ... -> pexit() -> ... -> log_event() + */ + if (in_logger) return; + in_logger = 1; + + count1 = log_time(); + if (count1 > 0 && + count1 + strlen(format) < LINE_BUFFER_SIZE - 500 - 1) { + log.ptr += count1; + + va_start(args, format); + count2 = (int)vsprintf(log.ptr, format, args); + va_end(args); + + if (count2 > 0) { + log.ptr += count2; + *log.ptr++ = '\n'; + } else + log.ptr -= count1; + + if (log_file_write(&log)) + log_file_flush(&pot); + } + + in_logger = 0; +} + +void log_discard(void) +{ + log.ptr = log.buffer; +} + +void log_flush(void) +{ + in_logger = 1; + + if (options.fork) + log_file_flush(&log); + else + log_file_fsync(&log); + log_file_fsync(&pot); + + in_logger = 0; +} + +void log_done(void) +{ +/* + * Handle possible recursion: + * log_*() -> ... -> pexit() -> ... -> log_done() + */ + if (in_logger) return; + in_logger = 1; + + log_file_done(&log, !options.fork); + log_file_done(&pot, 1); + + in_logger = 0; +} diff --git a/src/logger.h b/src/logger.h new file mode 100644 index 0000000..f35e3af --- /dev/null +++ b/src/logger.h @@ -0,0 +1,57 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Event logging routines. + */ + +#ifndef _JOHN_LOGGER_H +#define _JOHN_LOGGER_H + +/* + * Initializes the logger (opens john.pot and a log file). + */ +extern void log_init(char *log_name, char *pot_name, char *session); + +/* + * Prints a guessed password to stdout and logs it to john.pot (unless + * ciphertext is NULL) and other related information to the log file. + */ +extern void log_guess(char *login, char *ciphertext, char *plaintext); + +/* + * Logs an arbitrary event. + * + * The caller must make sure that any conversion specifiers in the + * format string expand to no more than 500 characters. + */ +extern void log_event(const char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 1, 2))); +#else + ; +#endif + +/* + * Discards any buffered log data. + */ +extern void log_discard(void); + +/* + * Flushes the john.pot and log file buffers to disk. + */ +extern void log_flush(void); + +/* + * Closes john.pot and the log file. + */ +extern void log_done(void); + +#endif diff --git a/src/math.c b/src/math.c new file mode 100644 index 0000000..28796a4 --- /dev/null +++ b/src/math.c @@ -0,0 +1,116 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include "arch.h" +#include "math.h" + +void add32to64(int64 *dst, unsigned int src) +{ + unsigned int saved; + + saved = dst->lo; + dst->lo += src; + +#if ARCH_INT_GT_32 + dst->lo &= 0xFFFFFFFF; +#endif + + if (dst->lo < saved) dst->hi++; +} + +void add64to64(int64 *dst, int64 *src) +{ + add32to64(dst, src->lo); + dst->hi += src->hi; +} + +void neg64(int64 *dst) +{ + dst->lo = ~dst->lo; dst->hi = ~dst->hi; + add32to64(dst, 1); +} + +static void add32to64m(int64 *dst, unsigned int a) +{ + unsigned int saved; + + saved = dst->lo; + dst->lo += a << 16; + +#if ARCH_INT_GT_32 + dst->lo &= 0xFFFFFFFF; +#endif + + dst->hi += ((dst->lo < saved) ? 1 : 0) + (a >> 16); +} + +void mul32by32(int64 *dst, unsigned int m1, unsigned int m2) +{ + dst->lo = (m1 & 0xFFFF) * (m2 & 0xFFFF); + dst->hi = 0; + + add32to64m(dst, (m1 >> 16) * (m2 & 0xFFFF)); + add32to64m(dst, (m2 >> 16) * (m1 & 0xFFFF)); + + dst->hi += (m1 >> 16) * (m2 >> 16); +} + +void mul64by32(int64 *dst, unsigned int m) +{ + int64 tmp; + + mul32by32(&tmp, dst->hi, m); + dst->hi = tmp.lo; + mul32by32(&tmp, dst->lo, m); + dst->lo = tmp.lo; + dst->hi += tmp.hi; +} + +unsigned int div64by32lo(int64 *src, unsigned int d) +{ + unsigned int lo, hi, q, s, mask; + + lo = src->lo; hi = src->hi; + +#if ARCH_INT_GT_32 + hi += lo >> 32; + lo &= 0xFFFFFFFF; +#endif + + if (hi >= d) return 0xFFFFFFFF; + + q = 0; mask = 0x80000000; + do { + s = hi; + hi = (hi << 1) | (lo >> 31); + lo <<= 1; + +#if ARCH_INT_GT_32 + lo &= 0xFFFFFFFF; +#endif + + if ((s & 0x80000000) || hi >= d) { + hi -= d; + q |= mask; + } + } while (mask >>= 1); + + return q; +} + +void div64by32(int64 *dst, unsigned int d) +{ + int64 tmp; + + tmp.lo = dst->lo; + tmp.hi = dst->hi % d; + dst->lo = div64by32lo(&tmp, d); + dst->hi /= d; +} diff --git a/src/math.h b/src/math.h new file mode 100644 index 0000000..d500165 --- /dev/null +++ b/src/math.h @@ -0,0 +1,33 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * 64-bit integer math functions. + */ + +#ifndef _JOHN_MATH_H +#define _JOHN_MATH_H + +#undef int64 +#define int64 _john_int64_t + +typedef struct { + unsigned int lo, hi; +} int64; + +extern void add32to64(int64 *dst, unsigned int src); +extern void add64to64(int64 *dst, int64 *src); +extern void neg64(int64 *dst); +extern void mul32by32(int64 *dst, unsigned int m1, unsigned int m2); +extern void mul64by32(int64 *dst, unsigned int m); +extern unsigned int div64by32lo(int64 *src, unsigned int d); +extern void div64by32(int64 *dst, unsigned int d); + +#endif diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..07f1c7e --- /dev/null +++ b/src/memory.c @@ -0,0 +1,92 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2010,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "memory.h" + +unsigned int mem_saving_level = 0; + +void *mem_alloc(size_t size) +{ + void *res; + + if (!size) return NULL; + + if (!(res = malloc(size))) { + fprintf(stderr, "malloc: %s\n", strerror(ENOMEM)); + error(); + } + + return res; +} + +void *mem_alloc_tiny(size_t size, size_t align) +{ + static char *buffer = NULL; + static size_t bufree = 0; + size_t mask; + char *p; + +#if ARCH_ALLOWS_UNALIGNED + if (mem_saving_level > 2) + align = MEM_ALIGN_NONE; +#endif + + mask = align - 1; + + do { + if (buffer) { + size_t need = + size + mask - (((size_t)buffer + mask) & mask); + if (bufree >= need) { + p = buffer; + p += mask; + p -= (size_t)p & mask; + bufree -= need; + buffer = p + size; + return p; + } + } + + if (size + mask > MEM_ALLOC_SIZE || + bufree > MEM_ALLOC_MAX_WASTE) + break; + + buffer = mem_alloc(MEM_ALLOC_SIZE); + bufree = MEM_ALLOC_SIZE; + } while (1); + + p = mem_alloc(size + mask); + p += mask; + p -= (size_t)p & mask; + return p; +} + +void *mem_alloc_copy(void *src, size_t size, size_t align) +{ + return memcpy(mem_alloc_tiny(size, align), src, size); +} + +char *str_alloc_copy(char *src) +{ + size_t size; + + if (!src) return ""; + if (!*src) return ""; + + size = strlen(src) + 1; + return (char *)memcpy(mem_alloc_tiny(size, MEM_ALIGN_NONE), src, size); +} diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..7c284ab --- /dev/null +++ b/src/memory.h @@ -0,0 +1,90 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2003,2010-2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Memory allocation routines. + */ + +#ifndef _JOHN_MEMORY_H +#define _JOHN_MEMORY_H + +#include +#include + +#include "arch.h" + +/* + * Standard alignments for mem_alloc_tiny(). + */ +#define MEM_ALIGN_NONE 1 +#define MEM_ALIGN_WORD ARCH_SIZE +/* + * These are hopefully suitable guesses. They are right for only a subset of + * the architectures/CPUs we support, yet our use of them does not require that + * they be entirely correct. + */ +#define MEM_ALIGN_CACHE (ARCH_SIZE * 8) +#define MEM_ALIGN_PAGE 0x1000 + +/* + * Block size used by mem_alloc_tiny(). + */ +#define MEM_ALLOC_SIZE 0x10000 + +/* + * Use mem_alloc() instead of allocating a new block in mem_alloc_tiny() + * if more than MEM_ALLOC_MAX_WASTE bytes would be lost. + * This shouldn't be set too small, or mem_alloc_tiny() will keep calling + * mem_alloc() for many allocations in a row, which might end up wasting even + * more memory to malloc() overhead. + */ +#define MEM_ALLOC_MAX_WASTE 0xff + +/* + * Memory saving level, setting this high enough disables alignments (if the + * architecture allows). + */ +extern unsigned int mem_saving_level; + +/* + * Allocates size bytes and returns a pointer to the allocated memory. + * If an error occurs, the function does not return. + */ +extern void *mem_alloc(size_t size); + +/* + * Frees memory allocated with mem_alloc() and sets the pointer to NULL. + * Does nothing if the pointer is already NULL. + */ +#define MEM_FREE(ptr) \ +{ \ + if ((ptr)) { \ + free((ptr)); \ + (ptr) = NULL; \ + } \ +} + +/* + * Similar to the above function, except the memory can't be freed. + * This one is used to reduce the overhead. + */ +extern void *mem_alloc_tiny(size_t size, size_t align); + +/* + * Uses mem_alloc_tiny() to allocate the memory, and copies src in there. + */ +extern void *mem_alloc_copy(void *src, size_t size, size_t align); + +/* + * Similar to the above function, but for ASCIIZ strings. + */ +extern char *str_alloc_copy(char *src); + +#endif diff --git a/src/mips32.h b/src/mips32.h new file mode 100644 index 0000000..a33ffa7 --- /dev/null +++ b/src/mips32.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for MIPS 32-bit. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/mips64.h b/src/mips64.h new file mode 100644 index 0000000..61622f0 --- /dev/null +++ b/src/mips64.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for MIPS 64-bit. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 0 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..73ff89d --- /dev/null +++ b/src/misc.c @@ -0,0 +1,143 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include +#include +#include +#include +#include + +#include "logger.h" + +void error(void) +{ +#ifndef _JOHN_MISC_NO_LOG + log_event("Terminating on error"); + log_done(); +#endif + + exit(1); +} + +void pexit(char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, ": %s\n", strerror(errno)); + + error(); +} + +int write_loop(int fd, char *buffer, int count) +{ + int offset, block; + + offset = 0; + while (count > 0) { + block = write(fd, &buffer[offset], count); + +/* If any write(2) fails, we consider that the entire write_loop() has + * failed to do its job, unless we were interrupted by a signal. */ + if (block < 0) { + if (errno == EINTR) continue; + return block; + } + + offset += block; + count -= block; + } + +/* Should be equal to the requested size, unless our kernel got crazy. */ + return offset; +} + +char *fgetl(char *s, int size, FILE *stream) +{ + char *res, *pos; + int c; + + if ((res = fgets(s, size, stream))) { + if (!*res) return res; + + pos = res + strlen(res) - 1; + if (*pos == '\n') { + *pos = 0; + if (pos > res) + if (*--pos == '\r') *pos = 0; + } else + if ((c = getc(stream)) == '\n') { + if (*pos == '\r') *pos = 0; + } else + while (c != EOF && c != '\n') + c = getc(stream); + } + + return res; +} + +char *strnfcpy(char *dst, char *src, int size) +{ + char *dptr = dst, *sptr = src; + int count = size; + + while (count--) + if (!(*dptr++ = *sptr++)) break; + + return dst; +} + +char *strnzcpy(char *dst, char *src, int size) +{ + char *dptr = dst, *sptr = src; + int count = size; + + if (count) + while (--count) + if (!(*dptr++ = *sptr++)) break; + *dptr = 0; + + return dst; +} + +char *strnzcat(char *dst, char *src, int size) +{ + char *dptr = dst, *sptr = src; + int count = size; + + if (count) { + while (count && *dptr) { + count--; dptr++; + } + if (count) + while (--count) + if (!(*dptr++ = *sptr++)) break; + } + *dptr = 0; + + return dst; +} + +char *strlwr(char *s) +{ + unsigned char *ptr = (unsigned char *)s; + + while (*ptr) + if (*ptr >= 'A' && *ptr <= 'Z') + *ptr++ |= 0x20; + else + ptr++; + + return s; +} diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 0000000..fbb3df3 --- /dev/null +++ b/src/misc.h @@ -0,0 +1,71 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Miscellaneous routines. + */ + +#ifndef _JOHN_MISC_H +#define _JOHN_MISC_H + +#include + +/* + * Exit on error. Logs the event, closes john.pot and the log file, and + * terminates the process with non-zero exit status. + */ +extern void error(void); + +/* + * Similar to perror(), but supports formatted output, and calls error(). + */ +extern void pexit(char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 1, 2))); +#else + ; +#endif + +/* + * Attempts to write all the supplied data. Returns the number of bytes + * written, or -1 on error. + */ +extern int write_loop(int fd, char *buffer, int count); + +/* + * Similar to fgets(), but doesn't leave the newline character in the buffer, + * and skips to the end of long lines. Handles both Unix and DOS style text + * files correctly. + */ +extern char *fgetl(char *s, int size, FILE *stream); + +/* + * Similar to strncpy(), but terminates with only one NUL if there's room + * instead of padding to the supplied size like strncpy() does. + */ +extern char *strnfcpy(char *dst, char *src, int size); + +/* + * Similar to the above, but always NUL terminates the string. + */ +extern char *strnzcpy(char *dst, char *src, int size); + +/* + * Similar to strncat(), but total buffer size is supplied, and always NUL + * terminates the string. + */ +extern char *strnzcat(char *dst, char *src, int size); + +/* + * Converts a string to lowercase. + */ +extern char *strlwr(char *s); + +#endif diff --git a/src/nonstd.c b/src/nonstd.c new file mode 100644 index 0000000..6076d2f --- /dev/null +++ b/src/nonstd.c @@ -0,0 +1,3087 @@ +/* + * Bitslice DES S-boxes for x86 with MMX/SSE2/AVX and for typical RISC + * architectures. These use AND, OR, XOR, NOT, and AND-NOT gates. + * + * Gate counts: 49 44 46 33 48 46 46 41 + * Average: 44.125 + * + * Several same-gate-count expressions for each S-box are included (for use on + * different CPUs/GPUs). + * + * These Boolean expressions corresponding to DES S-boxes have been generated + * by Roman Rusakov for use in Openwall's + * John the Ripper password cracker: http://www.openwall.com/john/ + * Being mathematical formulas, they are not copyrighted and are free for reuse + * by anyone. + * + * This file (a specific representation of the S-box expressions, surrounding + * logic) is Copyright (c) 2011 by Solar Designer . + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. (This is a heavily cut-down "BSD license".) + * + * The effort has been sponsored by Rapid7: http://www.rapid7.com + */ + +#ifndef andn +#define andn 1 +#endif + +#undef triop +#if (defined(__x86_64__) || defined(__i386__)) && !defined(__AVX__) +#define triop 0 +#else +#define triop 1 +#endif + +#undef regs +#if defined(__x86_64__) && defined(__SSE2__) +/* Also for AVX, XOP (we assume that these imply/define SSE2) */ +#define regs 16 +#elif defined(__x86_64__) +#define regs 15 +#elif defined(__i386__) +/* Hopefully, at least MMX */ +#define regs 8 +#else +/* PowerPC with AltiVec, etc. */ +#define regs 32 +#endif + +#undef latency +/* Latency 2 may also mean dual-issue with latency 1 */ +#define latency 2 + +#if andn && triop && regs >= 18 && latency <= 3 +/* s1-00104, 49 gates, 18 regs, 13 andn, 2/7/41/79/122 stalls, 75 biop */ +MAYBE_INLINE static void +s1(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55005500, x5A0F5A0F, x3333FFFF, x66666666, x22226666, x2D2D6969, + x25202160; + vtype x00FFFF00, x33CCCC33, x4803120C, x2222FFFF, x6A21EDF3, x4A01CC93; + vtype x5555FFFF, x7F75FFFF, x00D20096, x7FA7FF69; + vtype x0A0A0000, x0AD80096, x00999900, x0AD99996; + vtype x22332233, x257AA5F0, x054885C0, xFAB77A3F, x2221EDF3, xD89697CC; + vtype x05B77AC0, x05F77AD6, x50A22F83, x6391D07C, xBB0747B0; + vtype x00B700C0, x5AB85ACF, x50204249, x4090904C, x10B0D205; + vtype x2220EDF3, x99070200, x9CB078C0, xDCB07AC9; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x55005500, a1, a5); + vxor(x5A0F5A0F, a4, x55005500); + vor(x3333FFFF, a3, a6); + vxor(x66666666, a1, a3); + vand(x22226666, x3333FFFF, x66666666); + vxor(x2D2D6969, a4, x22226666); + vandn(x25202160, x2D2D6969, x5A0F5A0F); + + vxor(x00FFFF00, a5, a6); + vxor(x33CCCC33, a3, x00FFFF00); + vandn(x4803120C, x5A0F5A0F, x33CCCC33); + vor(x2222FFFF, a6, x22226666); + vxor(x6A21EDF3, x4803120C, x2222FFFF); + vandn(x4A01CC93, x6A21EDF3, x25202160); + + vor(x5555FFFF, a1, a6); + vor(x7F75FFFF, x6A21EDF3, x5555FFFF); + vandn(x00D20096, a5, x2D2D6969); + vxor(x7FA7FF69, x7F75FFFF, x00D20096); + + vandn(x0A0A0000, a4, x5555FFFF); + vxor(x0AD80096, x00D20096, x0A0A0000); + vandn(x00999900, x00FFFF00, x66666666); + vor(x0AD99996, x0AD80096, x00999900); + + vandn(x22332233, a3, x55005500); + vxor(x257AA5F0, x5A0F5A0F, x7F75FFFF); + vandn(x054885C0, x257AA5F0, x22332233); + vnot(xFAB77A3F, x054885C0); + vand(x2221EDF3, x3333FFFF, x6A21EDF3); + vxor(xD89697CC, xFAB77A3F, x2221EDF3); + vandn(x20, x7FA7FF69, a2); + vxor(x21, x20, xD89697CC); + vxor(*out3, *out3, x21); + + vxor(x05B77AC0, x00FFFF00, x054885C0); + vor(x05F77AD6, x00D20096, x05B77AC0); + vxor(x50A22F83, a1, x05F77AD6); + vxor(x6391D07C, x3333FFFF, x50A22F83); + vxor(xBB0747B0, xD89697CC, x6391D07C); + vor(x00, x25202160, a2); + vxor(x01, x00, xBB0747B0); + vxor(*out1, *out1, x01); + + vand(x00B700C0, a5, x05B77AC0); + vxor(x5AB85ACF, x5A0F5A0F, x00B700C0); + vandn(x50204249, x5AB85ACF, x0AD99996); + vand(x4090904C, xD89697CC, x6391D07C); + vxor(x10B0D205, x50204249, x4090904C); + vor(x30, x10B0D205, a2); + vxor(x31, x30, x0AD99996); + vxor(*out4, *out4, x31); + + vand(x2220EDF3, x2222FFFF, x6A21EDF3); + vandn(x99070200, xBB0747B0, x2220EDF3); + vxor(x9CB078C0, x05B77AC0, x99070200); + vor(xDCB07AC9, x50204249, x9CB078C0); + vandn(x10, a2, x4A01CC93); + vxor(x11, x10, xDCB07AC9); + vxor(*out2, *out2, x11); +} +#elif !andn || !triop || latency >= 3 +/* s1-00484, 49 gates, 17 regs, 11 andn, 4/9/39/79/120 stalls, 74 biop */ +/* Currently used for MMX/SSE2 and x86-64 SSE2 */ +MAYBE_INLINE static void +s1(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55005500, x5A0F5A0F, x3333FFFF, x66666666, x22226666, x2D2D6969, + x25202160; + vtype x00FFFF00, x33CCCC33, x4803120C, x2222FFFF, x6A21EDF3, x4A01CC93; + vtype x5555FFFF, x7F75FFFF, x00D20096, x7FA7FF69; + vtype x0A0A0000, x0AD80096, x00999900, x0AD99996; + vtype x22332233, x257AA5F0, x054885C0, xFAB77A3F, x2221EDF3, xD89697CC; + vtype x05B77AC0, x05F77AD6, x36C48529, x6391D07C, xBB0747B0; + vtype x4C460000, x4EDF9996, x2D4E49EA, xBBFFFFB0, x96B1B65A; + vtype x5AFF5AFF, x52B11215, x4201C010, x10B0D205; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x55005500, a1, a5); + vxor(x5A0F5A0F, a4, x55005500); + vor(x3333FFFF, a3, a6); + vxor(x66666666, a1, a3); + vand(x22226666, x3333FFFF, x66666666); + vxor(x2D2D6969, a4, x22226666); + vandn(x25202160, x2D2D6969, x5A0F5A0F); + + vxor(x00FFFF00, a5, a6); + vxor(x33CCCC33, a3, x00FFFF00); + vandn(x4803120C, x5A0F5A0F, x33CCCC33); + vor(x2222FFFF, a6, x22226666); + vxor(x6A21EDF3, x4803120C, x2222FFFF); + vandn(x4A01CC93, x6A21EDF3, x25202160); + + vor(x5555FFFF, a1, a6); + vor(x7F75FFFF, x6A21EDF3, x5555FFFF); + vandn(x00D20096, a5, x2D2D6969); + vxor(x7FA7FF69, x7F75FFFF, x00D20096); + + vandn(x0A0A0000, a4, x5555FFFF); + vxor(x0AD80096, x00D20096, x0A0A0000); + vandn(x00999900, x00FFFF00, x66666666); + vor(x0AD99996, x0AD80096, x00999900); + + vandn(x22332233, a3, x55005500); + vxor(x257AA5F0, x5A0F5A0F, x7F75FFFF); + vandn(x054885C0, x257AA5F0, x22332233); + vnot(xFAB77A3F, x054885C0); + vand(x2221EDF3, x3333FFFF, x6A21EDF3); + vxor(xD89697CC, xFAB77A3F, x2221EDF3); + vandn(x20, x7FA7FF69, a2); + vxor(x21, x20, xD89697CC); + vxor(*out3, *out3, x21); + + vxor(x05B77AC0, x00FFFF00, x054885C0); + vor(x05F77AD6, x00D20096, x05B77AC0); + vxor(x36C48529, x3333FFFF, x05F77AD6); + vxor(x6391D07C, a1, x36C48529); + vxor(xBB0747B0, xD89697CC, x6391D07C); + vor(x00, x25202160, a2); + vxor(x01, x00, xBB0747B0); + vxor(*out1, *out1, x01); + + vxor(x4C460000, x3333FFFF, x7F75FFFF); + vor(x4EDF9996, x0AD99996, x4C460000); + vxor(x2D4E49EA, x6391D07C, x4EDF9996); + vor(xBBFFFFB0, x00FFFF00, xBB0747B0); + vxor(x96B1B65A, x2D4E49EA, xBBFFFFB0); + vor(x10, x4A01CC93, a2); + vxor(x11, x10, x96B1B65A); + vxor(*out2, *out2, x11); + + vor(x5AFF5AFF, a5, x5A0F5A0F); + vandn(x52B11215, x5AFF5AFF, x2D4E49EA); + vand(x4201C010, x4A01CC93, x6391D07C); + vxor(x10B0D205, x52B11215, x4201C010); + vor(x30, x10B0D205, a2); + vxor(x31, x30, x0AD99996); + vxor(*out4, *out4, x31); +} +#else +/* s1-01753, 49 gates, 17/18 regs, 14 andn, 3/16/48/88/132 stalls, 76 biop */ +MAYBE_INLINE static void +s1(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55005500, x5A0F5A0F, x3333FFFF, x66666666, x22226666, x2D2D6969, + x25202160; + vtype x00FFFF00, x33CCCC33, x4803120C, x2222FFFF, x6A21EDF3, x4A01CC93; + vtype x5555FFFF, x7F75FFFF, x00D20096, x7FA7FF69; + vtype x0A0A0000, x0AD80096, x00999900, x0AD99996; + vtype x22332233, x257AA5F0, x054885C0, xFAB77A3F, x2221EDF3, xD89697CC; + vtype x05B77AC0, x05F77AD6, x36C48529, x6391D07C, xBB0747B0; + vtype x50064209, x55B138C9, x361685BF, x89014200, xDCB07AC9; + vtype x33555533, xDC54BDFF, xCC00A8CC, x10B0D205; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x55005500, a1, a5); + vxor(x5A0F5A0F, a4, x55005500); + vor(x3333FFFF, a3, a6); + vxor(x66666666, a1, a3); + vand(x22226666, x3333FFFF, x66666666); + vxor(x2D2D6969, a4, x22226666); + vandn(x25202160, x2D2D6969, x5A0F5A0F); + + vxor(x00FFFF00, a5, a6); + vxor(x33CCCC33, a3, x00FFFF00); + vandn(x4803120C, x5A0F5A0F, x33CCCC33); + vor(x2222FFFF, a6, x22226666); + vxor(x6A21EDF3, x4803120C, x2222FFFF); + vandn(x4A01CC93, x6A21EDF3, x25202160); + + vor(x5555FFFF, a1, a6); + vor(x7F75FFFF, x6A21EDF3, x5555FFFF); + vandn(x00D20096, a5, x2D2D6969); + vxor(x7FA7FF69, x7F75FFFF, x00D20096); + + vandn(x0A0A0000, a4, x5555FFFF); + vxor(x0AD80096, x00D20096, x0A0A0000); + vandn(x00999900, x00FFFF00, x66666666); + vor(x0AD99996, x0AD80096, x00999900); + + vandn(x22332233, a3, x55005500); + vxor(x257AA5F0, x5A0F5A0F, x7F75FFFF); + vandn(x054885C0, x257AA5F0, x22332233); + vnot(xFAB77A3F, x054885C0); + vand(x2221EDF3, x3333FFFF, x6A21EDF3); + vxor(xD89697CC, xFAB77A3F, x2221EDF3); + vandn(x20, x7FA7FF69, a2); + vxor(x21, x20, xD89697CC); + vxor(*out3, *out3, x21); + + vxor(x05B77AC0, x00FFFF00, x054885C0); + vor(x05F77AD6, x00D20096, x05B77AC0); + vxor(x36C48529, x3333FFFF, x05F77AD6); + vxor(x6391D07C, a1, x36C48529); + vxor(xBB0747B0, xD89697CC, x6391D07C); + vor(x00, x25202160, a2); + vxor(x01, x00, xBB0747B0); + vxor(*out1, *out1, x01); + + vandn(x50064209, x5A0F5A0F, x0AD99996); + vxor(x55B138C9, x05B77AC0, x50064209); + vxor(x361685BF, x00D20096, x36C48529); + vandn(x89014200, xBB0747B0, x361685BF); + vxor(xDCB07AC9, x55B138C9, x89014200); + vandn(x10, a2, x4A01CC93); + vxor(x11, x10, xDCB07AC9); + vxor(*out2, *out2, x11); + + vxor(x33555533, x33CCCC33, x00999900); + vxor(xDC54BDFF, x5555FFFF, x89014200); + vandn(xCC00A8CC, xDC54BDFF, x33555533); + vxor(x10B0D205, xDCB07AC9, xCC00A8CC); + vor(x30, x10B0D205, a2); + vxor(x31, x30, x0AD99996); + vxor(*out4, *out4, x31); +} +#endif + +#if andn && triop && latency <= 4 +/* s2-016251, 44 gates, 14 regs, 13 andn, 1/9/22/61/108 stalls, 66 biop */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x55550000, x00AA00FF, x33BB33FF; + vtype x33CC0000, x11441144, x11BB11BB, x003311BB; + vtype x00000F0F, x336600FF, x332200FF, x332200F0; + vtype x0302000F, xAAAAAAAA, xA9A8AAA5, x33CCCC33, x33CCC030, x9A646A95; + vtype x00333303, x118822B8, xA8208805, x3CC3C33C, x94E34B39; + vtype x0331330C, x3FF3F33C, xA9DF596A, xA9DF5F6F, x962CAC53; + vtype x0A042084, x12752248, x1A7522CC, x00301083, x1A45324F; + vtype x0A451047, xBBDFDD7B, xB19ACD3C; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vandn(x55550000, a1, a6); + vandn(x00AA00FF, a5, x55550000); + vor(x33BB33FF, a2, x00AA00FF); + + vandn(x33CC0000, x33CC33CC, a6); + vand(x11441144, a1, x33CC33CC); + vxor(x11BB11BB, a5, x11441144); + vandn(x003311BB, x11BB11BB, x33CC0000); + + vand(x00000F0F, a3, a6); + vxor(x336600FF, x00AA00FF, x33CC0000); + vand(x332200FF, x33BB33FF, x336600FF); + vandn(x332200F0, x332200FF, x00000F0F); + + vand(x0302000F, a3, x332200FF); + vnot(xAAAAAAAA, a1); + vxor(xA9A8AAA5, x0302000F, xAAAAAAAA); + vxor(x33CCCC33, a6, x33CC33CC); + vandn(x33CCC030, x33CCCC33, x00000F0F); + vxor(x9A646A95, xA9A8AAA5, x33CCC030); + vandn(x10, a4, x332200F0); + vxor(x11, x10, x9A646A95); + vxor(*out2, *out2, x11); + + vandn(x00333303, a2, x33CCC030); + vxor(x118822B8, x11BB11BB, x00333303); + vandn(xA8208805, xA9A8AAA5, x118822B8); + vxor(x3CC3C33C, a3, x33CCCC33); + vxor(x94E34B39, xA8208805, x3CC3C33C); + vandn(x00, x33BB33FF, a4); + vxor(x01, x00, x94E34B39); + vxor(*out1, *out1, x01); + + vxor(x0331330C, x0302000F, x00333303); + vor(x3FF3F33C, x3CC3C33C, x0331330C); + vxor(xA9DF596A, x33BB33FF, x9A646A95); + vor(xA9DF5F6F, x00000F0F, xA9DF596A); + vxor(x962CAC53, x3FF3F33C, xA9DF5F6F); + + vandn(x0A042084, x9A646A95, x94E34B39); + vxor(x12752248, x11441144, x0331330C); + vor(x1A7522CC, x0A042084, x12752248); + vandn(x00301083, x003311BB, x3CC3C33C); + vxor(x1A45324F, x1A7522CC, x00301083); + vor(x20, x1A45324F, a4); + vxor(x21, x20, x962CAC53); + vxor(*out3, *out3, x21); + + vandn(x0A451047, x1A45324F, x118822B8); + vor(xBBDFDD7B, x33CCCC33, xA9DF596A); + vxor(xB19ACD3C, x0A451047, xBBDFDD7B); + vor(x30, x003311BB, a4); + vxor(x31, x30, xB19ACD3C); + vxor(*out4, *out4, x31); +} +#elif !andn && regs >= 15 +/* s2-016276, 44 gates, 15 regs, 11 andn, 1/9/24/59/104 stalls, 67 biop */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x55550000, x00AA00FF, x33BB33FF; + vtype x33CC0000, x11441144, x11BB11BB, x003311BB; + vtype x00000F0F, x336600FF, x332200FF, x332200F0; + vtype x0302000F, xAAAAAAAA, xA9A8AAA5, x33CCCC33, x33CCC030, x9A646A95; + vtype x00333303, x118822B8, xA8208805, x3CC3C33C, x94E34B39; + vtype x0331330C, x3FF3F33C, xA9DF596A, xA9DF5F6F, x962CAC53; + vtype xA9466A6A, x3DA52153, x29850143, x33C0330C, x1A45324F; + vtype x0A451047, xBBDFDD7B, xB19ACD3C; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vandn(x55550000, a1, a6); + vandn(x00AA00FF, a5, x55550000); + vor(x33BB33FF, a2, x00AA00FF); + + vandn(x33CC0000, x33CC33CC, a6); + vand(x11441144, a1, x33CC33CC); + vxor(x11BB11BB, a5, x11441144); + vandn(x003311BB, x11BB11BB, x33CC0000); + + vand(x00000F0F, a3, a6); + vxor(x336600FF, x00AA00FF, x33CC0000); + vand(x332200FF, x33BB33FF, x336600FF); + vandn(x332200F0, x332200FF, x00000F0F); + + vand(x0302000F, a3, x332200FF); + vnot(xAAAAAAAA, a1); + vxor(xA9A8AAA5, x0302000F, xAAAAAAAA); + vxor(x33CCCC33, a6, x33CC33CC); + vandn(x33CCC030, x33CCCC33, x00000F0F); + vxor(x9A646A95, xA9A8AAA5, x33CCC030); + vandn(x10, a4, x332200F0); + vxor(x11, x10, x9A646A95); + vxor(*out2, *out2, x11); + + vandn(x00333303, a2, x33CCC030); + vxor(x118822B8, x11BB11BB, x00333303); + vandn(xA8208805, xA9A8AAA5, x118822B8); + vxor(x3CC3C33C, a3, x33CCCC33); + vxor(x94E34B39, xA8208805, x3CC3C33C); + vandn(x00, x33BB33FF, a4); + vxor(x01, x00, x94E34B39); + vxor(*out1, *out1, x01); + + vxor(x0331330C, x0302000F, x00333303); + vor(x3FF3F33C, x3CC3C33C, x0331330C); + vxor(xA9DF596A, x33BB33FF, x9A646A95); + vor(xA9DF5F6F, x00000F0F, xA9DF596A); + vxor(x962CAC53, x3FF3F33C, xA9DF5F6F); + + vxor(xA9466A6A, x332200FF, x9A646A95); + vxor(x3DA52153, x94E34B39, xA9466A6A); + vand(x29850143, xA9DF5F6F, x3DA52153); + vand(x33C0330C, x33CC33CC, x3FF3F33C); + vxor(x1A45324F, x29850143, x33C0330C); + vor(x20, x1A45324F, a4); + vxor(x21, x20, x962CAC53); + vxor(*out3, *out3, x21); + + vandn(x0A451047, x1A45324F, x118822B8); + vor(xBBDFDD7B, x33CCCC33, xA9DF596A); + vxor(xB19ACD3C, x0A451047, xBBDFDD7B); + vor(x30, x003311BB, a4); + vxor(x31, x30, xB19ACD3C); + vxor(*out4, *out4, x31); +} +#elif andn && !triop && regs >= 15 && latency <= 2 +/* s2-016277, 44 gates, 15 regs, 12 andn, 4/15/35/74/121 stalls, 65 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x55550000, x00AA00FF, x33BB33FF; + vtype x33CC0000, x11441144, x11BB11BB, x003311BB; + vtype x00000F0F, x336600FF, x332200FF, x332200F0; + vtype x0302000F, xAAAAAAAA, xA9A8AAA5, x33CCCC33, x33CCC030, x9A646A95; + vtype x00333303, x118822B8, xA8208805, x3CC3C33C, x94E34B39; + vtype x0331330C, x3FF3F33C, xA9DF596A, xA9DF5F6F, x962CAC53; + vtype x97D27835, x81D25825, x812D58DA, x802158DA, x1A45324F; + vtype x0A451047, xBBDFDD7B, xB19ACD3C; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vandn(x55550000, a1, a6); + vandn(x00AA00FF, a5, x55550000); + vor(x33BB33FF, a2, x00AA00FF); + + vandn(x33CC0000, x33CC33CC, a6); + vand(x11441144, a1, x33CC33CC); + vxor(x11BB11BB, a5, x11441144); + vandn(x003311BB, x11BB11BB, x33CC0000); + + vand(x00000F0F, a3, a6); + vxor(x336600FF, x00AA00FF, x33CC0000); + vand(x332200FF, x33BB33FF, x336600FF); + vandn(x332200F0, x332200FF, x00000F0F); + + vand(x0302000F, a3, x332200FF); + vnot(xAAAAAAAA, a1); + vxor(xA9A8AAA5, x0302000F, xAAAAAAAA); + vxor(x33CCCC33, a6, x33CC33CC); + vandn(x33CCC030, x33CCCC33, x00000F0F); + vxor(x9A646A95, xA9A8AAA5, x33CCC030); + vandn(x10, a4, x332200F0); + vxor(x11, x10, x9A646A95); + vxor(*out2, *out2, x11); + + vandn(x00333303, a2, x33CCC030); + vxor(x118822B8, x11BB11BB, x00333303); + vandn(xA8208805, xA9A8AAA5, x118822B8); + vxor(x3CC3C33C, a3, x33CCCC33); + vxor(x94E34B39, xA8208805, x3CC3C33C); + vandn(x00, x33BB33FF, a4); + vxor(x01, x00, x94E34B39); + vxor(*out1, *out1, x01); + + vxor(x0331330C, x0302000F, x00333303); + vor(x3FF3F33C, x3CC3C33C, x0331330C); + vxor(xA9DF596A, x33BB33FF, x9A646A95); + vor(xA9DF5F6F, x00000F0F, xA9DF596A); + vxor(x962CAC53, x3FF3F33C, xA9DF5F6F); + + vxor(x97D27835, x94E34B39, x0331330C); + vand(x81D25825, xA9DF5F6F, x97D27835); + vxor(x812D58DA, a5, x81D25825); + vandn(x802158DA, x812D58DA, x33CC0000); + vxor(x1A45324F, x9A646A95, x802158DA); + vor(x20, x1A45324F, a4); + vxor(x21, x20, x962CAC53); + vxor(*out3, *out3, x21); + + vandn(x0A451047, x1A45324F, x118822B8); + vor(xBBDFDD7B, x33CCCC33, xA9DF596A); + vxor(xB19ACD3C, x0A451047, xBBDFDD7B); + vor(x30, x003311BB, a4); + vxor(x31, x30, xB19ACD3C); + vxor(*out4, *out4, x31); +} +#elif !andn || (triop && latency >= 5) +/* s2-016380, 44 gates, 14/15 regs, 12 andn, 1/9/27/55/99 stalls, 68 biop */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x55550000, x00AA00FF, x33BB33FF; + vtype x33CC0000, x11441144, x11BB11BB, x003311BB; + vtype x00000F0F, x336600FF, x332200FF, x332200F0; + vtype x0302000F, xAAAAAAAA, xA9A8AAA5, x33CCCC33, x33CCC030, x9A646A95; + vtype x00333303, x118822B8, xA8208805, x3CC3C33C, x94E34B39; + vtype x33333030, x3FF3F33C, xA9DF596A, xA9DF5F6F, x962CAC53; + vtype xA9466A6A, x3DA52153, x29850143, x33C0330C, x1A45324F; + vtype x0A451047, xBBDFDD7B, xB19ACD3C; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vandn(x55550000, a1, a6); + vandn(x00AA00FF, a5, x55550000); + vor(x33BB33FF, a2, x00AA00FF); + + vandn(x33CC0000, x33CC33CC, a6); + vand(x11441144, a1, x33CC33CC); + vxor(x11BB11BB, a5, x11441144); + vandn(x003311BB, x11BB11BB, x33CC0000); + + vand(x00000F0F, a3, a6); + vxor(x336600FF, x00AA00FF, x33CC0000); + vand(x332200FF, x33BB33FF, x336600FF); + vandn(x332200F0, x332200FF, x00000F0F); + + vand(x0302000F, a3, x332200FF); + vnot(xAAAAAAAA, a1); + vxor(xA9A8AAA5, x0302000F, xAAAAAAAA); + vxor(x33CCCC33, a6, x33CC33CC); + vandn(x33CCC030, x33CCCC33, x00000F0F); + vxor(x9A646A95, xA9A8AAA5, x33CCC030); + vandn(x10, a4, x332200F0); + vxor(x11, x10, x9A646A95); + vxor(*out2, *out2, x11); + + vandn(x00333303, a2, x33CCC030); + vxor(x118822B8, x11BB11BB, x00333303); + vandn(xA8208805, xA9A8AAA5, x118822B8); + vxor(x3CC3C33C, a3, x33CCCC33); + vxor(x94E34B39, xA8208805, x3CC3C33C); + vandn(x00, x33BB33FF, a4); + vxor(x01, x00, x94E34B39); + vxor(*out1, *out1, x01); + + vandn(x33333030, a2, x00000F0F); + vor(x3FF3F33C, x3CC3C33C, x33333030); + vxor(xA9DF596A, x33BB33FF, x9A646A95); + vor(xA9DF5F6F, x00000F0F, xA9DF596A); + vxor(x962CAC53, x3FF3F33C, xA9DF5F6F); + + vxor(xA9466A6A, x332200FF, x9A646A95); + vxor(x3DA52153, x94E34B39, xA9466A6A); + vand(x29850143, xA9DF5F6F, x3DA52153); + vand(x33C0330C, x33CC33CC, x3FF3F33C); + vxor(x1A45324F, x29850143, x33C0330C); + vor(x20, x1A45324F, a4); + vxor(x21, x20, x962CAC53); + vxor(*out3, *out3, x21); + + vandn(x0A451047, x1A45324F, x118822B8); + vor(xBBDFDD7B, x33CCCC33, xA9DF596A); + vxor(xB19ACD3C, x0A451047, xBBDFDD7B); + vor(x30, x003311BB, a4); + vxor(x31, x30, xB19ACD3C); + vxor(*out4, *out4, x31); +} +#else +/* s2-016520, 44 gates, 15 regs, 13 andn, 5/17/41/78/125 stalls, 68 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x55550000, x00AA00FF, x33BB33FF; + vtype x33CC0000, x11441144, x11BB11BB, x003311BB; + vtype x00000F0F, x336600FF, x332200FF, x332200F0; + vtype x0302000F, xAAAAAAAA, xA9A8AAA5, x33CCCC33, x33CCC030, x9A646A95; + vtype x00333303, x118822B8, xA8208805, x3CC3C33C, x94E34B39; + vtype x03303003, xA9DF596A, xAAEF6969, xAAEF6F6F, x962CAC53; + vtype x0903030C, x093012B7, x19B832BF, x03FD00F0, x1A45324F; + vtype x0A451047, xBBDFDD7B, xB19ACD3C; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vandn(x55550000, a1, a6); + vandn(x00AA00FF, a5, x55550000); + vor(x33BB33FF, a2, x00AA00FF); + + vandn(x33CC0000, x33CC33CC, a6); + vand(x11441144, a1, x33CC33CC); + vxor(x11BB11BB, a5, x11441144); + vandn(x003311BB, x11BB11BB, x33CC0000); + + vand(x00000F0F, a3, a6); + vxor(x336600FF, x00AA00FF, x33CC0000); + vand(x332200FF, x33BB33FF, x336600FF); + vandn(x332200F0, x332200FF, x00000F0F); + + vand(x0302000F, a3, x332200FF); + vnot(xAAAAAAAA, a1); + vxor(xA9A8AAA5, x0302000F, xAAAAAAAA); + vxor(x33CCCC33, a6, x33CC33CC); + vandn(x33CCC030, x33CCCC33, x00000F0F); + vxor(x9A646A95, xA9A8AAA5, x33CCC030); + vandn(x10, a4, x332200F0); + vxor(x11, x10, x9A646A95); + vxor(*out2, *out2, x11); + + vandn(x00333303, a2, x33CCC030); + vxor(x118822B8, x11BB11BB, x00333303); + vandn(xA8208805, xA9A8AAA5, x118822B8); + vxor(x3CC3C33C, a3, x33CCCC33); + vxor(x94E34B39, xA8208805, x3CC3C33C); + vandn(x00, x33BB33FF, a4); + vxor(x01, x00, x94E34B39); + vxor(*out1, *out1, x01); + + vandn(x03303003, a2, x3CC3C33C); + vxor(xA9DF596A, x33BB33FF, x9A646A95); + vxor(xAAEF6969, x03303003, xA9DF596A); + vor(xAAEF6F6F, x00000F0F, xAAEF6969); + vxor(x962CAC53, x3CC3C33C, xAAEF6F6F); + + vandn(x0903030C, a3, x962CAC53); + vxor(x093012B7, x003311BB, x0903030C); + vor(x19B832BF, x118822B8, x093012B7); + vxor(x03FD00F0, a5, x0302000F); + vxor(x1A45324F, x19B832BF, x03FD00F0); + vor(x20, x1A45324F, a4); + vxor(x21, x20, x962CAC53); + vxor(*out3, *out3, x21); + + vandn(x0A451047, x1A45324F, x118822B8); + vor(xBBDFDD7B, x33CCCC33, xA9DF596A); + vxor(xB19ACD3C, x0A451047, xBBDFDD7B); + vor(x30, x003311BB, a4); + vxor(x31, x30, xB19ACD3C); + vxor(*out4, *out4, x31); +} +#endif + +#if andn && !triop && regs < 16 +/* s3-000406, 46 gates, 15 regs, 12 andn, 3/7/19/50/89 stalls, 70 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204000D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype x3F3F3F3F, x40C040C0, x69963C69, x9669C396, xD6A98356; + vtype x7A855A0A, xFEEDDB9E, xB108856A, x8D6112FC, xB25E2DC3; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vandn(x204000D0, x284100D8, a3); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204000D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vor(x3F3F3F3F, a2, a3); + vandn(x40C040C0, x4FE55EF4, x3F3F3F3F); + vxor(x69963C69, x3C3CC3C3, x55AAFFAA); + vnot(x9669C396, x69963C69); + vxor(xD6A98356, x40C040C0, x9669C396); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vxor(x7A855A0A, a1, x2FD00F5F); + vor(xFEEDDB9E, x9669C396, x7A855A0A); + vxor(xB108856A, x4FE55EF4, xFEEDDB9E); + vxor(x8D6112FC, x3C699796, xB108856A); + vxor(xB25E2DC3, x3F3F3F3F, x8D6112FC); + vor(x20, x284100D8, a5); + vxor(x21, x20, xB25E2DC3); + vxor(*out3, *out3, x21); +} +#elif andn && !triop && regs >= 16 +/* s3-000426, 46 gates, 16 regs, 14 andn, 2/5/12/35/75 stalls, 68 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204000D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype x4CC44CC4, x40C040C0, x69963C69, x9669C396, xD6A98356; + vtype x000F00F0, xFEBDC3D7, xFEB0C307, x4CEEEEC4, xB25E2DC3; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vandn(x204000D0, x284100D8, a3); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204000D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vandn(x4CC44CC4, x4FE55EF4, a2); + vandn(x40C040C0, x4CC44CC4, a3); + vxor(x69963C69, x3C3CC3C3, x55AAFFAA); + vnot(x9669C396, x69963C69); + vxor(xD6A98356, x40C040C0, x9669C396); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vand(x000F00F0, a4, x0F0FF0F0); + vor(xFEBDC3D7, x3C3CC3C3, xD6A98356); + vandn(xFEB0C307, xFEBDC3D7, x000F00F0); + vor(x4CEEEEC4, x00AAAA00, x4CC44CC4); + vxor(xB25E2DC3, xFEB0C307, x4CEEEEC4); + vor(x20, x284100D8, a5); + vxor(x21, x20, xB25E2DC3); + vxor(*out3, *out3, x21); +} +#elif andn && triop && !(regs >= 17 && latency == 3) +/* s3-000470, 46 gates, 15 regs, 15 andn, 2/5/10/30/69 stalls, 69 biop */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204000D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype x4CC44CC4, x40C040C0, xC3C33C3C, x9669C396, xD6A98356; + vtype xD6E9C3D6, x4CEEEEC4, x9A072D12, x001A000B, x9A1F2D1B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vandn(x204000D0, x284100D8, a3); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204000D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vandn(x4CC44CC4, x4FE55EF4, a2); + vandn(x40C040C0, x4CC44CC4, a3); + vnot(xC3C33C3C, x3C3CC3C3); + vxor(x9669C396, x55AAFFAA, xC3C33C3C); + vxor(xD6A98356, x40C040C0, x9669C396); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vor(xD6E9C3D6, x40C040C0, x9669C396); + vor(x4CEEEEC4, x00AAAA00, x4CC44CC4); + vxor(x9A072D12, xD6E9C3D6, x4CEEEEC4); + vandn(x001A000B, a4, x4FE55EF4); + vor(x9A1F2D1B, x9A072D12, x001A000B); + vandn(x20, a5, x284100D8); + vxor(x21, x20, x9A1F2D1B); + vxor(*out3, *out3, x21); +} +#elif !andn && triop && regs >= 17 && latency >= 4 +/* s3-001117, 46 gates, 17 regs, 10 andn, 2/4/19/47/92 stalls, 69 biop */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204100D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype x3F3F3F3F, xB01AA10B, xBF3FBF3F, x83037CFC, xD6A98356; + vtype x001A000B, x3C73979D, xBF73FFFD, x0D2DD23E, xB25E2DC3; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vand(x204100D0, x7373F4F4, x284100D8); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204100D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vor(x3F3F3F3F, a2, a3); + vnot(xB01AA10B, x4FE55EF4); + vor(xBF3FBF3F, x3F3F3F3F, xB01AA10B); + vxor(x83037CFC, x3C3CC3C3, xBF3FBF3F); + vxor(xD6A98356, x55AAFFAA, x83037CFC); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vand(x001A000B, a4, xB01AA10B); + vxor(x3C73979D, x3C699796, x001A000B); + vor(xBF73FFFD, x83037CFC, x3C73979D); + vxor(x0D2DD23E, x44444444, x4969967A); + vxor(xB25E2DC3, xBF73FFFD, x0D2DD23E); + vor(x20, x284100D8, a5); + vxor(x21, x20, xB25E2DC3); + vxor(*out3, *out3, x21); +} +#elif triop && regs >= 17 && latency <= 3 +/* s3-001172, 46 gates, 17 regs, 10 andn, 2/3/19/55/98 stalls, 69 biop */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204100D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype xB01AA10B, xB33BB33B, xBF3FBF3F, x83037CFC, xD6A98356; + vtype x001A000B, x3C73979D, xBF73FFFD, x0D2DD23E, xB25E2DC3; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vand(x204100D0, x7373F4F4, x284100D8); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204100D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vnot(xB01AA10B, x4FE55EF4); + vor(xB33BB33B, a2, xB01AA10B); + vor(xBF3FBF3F, a3, xB33BB33B); + vxor(x83037CFC, x3C3CC3C3, xBF3FBF3F); + vxor(xD6A98356, x55AAFFAA, x83037CFC); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vand(x001A000B, a4, xB01AA10B); + vxor(x3C73979D, x3C699796, x001A000B); + vor(xBF73FFFD, x83037CFC, x3C73979D); + vxor(x0D2DD23E, x44444444, x4969967A); + vxor(xB25E2DC3, xBF73FFFD, x0D2DD23E); + vor(x20, x284100D8, a5); + vxor(x21, x20, xB25E2DC3); + vxor(*out3, *out3, x21); +} +#else +/* s3-001283, 46 gates, 16 regs, 14 andn, 2/5/10/30/69 stalls, 69 biop */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44444444, x0F0FF0F0, x4F4FF4F4, x00FFFF00, x00AAAA00, x4FE55EF4; + vtype x3C3CC3C3, x3C3C0000, x7373F4F4, x0C840A00; + vtype x00005EF4, x00FF5EFF, x00555455, x3C699796; + vtype x000FF000, x55AA55AA, x26D9A15E, x2FDFAF5F, x2FD00F5F; + vtype x55AAFFAA, x28410014, x000000FF, x000000CC, x284100D8; + vtype x204100D0, x3C3CC3FF, x1C3CC32F, x4969967A; + vtype x4CC44CC4, x40C040C0, xC3C33C3C, x9669C396, xD6A98356; + vtype xD6E9C3D6, x4CEEEEC4, x9A072D12, x001A000B, x9A1F2D1B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x44444444, a1, a2); + vxor(x0F0FF0F0, a3, a6); + vor(x4F4FF4F4, x44444444, x0F0FF0F0); + vxor(x00FFFF00, a4, a6); + vandn(x00AAAA00, x00FFFF00, a1); + vxor(x4FE55EF4, x4F4FF4F4, x00AAAA00); + + vxor(x3C3CC3C3, a2, x0F0FF0F0); + vandn(x3C3C0000, x3C3CC3C3, a6); + vxor(x7373F4F4, x4F4FF4F4, x3C3C0000); + vandn(x0C840A00, x4FE55EF4, x7373F4F4); + + vand(x00005EF4, a6, x4FE55EF4); + vor(x00FF5EFF, a4, x00005EF4); + vand(x00555455, a1, x00FF5EFF); + vxor(x3C699796, x3C3CC3C3, x00555455); + vandn(x30, x4FE55EF4, a5); + vxor(x31, x30, x3C699796); + vxor(*out4, *out4, x31); + + vand(x000FF000, x0F0FF0F0, x00FFFF00); + vxor(x55AA55AA, a1, a4); + vxor(x26D9A15E, x7373F4F4, x55AA55AA); + vor(x2FDFAF5F, a3, x26D9A15E); + vandn(x2FD00F5F, x2FDFAF5F, x000FF000); + + vor(x55AAFFAA, x00AAAA00, x55AA55AA); + vandn(x28410014, x3C699796, x55AAFFAA); + vand(x000000FF, a4, a6); + vandn(x000000CC, x000000FF, a2); + vxor(x284100D8, x28410014, x000000CC); + + vand(x204100D0, x7373F4F4, x284100D8); + vor(x3C3CC3FF, x3C3CC3C3, x000000FF); + vandn(x1C3CC32F, x3C3CC3FF, x204100D0); + vxor(x4969967A, a1, x1C3CC32F); + vand(x10, x2FD00F5F, a5); + vxor(x11, x10, x4969967A); + vxor(*out2, *out2, x11); + + vandn(x4CC44CC4, x4FE55EF4, a2); + vandn(x40C040C0, x4CC44CC4, a3); + vnot(xC3C33C3C, x3C3CC3C3); + vxor(x9669C396, x55AAFFAA, xC3C33C3C); + vxor(xD6A98356, x40C040C0, x9669C396); + vandn(x00, a5, x0C840A00); + vxor(x01, x00, xD6A98356); + vxor(*out1, *out1, x01); + + vor(xD6E9C3D6, x40C040C0, x9669C396); + vor(x4CEEEEC4, x00AAAA00, x4CC44CC4); + vxor(x9A072D12, xD6E9C3D6, x4CEEEEC4); + vandn(x001A000B, a4, x4FE55EF4); + vor(x9A1F2D1B, x9A072D12, x001A000B); + vandn(x20, a5, x284100D8); + vxor(x21, x20, x9A1F2D1B); + vxor(*out3, *out3, x21); +} +#endif + +/* s4, 33 gates, 11/12 regs, 9 andn, 2/21/53/86/119 stalls, 52 biop */ +MAYBE_INLINE static void +s4(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x5A5A5A5A, x0F0FF0F0; + vtype x33FF33FF, x33FFCC00, x0C0030F0, x0C0CC0C0, x0CF3C03F, x5EFBDA7F, + x52FBCA0F, x61C8F93C; + vtype x00C0C03C, x0F0F30C0, x3B92A366, x30908326, x3C90B3D6; + vtype x33CC33CC, x0C0CFFFF, x379E5C99, x04124C11, x56E9861E, xA91679E1; + vtype x9586CA37, x8402C833, x84C2C83F, xB35C94A6; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x5A5A5A5A, a1, a3); + vxor(x0F0FF0F0, a3, a5); + vor(x33FF33FF, a2, a4); + vxor(x33FFCC00, a5, x33FF33FF); + vandn(x0C0030F0, x0F0FF0F0, x33FFCC00); + vandn(x0C0CC0C0, x0F0FF0F0, a2); + vxor(x0CF3C03F, a4, x0C0CC0C0); + vor(x5EFBDA7F, x5A5A5A5A, x0CF3C03F); + vandn(x52FBCA0F, x5EFBDA7F, x0C0030F0); + vxor(x61C8F93C, a2, x52FBCA0F); + + vand(x00C0C03C, x0CF3C03F, x61C8F93C); + vandn(x0F0F30C0, x0F0FF0F0, x00C0C03C); + vxor(x3B92A366, x5A5A5A5A, x61C8F93C); + vandn(x30908326, x3B92A366, x0F0F30C0); + vxor(x3C90B3D6, x0C0030F0, x30908326); + + vxor(x33CC33CC, a2, a4); + vor(x0C0CFFFF, a5, x0C0CC0C0); + vxor(x379E5C99, x3B92A366, x0C0CFFFF); + vandn(x04124C11, x379E5C99, x33CC33CC); + vxor(x56E9861E, x52FBCA0F, x04124C11); + vandn(x00, a6, x3C90B3D6); + vxor(x01, x00, x56E9861E); + vxor(*out1, *out1, x01); + + vnot(xA91679E1, x56E9861E); + vandn(x10, x3C90B3D6, a6); + vxor(x11, x10, xA91679E1); + vxor(*out2, *out2, x11); + + vxor(x9586CA37, x3C90B3D6, xA91679E1); + vandn(x8402C833, x9586CA37, x33CC33CC); + vor(x84C2C83F, x00C0C03C, x8402C833); + vxor(xB35C94A6, x379E5C99, x84C2C83F); + vor(x20, x61C8F93C, a6); + vxor(x21, x20, xB35C94A6); + vxor(*out3, *out3, x21); + + vand(x30, a6, x61C8F93C); + vxor(x31, x30, xB35C94A6); + vxor(*out4, *out4, x31); +} + +#if triop && latency >= 3 && latency <= 5 +/* s5-02432, 48 gates, 15/16 regs, 9 andn, 6/22/61/109/160 stalls, 72 biop */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x77777777, x77770000, x22225555, x11116666, x1F1F6F6F; + vtype x70700000, x43433333, x00430033, x55557777, x55167744, x5A19784B; + vtype x5A1987B4, x7A3BD7F5, x003B00F5, x221955A0, x05050707, x271C52A7; + vtype x2A2A82A0, x6969B193, x1FE06F90, x16804E00, xE97FB1FF; + vtype x43403302, x35CAED30, x37DEFFB7, x349ECCB5, x0B01234A; + vtype x101884B4, x0FF8EB24, x41413113, x4FF9FB37, x4FC2FBC2; + vtype x43E9BBC2, x16BCEE97, x0F080B04, x19B4E593; + vtype x5C5C5C5C, x4448184C, x2DDABE71, x6992A63D; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vor(x77777777, a1, a3); + vandn(x77770000, x77777777, a6); + vxor(x22225555, a1, x77770000); + vxor(x11116666, a3, x22225555); + vor(x1F1F6F6F, a4, x11116666); + + vandn(x70700000, x77770000, a4); + vxor(x43433333, a3, x70700000); + vand(x00430033, a5, x43433333); + vor(x55557777, a1, x11116666); + vxor(x55167744, x00430033, x55557777); + vxor(x5A19784B, a4, x55167744); + + vxor(x5A1987B4, a6, x5A19784B); + vor(x7A3BD7F5, x22225555, x5A1987B4); + vand(x003B00F5, a5, x7A3BD7F5); + vxor(x221955A0, x22225555, x003B00F5); + vand(x05050707, a4, x55557777); + vxor(x271C52A7, x221955A0, x05050707); + + vandn(x2A2A82A0, x7A3BD7F5, a1); + vxor(x6969B193, x43433333, x2A2A82A0); + vxor(x1FE06F90, a5, x1F1F6F6F); + vandn(x16804E00, x1FE06F90, x6969B193); + vnot(xE97FB1FF, x16804E00); + vandn(x20, xE97FB1FF, a2); + vxor(x21, x20, x5A19784B); + vxor(*out3, *out3, x21); + + vandn(x43403302, x43433333, x003B00F5); + vxor(x35CAED30, x2A2A82A0, x1FE06F90); + vor(x37DEFFB7, x271C52A7, x35CAED30); + vandn(x349ECCB5, x37DEFFB7, x43403302); + vandn(x0B01234A, x1F1F6F6F, x349ECCB5); + + vand(x101884B4, x5A1987B4, x349ECCB5); + vxor(x0FF8EB24, x1FE06F90, x101884B4); + vand(x41413113, x43433333, x6969B193); + vor(x4FF9FB37, x0FF8EB24, x41413113); + vxor(x4FC2FBC2, x003B00F5, x4FF9FB37); + vand(x30, x4FC2FBC2, a2); + vxor(x31, x30, x271C52A7); + vxor(*out4, *out4, x31); + + vxor(x43E9BBC2, x77777777, x349ECCB5); + vxor(x16BCEE97, a1, x43E9BBC2); + vand(x0F080B04, a4, x0FF8EB24); + vxor(x19B4E593, x16BCEE97, x0F080B04); + vor(x00, x0B01234A, a2); + vxor(x01, x00, x19B4E593); + vxor(*out1, *out1, x01); + + vxor(x5C5C5C5C, x1F1F6F6F, x43433333); + vandn(x4448184C, x5C5C5C5C, x19B4E593); + vxor(x2DDABE71, x22225555, x0FF8EB24); + vxor(x6992A63D, x4448184C, x2DDABE71); + vand(x10, x1F1F6F6F, a2); + vxor(x11, x10, x6992A63D); + vxor(*out2, *out2, x11); +} +#elif (!triop && regs >= 16) || (triop && latency <= 2) +/* s5-04829, 48 gates, 15/16 regs, 9 andn, 4/24/65/113/163 stalls, 72 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x77777777, x77770000, x22225555, x11116666, x1F1F6F6F; + vtype x70700000, x43433333, x00430033, x55557777, x55167744, x5A19784B; + vtype x5A1987B4, x7A3BD7F5, x003B00F5, x221955A0, x05050707, x271C52A7; + vtype x2A2A82A0, x6969B193, x1FE06F90, x16804E00, xE97FB1FF; + vtype x43403302, x35CAED30, x37DEFFB7, x349ECCB5, x0B01234A; + vtype x101884B4, x0FF8EB24, x41413333, x4FF9FB37, x4FC2FBC2; + vtype x22222222, x16BCEE97, x0F080B04, x19B4E593; + vtype x5C5C5C5C, x4448184C, x2DDABE71, x6992A63D; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vor(x77777777, a1, a3); + vandn(x77770000, x77777777, a6); + vxor(x22225555, a1, x77770000); + vxor(x11116666, a3, x22225555); + vor(x1F1F6F6F, a4, x11116666); + + vandn(x70700000, x77770000, a4); + vxor(x43433333, a3, x70700000); + vand(x00430033, a5, x43433333); + vor(x55557777, a1, x11116666); + vxor(x55167744, x00430033, x55557777); + vxor(x5A19784B, a4, x55167744); + + vxor(x5A1987B4, a6, x5A19784B); + vor(x7A3BD7F5, x22225555, x5A1987B4); + vand(x003B00F5, a5, x7A3BD7F5); + vxor(x221955A0, x22225555, x003B00F5); + vand(x05050707, a4, x55557777); + vxor(x271C52A7, x221955A0, x05050707); + + vandn(x2A2A82A0, x7A3BD7F5, a1); + vxor(x6969B193, x43433333, x2A2A82A0); + vxor(x1FE06F90, a5, x1F1F6F6F); + vandn(x16804E00, x1FE06F90, x6969B193); + vnot(xE97FB1FF, x16804E00); + vandn(x20, xE97FB1FF, a2); + vxor(x21, x20, x5A19784B); + vxor(*out3, *out3, x21); + + vandn(x43403302, x43433333, x003B00F5); + vxor(x35CAED30, x2A2A82A0, x1FE06F90); + vor(x37DEFFB7, x271C52A7, x35CAED30); + vandn(x349ECCB5, x37DEFFB7, x43403302); + vandn(x0B01234A, x1F1F6F6F, x349ECCB5); + + vand(x101884B4, x5A1987B4, x349ECCB5); + vxor(x0FF8EB24, x1FE06F90, x101884B4); + vand(x41413333, x43433333, x55557777); + vor(x4FF9FB37, x0FF8EB24, x41413333); + vxor(x4FC2FBC2, x003B00F5, x4FF9FB37); + vand(x30, x4FC2FBC2, a2); + vxor(x31, x30, x271C52A7); + vxor(*out4, *out4, x31); + + vxor(x22222222, a1, x77777777); + vxor(x16BCEE97, x349ECCB5, x22222222); + vand(x0F080B04, a4, x0FF8EB24); + vxor(x19B4E593, x16BCEE97, x0F080B04); + vor(x00, x0B01234A, a2); + vxor(x01, x00, x19B4E593); + vxor(*out1, *out1, x01); + + vxor(x5C5C5C5C, x1F1F6F6F, x43433333); + vandn(x4448184C, x5C5C5C5C, x19B4E593); + vxor(x2DDABE71, x22225555, x0FF8EB24); + vxor(x6992A63D, x4448184C, x2DDABE71); + vand(x10, x1F1F6F6F, a2); + vxor(x11, x10, x6992A63D); + vxor(*out2, *out2, x11); +} +#else +/* s5-04832, 48 gates, 15/16 regs, 9 andn, 5/23/62/109/159 stalls, 72 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x77777777, x77770000, x22225555, x11116666, x1F1F6F6F; + vtype x70700000, x43433333, x00430033, x55557777, x55167744, x5A19784B; + vtype x5A1987B4, x7A3BD7F5, x003B00F5, x221955A0, x05050707, x271C52A7; + vtype x2A2A82A0, x6969B193, x1FE06F90, x16804E00, xE97FB1FF; + vtype x43403302, x35CAED30, x37DEFFB7, x349ECCB5, x0B01234A; + vtype x101884B4, x0FF8EB24, x41413333, x4FF9FB37, x4FC2FBC2; + vtype x43E9BBC2, x16BCEE97, x0F080B04, x19B4E593; + vtype x5C5C5C5C, x4448184C, x2DDABE71, x6992A63D; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vor(x77777777, a1, a3); + vandn(x77770000, x77777777, a6); + vxor(x22225555, a1, x77770000); + vxor(x11116666, a3, x22225555); + vor(x1F1F6F6F, a4, x11116666); + + vandn(x70700000, x77770000, a4); + vxor(x43433333, a3, x70700000); + vand(x00430033, a5, x43433333); + vor(x55557777, a1, x11116666); + vxor(x55167744, x00430033, x55557777); + vxor(x5A19784B, a4, x55167744); + + vxor(x5A1987B4, a6, x5A19784B); + vor(x7A3BD7F5, x22225555, x5A1987B4); + vand(x003B00F5, a5, x7A3BD7F5); + vxor(x221955A0, x22225555, x003B00F5); + vand(x05050707, a4, x55557777); + vxor(x271C52A7, x221955A0, x05050707); + + vandn(x2A2A82A0, x7A3BD7F5, a1); + vxor(x6969B193, x43433333, x2A2A82A0); + vxor(x1FE06F90, a5, x1F1F6F6F); + vandn(x16804E00, x1FE06F90, x6969B193); + vnot(xE97FB1FF, x16804E00); + vandn(x20, xE97FB1FF, a2); + vxor(x21, x20, x5A19784B); + vxor(*out3, *out3, x21); + + vandn(x43403302, x43433333, x003B00F5); + vxor(x35CAED30, x2A2A82A0, x1FE06F90); + vor(x37DEFFB7, x271C52A7, x35CAED30); + vandn(x349ECCB5, x37DEFFB7, x43403302); + vandn(x0B01234A, x1F1F6F6F, x349ECCB5); + + vand(x101884B4, x5A1987B4, x349ECCB5); + vxor(x0FF8EB24, x1FE06F90, x101884B4); + vand(x41413333, x43433333, x55557777); + vor(x4FF9FB37, x0FF8EB24, x41413333); + vxor(x4FC2FBC2, x003B00F5, x4FF9FB37); + vand(x30, x4FC2FBC2, a2); + vxor(x31, x30, x271C52A7); + vxor(*out4, *out4, x31); + + vxor(x43E9BBC2, x77777777, x349ECCB5); + vxor(x16BCEE97, a1, x43E9BBC2); + vand(x0F080B04, a4, x0FF8EB24); + vxor(x19B4E593, x16BCEE97, x0F080B04); + vor(x00, x0B01234A, a2); + vxor(x01, x00, x19B4E593); + vxor(*out1, *out1, x01); + + vxor(x5C5C5C5C, x1F1F6F6F, x43433333); + vandn(x4448184C, x5C5C5C5C, x19B4E593); + vxor(x2DDABE71, x22225555, x0FF8EB24); + vxor(x6992A63D, x4448184C, x2DDABE71); + vand(x10, x1F1F6F6F, a2); + vxor(x11, x10, x6992A63D); + vxor(*out2, *out2, x11); +} +#endif + +#if !triop && regs >= 16 +/* s6-000007, 46 gates, 19 regs, 8 andn, 3/19/39/66/101 stalls, 69 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x3333FFFF, x11115555, x22DD6699, x22DD9966, x00220099; + vtype x00551144, x33662277, x5A5A5A5A, x7B7E7A7F, x59A31CE6; + vtype x09030C06, x09030000, x336622FF, x3A6522FF; + vtype x484D494C, x0000B6B3, x0F0FB9BC, x00FC00F9, x0FFFB9FD; + vtype x5DF75DF7, x116600F7, x1E69B94B, x1668B94B; + vtype x7B7B7B7B, x411E5984, x1FFFFDFD, x5EE1A479; + vtype x3CB4DFD2, x004B002D, xB7B2B6B3, xCCC9CDC8, xCC82CDE5; + vtype x0055EEBB, x5A5AECE9, x0050ECA9, xC5CAC1CE, xC59A2D67; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vor(x3333FFFF, a2, a6); + vand(x11115555, a1, x3333FFFF); + vxor(x22DD6699, x33CC33CC, x11115555); + vxor(x22DD9966, a6, x22DD6699); + vandn(x00220099, a5, x22DD9966); + + vand(x00551144, a1, x22DD9966); + vxor(x33662277, a2, x00551144); + vxor(x5A5A5A5A, a1, a3); + vor(x7B7E7A7F, x33662277, x5A5A5A5A); + vxor(x59A31CE6, x22DD6699, x7B7E7A7F); + + vand(x09030C06, a3, x59A31CE6); + vandn(x09030000, x09030C06, a6); + vor(x336622FF, x00220099, x33662277); + vxor(x3A6522FF, x09030000, x336622FF); + vand(x30, x3A6522FF, a4); + vxor(x31, x30, x59A31CE6); + vxor(*out4, *out4, x31); + + vxor(x484D494C, a2, x7B7E7A7F); + vandn(x0000B6B3, a6, x484D494C); + vxor(x0F0FB9BC, a3, x0000B6B3); + vandn(x00FC00F9, a5, x09030C06); + vor(x0FFFB9FD, x0F0FB9BC, x00FC00F9); + + vor(x5DF75DF7, a1, x59A31CE6); + vand(x116600F7, x336622FF, x5DF75DF7); + vxor(x1E69B94B, x0F0FB9BC, x116600F7); + vandn(x1668B94B, x1E69B94B, x09030000); + vor(x20, x00220099, a4); + vxor(x21, x20, x1668B94B); + vxor(*out3, *out3, x21); + + vor(x7B7B7B7B, a2, x5A5A5A5A); + vxor(x411E5984, x3A6522FF, x7B7B7B7B); + vor(x1FFFFDFD, x11115555, x0FFFB9FD); + vxor(x5EE1A479, x411E5984, x1FFFFDFD); + + vxor(x3CB4DFD2, x22DD6699, x1E69B94B); + vandn(x004B002D, a5, x3CB4DFD2); + vnot(xB7B2B6B3, x484D494C); + vxor(xCCC9CDC8, x7B7B7B7B, xB7B2B6B3); + vxor(xCC82CDE5, x004B002D, xCCC9CDC8); + vandn(x10, xCC82CDE5, a4); + vxor(x11, x10, x5EE1A479); + vxor(*out2, *out2, x11); + + vxor(x0055EEBB, a6, x00551144); + vxor(x5A5AECE9, a1, x0F0FB9BC); + vand(x0050ECA9, x0055EEBB, x5A5AECE9); + vxor(xC5CAC1CE, x09030C06, xCCC9CDC8); + vxor(xC59A2D67, x0050ECA9, xC5CAC1CE); + vandn(x00, x0FFFB9FD, a4); + vxor(x01, x00, xC59A2D67); + vxor(*out1, *out1, x01); +} +#elif !triop && regs < 16 +/* s6-000009, 46 gates, 19 regs, 8 andn, 3/20/41/69/110 stalls, 69 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x3333FFFF, x11115555, x22DD6699, x22DD9966, x00220099; + vtype x00551144, x33662277, x5A5A5A5A, x7B7E7A7F, x59A31CE6; + vtype x09030C06, x09030000, x336622FF, x3A6522FF; + vtype x484D494C, x0000B6B3, x0F0FB9BC, x00FC00F9, x0FFFB9FD; + vtype x5DF75DF7, x116600F7, x1E69B94B, x1668B94B; + vtype x1FFFFDFD, x7B7B7B7B, x64848686, x5EE1A479; + vtype x3CB4DFD2, x004B002D, x33363237, xCCC9CDC8, xCC82CDE5; + vtype x0055EEBB, x5A5AECE9, x0050ECA9, x0953E0AF, xC59A2D67; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vor(x3333FFFF, a2, a6); + vand(x11115555, a1, x3333FFFF); + vxor(x22DD6699, x33CC33CC, x11115555); + vxor(x22DD9966, a6, x22DD6699); + vandn(x00220099, a5, x22DD9966); + + vand(x00551144, a1, x22DD9966); + vxor(x33662277, a2, x00551144); + vxor(x5A5A5A5A, a1, a3); + vor(x7B7E7A7F, x33662277, x5A5A5A5A); + vxor(x59A31CE6, x22DD6699, x7B7E7A7F); + + vand(x09030C06, a3, x59A31CE6); + vandn(x09030000, x09030C06, a6); + vor(x336622FF, x00220099, x33662277); + vxor(x3A6522FF, x09030000, x336622FF); + vand(x30, x3A6522FF, a4); + vxor(x31, x30, x59A31CE6); + vxor(*out4, *out4, x31); + + vxor(x484D494C, a2, x7B7E7A7F); + vandn(x0000B6B3, a6, x484D494C); + vxor(x0F0FB9BC, a3, x0000B6B3); + vandn(x00FC00F9, a5, x09030C06); + vor(x0FFFB9FD, x0F0FB9BC, x00FC00F9); + + vor(x5DF75DF7, a1, x59A31CE6); + vand(x116600F7, x336622FF, x5DF75DF7); + vxor(x1E69B94B, x0F0FB9BC, x116600F7); + vandn(x1668B94B, x1E69B94B, x09030000); + vor(x20, x00220099, a4); + vxor(x21, x20, x1668B94B); + vxor(*out3, *out3, x21); + + vor(x1FFFFDFD, x11115555, x0FFFB9FD); + vor(x7B7B7B7B, a2, x5A5A5A5A); + vxor(x64848686, x1FFFFDFD, x7B7B7B7B); + vxor(x5EE1A479, x3A6522FF, x64848686); + + vxor(x3CB4DFD2, x22DD6699, x1E69B94B); + vandn(x004B002D, a5, x3CB4DFD2); + vxor(x33363237, x484D494C, x7B7B7B7B); + vnot(xCCC9CDC8, x33363237); + vxor(xCC82CDE5, x004B002D, xCCC9CDC8); + vandn(x10, xCC82CDE5, a4); + vxor(x11, x10, x5EE1A479); + vxor(*out2, *out2, x11); + + vxor(x0055EEBB, a6, x00551144); + vxor(x5A5AECE9, a1, x0F0FB9BC); + vand(x0050ECA9, x0055EEBB, x5A5AECE9); + vxor(x0953E0AF, x09030C06, x0050ECA9); + vxor(xC59A2D67, xCCC9CDC8, x0953E0AF); + vandn(x00, x0FFFB9FD, a4); + vxor(x01, x00, xC59A2D67); + vxor(*out1, *out1, x01); +} +#elif latency >= 3 +/* s6-000028, 46 gates, 19 regs, 8 andn, 4/16/39/65/101 stalls, 69 biop */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x3333FFFF, x11115555, x22DD6699, x22DD9966, x00220099; + vtype x00551144, x33662277, x5A5A5A5A, x7B7E7A7F, x59A31CE6; + vtype x09030C06, x09030000, x336622FF, x3A6522FF; + vtype x484D494C, x0000B6B3, x0F0FB9BC, x00FC00F9, x0FFFB9FD; + vtype x7B7B7B7B, x411E5984, x1FFFFDFD, x5EE1A479; + vtype x5DF75DF7, x116600F7, x1E69B94B, x1668B94B; + vtype x3CB4DFD2, x004B002D, x33363237, xCCC9CDC8, xCC82CDE5; + vtype x0055EEBB, x5A5AECE9, x0050ECA9, xC5CAC1CE, xC59A2D67; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vor(x3333FFFF, a2, a6); + vand(x11115555, a1, x3333FFFF); + vxor(x22DD6699, x33CC33CC, x11115555); + vxor(x22DD9966, a6, x22DD6699); + vandn(x00220099, a5, x22DD9966); + + vand(x00551144, a1, x22DD9966); + vxor(x33662277, a2, x00551144); + vxor(x5A5A5A5A, a1, a3); + vor(x7B7E7A7F, x33662277, x5A5A5A5A); + vxor(x59A31CE6, x22DD6699, x7B7E7A7F); + + vand(x09030C06, a3, x59A31CE6); + vandn(x09030000, x09030C06, a6); + vor(x336622FF, x00220099, x33662277); + vxor(x3A6522FF, x09030000, x336622FF); + vand(x30, x3A6522FF, a4); + vxor(x31, x30, x59A31CE6); + vxor(*out4, *out4, x31); + + vxor(x484D494C, a2, x7B7E7A7F); + vandn(x0000B6B3, a6, x484D494C); + vxor(x0F0FB9BC, a3, x0000B6B3); + vandn(x00FC00F9, a5, x09030C06); + vor(x0FFFB9FD, x0F0FB9BC, x00FC00F9); + + vor(x7B7B7B7B, a2, x5A5A5A5A); + vxor(x411E5984, x3A6522FF, x7B7B7B7B); + vor(x1FFFFDFD, x11115555, x0FFFB9FD); + vxor(x5EE1A479, x411E5984, x1FFFFDFD); + + vor(x5DF75DF7, a1, x59A31CE6); + vand(x116600F7, x336622FF, x5DF75DF7); + vxor(x1E69B94B, x0F0FB9BC, x116600F7); + vandn(x1668B94B, x1E69B94B, x09030000); + vor(x20, x00220099, a4); + vxor(x21, x20, x1668B94B); + vxor(*out3, *out3, x21); + + vxor(x3CB4DFD2, x22DD6699, x1E69B94B); + vandn(x004B002D, a5, x3CB4DFD2); + vxor(x33363237, x484D494C, x7B7B7B7B); + vnot(xCCC9CDC8, x33363237); + vxor(xCC82CDE5, x004B002D, xCCC9CDC8); + vandn(x10, xCC82CDE5, a4); + vxor(x11, x10, x5EE1A479); + vxor(*out2, *out2, x11); + + vxor(x0055EEBB, a6, x00551144); + vxor(x5A5AECE9, a1, x0F0FB9BC); + vand(x0050ECA9, x0055EEBB, x5A5AECE9); + vxor(xC5CAC1CE, x09030C06, xCCC9CDC8); + vxor(xC59A2D67, x0050ECA9, xC5CAC1CE); + vandn(x00, x0FFFB9FD, a4); + vxor(x01, x00, xC59A2D67); + vxor(*out1, *out1, x01); +} +#else +/* s6-000031, 46 gates, 19 regs, 8 andn, 3/16/42/68/111 stalls, 69 biop */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x33CC33CC; + vtype x3333FFFF, x11115555, x22DD6699, x22DD9966, x00220099; + vtype x00551144, x33662277, x5A5A5A5A, x7B7E7A7F, x59A31CE6; + vtype x09030C06, x09030000, x336622FF, x3A6522FF; + vtype x484D494C, x0000B6B3, x0F0FB9BC, x00FC00F9, x0FFFB9FD; + vtype x7B7B7B7B, x411E5984, x1FFFFDFD, x5EE1A479; + vtype x5DF75DF7, x116600F7, x1E69B94B, x1668B94B; + vtype x3CB4DFD2, x004B002D, x84848484, xCCC9CDC8, xCC82CDE5; + vtype x0055EEBB, x5A5AECE9, x0050ECA9, xC5CAC1CE, xC59A2D67; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x33CC33CC, a2, a5); + + vor(x3333FFFF, a2, a6); + vand(x11115555, a1, x3333FFFF); + vxor(x22DD6699, x33CC33CC, x11115555); + vxor(x22DD9966, a6, x22DD6699); + vandn(x00220099, a5, x22DD9966); + + vand(x00551144, a1, x22DD9966); + vxor(x33662277, a2, x00551144); + vxor(x5A5A5A5A, a1, a3); + vor(x7B7E7A7F, x33662277, x5A5A5A5A); + vxor(x59A31CE6, x22DD6699, x7B7E7A7F); + + vand(x09030C06, a3, x59A31CE6); + vandn(x09030000, x09030C06, a6); + vor(x336622FF, x00220099, x33662277); + vxor(x3A6522FF, x09030000, x336622FF); + vand(x30, x3A6522FF, a4); + vxor(x31, x30, x59A31CE6); + vxor(*out4, *out4, x31); + + vxor(x484D494C, a2, x7B7E7A7F); + vandn(x0000B6B3, a6, x484D494C); + vxor(x0F0FB9BC, a3, x0000B6B3); + vandn(x00FC00F9, a5, x09030C06); + vor(x0FFFB9FD, x0F0FB9BC, x00FC00F9); + + vor(x7B7B7B7B, a2, x5A5A5A5A); + vxor(x411E5984, x3A6522FF, x7B7B7B7B); + vor(x1FFFFDFD, x11115555, x0FFFB9FD); + vxor(x5EE1A479, x411E5984, x1FFFFDFD); + + vor(x5DF75DF7, a1, x59A31CE6); + vand(x116600F7, x336622FF, x5DF75DF7); + vxor(x1E69B94B, x0F0FB9BC, x116600F7); + vandn(x1668B94B, x1E69B94B, x09030000); + vor(x20, x00220099, a4); + vxor(x21, x20, x1668B94B); + vxor(*out3, *out3, x21); + + vxor(x3CB4DFD2, x22DD6699, x1E69B94B); + vandn(x004B002D, a5, x3CB4DFD2); + vnot(x84848484, x7B7B7B7B); + vxor(xCCC9CDC8, x484D494C, x84848484); + vxor(xCC82CDE5, x004B002D, xCCC9CDC8); + vandn(x10, xCC82CDE5, a4); + vxor(x11, x10, x5EE1A479); + vxor(*out2, *out2, x11); + + vxor(x0055EEBB, a6, x00551144); + vxor(x5A5AECE9, a1, x0F0FB9BC); + vand(x0050ECA9, x0055EEBB, x5A5AECE9); + vxor(xC5CAC1CE, x09030C06, xCCC9CDC8); + vxor(xC59A2D67, x0050ECA9, xC5CAC1CE); + vandn(x00, x0FFFB9FD, a4); + vxor(x01, x00, xC59A2D67); + vxor(*out1, *out1, x01); +} +#endif + +#if andn && triop && regs <= 16 && latency >= 5 +/* s7-000072, 46 gates, 16 regs, 10 andn, 2/5/17/51/93 stalls, 69 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x5BD6B55B, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x550A0255, x68E58668, x7DEF867D, x4E39B586; + vtype x50000050, x518C1051, x518C0000, x0B29A55A, x38D696A5; + vtype x63333363, x23132343, x26BC7346, x5B53F53B; + vtype xFFFF0000, xFFFF54A0, xADAF53FA, xA8AA02AA, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x5BD6B55B, x5AA5A55A, x01731001); + vandn(x04294004, x05AF5005, x5BD6B55B); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vand(x550A0255, x55AAAA55, x575F575F); + vxor(x68E58668, a2, x5BD6B55B); + vor(x7DEF867D, x550A0255, x68E58668); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vand(x50000050, x5AA5A55A, x550A0255); + vor(x518C1051, x018C1001, x50000050); + vandn(x518C0000, x518C1051, a5); + vxor(x0B29A55A, x5AA5A55A, x518C0000); + vxor(x38D696A5, x33FF33FF, x0B29A55A); + + vxor(x63333363, a2, x50000050); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vnot(xFFFF0000, a5); + vor(xFFFF54A0, x54A054A0, xFFFF0000); + vxor(xADAF53FA, x5250075A, xFFFF54A0); + vandn(xA8AA02AA, xADAF53FA, a1); + vxor(x8E1671EC, x26BC7346, xA8AA02AA); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs <= 16 && latency == 3 +/* s7-000788, 46 gates, 16 regs, 10 andn, 2/3/18/51/94 stalls, 69 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x5BD6B55B, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x550A0255, x68E58668, x7DEF867D, x4E39B586; + vtype x50000050, x63333363, x23132343, x26BC7346, x5B53F53B; + vtype x518C1051, x518C0000, x0B29A55A, x38D696A5; + vtype x0000AB5F, x5250AC05, x5755FD55, xD9438CB9, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x5BD6B55B, x5AA5A55A, x01731001); + vandn(x04294004, x05AF5005, x5BD6B55B); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vand(x550A0255, x55AAAA55, x575F575F); + vxor(x68E58668, a2, x5BD6B55B); + vor(x7DEF867D, x550A0255, x68E58668); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vand(x50000050, x5AA5A55A, x550A0255); + vxor(x63333363, a2, x50000050); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + + vor(x518C1051, x018C1001, x50000050); + vandn(x518C0000, x518C1051, a5); + vxor(x0B29A55A, x5AA5A55A, x518C0000); + vxor(x38D696A5, x33FF33FF, x0B29A55A); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vandn(x0000AB5F, a5, x54A054A0); + vxor(x5250AC05, x5250075A, x0000AB5F); + vor(x5755FD55, a1, x5250AC05); + vnot(xD9438CB9, x26BC7346); + vxor(x8E1671EC, x5755FD55, xD9438CB9); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs == 18 && latency >= 6 +/* s7-002149, 46 gates, 18 regs, 11 andn, 2/5/20/40/66 stalls, 68 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x69969669, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x68E58668, x550A0255, x7DEF867D, x4E39B586; + vtype x0AA5A50A, x63333363, x23132343, x26BC7346, x5B53F53B; + vtype x018C0000, x63FF33FF, x627333FF, x38D696A5; + vtype x5659A956, x0251A854, x5755FD55, xA8AA02AA, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x69969669, a2, x5AA5A55A); + vandn(x04294004, x05AF5005, x69969669); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vxor(x68E58668, x01731001, x69969669); + vand(x550A0255, x55AAAA55, x575F575F); + vor(x7DEF867D, x68E58668, x550A0255); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vandn(x0AA5A50A, x5AA5A55A, x550A0255); + vxor(x63333363, x69969669, x0AA5A50A); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + + vandn(x018C0000, x018C1001, a5); + vor(x63FF33FF, a4, x63333363); + vxor(x627333FF, x018C0000, x63FF33FF); + vxor(x38D696A5, x5AA5A55A, x627333FF); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vxor(x5659A956, x3FCF3F3F, x69969669); + vandn(x0251A854, x5659A956, x55AA55AA); + vor(x5755FD55, a1, x0251A854); + vnot(xA8AA02AA, x5755FD55); + vxor(x8E1671EC, x26BC7346, xA8AA02AA); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs >= 18 && latency == 5 +/* s7-002689, 46 gates, 18 regs, 10 andn, 2/5/14/31/69 stalls, 69 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x69969669, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x68E58668, x550A0255, x7DEF867D, x4E39B586; + vtype x50000050, x63333363, x23132343, x26BC7346, x5B53F53B; + vtype x518C1051, x518C0000, x0B29A55A, x38D696A5; + vtype xFFFF0000, xA8A0575F, xA8FF57FF, xA8AA02AA, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x69969669, a2, x5AA5A55A); + vandn(x04294004, x05AF5005, x69969669); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vxor(x68E58668, x01731001, x69969669); + vand(x550A0255, x55AAAA55, x575F575F); + vor(x7DEF867D, x68E58668, x550A0255); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vand(x50000050, x5AA5A55A, x550A0255); + vxor(x63333363, a2, x50000050); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + + vor(x518C1051, x018C1001, x50000050); + vandn(x518C0000, x518C1051, a5); + vxor(x0B29A55A, x5AA5A55A, x518C0000); + vxor(x38D696A5, x33FF33FF, x0B29A55A); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vnot(xFFFF0000, a5); + vxor(xA8A0575F, x575F575F, xFFFF0000); + vor(xA8FF57FF, a4, xA8A0575F); + vandn(xA8AA02AA, xA8FF57FF, a1); + vxor(x8E1671EC, x26BC7346, xA8AA02AA); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs >= 19 && latency >= 6 +/* s7-003344, 46 gates, 19 regs, 10 andn, 3/9/14/39/66 stalls, 68 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x69969669, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x68E58668, x550A0255, x7DEF867D, x4E39B586; + vtype x50000050, x63333363, x23132343, x26BC7346, x5B53F53B; + vtype x518C1051, x518C0000, x695A96A5, x38D696A5; + vtype x5659A956, x0251A854, x5755FD55, xA8AA02AA, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x69969669, a2, x5AA5A55A); + vandn(x04294004, x05AF5005, x69969669); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vxor(x68E58668, x01731001, x69969669); + vand(x550A0255, x55AAAA55, x575F575F); + vor(x7DEF867D, x68E58668, x550A0255); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vand(x50000050, x5AA5A55A, x550A0255); + vxor(x63333363, a2, x50000050); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + + vor(x518C1051, x018C1001, x50000050); + vandn(x518C0000, x518C1051, a5); + vxor(x695A96A5, x5AA5A55A, x33FF33FF); + vxor(x38D696A5, x518C0000, x695A96A5); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vxor(x5659A956, x3FCF3F3F, x69969669); + vandn(x0251A854, x5659A956, x55AA55AA); + vor(x5755FD55, a1, x0251A854); + vnot(xA8AA02AA, x5755FD55); + vxor(x8E1671EC, x26BC7346, xA8AA02AA); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs >= 17 && latency >= 4 +/* s7-003395, 46 gates, 17 regs, 11 andn, 3/5/10/39/67 stalls, 70 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x00FF0000, x33CC3333, x3FCF3F3F, x55AA55AA, x55AAAA55, x6A65956A; + vtype x5AA5A55A, x05505005, x05AF5005, x018C1001, x01731001; + vtype x33FF33FF, x030F030F, x575F575F, x5250075A; + vtype x69969669, x04294004, x33D633FB, x54A054A0, x6776675B; + vtype x68E58668, x550A0255, x7DEF867D, x4E39B586; + vtype x50000050, x63333363, x23132343, x26BC7346, x5B53F53B; + vtype x518C1051, x518C0000, x695A96A5, x38D696A5; + vtype x0000AB5F, x5250AC05, xAAAAAAAA, xA8AA02AA, x8E1671EC; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x00FF0000, a4, a5); + vxor(x33CC3333, a2, x00FF0000); + vor(x3FCF3F3F, a3, x33CC3333); + vxor(x55AA55AA, a1, a4); + vxor(x55AAAA55, a5, x55AA55AA); + vxor(x6A65956A, x3FCF3F3F, x55AAAA55); + + vxor(x5AA5A55A, a3, x55AAAA55); + vandn(x05505005, a1, x5AA5A55A); + vxor(x05AF5005, x00FF0000, x05505005); + vand(x018C1001, x33CC3333, x05AF5005); + vxor(x01731001, x00FF0000, x018C1001); + vandn(x30, a6, x01731001); + vxor(x31, x30, x6A65956A); + vxor(*out4, *out4, x31); + + vor(x33FF33FF, a2, a4); + vand(x030F030F, a3, x33FF33FF); + vor(x575F575F, a1, x030F030F); + vandn(x5250075A, x575F575F, x05AF5005); + + vxor(x69969669, a2, x5AA5A55A); + vandn(x04294004, x05AF5005, x69969669); + vandn(x33D633FB, x33FF33FF, x04294004); + vandn(x54A054A0, x55AA55AA, x030F030F); + vxor(x6776675B, x33D633FB, x54A054A0); + + vxor(x68E58668, x01731001, x69969669); + vand(x550A0255, x55AAAA55, x575F575F); + vor(x7DEF867D, x68E58668, x550A0255); + vxor(x4E39B586, x33D633FB, x7DEF867D); + vor(x00, x5250075A, a6); + vxor(x01, x00, x4E39B586); + vxor(*out1, *out1, x01); + + vand(x50000050, x5AA5A55A, x550A0255); + vxor(x63333363, a2, x50000050); + vandn(x23132343, x63333363, x54A054A0); + vxor(x26BC7346, x05AF5005, x23132343); + vxor(x5B53F53B, x7DEF867D, x26BC7346); + + vor(x518C1051, x018C1001, x50000050); + vandn(x518C0000, x518C1051, a5); + vxor(x695A96A5, x5AA5A55A, x33FF33FF); + vxor(x38D696A5, x518C0000, x695A96A5); + vand(x20, x5B53F53B, a6); + vxor(x21, x20, x38D696A5); + vxor(*out3, *out3, x21); + + vandn(x0000AB5F, a5, x54A054A0); + vxor(x5250AC05, x5250075A, x0000AB5F); + vnot(xAAAAAAAA, a1); + vandn(xA8AA02AA, xAAAAAAAA, x5250AC05); + vxor(x8E1671EC, x26BC7346, xA8AA02AA); + vand(x10, x6776675B, a6); + vxor(x11, x10, x8E1671EC); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs >= 17 +/* s7-036457, 46 gates, 17 regs, 9 andn, 1/6/16/50/93 stalls, 71 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x0FC3C3F3, x0000C3F3, x0000DBF3, x4F9493BB; + vtype x96B1A572, xB14E6EBF, x00008AA2, xB14EE41D; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vxor(x0FC3C3F3, x003C003C, x0FFFC3CF); + vand(x0000C3F3, a6, x0FC3C3F3); + vor(x0000DBF3, x00001841, x0000C3F3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vnot(x96B1A572, x694E5A8D); + vxor(xB14E6EBF, x27FFCBCD, x96B1A572); + vandn(x00008AA2, x0000DBF3, a2); + vxor(xB14EE41D, xB14E6EBF, x00008AA2); + vandn(x10, a1, x686B8385); + vxor(x11, x10, xB14EE41D); + vxor(*out2, *out2, x11); +} +#elif !andn && triop && regs >= 17 && latency <= 4 +/* s7-036496, 46 gates, 17 regs, 7 andn, 3/9/20/52/95 stalls, 70 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x0FC3C3F3, x0000C3F3, x0000DBF3, x4F9493BB; + vtype x00005151, x96B1A572, x96B1F423, xD9256798; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vxor(x0FC3C3F3, x003C003C, x0FFFC3CF); + vand(x0000C3F3, a6, x0FC3C3F3); + vor(x0000DBF3, x00001841, x0000C3F3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vand(x00005151, a2, x0000DBF3); + vnot(x96B1A572, x694E5A8D); + vxor(x96B1F423, x00005151, x96B1A572); + vxor(xD9256798, x4F9493BB, x96B1F423); + vor(x10, x686B8385, a1); + vxor(x11, x10, xD9256798); + vxor(*out2, *out2, x11); +} +#elif !andn && triop && regs >= 17 && latency >= 5 +/* s7-036532, 46 gates, 17 regs, 7 andn, 3/9/23/51/93 stalls, 71 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x0FC3C3F3, x0FC3DBF3, x0000DBF3, x4F9493BB; + vtype xFFFF240C, xFFFF755D, x26DA12C5, xD9256798; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vxor(x0FC3C3F3, x003C003C, x0FFFC3CF); + vor(x0FC3DBF3, x00001841, x0FC3C3F3); + vand(x0000DBF3, a6, x0FC3DBF3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vnot(xFFFF240C, x0000DBF3); + vor(xFFFF755D, a2, xFFFF240C); + vxor(x26DA12C5, x694E5A8D, x4F944848); + vxor(xD9256798, xFFFF755D, x26DA12C5); + vor(x10, x686B8385, a1); + vxor(x11, x10, xD9256798); + vxor(*out2, *out2, x11); +} +#elif andn && triop && regs <= 16 +/* s7-036610, 46 gates, 16 regs, 9 andn, 1/6/16/53/98 stalls, 70 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x6FFFDBCF, x6FC3DBF3, x0000DBF3, x4F9493BB; + vtype x96B1A572, xB14E6EBF, x00008AA2, xB14EE41D; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vor(x6FFFDBCF, x694E5A8D, x0FFFC3CF); + vxor(x6FC3DBF3, x003C003C, x6FFFDBCF); + vand(x0000DBF3, a6, x6FC3DBF3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vnot(x96B1A572, x694E5A8D); + vxor(xB14E6EBF, x27FFCBCD, x96B1A572); + vandn(x00008AA2, x0000DBF3, a2); + vxor(xB14EE41D, xB14E6EBF, x00008AA2); + vandn(x10, a1, x686B8385); + vxor(x11, x10, xB14EE41D); + vxor(*out2, *out2, x11); +} +#elif !andn && triop && latency >= 5 +/* s7-036634, 46 gates, 16 regs, 7 andn, 3/9/23/54/98 stalls, 70 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x6FFFDBCF, x6FC3DBF3, x0000DBF3, x4F9493BB; + vtype xFFFF240C, xFFFF755D, x26DA12C5, xD9256798; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vor(x6FFFDBCF, x694E5A8D, x0FFFC3CF); + vxor(x6FC3DBF3, x003C003C, x6FFFDBCF); + vand(x0000DBF3, a6, x6FC3DBF3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vnot(xFFFF240C, x0000DBF3); + vor(xFFFF755D, a2, xFFFF240C); + vxor(x26DA12C5, x694E5A8D, x4F944848); + vxor(xD9256798, xFFFF755D, x26DA12C5); + vor(x10, x686B8385, a1); + vxor(x11, x10, xD9256798); + vxor(*out2, *out2, x11); +} +#elif !andn && triop && latency <= 4 +/* s7-036649, 46 gates, 16 regs, 7 andn, 3/9/20/55/100 stalls, 69 biop */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x0FF0C0CC, x0FFFC3CF, x2E222B22, x28000802, x27FFCBCD; + vtype x48444844, x4FF4C8CC, x6F9C5F5B, x4F944848, x686B8385; + vtype x6FFFDBCF, x6FC3DBF3, x0000DBF3, x4F9493BB; + vtype x00005151, x96B1A572, x96B1F423, xD9256798; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vandn(x0FF0C0CC, x0FF0CCCC, x00000F00); + vor(x0FFFC3CF, x000F0303, x0FF0C0CC); + vxor(x2E222B22, a2, x7B777E77); + vand(x28000802, x699C585B, x2E222B22); + vxor(x27FFCBCD, x0FFFC3CF, x28000802); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vandn(x48444844, x5A555A55, a3); + vor(x4FF4C8CC, x0FF0C0CC, x48444844); + vor(x6F9C5F5B, x0F000F00, x699C585B); + vand(x4F944848, x4FF4C8CC, x6F9C5F5B); + vxor(x686B8385, x27FFCBCD, x4F944848); + + vor(x6FFFDBCF, x694E5A8D, x0FFFC3CF); + vxor(x6FC3DBF3, x003C003C, x6FFFDBCF); + vand(x0000DBF3, a6, x6FC3DBF3); + vxor(x4F9493BB, x4F944848, x0000DBF3); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vand(x00005151, a2, x0000DBF3); + vnot(x96B1A572, x694E5A8D); + vxor(x96B1F423, x00005151, x96B1A572); + vxor(xD9256798, x4F9493BB, x96B1F423); + vor(x10, x686B8385, a1); + vxor(x11, x10, xD9256798); + vxor(*out2, *out2, x11); +} +#elif andn && !triop && regs >= 16 +/* s7-056931, 46 gates, 16 regs, 7 andn, 7/24/55/100/149 stalls, 67 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x7F878F78, x21101013, x7F979F7B, x30030CC0, x4F9493BB; + vtype x6F9CDBFB, x0000DBFB, x00005151, x26DAC936, x26DA9867; + vtype x21FF10FF, x21FFCB04, x2625C9C9, x27FFCBCD; + vtype x27FF1036, x27FF103E, xB06B6C44, x97947C7A; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vor(x7F878F78, x0F000F00, x74878E78); + vand(x21101013, a3, x699C585B); + vor(x7F979F7B, x7F878F78, x21101013); + vandn(x30030CC0, x3CC33CC3, x0FF0F00F); + vxor(x4F9493BB, x7F979F7B, x30030CC0); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vor(x6F9CDBFB, x699C585B, x4F9493BB); + vand(x0000DBFB, a6, x6F9CDBFB); + vand(x00005151, a2, x0000DBFB); + vxor(x26DAC936, x694E5A8D, x4F9493BB); + vxor(x26DA9867, x00005151, x26DAC936); + + vor(x21FF10FF, a5, x21101013); + vxor(x21FFCB04, x0000DBFB, x21FF10FF); + vxor(x2625C9C9, a5, x26DAC936); + vor(x27FFCBCD, x21FFCB04, x2625C9C9); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vxor(x27FF1036, x0000DBFB, x27FFCBCD); + vor(x27FF103E, x003C003C, x27FF1036); + vnot(xB06B6C44, x4F9493BB); + vxor(x97947C7A, x27FF103E, xB06B6C44); + vandn(x10, x97947C7A, a1); + vxor(x11, x10, x26DA9867); + vxor(*out2, *out2, x11); +} +#else +/* s7-056945, 46 gates, 16 regs, 7 andn, 10/31/62/107/156 stalls, 67 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0FF00FF0, x3CC33CC3, x00003CC3, x0F000F00, x5A555A55, x00001841; + vtype x00000F00, x33333C33, x7B777E77, x0FF0F00F, x74878E78; + vtype x003C003C, x5A7D5A7D, x333300F0, x694E5A8D; + vtype x0FF0CCCC, x000F0303, x5A505854, x33CC000F, x699C585B; + vtype x7F878F78, x21101013, x7F979F7B, x30030CC0, x4F9493BB; + vtype x6F9CDBFB, x0000DBFB, x00005151, x26DAC936, x26DA9867; + vtype x27DA9877, x27DA438C, x2625C9C9, x27FFCBCD; + vtype x27FF1036, x27FF103E, xB06B6C44, x97947C7A; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vxor(x0FF00FF0, a4, a5); + vxor(x3CC33CC3, a3, x0FF00FF0); + vand(x00003CC3, a6, x3CC33CC3); + vand(x0F000F00, a4, x0FF00FF0); + vxor(x5A555A55, a2, x0F000F00); + vand(x00001841, x00003CC3, x5A555A55); + + vand(x00000F00, a6, x0F000F00); + vxor(x33333C33, a3, x00000F00); + vor(x7B777E77, x5A555A55, x33333C33); + vxor(x0FF0F00F, a6, x0FF00FF0); + vxor(x74878E78, x7B777E77, x0FF0F00F); + vandn(x30, a1, x00001841); + vxor(x31, x30, x74878E78); + vxor(*out4, *out4, x31); + + vandn(x003C003C, a5, x3CC33CC3); + vor(x5A7D5A7D, x5A555A55, x003C003C); + vxor(x333300F0, x00003CC3, x33333C33); + vxor(x694E5A8D, x5A7D5A7D, x333300F0); + + vxor(x0FF0CCCC, x00003CC3, x0FF0F00F); + vandn(x000F0303, a4, x0FF0CCCC); + vandn(x5A505854, x5A555A55, x000F0303); + vxor(x33CC000F, a5, x333300F0); + vxor(x699C585B, x5A505854, x33CC000F); + + vor(x7F878F78, x0F000F00, x74878E78); + vand(x21101013, a3, x699C585B); + vor(x7F979F7B, x7F878F78, x21101013); + vandn(x30030CC0, x3CC33CC3, x0FF0F00F); + vxor(x4F9493BB, x7F979F7B, x30030CC0); + vandn(x00, x4F9493BB, a1); + vxor(x01, x00, x694E5A8D); + vxor(*out1, *out1, x01); + + vor(x6F9CDBFB, x699C585B, x4F9493BB); + vand(x0000DBFB, a6, x6F9CDBFB); + vand(x00005151, a2, x0000DBFB); + vxor(x26DAC936, x694E5A8D, x4F9493BB); + vxor(x26DA9867, x00005151, x26DAC936); + + vor(x27DA9877, x21101013, x26DA9867); + vxor(x27DA438C, x0000DBFB, x27DA9877); + vxor(x2625C9C9, a5, x26DAC936); + vor(x27FFCBCD, x27DA438C, x2625C9C9); + vand(x20, x27FFCBCD, a1); + vxor(x21, x20, x699C585B); + vxor(*out3, *out3, x21); + + vxor(x27FF1036, x0000DBFB, x27FFCBCD); + vor(x27FF103E, x003C003C, x27FF1036); + vnot(xB06B6C44, x4F9493BB); + vxor(x97947C7A, x27FF103E, xB06B6C44); + vandn(x10, x97947C7A, a1); + vxor(x11, x10, x26DA9867); + vxor(*out2, *out2, x11); +} +#endif + +#if andn && !triop && regs <= 8 +/* s8-004798, 41 gates, 14 regs, 7 andn, 7/35/76/118/160 stalls, 59 biop */ +/* Currently used for MMX/SSE2 */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0C0C0C0C, x0000F0F0, x00FFF00F, x00555005, x00515001; + vtype x33000330, x77555775, x30303030, x3030CFCF, x30104745, x30555745; + vtype x30EFB74A, xCF1048B5, x080A080A, xC71A40BF, xCB164CB3; + vtype x9E4319E6, x000019E6, xF429738C, xF4296A6A, xC729695A; + vtype xF4FF73FF, x33D61AA5, x03E6D56A, x56B3803F; + vtype xC47C3D2F, xF77F3F3F, x693C26D9, x693CD926; + vtype x9EFF19FF, x6100C000, x6151D001, x62B7056B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x0C0C0C0C, a3, a2); + vandn(x0000F0F0, a5, a3); + vxor(x00FFF00F, a4, x0000F0F0); + vand(x00555005, a1, x00FFF00F); + vandn(x00515001, x00555005, x0C0C0C0C); + + vandn(x33000330, a2, x00FFF00F); + vor(x77555775, a1, x33000330); + vandn(x30303030, a2, a3); + vxor(x3030CFCF, a5, x30303030); + vand(x30104745, x77555775, x3030CFCF); + vor(x30555745, x00555005, x30104745); + + vxor(x30EFB74A, x00FFF00F, x30104745); + vnot(xCF1048B5, x30EFB74A); + vandn(x080A080A, a3, x77555775); + vxor(xC71A40BF, xCF1048B5, x080A080A); + vxor(xCB164CB3, x0C0C0C0C, xC71A40BF); + vor(x10, x00515001, a6); + vxor(x11, x10, xCB164CB3); + vxor(*out2, *out2, x11); + + vxor(x9E4319E6, a1, xCB164CB3); + vand(x000019E6, a5, x9E4319E6); + vxor(xF429738C, a2, xC71A40BF); + vxor(xF4296A6A, x000019E6, xF429738C); + vxor(xC729695A, x33000330, xF4296A6A); + + vor(xF4FF73FF, a4, xF429738C); + vxor(x33D61AA5, xC729695A, xF4FF73FF); + vxor(x03E6D56A, x3030CFCF, x33D61AA5); + vxor(x56B3803F, a1, x03E6D56A); + vand(x30, x56B3803F, a6); + vxor(x31, x30, xC729695A); + vxor(*out4, *out4, x31); + + vxor(xC47C3D2F, x30555745, xF4296A6A); + vor(xF77F3F3F, a2, xC47C3D2F); + vxor(x693C26D9, x9E4319E6, xF77F3F3F); + vxor(x693CD926, a5, x693C26D9); + vand(x20, x30555745, a6); + vxor(x21, x20, x693CD926); + vxor(*out3, *out3, x21); + + vor(x9EFF19FF, a4, x9E4319E6); + vandn(x6100C000, x693CD926, x9EFF19FF); + vor(x6151D001, x00515001, x6100C000); + vxor(x62B7056B, x03E6D56A, x6151D001); + vor(x00, x62B7056B, a6); + vxor(x01, x00, xC729695A); + vxor(*out1, *out1, x01); +} +#elif andn && triop && latency <= 2 +/* s8-005322, 41 gates, 14 regs, 11 andn, 3/26/67/109/151 stalls, 62 biop */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0C0C0C0C, x0000F0F0, x00FFF00F, x00555005, x00515001; + vtype x33000330, x77555775, x30303030, x3030CFCF, x30104745, x30555745; + vtype x30EFB74A, xCF1048B5, x080A080A, xC71A40BF, xCB164CB3; + vtype x9E4319E6, x000019E6, x33001AD6, xF429738C, xC729695A; + vtype x00332121, x9E4018C6, xC72996A5, x59698E63; + vtype xF4FF73FF, x33D6E55A, x65656565, x56B3803F; + vtype xF40083F0, x03D6640A, x61616161, x62B7056B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x0C0C0C0C, a3, a2); + vandn(x0000F0F0, a5, a3); + vxor(x00FFF00F, a4, x0000F0F0); + vand(x00555005, a1, x00FFF00F); + vandn(x00515001, x00555005, x0C0C0C0C); + + vandn(x33000330, a2, x00FFF00F); + vor(x77555775, a1, x33000330); + vandn(x30303030, a2, a3); + vxor(x3030CFCF, a5, x30303030); + vand(x30104745, x77555775, x3030CFCF); + vor(x30555745, x00555005, x30104745); + + vxor(x30EFB74A, x00FFF00F, x30104745); + vnot(xCF1048B5, x30EFB74A); + vandn(x080A080A, a3, x77555775); + vxor(xC71A40BF, xCF1048B5, x080A080A); + vxor(xCB164CB3, x0C0C0C0C, xC71A40BF); + vor(x10, x00515001, a6); + vxor(x11, x10, xCB164CB3); + vxor(*out2, *out2, x11); + + vxor(x9E4319E6, a1, xCB164CB3); + vand(x000019E6, a5, x9E4319E6); + vxor(x33001AD6, x33000330, x000019E6); + vxor(xF429738C, a2, xC71A40BF); + vxor(xC729695A, x33001AD6, xF429738C); + + vandn(x00332121, a2, x33001AD6); + vandn(x9E4018C6, x9E4319E6, x00332121); + vxor(xC72996A5, a5, xC729695A); + vxor(x59698E63, x9E4018C6, xC72996A5); + vandn(x20, x30555745, a6); + vxor(x21, x20, x59698E63); + vxor(*out3, *out3, x21); + + vor(xF4FF73FF, a4, xF429738C); + vxor(x33D6E55A, xC72996A5, xF4FF73FF); + vxor(x65656565, a1, x30303030); + vxor(x56B3803F, x33D6E55A, x65656565); + vand(x30, x56B3803F, a6); + vxor(x31, x30, xC729695A); + vxor(*out4, *out4, x31); + + vxor(xF40083F0, x00FFF00F, xF4FF73FF); + vandn(x03D6640A, x33D6E55A, xF40083F0); + vandn(x61616161, x65656565, x0C0C0C0C); + vxor(x62B7056B, x03D6640A, x61616161); + vor(x00, x62B7056B, a6); + vxor(x01, x00, xC729695A); + vxor(*out1, *out1, x01); +} +#elif triop && (latency >= 4 || (!andn && latency == 3)) +/* s8-015415, 41 gates, 14 regs, 7 andn, 5/23/57/98/140 stalls, 60 biop */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0C0C0C0C, x0000F0F0, x00FFF00F, x00555005, x00515001; + vtype x33000330, x77555775, x30303030, x3030CFCF, x30104745, x30555745; + vtype xFF000FF0, xCF1048B5, x080A080A, xC71A40BF, xCB164CB3; + vtype xF429738C, xC72970BC, x9E4319E6, x000019E6, xC729695A; + vtype xF77C3E1F, xF77F3F3F, x9E43E619, x693CD926; + vtype xF719A695, xF4FF73FF, x03E6D56A, x56B3803F; + vtype xF700A600, x61008000, x03B7856B, x62B7056B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x0C0C0C0C, a3, a2); + vandn(x0000F0F0, a5, a3); + vxor(x00FFF00F, a4, x0000F0F0); + vand(x00555005, a1, x00FFF00F); + vandn(x00515001, x00555005, x0C0C0C0C); + + vandn(x33000330, a2, x00FFF00F); + vor(x77555775, a1, x33000330); + vandn(x30303030, a2, a3); + vxor(x3030CFCF, a5, x30303030); + vand(x30104745, x77555775, x3030CFCF); + vor(x30555745, x00555005, x30104745); + + vnot(xFF000FF0, x00FFF00F); + vxor(xCF1048B5, x30104745, xFF000FF0); + vandn(x080A080A, a3, x77555775); + vxor(xC71A40BF, xCF1048B5, x080A080A); + vxor(xCB164CB3, x0C0C0C0C, xC71A40BF); + vor(x10, x00515001, a6); + vxor(x11, x10, xCB164CB3); + vxor(*out2, *out2, x11); + + vxor(xF429738C, a2, xC71A40BF); + vxor(xC72970BC, x33000330, xF429738C); + vxor(x9E4319E6, a1, xCB164CB3); + vand(x000019E6, a5, x9E4319E6); + vxor(xC729695A, xC72970BC, x000019E6); + + vxor(xF77C3E1F, x30555745, xC729695A); + vor(xF77F3F3F, a2, xF77C3E1F); + vxor(x9E43E619, a5, x9E4319E6); + vxor(x693CD926, xF77F3F3F, x9E43E619); + vand(x20, x30555745, a6); + vxor(x21, x20, x693CD926); + vxor(*out3, *out3, x21); + + vxor(xF719A695, x3030CFCF, xC729695A); + vor(xF4FF73FF, a4, xF429738C); + vxor(x03E6D56A, xF719A695, xF4FF73FF); + vxor(x56B3803F, a1, x03E6D56A); + vand(x30, x56B3803F, a6); + vxor(x31, x30, xC729695A); + vxor(*out4, *out4, x31); + + vandn(xF700A600, xF719A695, a4); + vand(x61008000, x693CD926, xF700A600); + vxor(x03B7856B, x00515001, x03E6D56A); + vxor(x62B7056B, x61008000, x03B7856B); + vor(x00, x62B7056B, a6); + vxor(x01, x00, xC729695A); + vxor(*out1, *out1, x01); +} +#elif !andn || !triop +/* s8-019374, 41 gates, 14 regs, 7 andn, 4/25/61/103/145 stalls, 59 biop */ +/* Currently used for x86-64 SSE2 */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0C0C0C0C, x0000F0F0, x00FFF00F, x00555005, x00515001; + vtype x33000330, x77555775, x30303030, x3030CFCF, x30104745, x30555745; + vtype xFF000FF0, xCF1048B5, x080A080A, xC71A40BF, xCB164CB3; + vtype x9E4319E6, x000019E6, xF429738C, xF4296A6A, xC729695A; + vtype xC47C3D2F, xF77F3F3F, x9E43E619, x693CD926; + vtype xF719A695, xF4FF73FF, x03E6D56A, x56B3803F; + vtype xF700A600, x61008000, x03B7856B, x62B7056B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x0C0C0C0C, a3, a2); + vandn(x0000F0F0, a5, a3); + vxor(x00FFF00F, a4, x0000F0F0); + vand(x00555005, a1, x00FFF00F); + vandn(x00515001, x00555005, x0C0C0C0C); + + vandn(x33000330, a2, x00FFF00F); + vor(x77555775, a1, x33000330); + vandn(x30303030, a2, a3); + vxor(x3030CFCF, a5, x30303030); + vand(x30104745, x77555775, x3030CFCF); + vor(x30555745, x00555005, x30104745); + + vnot(xFF000FF0, x00FFF00F); + vxor(xCF1048B5, x30104745, xFF000FF0); + vandn(x080A080A, a3, x77555775); + vxor(xC71A40BF, xCF1048B5, x080A080A); + vxor(xCB164CB3, x0C0C0C0C, xC71A40BF); + vor(x10, x00515001, a6); + vxor(x11, x10, xCB164CB3); + vxor(*out2, *out2, x11); + + vxor(x9E4319E6, a1, xCB164CB3); + vand(x000019E6, a5, x9E4319E6); + vxor(xF429738C, a2, xC71A40BF); + vxor(xF4296A6A, x000019E6, xF429738C); + vxor(xC729695A, x33000330, xF4296A6A); + + vxor(xC47C3D2F, x30555745, xF4296A6A); + vor(xF77F3F3F, a2, xC47C3D2F); + vxor(x9E43E619, a5, x9E4319E6); + vxor(x693CD926, xF77F3F3F, x9E43E619); + vand(x20, x30555745, a6); + vxor(x21, x20, x693CD926); + vxor(*out3, *out3, x21); + + vxor(xF719A695, x3030CFCF, xC729695A); + vor(xF4FF73FF, a4, xF429738C); + vxor(x03E6D56A, xF719A695, xF4FF73FF); + vxor(x56B3803F, a1, x03E6D56A); + vand(x30, x56B3803F, a6); + vxor(x31, x30, xC729695A); + vxor(*out4, *out4, x31); + + vandn(xF700A600, xF719A695, a4); + vand(x61008000, x693CD926, xF700A600); + vxor(x03B7856B, x00515001, x03E6D56A); + vxor(x62B7056B, x61008000, x03B7856B); + vor(x00, x62B7056B, a6); + vxor(x01, x00, xC729695A); + vxor(*out1, *out1, x01); +} +#else +/* s8-019630, 41 gates, 14 regs, 11 andn, 4/21/60/101/143 stalls, 62 biop */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0C0C0C0C, x0000F0F0, x00FFF00F, x00555005, x00515001; + vtype x33000330, x77555775, x30303030, x3030CFCF, x30104745, x30555745; + vtype xFF000FF0, xCF1048B5, x080A080A, xC71A40BF, xCB164CB3; + vtype x9E4319E6, x000019E6, x33001AD6, xF429738C, xC729695A; + vtype x00332121, x9E4018C6, xC72996A5, x59698E63; + vtype xF4FF73FF, x33D6E55A, x65656565, x56B3803F; + vtype x38299955, x03D6640A, x61616161, x62B7056B; + vtype x00, x01, x10, x11, x20, x21, x30, x31; + + vandn(x0C0C0C0C, a3, a2); + vandn(x0000F0F0, a5, a3); + vxor(x00FFF00F, a4, x0000F0F0); + vand(x00555005, a1, x00FFF00F); + vandn(x00515001, x00555005, x0C0C0C0C); + + vandn(x33000330, a2, x00FFF00F); + vor(x77555775, a1, x33000330); + vandn(x30303030, a2, a3); + vxor(x3030CFCF, a5, x30303030); + vand(x30104745, x77555775, x3030CFCF); + vor(x30555745, x00555005, x30104745); + + vnot(xFF000FF0, x00FFF00F); + vxor(xCF1048B5, x30104745, xFF000FF0); + vandn(x080A080A, a3, x77555775); + vxor(xC71A40BF, xCF1048B5, x080A080A); + vxor(xCB164CB3, x0C0C0C0C, xC71A40BF); + vor(x10, x00515001, a6); + vxor(x11, x10, xCB164CB3); + vxor(*out2, *out2, x11); + + vxor(x9E4319E6, a1, xCB164CB3); + vand(x000019E6, a5, x9E4319E6); + vxor(x33001AD6, x33000330, x000019E6); + vxor(xF429738C, a2, xC71A40BF); + vxor(xC729695A, x33001AD6, xF429738C); + + vandn(x00332121, a2, x33001AD6); + vandn(x9E4018C6, x9E4319E6, x00332121); + vxor(xC72996A5, a5, xC729695A); + vxor(x59698E63, x9E4018C6, xC72996A5); + vandn(x20, x30555745, a6); + vxor(x21, x20, x59698E63); + vxor(*out3, *out3, x21); + + vor(xF4FF73FF, a4, xF429738C); + vxor(x33D6E55A, xC72996A5, xF4FF73FF); + vxor(x65656565, a1, x30303030); + vxor(x56B3803F, x33D6E55A, x65656565); + vand(x30, x56B3803F, a6); + vxor(x31, x30, xC729695A); + vxor(*out4, *out4, x31); + + vxor(x38299955, xFF000FF0, xC72996A5); + vandn(x03D6640A, x33D6E55A, x38299955); + vandn(x61616161, x65656565, x0C0C0C0C); + vxor(x62B7056B, x03D6640A, x61616161); + vor(x00, x62B7056B, a6); + vxor(x01, x00, xC729695A); + vxor(*out1, *out1, x01); +} +#endif diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..99b99c9 --- /dev/null +++ b/src/options.c @@ -0,0 +1,316 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define NEED_OS_FORK +#include "os.h" + +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "memory.h" +#include "list.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "bench.h" +#include "external.h" +#include "john.h" + +struct options_main options; + +static struct opt_entry opt_list[] = { + {"", FLG_PASSWD, 0, 0, 0, OPT_FMT_ADD_LIST, &options.passwd}, + {"single", FLG_SINGLE_SET, FLG_CRACKING_CHK}, + {"wordlist", FLG_WORDLIST_SET, FLG_CRACKING_CHK, + 0, OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.wordlist}, + {"stdin", FLG_STDIN_SET, FLG_CRACKING_CHK}, + {"rules", FLG_RULES, FLG_RULES, FLG_WORDLIST_CHK, FLG_STDIN_CHK}, + {"incremental", FLG_INC_SET, FLG_CRACKING_CHK, + 0, 0, OPT_FMT_STR_ALLOC, &options.charset}, + {"external", FLG_EXTERNAL_SET, FLG_EXTERNAL_CHK, + 0, OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.external}, + {"stdout", FLG_STDOUT, FLG_STDOUT, + FLG_CRACKING_SUP, FLG_SINGLE_CHK | FLG_BATCH_CHK, + "%u", &options.length}, + {"restore", FLG_RESTORE_SET, FLG_RESTORE_CHK, + 0, ~FLG_RESTORE_SET & ~OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.session}, + {"session", FLG_SESSION, FLG_SESSION, + FLG_CRACKING_SUP, OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.session}, + {"status", FLG_STATUS_SET, FLG_STATUS_CHK, + 0, ~FLG_STATUS_SET & ~OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.session}, + {"make-charset", FLG_MAKECHR_SET, FLG_MAKECHR_CHK, + 0, FLG_CRACKING_CHK | FLG_SESSION | OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.charset}, + {"show", FLG_SHOW_SET, FLG_SHOW_CHK, + 0, FLG_CRACKING_SUP | FLG_MAKECHR_CHK}, + {"test", FLG_TEST_SET, FLG_TEST_CHK, + 0, ~FLG_TEST_SET & ~FLG_FORMAT & ~FLG_SAVEMEM & ~OPT_REQ_PARAM, + "%u", &benchmark_time}, + {"users", FLG_NONE, 0, FLG_PASSWD, OPT_REQ_PARAM, + OPT_FMT_ADD_LIST_MULTI, &options.loader.users}, + {"groups", FLG_NONE, 0, FLG_PASSWD, OPT_REQ_PARAM, + OPT_FMT_ADD_LIST_MULTI, &options.loader.groups}, + {"shells", FLG_NONE, 0, FLG_PASSWD, OPT_REQ_PARAM, + OPT_FMT_ADD_LIST_MULTI, &options.loader.shells}, + {"salts", FLG_SALTS, FLG_SALTS, FLG_PASSWD, OPT_REQ_PARAM, + "%d", &options.loader.min_pps}, + {"save-memory", FLG_SAVEMEM, FLG_SAVEMEM, 0, OPT_REQ_PARAM, + "%u", &mem_saving_level}, + {"node", FLG_NODE, FLG_NODE, FLG_CRACKING_CHK, OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.node_str}, +#if OS_FORK + {"fork", FLG_FORK, FLG_FORK, + FLG_CRACKING_CHK, FLG_STDIN_CHK | FLG_STDOUT | OPT_REQ_PARAM, + "%u", &options.fork}, +#endif + {"format", FLG_FORMAT, FLG_FORMAT, + 0, FLG_STDOUT | OPT_REQ_PARAM, + OPT_FMT_STR_ALLOC, &options.format}, + {NULL} +}; + +#define JOHN_COPYRIGHT "Solar Designer" + +#if OS_FORK +#define JOHN_USAGE_FORK \ +"--fork=N fork N processes\n" +#else +#define JOHN_USAGE_FORK "" +#endif + +#define JOHN_USAGE \ +"John the Ripper password cracker, version " JOHN_VERSION "\n" \ +"Copyright (c) 1996-2013 by " JOHN_COPYRIGHT "\n" \ +"Homepage: http://www.openwall.com/john/\n" \ +"\n" \ +"Usage: %s [OPTIONS] [PASSWORD-FILES]\n" \ +"--single \"single crack\" mode\n" \ +"--wordlist=FILE --stdin wordlist mode, read words from FILE or stdin\n" \ +"--rules enable word mangling rules for wordlist mode\n" \ +"--incremental[=MODE] \"incremental\" mode [using section MODE]\n" \ +"--external=MODE external mode or word filter\n" \ +"--stdout[=LENGTH] just output candidate passwords [cut at LENGTH]\n" \ +"--restore[=NAME] restore an interrupted session [called NAME]\n" \ +"--session=NAME give a new session the NAME\n" \ +"--status[=NAME] print status of a session [called NAME]\n" \ +"--make-charset=FILE make a charset, FILE will be overwritten\n" \ +"--show show cracked passwords\n" \ +"--test[=TIME] run tests and benchmarks for TIME seconds each\n" \ +"--users=[-]LOGIN|UID[,..] [do not] load this (these) user(s) only\n" \ +"--groups=[-]GID[,..] load users [not] of this (these) group(s) only\n" \ +"--shells=[-]SHELL[,..] load users with[out] this (these) shell(s) only\n" \ +"--salts=[-]N load salts with[out] at least N passwords only\n" \ +"--save-memory=LEVEL enable memory saving, at LEVEL 1..3\n" \ +"--node=MIN[-MAX]/TOTAL this node's number range out of TOTAL count\n" \ +JOHN_USAGE_FORK \ +"--format=NAME force hash type NAME: " + +#define JOHN_USAGE_INDENT \ +" " + +static void print_usage(char *name) +{ + int column; + struct fmt_main *format; + + printf(JOHN_USAGE, name); + + column = strrchr(JOHN_USAGE, '\0') - strrchr(JOHN_USAGE, '\n') - 1; + format = fmt_list; + do { + char *label = format->params.label; + int length = strlen(label) + (format->next != NULL); + column += length; + if (column > 80) { + printf("\n" JOHN_USAGE_INDENT); + column = strlen(JOHN_USAGE_INDENT) + length; + } + printf("%s%c", label, format->next ? '/' : '\n'); + } while ((format = format->next)); + + exit(0); +} + +void opt_init(char *name, int argc, char **argv) +{ + if (argc < 2) + print_usage(name); + + memset(&options, 0, sizeof(options)); + + list_init(&options.passwd); + + options.loader.flags = DB_LOGIN; + list_init(&options.loader.users); + list_init(&options.loader.groups); + list_init(&options.loader.shells); + + options.length = -1; + + opt_process(opt_list, &options.flags, argv); + + ext_flags = 0; + if (options.flags & FLG_EXTERNAL_CHK) { + if (options.flags & (FLG_CRACKING_CHK | FLG_MAKECHR_CHK)) { + ext_flags = EXT_REQ_FILTER | EXT_USES_FILTER; + } else { + options.flags |= FLG_CRACKING_SET; + ext_flags = EXT_REQ_GENERATE | + EXT_USES_GENERATE | EXT_USES_FILTER; + } + } + + if (!(options.flags & FLG_ACTION)) + options.flags |= FLG_BATCH_SET; + + opt_check(opt_list, options.flags, argv); + + if (options.session) { + rec_name = options.session; + rec_name_completed = 0; + } + + if (options.flags & FLG_RESTORE_CHK) { +#if OS_FORK + char *rec_name_orig = rec_name; +#endif + rec_restore_args(1); +#if OS_FORK + if (options.fork) { + rec_name = rec_name_orig; + rec_name_completed = 0; + } +#endif + return; + } + + if (options.flags & FLG_STATUS_CHK) { +#if OS_FORK + char *rec_name_orig = rec_name; +#endif + rec_restore_args(0); + options.flags |= FLG_STATUS_SET; + status_init(NULL, 1); + status_print(); +#if OS_FORK + if (options.fork) { + unsigned int i; + for (i = 2; i <= options.fork; i++) { + rec_name = rec_name_orig; + rec_name_completed = 0; + rec_restoring_now = 0; + options.node_min = options.node_max = i; + john_main_process = 0; + rec_restore_args(0); + john_main_process = 1; + options.node_min = options.node_max = i; + options.flags |= FLG_STATUS_SET; + if (rec_restoring_now) + status_print(); + } + } +#endif + exit(0); + } + + if (options.flags & FLG_SALTS) + if (options.loader.min_pps < 0) { + options.loader.max_pps = -1 - options.loader.min_pps; + options.loader.min_pps = 0; + } + + if (options.length < 0) + options.length = PLAINTEXT_BUFFER_SIZE - 3; + else + if (options.length < 1 || options.length > PLAINTEXT_BUFFER_SIZE - 3) { + fprintf(stderr, "Invalid plaintext length requested\n"); + error(); + } + + if (options.flags & FLG_STDOUT) options.flags &= ~FLG_PWD_REQ; + +#if OS_FORK + if ((options.flags & FLG_FORK) && + (options.fork < 2 || options.fork > 1024)) { + fprintf(stderr, "--fork number must be between 2 and 1024\n"); + error(); + } +#endif + + if (options.node_str) { + const char *msg = NULL; + int n; + if ((n = sscanf(options.node_str, "%u-%u/%u", + &options.node_min, &options.node_max, + &options.node_count)) != 3) { + n = sscanf(options.node_str, "%u/%u", + &options.node_min, &options.node_count); + options.node_max = options.node_min; +#if OS_FORK + if (options.fork) + options.node_max += options.fork - 1; +#endif + } + if (n < 2) + msg = "valid syntax is MIN-MAX/TOTAL or N/TOTAL"; + else if (!options.node_min) + msg = "valid node numbers start from 1"; + else if (options.node_min > options.node_max) + msg = "range start can't exceed range end"; + else if (options.node_count < 2) + msg = "node count must be at least 2"; + else if (options.node_max > options.node_count) + msg = "node numbers can't exceed node count"; +#if OS_FORK + else if (options.fork && + options.node_max - options.node_min + 1 != options.fork) + msg = "range must be consistent with --fork number"; +#endif + else if (!options.fork && + options.node_max - options.node_min + 1 == + options.node_count) + msg = "node numbers can't span the whole range"; + if (msg) { + fprintf(stderr, "Invalid node specification: %s: %s\n", + options.node_str, msg); + error(); + } +#if OS_FORK + } else if (options.fork) { + options.node_min = 1; + options.node_max = options.node_min + options.fork - 1; + options.node_count = options.node_max; +#endif + } + + if ((options.flags & (FLG_PASSWD | FLG_PWD_REQ)) == FLG_PWD_REQ) { + fprintf(stderr, "Password files required, " + "but none specified\n"); + error(); + } + + if ((options.flags & (FLG_PASSWD | FLG_PWD_SUP)) == FLG_PASSWD) { + fprintf(stderr, "Password files specified, " + "but no option would use them\n"); + error(); + } + + rec_argc = argc; rec_argv = argv; + rec_check = 0; +} diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..bb80220 --- /dev/null +++ b/src/options.h @@ -0,0 +1,140 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2003,2006,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * John's command line options definition. + */ + +#ifndef _JOHN_OPTIONS_H +#define _JOHN_OPTIONS_H + +#include "list.h" +#include "loader.h" +#include "getopt.h" + +/* + * Option flags bitmasks. + */ +/* An action requested */ +#define FLG_ACTION 0x00000001 +/* Password files specified */ +#define FLG_PASSWD 0x00000002 +/* An option supports password files */ +#define FLG_PWD_SUP 0x00000004 +/* An option requires password files */ +#define FLG_PWD_REQ (0x00000008 | FLG_PWD_SUP) +/* Some option that doesn't have its own flag is specified */ +#define FLG_NONE 0x00000010 +/* A cracking mode enabled */ +#define FLG_CRACKING_CHK 0x00000020 +#define FLG_CRACKING_SUP 0x00000040 +#define FLG_CRACKING_SET \ + (FLG_CRACKING_CHK | FLG_CRACKING_SUP | FLG_ACTION | FLG_PWD_REQ) +/* Wordlist mode enabled, options.wordlist is set to the file name or NULL + * if reading from stdin. */ +#define FLG_WORDLIST_CHK 0x00000080 +#define FLG_WORDLIST_SET (FLG_WORDLIST_CHK | FLG_CRACKING_SET) +/* Wordlist mode enabled, reading from stdin */ +#define FLG_STDIN_CHK 0x00000100 +#define FLG_STDIN_SET (FLG_STDIN_CHK | FLG_WORDLIST_SET) +/* Wordlist rules enabled */ +#define FLG_RULES 0x00000200 +/* "Single crack" mode enabled */ +#define FLG_SINGLE_CHK 0x00000400 +#define FLG_SINGLE_SET (FLG_SINGLE_CHK | FLG_CRACKING_SET) +/* Incremental mode enabled */ +#define FLG_INC_CHK 0x00000800 +#define FLG_INC_SET (FLG_INC_CHK | FLG_CRACKING_SET) +/* External mode or word filter enabled */ +#define FLG_EXTERNAL_CHK 0x00001000 +#define FLG_EXTERNAL_SET \ + (FLG_EXTERNAL_CHK | FLG_ACTION | FLG_CRACKING_SUP | FLG_PWD_SUP) +/* Batch cracker */ +#define FLG_BATCH_CHK 0x00004000 +#define FLG_BATCH_SET (FLG_BATCH_CHK | FLG_CRACKING_SET) +/* Stdout mode */ +#define FLG_STDOUT 0x00008000 +/* Restoring an interrupted session */ +#define FLG_RESTORE_CHK 0x00010000 +#define FLG_RESTORE_SET (FLG_RESTORE_CHK | FLG_ACTION) +/* A session name is set */ +#define FLG_SESSION 0x00020000 +/* Print status of a session */ +#define FLG_STATUS_CHK 0x00040000 +#define FLG_STATUS_SET (FLG_STATUS_CHK | FLG_ACTION) +/* Make a charset */ +#define FLG_MAKECHR_CHK 0x00100000 +#define FLG_MAKECHR_SET \ + (FLG_MAKECHR_CHK | FLG_ACTION | FLG_PWD_SUP) +/* Show cracked passwords */ +#define FLG_SHOW_CHK 0x00200000 +#define FLG_SHOW_SET \ + (FLG_SHOW_CHK | FLG_ACTION | FLG_PWD_REQ) +/* Perform a benchmark */ +#define FLG_TEST_CHK 0x00400000 +#define FLG_TEST_SET \ + (FLG_TEST_CHK | FLG_CRACKING_SUP | FLG_ACTION) +/* Passwords per salt requested */ +#define FLG_SALTS 0x01000000 +/* Ciphertext format forced */ +#define FLG_FORMAT 0x02000000 +/* Memory saving enabled */ +#define FLG_SAVEMEM 0x04000000 +/* Node number(s) specified */ +#define FLG_NODE 0x10000000 +/* fork() requested, and process count specified */ +#define FLG_FORK 0x20000000 + +/* Note that 0x80000000 is taken for OPT_REQ_PARAM, see getopt.h */ + +/* + * Structure with option flags and all the parameters. + */ +struct options_main { +/* Option flags */ + opt_flags flags; + +/* Password files */ + struct list_main *passwd; + +/* Password file loader options */ + struct db_options loader; + +/* Session name */ + char *session; + +/* Ciphertext format name */ + char *format; + +/* Wordlist file name */ + char *wordlist; + +/* Charset file name */ + char *charset; + +/* External mode or word filter name */ + char *external; + +/* Maximum plaintext length for stdout mode */ + int length; + +/* Parallel processing options */ + char *node_str; + unsigned int node_min, node_max, node_count, fork; +}; + +extern struct options_main options; + +/* + * Initializes the options structure. + */ +extern void opt_init(char *name, int argc, char **argv); + +#endif diff --git a/src/os.h b/src/os.h new file mode 100644 index 0000000..17d3815 --- /dev/null +++ b/src/os.h @@ -0,0 +1,62 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * OS-specific parameters. + */ + +#ifndef _JOHN_OS_H +#define _JOHN_OS_H + +#ifdef NEED_OS_TIMER + +#if defined(__CYGWIN32__) || defined(__BEOS__) +#define OS_TIMER 0 +#else +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 /* for ITIMER_REAL */ +#endif +#include +#ifdef ITIMER_REAL +#define OS_TIMER 1 +#else +#define OS_TIMER 0 +#warning ITIMER_REAL is not available - will emulate timers +#endif +#endif + +#endif + +#ifdef NEED_OS_FLOCK + +#if defined(__APPLE__) && !defined(_DARWIN_C_SOURCE) +#define _DARWIN_C_SOURCE /* for LOCK_EX */ +#endif +#include +#ifdef LOCK_EX +#define OS_FLOCK 1 +#else +#define OS_FLOCK 0 +#warning LOCK_EX is not available - will skip locking +#endif + +#endif + +#ifdef NEED_OS_FORK + +#if defined(__DJGPP__) || defined(__CYGWIN32__) +#define OS_FORK 0 +#else +#define OS_FORK 1 +#endif + +#endif + +#endif diff --git a/src/pa-risc.h b/src/pa-risc.h new file mode 100644 index 0000000..21fa72d --- /dev/null +++ b/src/pa-risc.h @@ -0,0 +1,51 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for PA-RISC. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 1 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 8 +#define DES_BS_EXPAND 0 +#define DES_BS_ALGORITHM_NAME "DES 32/32 X8" + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 1 +#define BF_X2 0 + +#endif diff --git a/src/params.c b/src/params.c new file mode 100644 index 0000000..7728b27 --- /dev/null +++ b/src/params.c @@ -0,0 +1,31 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2010,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include "params.h" + +int password_hash_sizes[PASSWORD_HASH_SIZES] = { + PASSWORD_HASH_SIZE_0, + PASSWORD_HASH_SIZE_1, + PASSWORD_HASH_SIZE_2, + PASSWORD_HASH_SIZE_3, + PASSWORD_HASH_SIZE_4, + PASSWORD_HASH_SIZE_5, + PASSWORD_HASH_SIZE_6 +}; + +int password_hash_thresholds[PASSWORD_HASH_SIZES] = { + PASSWORD_HASH_THRESHOLD_0, + PASSWORD_HASH_THRESHOLD_1, + PASSWORD_HASH_THRESHOLD_2, + PASSWORD_HASH_THRESHOLD_3, + PASSWORD_HASH_THRESHOLD_4, + PASSWORD_HASH_THRESHOLD_5, + PASSWORD_HASH_THRESHOLD_6 +}; diff --git a/src/params.h b/src/params.h new file mode 100644 index 0000000..82eeaba --- /dev/null +++ b/src/params.h @@ -0,0 +1,332 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Some global parameters. + */ + +#ifndef _JOHN_PARAMS_H +#define _JOHN_PARAMS_H + +#include + +#include "arch.h" + +/* + * John's version number. + */ +#define JOHN_VERSION "1.8.0" + +/* + * Notes to packagers of John for *BSD "ports", Linux distributions, etc.: + * + * You do need to set JOHN_SYSTEMWIDE to 1, but you do not need to patch this + * file for that. Instead, you can pass -DJOHN_SYSTEMWIDE=1 in CFLAGS. You + * also do not need to patch the Makefile for that since you can pass the + * CFLAGS via "make" command line. Similarly, you do not need to patch + * anything to change JOHN_SYSTEMWIDE_EXEC and JOHN_SYSTEMWIDE_HOME (although + * the defaults for these should be fine). + * + * JOHN_SYSTEMWIDE_EXEC should be set to the _directory_ where John will look + * for its "CPU fallback" program binary (which should be another build of John + * itself). This is activated when John is compiled with -DCPU_FALLBACK=1. + * The fallback program binary name is defined with CPU_FALLBACK_BINARY in + * architecture-specific header files such as x86-64.h (and the default should + * be fine - no need to patch it). On x86-64, this may be used to + * transparently fallback from a -64-xop build to -64-avx, then to plain -64 + * (which implies SSE2). On 32-bit x86, this may be used to fallback from -xop + * to -avx, then to -sse2, then to -mmx, and finally to -any. Please do make + * use of this functionality in your package if it is built for x86-64 or + * 32-bit x86 (yes, you may need to make five builds of John for a single + * 32-bit x86 binary package). + * + * Similarly, -DOMP_FALLBACK=1 activates fallback to OMP_FALLBACK_BINARY in the + * JOHN_SYSTEMWIDE_EXEC directory when an OpenMP-enabled build of John + * determines that it would otherwise run only one thread, which would often + * be less optimal than running a non-OpenMP build. + * + * CPU_FALLBACK and OMP_FALLBACK may be used together, but in that case you + * need to override some of the default fallback binary filenames such that you + * can have both OpenMP-enabled and non-OpenMP fallback binaries that use the + * same CPU instruction set extensions. You can do these overrides with + * options like -DOMP_FALLBACK_BINARY='"john-non-omp-non-avx"' (leaving + * CPU_FALLBACK_BINARY at its default of "john-non-avx") or + * -DOMP_FALLBACK_BINARY='"john-sse2"' and + * -DCPU_FALLBACK_BINARY='"john-omp-sse2"' as fallbacks from an OpenMP-enabled + * -avx build. Please note that you do not need to patch any John files for + * this, not even the Makefile. For an example of passing these settings from + * an RPM spec file, please refer to john.spec used in Owl. + * + * "$JOHN" is supposed to be expanded at runtime. Please do not replace + * it with a specific path, neither in this file nor in the default + * john.conf, if at all possible. + */ + +/* + * Is this a system-wide installation? *BSD "ports" and Linux distributions + * will want to set this to 1 for their builds of John - please refer to the + * notes above. + */ +#ifndef JOHN_SYSTEMWIDE +#define JOHN_SYSTEMWIDE 0 +#endif + +#if JOHN_SYSTEMWIDE +#ifndef JOHN_SYSTEMWIDE_EXEC /* please refer to the notes above */ +#define JOHN_SYSTEMWIDE_EXEC "/usr/libexec/john" +#endif +#ifndef JOHN_SYSTEMWIDE_HOME +#define JOHN_SYSTEMWIDE_HOME "/usr/share/john" +#endif +#define JOHN_PRIVATE_HOME "~/.john" +#endif + +#ifndef OMP_FALLBACK +#define OMP_FALLBACK 0 +#endif + +#if OMP_FALLBACK && !defined(OMP_FALLBACK_BINARY) +#define OMP_FALLBACK_BINARY "john-non-omp" +#endif + +/* + * Crash recovery file format version strings. + */ +#define RECOVERY_V0 "REC0" +#define RECOVERY_V1 "REC1" +#define RECOVERY_V2 "REC2" +#define RECOVERY_V3 "REC3" +#define RECOVERY_V4 "REC4" +#define RECOVERY_V RECOVERY_V4 + +/* + * Charset file format version string. + */ +#define CHARSET_V3 "CHR3" +#define CHARSET_V CHARSET_V3 + +/* + * Timer interval in seconds. + */ +#define TIMER_INTERVAL 1 + +/* + * Default crash recovery file saving delay in timer intervals. + */ +#define TIMER_SAVE_DELAY (600 / TIMER_INTERVAL) + +/* + * Default benchmark time in seconds (per cracking algorithm). + */ +#define BENCHMARK_TIME 5 + +/* + * Number of salts to assume when benchmarking. + */ +#define BENCHMARK_MANY 0x100 + +/* + * File names. + */ +#define CFG_FULL_NAME "$JOHN/john.conf" +#define CFG_ALT_NAME "$JOHN/john.ini" +#if JOHN_SYSTEMWIDE +#define CFG_PRIVATE_FULL_NAME JOHN_PRIVATE_HOME "/john.conf" +#define CFG_PRIVATE_ALT_NAME JOHN_PRIVATE_HOME "/john.ini" +#define POT_NAME JOHN_PRIVATE_HOME "/john.pot" +#define LOG_NAME JOHN_PRIVATE_HOME "/john.log" +#define RECOVERY_NAME JOHN_PRIVATE_HOME "/john" +#else +#define POT_NAME "$JOHN/john.pot" +#define LOG_NAME "$JOHN/john.log" +#define RECOVERY_NAME "$JOHN/john" +#endif +#define LOG_SUFFIX ".log" +#define RECOVERY_SUFFIX ".rec" +#define WORDLIST_NAME "$JOHN/password.lst" + +/* + * Configuration file section names. + */ +#define SECTION_OPTIONS "Options" +#define SECTION_RULES "List.Rules:" +#define SUBSECTION_SINGLE "Single" +#define SUBSECTION_WORDLIST "Wordlist" +#define SECTION_INC "Incremental:" +#define SECTION_EXT "List.External:" + +/* + * Number of different password hash table sizes. + * This is not really configurable, but we define it here in order to have + * the number hard-coded in fewer places. + */ +#define PASSWORD_HASH_SIZES 7 + +/* + * Which hash table size (out of those listed below) the loader should use for + * its own purposes. This does not affect password cracking speed after the + * loading is complete. + */ +#define PASSWORD_HASH_SIZE_FOR_LDR 4 + +/* + * Hash table sizes. These may also be hardcoded into the hash functions. + */ +#define SALT_HASH_LOG 12 +#define SALT_HASH_SIZE (1 << SALT_HASH_LOG) +#define PASSWORD_HASH_SIZE_0 0x10 +#define PASSWORD_HASH_SIZE_1 0x100 +#define PASSWORD_HASH_SIZE_2 0x1000 +#define PASSWORD_HASH_SIZE_3 0x10000 +#define PASSWORD_HASH_SIZE_4 0x100000 +#define PASSWORD_HASH_SIZE_5 0x1000000 +#define PASSWORD_HASH_SIZE_6 0x8000000 + +/* + * Password hash table thresholds. These are the counts of entries required + * to enable the corresponding bitmap size. The corresponding hash table size + * may be smaller as determined by PASSWORD_HASH_SHR. + */ +#define PASSWORD_HASH_THRESHOLD_0 3 +#define PASSWORD_HASH_THRESHOLD_1 3 +#define PASSWORD_HASH_THRESHOLD_2 (PASSWORD_HASH_SIZE_1 / 25) +#define PASSWORD_HASH_THRESHOLD_3 (PASSWORD_HASH_SIZE_2 / 20) +#define PASSWORD_HASH_THRESHOLD_4 (PASSWORD_HASH_SIZE_3 / 10) +#define PASSWORD_HASH_THRESHOLD_5 (PASSWORD_HASH_SIZE_4 / 15) +#define PASSWORD_HASH_THRESHOLD_6 (PASSWORD_HASH_SIZE_5 / 5) + +/* + * Tables of the above values. + */ +extern int password_hash_sizes[PASSWORD_HASH_SIZES]; +extern int password_hash_thresholds[PASSWORD_HASH_SIZES]; + +/* + * How much smaller should the hash tables be than bitmaps in terms of entry + * count. Setting this to 0 will result in them having the same number of + * entries, 1 will make the hash tables twice smaller than bitmaps, etc. + * 5 or 6 will make them the same size in bytes on systems with 32-bit or + * 64-bit pointers, respectively. + */ +#define PASSWORD_HASH_SHR 2 + +/* + * Cracked password hash size, used while loading. + */ +#define CRACKED_HASH_LOG 16 +#define CRACKED_HASH_SIZE (1 << CRACKED_HASH_LOG) + +/* + * Buffered keys hash size, used for "single crack" mode. + */ +#if defined(_OPENMP) && DES_BS && !DES_BS_ASM +#define SINGLE_HASH_LOG 10 +#else +#define SINGLE_HASH_LOG 7 +#endif +#define SINGLE_HASH_SIZE (1 << SINGLE_HASH_LOG) + +/* + * Minimum buffered keys hash size, used if min_keys_per_crypt is even less. + */ +#define SINGLE_HASH_MIN 8 + +/* + * Shadow file entry hash table size, used by unshadow. + */ +#define SHADOW_HASH_LOG 18 +#define SHADOW_HASH_SIZE (1 << SHADOW_HASH_LOG) + +/* + * Hash and buffer sizes for unique. + */ +#define UNIQUE_HASH_LOG 20 +#define UNIQUE_HASH_SIZE (1 << UNIQUE_HASH_LOG) +#define UNIQUE_BUFFER_SIZE 0x4000000 + +/* + * Maximum number of GECOS words per password to load. + */ +#define LDR_WORDS_MAX 0x10 + +/* + * Maximum number of partial hash collisions in a db->password_hash[] bucket. + * If this limit is hit, we print a warning and disable detection of duplicate + * hashes (since it could be too slow). + */ +#define LDR_HASH_COLLISIONS_MAX 1000 + +/* + * Maximum number of GECOS words to try in pairs. + */ +#define SINGLE_WORDS_PAIR_MAX 4 + +/* + * Charset parameters. + * + * Please note that changes to these parameters make your build of John + * incompatible with charset files generated with other builds. + */ +#define CHARSET_MIN 0x01 +#define CHARSET_MAX 0xff +#define CHARSET_LENGTH 24 + +/* + * Compiler parameters. + */ +#define C_TOKEN_SIZE 0x100 +#define C_UNGET_SIZE (C_TOKEN_SIZE + 4) +#define C_EXPR_SIZE 0x100 +#define C_STACK_SIZE ((C_EXPR_SIZE + 4) * 4) +#define C_ARRAY_SIZE 0x1000000 +#define C_DATA_SIZE 0x8000000 + +/* + * Buffer size for rules. + */ +#define RULE_BUFFER_SIZE 0x100 + +/* + * Maximum number of character ranges for rules. + */ +#define RULE_RANGES_MAX 16 + +/* + * Buffer size for words while applying rules, should be at least as large + * as PLAINTEXT_BUFFER_SIZE. + */ +#define RULE_WORD_SIZE 0x80 + +/* + * Buffer size for plaintext passwords. + */ +#define PLAINTEXT_BUFFER_SIZE 0x80 + +/* + * Buffer size for fgets(). + */ +#define LINE_BUFFER_SIZE 0x400 + +/* + * john.pot and log file buffer sizes, can be zero. + */ +#define POT_BUFFER_SIZE 0x8000 +#define LOG_BUFFER_SIZE 0x8000 + +/* + * Buffer size for path names. + */ +#ifdef PATH_MAX +#define PATH_BUFFER_SIZE PATH_MAX +#else +#define PATH_BUFFER_SIZE 0x400 +#endif + +#endif diff --git a/src/path.c b/src/path.c new file mode 100644 index 0000000..2bee3c2 --- /dev/null +++ b/src/path.c @@ -0,0 +1,136 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "misc.h" +#include "params.h" +#include "memory.h" +#include "path.h" + +static char *john_home_path = NULL; +static int john_home_length; + +#if JOHN_SYSTEMWIDE +#include +#include +#include +#include +#include + +static char *user_home_path = NULL; +static int user_home_length; +#endif + +void path_init(char **argv) +{ +#if JOHN_SYSTEMWIDE + struct passwd *pw; +#ifdef JOHN_PRIVATE_HOME + char *private; +#endif +#else + char *pos; +#endif + +#if JOHN_SYSTEMWIDE + john_home_path = mem_alloc(PATH_BUFFER_SIZE); + strnzcpy(john_home_path, JOHN_SYSTEMWIDE_HOME "/", PATH_BUFFER_SIZE); + john_home_length = strlen(john_home_path); + + if (user_home_path) return; + pw = getpwuid(getuid()); + endpwent(); + if (!pw) return; + + user_home_length = strlen(pw->pw_dir) + 1; + if (user_home_length >= PATH_BUFFER_SIZE) return; + + user_home_path = mem_alloc(PATH_BUFFER_SIZE); + memcpy(user_home_path, pw->pw_dir, user_home_length - 1); + user_home_path[user_home_length - 1] = '/'; + +#ifdef JOHN_PRIVATE_HOME + private = path_expand(JOHN_PRIVATE_HOME); + if (mkdir(private, S_IRUSR | S_IWUSR | S_IXUSR)) { + if (errno != EEXIST) pexit("mkdir: %s", private); + } else + fprintf(stderr, "Created directory: %s\n", private); +#endif +#else + if (argv[0]) + if (!john_home_path && (pos = strrchr(argv[0], '/'))) { + john_home_length = pos - argv[0] + 1; + if (john_home_length >= PATH_BUFFER_SIZE) return; + + john_home_path = mem_alloc(PATH_BUFFER_SIZE); + memcpy(john_home_path, argv[0], john_home_length); + } +#endif +} + +char *path_expand(char *name) +{ + if (!strncmp(name, "$JOHN/", 6)) { + if (john_home_path && + john_home_length + strlen(name) - 6 < PATH_BUFFER_SIZE) { + strnzcpy(&john_home_path[john_home_length], &name[6], + PATH_BUFFER_SIZE - john_home_length); + return john_home_path; + } + return name + 6; + } + +#if JOHN_SYSTEMWIDE + if (!strncmp(name, "~/", 2)) { + if (user_home_path && + user_home_length + strlen(name) - 2 < PATH_BUFFER_SIZE) { + strnzcpy(&user_home_path[user_home_length], &name[2], + PATH_BUFFER_SIZE - user_home_length); + return user_home_path; + } + return name + 2; + } +#endif + + return name; +} + +char *path_session(char *session, char *suffix) +{ + int keep, add; + char *p; + + keep = strlen(session); +#ifdef __DJGPP__ + if ((p = strchr(session, '.'))) + keep = p - session; +#endif + + if (!keep) { + fprintf(stderr, "Invalid session name requested\n"); + error(); + } + + add = strlen(suffix) + 1; + p = mem_alloc_tiny(keep + add, MEM_ALIGN_NONE); + memcpy(p, session, keep); + memcpy(p + keep, suffix, add); + + return p; +} + +void path_done(void) +{ + MEM_FREE(john_home_path); +#if JOHN_SYSTEMWIDE + MEM_FREE(user_home_path); +#endif +} diff --git a/src/path.h b/src/path.h new file mode 100644 index 0000000..1575bb8 --- /dev/null +++ b/src/path.h @@ -0,0 +1,40 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Path name expansion routines. + */ + +#ifndef _JOHN_PATH_H +#define _JOHN_PATH_H + +/* + * Initializes the home directory path based on argv[0]. + */ +extern void path_init(char **argv); + +/* + * Expands "$JOHN/" and "~/" in a path name. + * The returned buffer might be overwritten with subsequent calls. + */ +extern char *path_expand(char *name); + +/* + * Generates a filename for the given session name and filename suffix. + * Memory for the resulting filename is allocated with mem_alloc_tiny(). + */ +extern char *path_session(char *session, char *suffix); + +/* + * Frees the memory allocated in path_init(). + */ +extern void path_done(void); + +#endif diff --git a/src/ppc32.h b/src/ppc32.h new file mode 100644 index 0000000..cf5cd0c --- /dev/null +++ b/src/ppc32.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2005,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for 32-bit PowerPC. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/ppc32alt.h b/src/ppc32alt.h new file mode 100644 index 0000000..7007798 --- /dev/null +++ b/src/ppc32alt.h @@ -0,0 +1,66 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2005,2008,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for 32-bit PowerPC w/ AltiVec (128-bit). + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD int +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 3 +#define DES_BS_EXPAND 0 + +#if 1 +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 AltiVec" +#elif 0 +/* It is likely unreasonable to use S-box expressions requiring vsel when this + * operation is only available in one of the two instruction sets. + * So let's revert to less demanding S-box expressions. */ +#undef DES_BS +#define DES_BS 1 +#define DES_BS_VECTOR 5 +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_ALGORITHM_NAME "DES 128/128 AltiVec + 32/32" +#else +#define DES_BS_VECTOR 8 +#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 AltiVec" +#endif + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/ppc64.h b/src/ppc64.h new file mode 100644 index 0000000..410b005 --- /dev/null +++ b/src/ppc64.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2005,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for 64-bit PowerPC. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/ppc64alt.h b/src/ppc64alt.h new file mode 100644 index 0000000..b3dea78 --- /dev/null +++ b/src/ppc64alt.h @@ -0,0 +1,66 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2005,2008,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for 64-bit PowerPC w/ AltiVec (128-bit). + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS_ASM 0 +#define DES_BS 3 +#define DES_BS_EXPAND 0 + +#if 1 +#define DES_BS_VECTOR 2 +#define DES_BS_ALGORITHM_NAME "DES 128/128 AltiVec" +#elif 0 +/* It is likely unreasonable to use S-box expressions requiring vsel when this + * operation is only available in one of the two instruction sets. + * So let's revert to less demanding S-box expressions. */ +#undef DES_BS +#define DES_BS 1 +#define DES_BS_VECTOR 3 +#define DES_BS_VECTOR_SIZE 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 AltiVec + 64/64" +#else +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 AltiVec" +#endif + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/recovery.c b/src/recovery.c new file mode 100644 index 0000000..b78a644 --- /dev/null +++ b/src/recovery.c @@ -0,0 +1,332 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2003,2005,2006,2009,2010,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#ifndef __FreeBSD__ +#define _XOPEN_SOURCE 500 /* for fdopen(3), fileno(3), fsync(2), ftruncate(2) */ +#endif + +#define NEED_OS_FLOCK +#include "os.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +extern int ftruncate(int fd, size_t length); +#endif + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "path.h" +#include "memory.h" +#include "options.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "john.h" + +char *rec_name = RECOVERY_NAME; +int rec_name_completed = 0; +int rec_version = 0; +int rec_argc = 0; +char **rec_argv; +unsigned int rec_check; +int rec_restoring_now = 0; + +static int rec_fd; +static FILE *rec_file = NULL; +static struct db_main *rec_db; +static void (*rec_save_mode)(FILE *file); + +static void rec_name_complete(void) +{ + if (rec_name_completed) + return; + + if (options.fork && !john_main_process) { + char *suffix = mem_alloc(1 + 20 + strlen(RECOVERY_SUFFIX) + 1); + sprintf(suffix, ".%u%s", options.node_min, RECOVERY_SUFFIX); + rec_name = path_session(rec_name, suffix); + MEM_FREE(suffix); + } else { + rec_name = path_session(rec_name, RECOVERY_SUFFIX); + } + + rec_name_completed = 1; +} + +#if OS_FLOCK +static void rec_lock(void) +{ + if (flock(rec_fd, LOCK_EX | LOCK_NB)) { + if (errno == EWOULDBLOCK) { + fprintf(stderr, "Crash recovery file is locked: %s\n", + path_expand(rec_name)); + error(); + } else + pexit("flock(LOCK_EX)"); + } +} +static void rec_unlock(void) +{ + if (flock(rec_fd, LOCK_UN)) + perror("flock(LOCK_UN)"); +} +#else +#define rec_lock() \ + {} +#define rec_unlock() \ + {} +#endif + +void rec_init(struct db_main *db, void (*save_mode)(FILE *file)) +{ + rec_done(1); + + if (!rec_argc) return; + + rec_name_complete(); + + if ((rec_fd = open(path_expand(rec_name), O_RDWR | O_CREAT, 0600)) < 0) + pexit("open: %s", path_expand(rec_name)); + rec_lock(); + if (!(rec_file = fdopen(rec_fd, "w"))) pexit("fdopen"); + + rec_db = db; + rec_save_mode = save_mode; +} + +void rec_save(void) +{ + int save_format; + long size; + char **opt; + + log_flush(); + + if (!rec_file) return; + + if (fseek(rec_file, 0, SEEK_SET)) pexit("fseek"); +#ifdef __CYGWIN32__ + if (ftruncate(rec_fd, 0)) pexit("ftruncate"); +#endif + + save_format = !options.format && rec_db->loaded; + + fprintf(rec_file, RECOVERY_V "\n%d\n", + rec_argc + (save_format ? 1 : 0)); + + opt = rec_argv; + while (*++opt) + fprintf(rec_file, "%s\n", *opt); + + if (save_format) + fprintf(rec_file, "--format=%s\n", + rec_db->format->params.label); + + fprintf(rec_file, "%u\n%u\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n" + "%d\n%d\n%d\n%x\n", + status_get_time() + 1, + status.guess_count, + status.combs.lo, + status.combs.hi, + status.combs_ehi, + status.crypts.lo, + status.crypts.hi, + status.cands.lo, + status.cands.hi, + status.compat, + status.pass, + status_get_progress ? status_get_progress() : -1, + rec_check); + + if (rec_save_mode) rec_save_mode(rec_file); + + if (ferror(rec_file)) pexit("fprintf"); + + if ((size = ftell(rec_file)) < 0) pexit("ftell"); + if (fflush(rec_file)) pexit("fflush"); + if (ftruncate(rec_fd, size)) pexit("ftruncate"); +#ifndef __CYGWIN32__ + if (!options.fork && fsync(rec_fd)) + pexit("fsync"); +#endif +} + +/* See the comment in recovery.h on how the "save" parameter is used */ +void rec_done(int save) +{ + if (!rec_file) + return; + +/* + * If we're the main process for a --fork'ed group of children, leave our .rec + * file around until the children terminate (at which time we may be called + * again with save < 0, meaning forced non-saving). + */ + if (!save && options.fork && john_main_process) { + rec_save(); + return; + } + + if (save > 0) + rec_save(); + else + log_flush(); + + if (fclose(rec_file)) + pexit("fclose"); + rec_file = NULL; + + if ((!save || save == -1) && unlink(path_expand(rec_name))) + pexit("unlink: %s", path_expand(rec_name)); +} + +static void rec_format_error(char *fn) +{ + if (fn && errno && ferror(rec_file)) + pexit("%s", fn); + else { + fprintf(stderr, "Incorrect crash recovery file: %s\n", + path_expand(rec_name)); + error(); + } +} + +void rec_restore_args(int lock) +{ + char line[LINE_BUFFER_SIZE]; + int index, argc; + char **argv; + char *save_rec_name; + + rec_name_complete(); + if (!(rec_file = fopen(path_expand(rec_name), "r+"))) { + if (options.fork && !john_main_process && errno == ENOENT) { + fprintf(stderr, "%u Session completed\n", + options.node_min); + if (options.flags & FLG_STATUS_CHK) + return; + log_event("No crash recovery file, terminating"); + log_done(); + exit(0); + } + pexit("fopen: %s", path_expand(rec_name)); + } + rec_fd = fileno(rec_file); + + if (lock) rec_lock(); + + if (!fgetl(line, sizeof(line), rec_file)) rec_format_error("fgets"); + + rec_version = 0; + if (!strcmp(line, RECOVERY_V4)) rec_version = 4; else + if (!strcmp(line, RECOVERY_V3)) rec_version = 3; else + if (!strcmp(line, RECOVERY_V2)) rec_version = 2; else + if (!strcmp(line, RECOVERY_V1)) rec_version = 1; else + if (strcmp(line, RECOVERY_V0)) rec_format_error(NULL); + + if (fscanf(rec_file, "%d\n", &argc) != 1) + rec_format_error("fscanf"); + if (argc < 2) + rec_format_error(NULL); + argv = mem_alloc_tiny(sizeof(char *) * (argc + 1), MEM_ALIGN_WORD); + + argv[0] = "john"; + + for (index = 1; index < argc; index++) + if (fgetl(line, sizeof(line), rec_file)) + argv[index] = str_alloc_copy(line); + else + rec_format_error("fgets"); + + argv[argc] = NULL; + + save_rec_name = rec_name; + opt_init(argv[0], argc, argv); + rec_name = save_rec_name; + rec_name_completed = 1; + + if (fscanf(rec_file, "%u\n%u\n%x\n%x\n", + &status_restored_time, + &status.guess_count, + &status.combs.lo, + &status.combs.hi) != 4) + rec_format_error("fscanf"); + if (!status_restored_time) + status_restored_time = 1; + + if (rec_version >= 4) { + if (fscanf(rec_file, "%x\n%x\n%x\n%x\n%x\n%d\n", + &status.combs_ehi, + &status.crypts.lo, + &status.crypts.hi, + &status.cands.lo, + &status.cands.hi, + &status.compat) != 6) + rec_format_error("fscanf"); + } else { +/* Historically, we were reusing what became the combs field for candidates + * count when in --stdout mode */ + status.cands = status.combs; + status.compat = 1; + } + + if (rec_version == 0) { + status.pass = 0; + status.progress = -1; + } else + if (fscanf(rec_file, "%d\n%d\n", &status.pass, &status.progress) != 2) + rec_format_error("fscanf"); + if (status.pass < 0 || status.pass > 3) + rec_format_error(NULL); + + if (rec_version < 3) + rec_check = 0; + else + if (fscanf(rec_file, "%x\n", &rec_check) != 1) + rec_format_error("fscanf"); + + rec_restoring_now = 1; +} + +void rec_restore_mode(int (*restore_mode)(FILE *file)) +{ + rec_name_complete(); + + if (!rec_file) return; + + if (restore_mode) + if (restore_mode(rec_file)) rec_format_error("fscanf"); + +/* + * Unlocking the file explicitly is normally not necessary since we're about to + * close it anyway (which would normally release the lock). However, when + * we're the main process running with --fork, our newborn children may hold a + * copy of the fd for a moment (until they close the fd themselves). Thus, if + * we don't explicitly remove the lock, there may be a race condition between + * our children closing the fd and us proceeding to re-open and re-lock it. + */ + rec_unlock(); + + if (fclose(rec_file)) pexit("fclose"); + rec_file = NULL; + + rec_restoring_now = 0; +} diff --git a/src/recovery.h b/src/recovery.h new file mode 100644 index 0000000..78f8e78 --- /dev/null +++ b/src/recovery.h @@ -0,0 +1,103 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2006,2010,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Crash recovery routines. + */ + +#ifndef _JOHN_RECOVERY_H +#define _JOHN_RECOVERY_H + +#include + +#include "loader.h" + +/* + * Crash recovery file name and whether it has been "completed" (by adding + * the filename suffix to the session name). + */ +extern char *rec_name; +extern int rec_name_completed; + +/* + * Crash recovery file format version number. + */ +extern int rec_version; + +/* + * Original command line arguments. + */ +extern int rec_argc; +extern char **rec_argv; + +/* + * Checksum (or equivalent) of the file(s) being processed by the current + * cracking mode. + */ +extern unsigned int rec_check; + +/* + * Are we between a rec_restore_args() and a rec_restore_mode()? + */ +extern int rec_restoring_now; + +/* + * Opens the crash recovery file for writing, and sets a function that will + * be called to save cracking mode specific information. + */ +extern void rec_init(struct db_main *db, void (*save_mode)(FILE *file)); + +/* + * Saves the command line arguments and cracking mode specific information. + */ +extern void rec_save(void); + +/* + * Calls log_flush(), optionally calls rec_save(), optionally closes the crash + * recovery file (which unlocks it), and finally optionally removes the file. + * + * The "save" parameter is interpreted as follows: + * + * "save == 1" means to call rec_save(), close the file, and keep it around; + * + * "save == 0" means to skip the rec_save() call and to close and remove the + * file, unless we're the main process of a --fork'ed group of children, in + * which case rec_save() is called and the file is left opened and non-removed; + * + * "save == -1" means to skip the rec_save() call and to close and remove the + * file (unconditionally); + * + * "save == -2" means to skip the rec_save() call and to close the file, yet + * leave it around. + * + * "save == 1" and "save == 0" are used from cracking-mode specific code, + * in the form of calling rec_done(event_abort) or similar. If we're aborting + * a session, we want to update its crash recovery file and keep the file + * around. If the session has completed, we want to remove the file, unless + * we're the main process and we need to wait for children (in which case our + * file is still needed to be able to restart and wait for those children again + * upon --restore). + * + * "save == -1" and "save == -2" are only used by the main process when and as + * appropriate, such as to complete the unfinished work of rec_done(0). + */ +extern void rec_done(int save); + +/* + * Opens the file and restores command line arguments. Leaves the file open. + */ +extern void rec_restore_args(int lock); + +/* + * Restores cracking mode specific information and closes the file. + */ +extern void rec_restore_mode(int (*restore_mode)(FILE *file)); + +#endif diff --git a/src/rpp.c b/src/rpp.c new file mode 100644 index 0000000..d7cef69 --- /dev/null +++ b/src/rpp.c @@ -0,0 +1,205 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2006,2009,2010,2011 by Solar Designer + */ + +#include + +#include "arch.h" +#include "params.h" +#include "config.h" +#include "rpp.h" + +int rpp_init(struct rpp_context *ctx, char *subsection) +{ + struct cfg_list *list; + + if ((list = cfg_get_list(SECTION_RULES, subsection))) + if ((ctx->input = list->head)) { + ctx->count = -1; + return 0; + } + + return 1; +} + +static void rpp_add_char(struct rpp_range *range, unsigned char c) +{ + if (range->flag_r) { + if (range->count >= 0x100) return; + } else { + int index = c / ARCH_BITS; + ARCH_WORD mask = (ARCH_WORD)1 << (c % ARCH_BITS); + + if (range->mask[index] & mask) return; + + range->mask[index] |= mask; + } + + range->chars[range->count++] = (char)c; +} + +static void rpp_process_rule(struct rpp_context *ctx) +{ + struct rpp_range *range; + unsigned char *input, *output, *end; + unsigned char c1, c2, c; + int flag_p, flag_r; + + input = (unsigned char *)ctx->input->data; + output = (unsigned char *)ctx->output; + end = output + RULE_BUFFER_SIZE - 1; + flag_p = flag_r = 0; + ctx->count = ctx->refs_count = 0; + + while (*input && output < end) + switch (*input) { + case '\\': + if (!(c = *++input)) break; + c1 = ctx->count ? '0' : '1'; + c2 = (ctx->count <= 9) ? '0' + ctx->count : '9'; + if (c >= c1 && c <= c2 && ctx->refs_count < RULE_RANGES_MAX) { + struct rpp_ref *ref = &ctx->refs[ctx->refs_count++]; + ref->pos = (char *)output; + ref->range = (c == '0') ? ctx->count - 1 : c - '1'; + } + input++; + if (ctx->count < RULE_RANGES_MAX) + switch (c) { + case 'p': + if ((c2 = *input) == '[' || c2 == '\\') { + flag_p = -1; + break; + } else if (c2 >= '0' && c2 <= '9') { + flag_p = (c2 == '0') ? ctx->count : c2 - '0'; + input++; + break; + } + *output++ = c; + break; + case 'r': + if (*input == '[' || *input == '\\') { + flag_r = 1; + break; + } + /* fall through */ + default: + *output++ = c; + } + break; + + case '[': + if (ctx->count >= RULE_RANGES_MAX) { + *output++ = *input++; + break; + } + input++; + + range = &ctx->ranges[ctx->count++]; + range->pos = (char *)output++; + range->index = range->count = 0; + range->flag_p = flag_p; flag_p = 0; + range->flag_r = flag_r; flag_r = 0; + memset(range->mask, 0, sizeof(range->mask)); + range->chars[0] = 0; + + c1 = 0; + while (*input && *input != ']') + switch (*input) { + case '\\': + if (*++input) rpp_add_char(range, c1 = *input++); + break; + + case '-': + if ((c2 = *++input)) { + input++; + if (c1 && range->count) { + if (c1 > c2) + for (c = c1 - 1; c >= c2; c--) + rpp_add_char(range, c); + else + for (c = c1 + 1; c <= c2; c++) + rpp_add_char(range, c); + } + } + c1 = c2; + break; + + default: + rpp_add_char(range, c1 = *input++); + } + if (*input) input++; + + break; + + default: + *output++ = *input++; + } + + *output = 0; +} + +char *rpp_next(struct rpp_context *ctx) +{ + struct rpp_range *range; + int index, done; + + if (ctx->count < 0) { + if (!ctx->input) return NULL; + rpp_process_rule(ctx); + } + + done = 1; + if ((index = ctx->count - 1) >= 0) { + do { + range = &ctx->ranges[index]; + *range->pos = range->chars[range->index]; + } while (index--); + + index = ctx->count - 1; + do { + range = &ctx->ranges[index]; + if (range->flag_p > 0) + continue; + if (++range->index < range->count) { + if (range->flag_p) + continue; + else + break; + } + range->index = 0; + } while (index--); + + done = index < 0; + + index = ctx->count - 1; + do { + range = &ctx->ranges[index]; + if (range->flag_p <= 0 || range->flag_p > ctx->count) + continue; + if (ctx->ranges[range->flag_p - 1].flag_p) + continue; /* don't bother to support this */ + range->index = ctx->ranges[range->flag_p - 1].index; + if (range->index >= range->count) + range->index = range->count - 1; + } while (index--); + } + + if (ctx->refs_count > 0) { + int ref_index = ctx->refs_count - 1; + do { + index = ctx->refs[ref_index].range; + if (index < ctx->count) { + range = &ctx->ranges[index]; + *ctx->refs[ref_index].pos = *range->pos; + } + } while (ref_index--); + } + + if (done) { + ctx->input = ctx->input->next; + ctx->count = -1; + } + + return ctx->output; +} diff --git a/src/rpp.h b/src/rpp.h new file mode 100644 index 0000000..2a7f6e0 --- /dev/null +++ b/src/rpp.h @@ -0,0 +1,88 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2009,2010 by Solar Designer + */ + +/* + * Rules preprocessor. + */ + +#ifndef _JOHN_RPP_H +#define _JOHN_RPP_H + +#include "arch.h" +#include "params.h" +#include "config.h" + +/* + * Character range. + */ +struct rpp_range { +/* Character position in output rule */ + char *pos; + +/* Number of character values */ + int count; + +/* Current character value index */ + int index; + +/* Whether the range should be processed "in parallel" with preceding ranges */ + int flag_p; + +/* Whether repeated characters should be added or discarded */ + int flag_r; + +/* Present characters bitmask for dupe checking */ + ARCH_WORD mask[0x100 / ARCH_BITS]; + +/* Character values */ + char chars[0x100]; +}; + +/* + * Reference to a character range. + */ +struct rpp_ref { +/* Character position in output rule */ + char *pos; + +/* Range being referenced (by number) */ + int range; +}; + +/* + * Preprocessor context. + */ +struct rpp_context { +/* Current rule before preprocessing */ + struct cfg_line *input; + +/* Current rule after preprocessing */ + char output[RULE_BUFFER_SIZE]; + +/* Number of character ranges in this rule */ + int count; + +/* Number of references to ranges in this rule */ + int refs_count; + +/* References to ranges (mapping of reference number to range number) */ + struct rpp_ref refs[RULE_RANGES_MAX]; + +/* Character ranges */ + struct rpp_range ranges[RULE_RANGES_MAX]; +}; + +/* + * Initializes the preprocessor's context for the supplied configuration file + * rules subsection. Returns a non-zero value on error (no rules found). + */ +extern int rpp_init(struct rpp_context *ctx, char *subsection); + +/* + * Returns a preprocessed rule and moves to the next one. + */ +extern char *rpp_next(struct rpp_context *ctx); + +#endif diff --git a/src/rules.c b/src/rules.c new file mode 100644 index 0000000..35cfe15 --- /dev/null +++ b/src/rules.c @@ -0,0 +1,1030 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2005,2009,2010 by Solar Designer + */ + +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "common.h" +#include "memory.h" +#include "formats.h" +#include "loader.h" +#include "logger.h" +#include "rpp.h" +#include "rules.h" + +/* + * Error codes. + */ +#define RULES_ERROR_NONE 0 +#define RULES_ERROR_END 1 +#define RULES_ERROR_UNKNOWN 2 +#define RULES_ERROR_UNALLOWED 3 +#define RULES_ERROR_POSITION 4 +#define RULES_ERROR_CLASS 5 +#define RULES_ERROR_REJECT 6 + +/* + * Error names. + */ +static const char * const rules_errors[] = { + NULL, /* No error */ + "Unexpected end of rule", + "Unknown command", + "Unallowed command", + "Invalid position code", + "Unknown character class code", + "Unknown rule reject flag" +}; + +/* + * Last error code. + */ +static int rules_errno; + +/* + * Configuration file line number, only set after a rules_check() call if + * rules_errno indicates an error. + */ +static int rules_line; + +static int rules_max_length = 0; + +static struct { + unsigned char vars[0x100]; +/* + * pass == -2 initial syntax checking of rules + * pass == -1 optimization of rules (no-ops are removed) + * pass == 0 actual processing of rules + */ + int pass; +/* + * Some rule commands may temporarily double the length, and we skip a few + * machine words to avoid cache bank conflicts when copying data between the + * buffers. We need three buffers because some rule commands require separate + * input and output buffers and we also need a buffer either for leaving the + * previous mangled word intact for a subsequent comparison (in wordlist mode) + * or for switching between two input words (in "single crack" mode). + * rules_apply() tries to minimize data copying, and thus it may return a + * pointer to any of the three buffers. + */ + union { + char buffer[3][RULE_WORD_SIZE * 2 + CACHE_BANK_SHIFT]; + ARCH_WORD dummy; + } aligned; +/* + * "memory" doesn't have to be static (could as well be on stack), but we keep + * it here to ensure it doesn't occasionally "overlap" with our other data in + * terms of cache tags. + */ + char memory[RULE_WORD_SIZE]; + char *classes[0x100]; +} CC_CACHE_ALIGN rules_data; + +#define rules_pass rules_data.pass +#define rules_classes rules_data.classes +#define rules_vars rules_data.vars +#define buffer rules_data.aligned.buffer +#define memory_buffer rules_data.memory + +#define CONV_SOURCE \ + "`1234567890-=\\qwertyuiop[]asdfghjkl;'zxcvbnm,./" \ + "~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?" +#define CONV_SHIFT \ + "~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?" \ + "`1234567890-=\\qwertyuiop[]asdfghjkl;'zxcvbnm,./" +#define CONV_INVERT \ + "`1234567890-=\\QWERTYUIOP[]ASDFGHJKL;'ZXCVBNM,./" \ + "~!@#$%^&*()_+|qwertyuiop{}asdfghjkl:\"zxcvbnm<>?" +#define CONV_VOWELS \ + "`1234567890-=\\QWeRTYuioP[]aSDFGHJKL;'ZXCVBNM,./" \ + "~!@#$%^&*()_+|QWeRTYuioP{}aSDFGHJKL:\"ZXCVBNM<>?" +#define CONV_RIGHT \ + "1234567890-=\\\\wertyuiop[]]sdfghjkl;''xcvbnm,./\\" \ + "!@#$%^&*()_+||WERTYUIOP{}}SDFGHJKL:\"\"XCVBNM<>?|" +#define CONV_LEFT \ + "``1234567890-=qqwertyuiop[aasdfghjkl;zzxcvbnm,." \ + "~~!@#$%^&*()_+QQWERTYUIOP{AASDFGHJKL:ZZXCVBNM<>" + +#define CHARS_LOWER \ + "abcdefghijklmnopqrstuvwxyz" +#define CHARS_UPPER \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define CHARS_DIGITS \ + "0123456789" + +static char *conv_source = CONV_SOURCE; +static char *conv_shift, *conv_invert, *conv_vowels, *conv_right, *conv_left; +static char *conv_tolower, *conv_toupper; + +#define INVALID_LENGTH 0x81 +#define INFINITE_LENGTH 0xFF + +#define RULE (*rule++) +#define LAST (*(rule - 1)) +#define NEXT (*rule) + +#define REJECT { \ + if (!rules_pass) goto out_NULL; \ +} + +#define VALUE(value) { \ + if (!((value) = RULE)) goto out_ERROR_END; \ +} + +#define POSITION(pos) { \ + if (((pos) = rules_vars[ARCH_INDEX(RULE)]) == INVALID_LENGTH) \ + goto out_ERROR_POSITION; \ +} + +#define CLASS_export_pos(start, true, false) { \ + char value, *class; \ + if ((value = RULE) == '?') { \ + if (!(class = rules_classes[ARCH_INDEX(RULE)])) \ + goto out_ERROR_CLASS; \ + for (pos = (start); ARCH_INDEX(in[pos]); pos++) \ + if (class[ARCH_INDEX(in[pos])]) { \ + true; \ + } else { \ + false; \ + } \ + } else { \ + if (!value) goto out_ERROR_END; \ + for (pos = (start); ARCH_INDEX(in[pos]); pos++) \ + if (in[pos] == value) { \ + true; \ + } else { \ + false; \ + } \ + } \ +} + +#define CLASS(start, true, false) { \ + int pos; \ + CLASS_export_pos(start, true, false); \ +} + +#define SKIP_CLASS { \ + char value; \ + VALUE(value) \ + if (value == '?') VALUE(value) \ +} + +#define CONV(conv) { \ + int pos; \ + for (pos = 0; (in[pos] = (conv)[ARCH_INDEX(in[pos])]); pos++); \ +} + +#define GET_OUT { \ + out = alt; \ + alt = in; \ +} + +static void rules_init_class(char name, char *valid) +{ + char *pos, inv; + + rules_classes[ARCH_INDEX(name)] = + mem_alloc_tiny(0x100, MEM_ALIGN_NONE); + memset(rules_classes[ARCH_INDEX(name)], 0, 0x100); + for (pos = valid; ARCH_INDEX(*pos); pos++) + rules_classes[ARCH_INDEX(name)][ARCH_INDEX(*pos)] = 1; + + if ((name | 0x20) >= 'a' && (name | 0x20) <= 'z') { + inv = name ^ 0x20; + rules_classes[ARCH_INDEX(inv)] = + mem_alloc_tiny(0x100, MEM_ALIGN_NONE); + memset(rules_classes[ARCH_INDEX(inv)], 1, 0x100); + for (pos = valid; ARCH_INDEX(*pos); pos++) + rules_classes[ARCH_INDEX(inv)][ARCH_INDEX(*pos)] = 0; + } +} + +static void rules_init_classes(void) +{ + memset(rules_classes, 0, sizeof(rules_classes)); + + rules_init_class('?', "?"); + rules_init_class('v', "aeiouAEIOU"); + rules_init_class('c', "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ"); + rules_init_class('w', " \t"); + rules_init_class('p', ".,:;'\"?!`"); + rules_init_class('s', "$%^&*()-_+=|\\<>[]{}#@/~"); + rules_init_class('l', CHARS_LOWER); + rules_init_class('u', CHARS_UPPER); + rules_init_class('d', CHARS_DIGITS); + rules_init_class('a', CHARS_LOWER CHARS_UPPER); + rules_init_class('x', CHARS_LOWER CHARS_UPPER CHARS_DIGITS); + rules_init_class('Z', ""); +} + +static char *rules_init_conv(char *src, char *dst) +{ + char *conv; + int pos; + + conv = mem_alloc_tiny(0x100, MEM_ALIGN_NONE); + for (pos = 0; pos < 0x100; pos++) conv[pos] = pos; + + while (*src) + conv[ARCH_INDEX(*src++)] = *dst++; + + return conv; +} + +static void rules_init_convs(void) +{ + conv_shift = rules_init_conv(conv_source, CONV_SHIFT); + conv_invert = rules_init_conv(conv_source, CONV_INVERT); + conv_vowels = rules_init_conv(conv_source, CONV_VOWELS); + conv_right = rules_init_conv(conv_source, CONV_RIGHT); + conv_left = rules_init_conv(conv_source, CONV_LEFT); + + conv_tolower = rules_init_conv(CHARS_UPPER, CHARS_LOWER); + conv_toupper = rules_init_conv(CHARS_LOWER, CHARS_UPPER); +} + +static void rules_init_length(int max_length) +{ + int c; + + memset(rules_vars, INVALID_LENGTH, sizeof(rules_vars)); + + for (c = '0'; c <= '9'; c++) rules_vars[c] = c - '0'; + for (c = 'A'; c <= 'Z'; c++) rules_vars[c] = c - ('A' - 10); + + rules_vars['*'] = rules_max_length = max_length; + rules_vars['-'] = max_length - 1; + rules_vars['+'] = max_length + 1; + + rules_vars['z'] = INFINITE_LENGTH; +} + +void rules_init(int max_length) +{ + rules_pass = 0; + rules_errno = RULES_ERROR_NONE; + + if (max_length > RULE_WORD_SIZE - 1) + max_length = RULE_WORD_SIZE - 1; + + if (max_length == rules_max_length) return; + + if (!rules_max_length) { + rules_init_classes(); + rules_init_convs(); + } + rules_init_length(max_length); +} + +char *rules_reject(char *rule, int split, char *last, struct db_main *db) +{ + static char out_rule[RULE_BUFFER_SIZE]; + + while (RULE) + switch (LAST) { + case ':': + case ' ': + case '\t': + break; + + case '-': + switch (RULE) { + case ':': + continue; + + case 'c': + if (!db) continue; + if (db->format->params.flags & FMT_CASE) continue; + return NULL; + + case '8': + if (!db) continue; + if (db->format->params.flags & FMT_8_BIT) continue; + return NULL; + + case 's': + if (!db) continue; + if (db->options->flags & DB_SPLIT) continue; + return NULL; + + case 'p': + if (split >= 0) continue; + return NULL; + + case '\0': + rules_errno = RULES_ERROR_END; + return NULL; + + default: + rules_errno = RULES_ERROR_REJECT; + return NULL; + } + + default: + goto accept; + } + +accept: + rules_pass--; + strnzcpy(out_rule, rule - 1, sizeof(out_rule)); + rules_apply("", out_rule, split, last); + rules_pass++; + + return out_rule; +} + +char *rules_apply(char *word, char *rule, int split, char *last) +{ + char *in, *alt, *memory = word; + int length; + int which; + + in = buffer[0]; + if (in == last) + in = buffer[2]; + + length = 0; + while (length < RULE_WORD_SIZE - 1) { + if (!(in[length] = word[length])) + break; + length++; + } + +/* + * This check assumes that rules_reject() has optimized the no-op rule + * (a colon) into an empty string. + */ + if (!NEXT) + goto out_OK; + + if (!length) REJECT + + alt = buffer[1]; + if (alt == last) + alt = buffer[2]; + +/* + * This assumes that RULE_WORD_SIZE is small enough that length can't reach or + * exceed INVALID_LENGTH. + */ + rules_vars['l'] = length; + rules_vars['m'] = (unsigned char)length - 1; + + which = 0; + + while (RULE) { + in[RULE_WORD_SIZE - 1] = 0; + + switch (LAST) { +/* Crack 4.1 rules */ + case ':': + case ' ': + case '\t': + if (rules_pass == -1) { + memmove(rule - 1, rule, strlen(rule) + 1); + rule--; + } + break; + + case '<': + { + int pos; + POSITION(pos) + if (length >= pos) REJECT + } + break; + + case '>': + { + int pos; + POSITION(pos) + if (length <= pos) REJECT + } + break; + + case 'l': + CONV(conv_tolower) + break; + + case 'u': + CONV(conv_toupper) + break; + + case 'c': + { + int pos = 0; + if ((in[0] = conv_toupper[ARCH_INDEX(in[0])])) + while (in[++pos]) + in[pos] = + conv_tolower[ARCH_INDEX(in[pos])]; + in[pos] = 0; + } + if (in[0] != 'M' || in[1] != 'c') + break; + in[2] = conv_toupper[ARCH_INDEX(in[2])]; + break; + + case 'r': + { + char *out; + GET_OUT + *(out += length) = 0; + while (*in) + *--out = *in++; + in = out; + } + break; + + case 'd': + memcpy(in + length, in, length); + in[length <<= 1] = 0; + break; + + case 'f': + { + int pos; + in[pos = (length <<= 1)] = 0; + { + char *p = in; + while (*p) + in[--pos] = *p++; + } + } + break; + + case 'p': + if (length < 2) break; + { + int pos = length - 1; + if (strchr("sxz", in[pos]) || + (pos > 1 && in[pos] == 'h' && + (in[pos - 1] == 'c' || in[pos - 1] == 's'))) + strcat(in, "es"); + else + if (in[pos] == 'f' && in[pos - 1] != 'f') + strcpy(&in[pos], "ves"); + else + if (pos > 1 && + in[pos] == 'e' && in[pos - 1] == 'f') + strcpy(&in[pos - 1], "ves"); + else + if (pos > 1 && in[pos] == 'y') { + if (strchr("aeiou", in[pos - 1])) + strcat(in, "s"); + else + strcpy(&in[pos], "ies"); + } else + strcat(in, "s"); + } + length = strlen(in); + break; + + case '$': + VALUE(in[length++]) + in[length] = 0; + break; + + case '^': + { + char *out; + GET_OUT + VALUE(out[0]) + strcpy(&out[1], in); + in = out; + } + length++; + break; + + case 'x': + { + int pos; + POSITION(pos) + if (pos < length) { + char *out; + GET_OUT + in += pos; + POSITION(pos) + strnzcpy(out, in, pos + 1); + length = strlen(in = out); + break; + } + POSITION(pos) + in[length = 0] = 0; + } + break; + + case 'i': + { + int pos; + POSITION(pos) + if (pos < length) { + char *p = in + pos; + memmove(p + 1, p, length++ - pos); + VALUE(*p) + in[length] = 0; + break; + } + } + VALUE(in[length++]) + in[length] = 0; + break; + + case 'o': + { + int pos; + char value; + POSITION(pos) + VALUE(value); + if (pos < length) + in[pos] = value; + } + break; + + case 's': + CLASS(0, in[pos] = NEXT, {}) + { + char value; + VALUE(value) + } + break; + + case '@': + length = 0; + CLASS(0, {}, in[length++] = in[pos]) + in[length] = 0; + break; + + case '!': + CLASS(0, REJECT, {}) + break; + + case '/': + { + int pos; + CLASS_export_pos(0, break, {}) + rules_vars['p'] = pos; + if (in[pos]) break; + } + REJECT + break; + + case '=': + { + int pos; + POSITION(pos) + if (pos >= length) { + SKIP_CLASS + REJECT + } else { + CLASS_export_pos(pos, break, REJECT) + } + } + break; + +/* Crack 5.0 rules */ + case '[': + if (length) { + char *out; + GET_OUT + strcpy(out, &in[1]); + length--; + in = out; + break; + } + in[0] = 0; + break; + + case ']': + if (length) + in[--length] = 0; + break; + + case 'C': + { + int pos = 0; + if ((in[0] = conv_tolower[ARCH_INDEX(in[0])])) + while (in[++pos]) + in[pos] = + conv_toupper[ARCH_INDEX(in[pos])]; + in[pos] = 0; + } + if (in[0] == 'm' && in[1] == 'C') + in[2] = conv_tolower[ARCH_INDEX(in[2])]; + break; + + case 't': + CONV(conv_invert) + break; + + case '(': + CLASS(0, break, REJECT) + break; + + case ')': + if (!length) { + SKIP_CLASS + REJECT + } else { + CLASS(length - 1, break, REJECT) + } + break; + + case '\'': + { + int pos; + POSITION(pos) + if (pos < length) + in[length = pos] = 0; + } + break; + + case '%': + { + int count = 0, required, pos; + POSITION(required) + CLASS_export_pos(0, + if (++count >= required) break, {}) + if (count < required) REJECT + rules_vars['p'] = pos; + } + break; + +/* Rules added in John */ + case 'A': /* append/insert/prepend string */ + { + int pos; + char term; + POSITION(pos) + VALUE(term) + if (pos >= length) { /* append */ + char *start, *end, *p; + start = p = &in[pos = length]; + end = &in[RULE_WORD_SIZE - 1]; + do { + char c = RULE; + if (c == term) + break; + if (p < end) + *p++ = c; + if (c) + continue; + goto out_ERROR_END; + } while (1); + *p = 0; + length += p - start; + break; + } + /* insert or prepend */ + { + char *out, *start, *end, *p; + GET_OUT + memcpy(out, in, pos); + start = p = &out[pos]; + end = &out[RULE_WORD_SIZE - 1]; + do { + char c = RULE; + if (c == term) + break; + if (p < end) + *p++ = c; + if (c) + continue; + goto out_ERROR_END; + } while (1); + strcpy(p, &in[pos]); + length += p - start; + in = out; + } + } + break; + + case 'T': + { + int pos; + POSITION(pos) + in[pos] = conv_invert[ARCH_INDEX(in[pos])]; + } + break; + + case 'D': + { + int pos; + POSITION(pos) + if (pos < length) { + char *out; + GET_OUT + memcpy(out, in, pos); + strcpy(&out[pos], &in[pos + 1]); + length--; + in = out; + } + } + break; + + case '{': + if (length) { + char *out; + GET_OUT + strcpy(out, &in[1]); + in[1] = 0; + strcat(out, in); + in = out; + break; + } + in[0] = 0; + break; + + case '}': + if (length) { + char *out; + int pos; + GET_OUT + out[0] = in[pos = length - 1]; + in[pos] = 0; + strcpy(&out[1], in); + in = out; + break; + } + in[0] = 0; + break; + + case 'S': + CONV(conv_shift); + break; + + case 'V': + CONV(conv_vowels); + break; + + case 'R': + CONV(conv_right); + break; + + case 'L': + CONV(conv_left); + break; + + case 'P': + { + int pos; + if ((pos = length - 1) < 2) break; + if (in[pos] == 'd' && in[pos - 1] == 'e') break; + if (in[pos] == 'y') in[pos] = 'i'; else + if (strchr("bgp", in[pos]) && + !strchr("bgp", in[pos - 1])) { + in[pos + 1] = in[pos]; + in[pos + 2] = 0; + } + if (in[pos] == 'e') + strcat(in, "d"); + else + strcat(in, "ed"); + } + length = strlen(in); + break; + + case 'I': + { + int pos; + if ((pos = length - 1) < 2) break; + if (in[pos] == 'g' && in[pos - 1] == 'n' && + in[pos - 2] == 'i') break; + if (strchr("aeiou", in[pos])) + strcpy(&in[pos], "ing"); + else { + if (strchr("bgp", in[pos]) && + !strchr("bgp", in[pos - 1])) { + in[pos + 1] = in[pos]; + in[pos + 2] = 0; + } + strcat(in, "ing"); + } + } + length = strlen(in); + break; + + case 'M': + strnfcpy(memory = memory_buffer, in, rules_max_length); + rules_vars['m'] = (unsigned char)length - 1; + break; + + case 'Q': + if (!strncmp(memory, in, rules_max_length)) + REJECT + break; + + case 'X': /* append/insert/prepend substring from memory */ + { + int mpos, count, ipos, mleft; + char *inp, *mp; + POSITION(mpos) + POSITION(count) + POSITION(ipos) + mleft = (int)(rules_vars['m'] + 1) - mpos; + if (count > mleft) + count = mleft; + if (count <= 0) + break; + mp = memory + mpos; + if (ipos >= length) { + memcpy(&in[length], mp, count); + in[length += count] = 0; + break; + } + inp = in + ipos; + memmove(inp + count, inp, length - ipos); + in[length += count] = 0; + memcpy(inp, mp, count); + } + break; + + case 'v': /* assign value to numeric variable */ + { + char var; + unsigned char a, s; + VALUE(var) + if (var < 'a' || var > 'k') + goto out_ERROR_POSITION; + rules_vars['l'] = length; + POSITION(a) + POSITION(s) + rules_vars[ARCH_INDEX(var)] = a - s; + } + break; + +/* Additional "single crack" mode rules */ + case '1': + if (split < 0) + goto out_ERROR_UNALLOWED; + if (!split) REJECT + if (which) + memcpy(buffer[2], in, length + 1); + else + strnzcpy(buffer[2], &word[split], + RULE_WORD_SIZE); + length = split; + if (length > RULE_WORD_SIZE - 1) + length = RULE_WORD_SIZE - 1; + memcpy(in, word, length); + in[length] = 0; + which = 1; + break; + + case '2': + if (split < 0) + goto out_ERROR_UNALLOWED; + if (!split) REJECT + if (which) { + memcpy(buffer[2], in, length + 1); + } else { + length = split; + if (length > RULE_WORD_SIZE - 1) + length = RULE_WORD_SIZE - 1; + strnzcpy(buffer[2], word, length + 1); + } + strnzcpy(in, &word[split], RULE_WORD_SIZE); + length = strlen(in); + which = 2; + break; + + case '+': + switch (which) { + case 1: + strcat(in, buffer[2]); + break; + + case 2: + { + char *out; + GET_OUT + strcpy(out, buffer[2]); + strcat(out, in); + in = out; + } + break; + + default: + goto out_ERROR_UNALLOWED; + } + length = strlen(in); + which = 0; + break; + + default: + goto out_ERROR_UNKNOWN; + } + + if (!length) REJECT + } + + if (which) + goto out_which; + +out_OK: + in[rules_max_length] = 0; + if (last) { + if (length > rules_max_length) + length = rules_max_length; + if (length >= ARCH_SIZE - 1) { + if (*(ARCH_WORD *)in != *(ARCH_WORD *)last) + return in; + if (strcmp(&in[ARCH_SIZE - 1], &last[ARCH_SIZE - 1])) + return in; + return NULL; + } + if (last[length]) + return in; + if (memcmp(in, last, length)) + return in; + return NULL; + } + return in; + +out_which: + if (which == 1) { + strcat(in, buffer[2]); + goto out_OK; + } + strcat(buffer[2], in); + in = buffer[2]; + goto out_OK; + +out_ERROR_POSITION: + rules_errno = RULES_ERROR_POSITION; + if (LAST) + goto out_NULL; + +out_ERROR_END: + rules_errno = RULES_ERROR_END; +out_NULL: + return NULL; + +out_ERROR_CLASS: + rules_errno = RULES_ERROR_CLASS; + if (LAST) + goto out_NULL; + goto out_ERROR_END; + +out_ERROR_UNKNOWN: + rules_errno = RULES_ERROR_UNKNOWN; + goto out_NULL; + +out_ERROR_UNALLOWED: + rules_errno = RULES_ERROR_UNALLOWED; + goto out_NULL; +} + +/* + * This function is currently not used outside of rules.c, thus not exported. + * + * Checks if all the rules for context are valid. Returns the number of rules, + * or returns zero and sets rules_errno on error. + * + * split == 0 "single crack" mode rules allowed + * split < 0 "single crack" mode rules are invalid + */ +static int rules_check(struct rpp_context *start, int split) +{ + struct rpp_context ctx; + char *rule; + int count; + + rules_errno = RULES_ERROR_NONE; + + memcpy(&ctx, start, sizeof(ctx)); + rules_line = ctx.input->number; + count = 0; + + rules_pass = -1; /* rules_reject() will turn this into -2 */ + while ((rule = rpp_next(&ctx))) { + rules_reject(rule, split, NULL, NULL); + if (rules_errno) break; + + if (ctx.input) rules_line = ctx.input->number; + count++; + } + rules_pass = 0; + + return rules_errno ? 0 : count; +} + +int rules_count(struct rpp_context *start, int split) +{ + int count; + + if (!(count = rules_check(start, split))) { + log_event("! Invalid rule at line %d: %.100s", + rules_line, rules_errors[rules_errno]); + fprintf(stderr, "Invalid rule in %s at line %d: %s\n", + cfg_name, rules_line, + rules_errors[rules_errno]); + error(); + } + + return count; +} diff --git a/src/rules.h b/src/rules.h new file mode 100644 index 0000000..6fa0f6f --- /dev/null +++ b/src/rules.h @@ -0,0 +1,57 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98,2009 by Solar Designer + */ + +/* + * Rules support routines. + */ + +#ifndef _JOHN_RULES_H +#define _JOHN_RULES_H + +#include "loader.h" +#include "rpp.h" + +/* + * Initializes the rules support. + */ +extern void rules_init(int max_length); + +/* + * Processes rule reject flags, based on information from the database. + * Returns a pointer to the first command in the rule if it's accepted, + * or NULL if rejected or an error occurred. Also sets rules_errno on + * error. If the database is NULL, almost all rules are accepted (to be + * used for syntax checking). + * + * split == 0 "single crack" mode rules allowed + * split < 0 "single crack" mode rules are invalid + * + * last may specify which internal buffer must not be touched. + */ +extern char *rules_reject(char *rule, int split, char *last, + struct db_main *db); + +/* + * Applies rule to a word. Returns the updated word, or NULL if rejected or + * an error occurred. Also sets rules_errno on error. + * + * split > 0 "single crack" mode, split is the second word's position + * split == 0 "single crack" mode, only one word + * split < 0 other cracking modes, "single crack" mode rules are invalid + * + * If last is non-NULL, it should be the previous mangled word and it is + * assumed to be properly aligned for ARCH_WORD accesses (pointers returned by + * rules_apply() are properly aligned). If the new mangled word matches the + * previous one, it will be rejected (rules_apply() will return NULL). + */ +extern char *rules_apply(char *word, char *rule, int split, char *last); + +/* + * Similar to rules_check(), but displays a message and does not return on + * error. + */ +extern int rules_count(struct rpp_context *start, int split); + +#endif diff --git a/src/sboxes-s.c b/src/sboxes-s.c new file mode 100644 index 0000000..852a474 --- /dev/null +++ b/src/sboxes-s.c @@ -0,0 +1,1400 @@ +/* + * Bitslice DES S-boxes making use of a vector conditional select operation + * (e.g., vsel on PowerPC with AltiVec). + * + * Gate counts: 36 33 33 26 35 34 34 32 + * Average: 32.875 + * + * Several same-gate-count expressions for each S-box are included (for use on + * different CPUs/GPUs). + * + * These Boolean expressions corresponding to DES S-boxes have been generated + * by Roman Rusakov for use in Openwall's + * John the Ripper password cracker: http://www.openwall.com/john/ + * Being mathematical formulas, they are not copyrighted and are free for reuse + * by anyone. + * + * This file (a specific representation of the S-box expressions, surrounding + * logic) is Copyright (c) 2011 by Solar Designer . + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. (This is a heavily cut-down "BSD license".) + * + * The effort has been sponsored by Rapid7: http://www.rapid7.com + */ + +#undef regs +#if defined(__x86_64__) && defined(__XOP__) +#define regs 16 +#elif defined(__x86_64__) +#define regs 15 +#elif defined(__i386__) +/* Hopefully, AMD XOP (but in 32-bit mode) */ +#define regs 8 +#else +/* PowerPC with AltiVec, etc. */ +#define regs 32 +#endif + +#undef latency +/* Latency 2 may also mean dual-issue with latency 1 */ +#define latency 2 + +#if regs >= 17 || latency >= 3 +/* s1-000010, 36 gates, 17 regs, 8/28/65/102/139 stall cycles */ +MAYBE_INLINE static void +s1(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0F0F3333, x3C3C3C3C, x55FF55FF, x69C369C3, x0903B73F, x09FCB7C0, + x5CA9E295; + vtype x55AFD1B7, x3C3C69C3, x6993B874; + vtype x5CEDE59F, x09FCE295, x5D91A51E, x529E962D; + vtype x29EEADC0, x4B8771A3, x428679F3, x6B68D433; + vtype x5BA7E193, x026F12F3, x6B27C493, x94D83B6C; + vtype x965E0B0F, x3327A113, x847F0A1F, xD6E19C32; + vtype x0DBCE883, x3A25A215, x37994A96; + vtype xC9C93B62, x89490F02, xB96C2D16; + vtype x0, x1, x2, x3; + + vsel(x0F0F3333, a3, a2, a5); + vxor(x3C3C3C3C, a2, a3); + vor(x55FF55FF, a1, a4); + vxor(x69C369C3, x3C3C3C3C, x55FF55FF); + vsel(x0903B73F, a5, x0F0F3333, x69C369C3); + vxor(x09FCB7C0, a4, x0903B73F); + vxor(x5CA9E295, a1, x09FCB7C0); + + vsel(x55AFD1B7, x5CA9E295, x55FF55FF, x0F0F3333); + vsel(x3C3C69C3, x3C3C3C3C, x69C369C3, a5); + vxor(x6993B874, x55AFD1B7, x3C3C69C3); + + vsel(x5CEDE59F, x55FF55FF, x5CA9E295, x6993B874); + vsel(x09FCE295, x09FCB7C0, x5CA9E295, a5); + vsel(x5D91A51E, x5CEDE59F, x6993B874, x09FCE295); + vxor(x529E962D, x0F0F3333, x5D91A51E); + + vsel(x29EEADC0, x69C369C3, x09FCB7C0, x5CEDE59F); + vsel(x4B8771A3, x0F0F3333, x69C369C3, x5CA9E295); + vsel(x428679F3, a5, x4B8771A3, x529E962D); + vxor(x6B68D433, x29EEADC0, x428679F3); + + vsel(x5BA7E193, x5CA9E295, x4B8771A3, a3); + vsel(x026F12F3, a4, x0F0F3333, x529E962D); + vsel(x6B27C493, x6B68D433, x5BA7E193, x026F12F3); + vnot(x94D83B6C, x6B27C493); + vsel(x0, x94D83B6C, x6B68D433, a6); + vxor(*out1, *out1, x0); + + vsel(x965E0B0F, x94D83B6C, a3, x428679F3); + vsel(x3327A113, x5BA7E193, a2, x69C369C3); + vsel(x847F0A1F, x965E0B0F, a4, x3327A113); + vxor(xD6E19C32, x529E962D, x847F0A1F); + vsel(x1, xD6E19C32, x5CA9E295, a6); + vxor(*out2, *out2, x1); + + vsel(x0DBCE883, x09FCE295, x3C3C69C3, x847F0A1F); + vsel(x3A25A215, x3327A113, x5CA9E295, x0903B73F); + vxor(x37994A96, x0DBCE883, x3A25A215); + vsel(x3, x37994A96, x529E962D, a6); + vxor(*out4, *out4, x3); + + vsel(xC9C93B62, x94D83B6C, x69C369C3, x5D91A51E); + vsel(x89490F02, a3, xC9C93B62, x965E0B0F); + vsel(xB96C2D16, x89490F02, x3C3C3C3C, x3A25A215); + vsel(x2, xB96C2D16, x6993B874, a6); + vxor(*out3, *out3, x2); +} +#else +/* s1-000011, 36 gates, 16 regs, 10/37/74/111/148 stall cycles */ +MAYBE_INLINE static void +s1(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0F0F3333, x3C3C3C3C, x55FF55FF, x69C369C3, x0903B73F, x09FCB7C0, + x5CA9E295; + vtype x55AFD1B7, x3C3C69C3, x6993B874; + vtype x5CEDE59F, x09FCE295, x5D91A51E, x529E962D; + vtype x29EEADC0, x4B8771A3, x428679F3, x6B68D433; + vtype x5BA7E193, x026F12F3, x6B27C493, x94D83B6C; + vtype x965E0B0F, x3327A113, x847F0A1F, xD6E19C32; + vtype x0DBCE883, x3A25A215, x37994A96; + vtype x8A487EA7, x8B480F07, xB96C2D16; + vtype x0, x1, x2, x3; + + vsel(x0F0F3333, a3, a2, a5); + vxor(x3C3C3C3C, a2, a3); + vor(x55FF55FF, a1, a4); + vxor(x69C369C3, x3C3C3C3C, x55FF55FF); + vsel(x0903B73F, a5, x0F0F3333, x69C369C3); + vxor(x09FCB7C0, a4, x0903B73F); + vxor(x5CA9E295, a1, x09FCB7C0); + + vsel(x55AFD1B7, x5CA9E295, x55FF55FF, x0F0F3333); + vsel(x3C3C69C3, x3C3C3C3C, x69C369C3, a5); + vxor(x6993B874, x55AFD1B7, x3C3C69C3); + + vsel(x5CEDE59F, x55FF55FF, x5CA9E295, x6993B874); + vsel(x09FCE295, x09FCB7C0, x5CA9E295, a5); + vsel(x5D91A51E, x5CEDE59F, x6993B874, x09FCE295); + vxor(x529E962D, x0F0F3333, x5D91A51E); + + vsel(x29EEADC0, x69C369C3, x09FCB7C0, x5CEDE59F); + vsel(x4B8771A3, x0F0F3333, x69C369C3, x5CA9E295); + vsel(x428679F3, a5, x4B8771A3, x529E962D); + vxor(x6B68D433, x29EEADC0, x428679F3); + + vsel(x5BA7E193, x5CA9E295, x4B8771A3, a3); + vsel(x026F12F3, a4, x0F0F3333, x529E962D); + vsel(x6B27C493, x6B68D433, x5BA7E193, x026F12F3); + vnot(x94D83B6C, x6B27C493); + vsel(x0, x94D83B6C, x6B68D433, a6); + vxor(*out1, *out1, x0); + + vsel(x965E0B0F, x94D83B6C, a3, x428679F3); + vsel(x3327A113, x5BA7E193, a2, x69C369C3); + vsel(x847F0A1F, x965E0B0F, a4, x3327A113); + vxor(xD6E19C32, x529E962D, x847F0A1F); + vsel(x1, xD6E19C32, x5CA9E295, a6); + vxor(*out2, *out2, x1); + + vsel(x0DBCE883, x09FCE295, x3C3C69C3, x847F0A1F); + vsel(x3A25A215, x3327A113, x5CA9E295, x0903B73F); + vxor(x37994A96, x0DBCE883, x3A25A215); + vsel(x3, x37994A96, x529E962D, a6); + vxor(*out4, *out4, x3); + + vxor(x8A487EA7, x5CA9E295, xD6E19C32); + vsel(x8B480F07, a3, x8A487EA7, x847F0A1F); + vsel(xB96C2D16, x8B480F07, x3C3C3C3C, x3A25A215); + vsel(x2, xB96C2D16, x6993B874, a6); + vxor(*out3, *out3, x2); +} +#endif + +#if regs >= 18 && latency <= 2 +/* s2-000000, 33 gates, 18 regs, 3/26/57/90/125 stall cycles */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55553333, x0055FF33, x33270F03, x66725A56, x00FFFF00, x668DA556; + vtype x0F0F5A56, xF0F0A5A9, xA5A5969A, xA55A699A; + vtype x0F5AF03C, x6600FF56, x87A5F09C; + vtype xA55A963C, x3C69C30F, xB44BC32D; + vtype x66D7CC56, x0F4B0F2D, x699CC37B, x996C66D2; + vtype xB46C662D, x278DB412, xB66CB43B; + vtype xD2DC4E52, x27993333, xD2994E33; + vtype x278D0F2D, x2E0E547B, x09976748; + vtype x0, x1, x2, x3; + + vsel(x55553333, a1, a3, a6); + vsel(x0055FF33, a6, x55553333, a5); + vsel(x33270F03, a3, a4, x0055FF33); + vxor(x66725A56, a1, x33270F03); + vxor(x00FFFF00, a5, a6); + vxor(x668DA556, x66725A56, x00FFFF00); + + vsel(x0F0F5A56, a4, x66725A56, a6); + vnot(xF0F0A5A9, x0F0F5A56); + vxor(xA5A5969A, x55553333, xF0F0A5A9); + vxor(xA55A699A, x00FFFF00, xA5A5969A); + vsel(x1, xA55A699A, x668DA556, a2); + vxor(*out2, *out2, x1); + + vxor(x0F5AF03C, a4, x0055FF33); + vsel(x6600FF56, x66725A56, a6, x00FFFF00); + vsel(x87A5F09C, xA5A5969A, x0F5AF03C, x6600FF56); + + vsel(xA55A963C, xA5A5969A, x0F5AF03C, a5); + vxor(x3C69C30F, a3, x0F5AF03C); + vsel(xB44BC32D, xA55A963C, x3C69C30F, a1); + + vsel(x66D7CC56, x66725A56, x668DA556, xA5A5969A); + vsel(x0F4B0F2D, a4, xB44BC32D, a5); + vxor(x699CC37B, x66D7CC56, x0F4B0F2D); + vxor(x996C66D2, xF0F0A5A9, x699CC37B); + vsel(x0, x996C66D2, xB44BC32D, a2); + vxor(*out1, *out1, x0); + + vsel(xB46C662D, xB44BC32D, x996C66D2, x00FFFF00); + vsel(x278DB412, x668DA556, xA5A5969A, a1); + vsel(xB66CB43B, xB46C662D, x278DB412, x6600FF56); + + vsel(xD2DC4E52, x66D7CC56, x996C66D2, xB44BC32D); + vsel(x27993333, x278DB412, a3, x0055FF33); + vsel(xD2994E33, xD2DC4E52, x27993333, a5); + vsel(x3, x87A5F09C, xD2994E33, a2); + vxor(*out4, *out4, x3); + + vsel(x278D0F2D, x278DB412, x0F4B0F2D, a6); + vsel(x2E0E547B, x0F0F5A56, xB66CB43B, x278D0F2D); + vxor(x09976748, x27993333, x2E0E547B); + vsel(x2, xB66CB43B, x09976748, a2); + vxor(*out3, *out3, x2); +} +#elif regs >= 18 && latency >= 4 +/* s2-000002, 33 gates, 18 regs, 4/22/49/82/117 stall cycles */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55553333, x0055FF33, x33270F03, x66725A56, x00FFFF00, x668DA556; + vtype x0F0F5A56, xF0F0A5A9, xA5A5969A, xA55A699A; + vtype x0F5AF03C, x6600FF56, x87A5F09C; + vtype xA55A963C, x3C69C30F, xB44BC32D; + vtype x0F4B0F2D, x66D7CC56, x962769FF, x996C66D2; + vtype xB46C662D, x278DB412, xB66CB43B; + vtype xD2DC4E52, x27993333, xD2994E33; + vtype x278D0F2D, x2E0E547B, x09976748; + vtype x0, x1, x2, x3; + + vsel(x55553333, a1, a3, a6); + vsel(x0055FF33, a6, x55553333, a5); + vsel(x33270F03, a3, a4, x0055FF33); + vxor(x66725A56, a1, x33270F03); + vxor(x00FFFF00, a5, a6); + vxor(x668DA556, x66725A56, x00FFFF00); + + vsel(x0F0F5A56, a4, x66725A56, a6); + vnot(xF0F0A5A9, x0F0F5A56); + vxor(xA5A5969A, x55553333, xF0F0A5A9); + vxor(xA55A699A, x00FFFF00, xA5A5969A); + vsel(x1, xA55A699A, x668DA556, a2); + vxor(*out2, *out2, x1); + + vxor(x0F5AF03C, a4, x0055FF33); + vsel(x6600FF56, x66725A56, a6, x00FFFF00); + vsel(x87A5F09C, xA5A5969A, x0F5AF03C, x6600FF56); + + vsel(xA55A963C, xA5A5969A, x0F5AF03C, a5); + vxor(x3C69C30F, a3, x0F5AF03C); + vsel(xB44BC32D, xA55A963C, x3C69C30F, a1); + + vsel(x0F4B0F2D, a4, xB44BC32D, a5); + vsel(x66D7CC56, x66725A56, x668DA556, xA5A5969A); + vxor(x962769FF, xF0F0A5A9, x66D7CC56); + vxor(x996C66D2, x0F4B0F2D, x962769FF); + vsel(x0, x996C66D2, xB44BC32D, a2); + vxor(*out1, *out1, x0); + + vsel(xB46C662D, xB44BC32D, x996C66D2, x00FFFF00); + vsel(x278DB412, x668DA556, xA5A5969A, a1); + vsel(xB66CB43B, xB46C662D, x278DB412, x6600FF56); + + vsel(xD2DC4E52, x66D7CC56, x996C66D2, xB44BC32D); + vsel(x27993333, x278DB412, a3, x0055FF33); + vsel(xD2994E33, xD2DC4E52, x27993333, a5); + vsel(x3, x87A5F09C, xD2994E33, a2); + vxor(*out4, *out4, x3); + + vsel(x278D0F2D, x278DB412, x0F4B0F2D, a6); + vsel(x2E0E547B, x0F0F5A56, xB66CB43B, x278D0F2D); + vxor(x09976748, x27993333, x2E0E547B); + vsel(x2, xB66CB43B, x09976748, a2); + vxor(*out3, *out3, x2); +} +#else +/* s2-000012, 33 gates, 17 regs, 5/17/51/86/121 stall cycles */ +MAYBE_INLINE static void +s2(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x55553333, x0055FF33, x33270F03, x66725A56, x00FFFF00, x668DA556; + vtype x0F0F5A56, xF0F0A5A9, xA5A5969A, xA55A699A; + vtype x0F5AF03C, x6600FF56, x87A5F09C; + vtype x875AF03C, xF00F0FA9, xB44BC32D; + vtype x6627A556, xD26C667B, x278DB412, xB66CB43B; + vtype x668DC32D, x99723CD2, x996C66D2; + vtype xD20E4EA9, x27993333, xD2994E33; + vtype x9927C3E1, x089F3F0C, x09976748; + vtype x0, x1, x2, x3; + + vsel(x55553333, a1, a3, a6); + vsel(x0055FF33, a6, x55553333, a5); + vsel(x33270F03, a3, a4, x0055FF33); + vxor(x66725A56, a1, x33270F03); + vxor(x00FFFF00, a5, a6); + vxor(x668DA556, x66725A56, x00FFFF00); + + vsel(x0F0F5A56, a4, x66725A56, a6); + vnot(xF0F0A5A9, x0F0F5A56); + vxor(xA5A5969A, x55553333, xF0F0A5A9); + vxor(xA55A699A, x00FFFF00, xA5A5969A); + vsel(x1, xA55A699A, x668DA556, a2); + vxor(*out2, *out2, x1); + + vxor(x0F5AF03C, a4, x0055FF33); + vsel(x6600FF56, x66725A56, a6, x00FFFF00); + vsel(x87A5F09C, xA5A5969A, x0F5AF03C, x6600FF56); + + vsel(x875AF03C, x87A5F09C, x0F5AF03C, a5); + vsel(xF00F0FA9, xF0F0A5A9, a4, x00FFFF00); + vsel(xB44BC32D, x875AF03C, xF00F0FA9, a3); + + vsel(x6627A556, x66725A56, x668DA556, x0055FF33); + vxor(xD26C667B, xB44BC32D, x6627A556); + vsel(x278DB412, x668DA556, xA5A5969A, a1); + vsel(xB66CB43B, xD26C667B, x278DB412, x6600FF56); + + vsel(x668DC32D, x668DA556, xB44BC32D, a6); + vnot(x99723CD2, x668DC32D); + vsel(x996C66D2, x99723CD2, xD26C667B, x00FFFF00); + vsel(x0, x996C66D2, xB44BC32D, a2); + vxor(*out1, *out1, x0); + + vsel(xD20E4EA9, xF00F0FA9, xD26C667B, x668DC32D); + vsel(x27993333, x278DB412, a3, x0055FF33); + vsel(xD2994E33, xD20E4EA9, x27993333, a5); + vsel(x3, x87A5F09C, xD2994E33, a2); + vxor(*out4, *out4, x3); + + vxor(x9927C3E1, x0055FF33, x99723CD2); + vsel(x089F3F0C, a4, x00FFFF00, x27993333); + vsel(x09976748, x089F3F0C, x9927C3E1, x0F0F5A56); + vsel(x2, xB66CB43B, x09976748, a2); + vxor(*out3, *out3, x2); +} +#endif + +#if latency >= 3 +/* s3-000000, 33 gates, 17 regs, 6/10/33/66/102 stall cycles */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0F330F33, x0F33F0CC, x5A66A599; + vtype x2111B7BB, x03FF3033, x05BB50EE, x074F201F, x265E97A4; + vtype x556BA09E, x665A93AC, x99A56C53; + vtype x25A1A797, x5713754C, x66559355, x47B135C6; + vtype x9A5A5C60, xD07AF8F8, x87698DB4, xE13C1EE1; + vtype x9E48CDE4, x655B905E, x00A55CFF, x9E49915E; + vtype xD6599874, x05330022, xD2699876; + vtype x665F9364, xD573F0F2, xB32C6396; + vtype x0, x1, x2, x3; + + vsel(x0F330F33, a4, a3, a5); + vxor(x0F33F0CC, a6, x0F330F33); + vxor(x5A66A599, a2, x0F33F0CC); + + vsel(x2111B7BB, a3, a6, x5A66A599); + vsel(x03FF3033, a5, a3, x0F33F0CC); + vsel(x05BB50EE, a5, x0F33F0CC, a2); + vsel(x074F201F, x03FF3033, a4, x05BB50EE); + vxor(x265E97A4, x2111B7BB, x074F201F); + + vsel(x556BA09E, x5A66A599, x05BB50EE, a4); + vsel(x665A93AC, x556BA09E, x265E97A4, a3); + vnot(x99A56C53, x665A93AC); + vsel(x1, x265E97A4, x99A56C53, a1); + vxor(*out2, *out2, x1); + + vxor(x25A1A797, x03FF3033, x265E97A4); + vsel(x5713754C, a2, x0F33F0CC, x074F201F); + vsel(x66559355, x665A93AC, a2, a5); + vsel(x47B135C6, x25A1A797, x5713754C, x66559355); + + vxor(x9A5A5C60, x03FF3033, x99A56C53); + vsel(xD07AF8F8, x9A5A5C60, x556BA09E, x5A66A599); + vxor(x87698DB4, x5713754C, xD07AF8F8); + vxor(xE13C1EE1, x66559355, x87698DB4); + + vsel(x9E48CDE4, x9A5A5C60, x87698DB4, x265E97A4); + vsel(x655B905E, x66559355, x05BB50EE, a4); + vsel(x00A55CFF, a5, a6, x9A5A5C60); + vsel(x9E49915E, x9E48CDE4, x655B905E, x00A55CFF); + vsel(x0, x9E49915E, xE13C1EE1, a1); + vxor(*out1, *out1, x0); + + vsel(xD6599874, xD07AF8F8, x66559355, x0F33F0CC); + vand(x05330022, x0F330F33, x05BB50EE); + vsel(xD2699876, xD6599874, x00A55CFF, x05330022); + vsel(x3, x5A66A599, xD2699876, a1); + vxor(*out4, *out4, x3); + + vsel(x665F9364, x265E97A4, x66559355, x47B135C6); + vsel(xD573F0F2, xD07AF8F8, x05330022, a4); + vxor(xB32C6396, x665F9364, xD573F0F2); + vsel(x2, xB32C6396, x47B135C6, a1); + vxor(*out3, *out3, x2); +} +#else +/* s3-000004, 33 gates, 17 regs, 3/13/41/77/113 stall cycles */ +MAYBE_INLINE static void +s3(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0F330F33, x0F33F0CC, x5A66A599; + vtype x2111B7BB, x03FF3033, x05BB50EE, x074F201F, x265E97A4; + vtype x556BA09E, x665A93AC, x99A56C53; + vtype x25A1A797, x5713754C, x66559355, x47B135C6; + vtype x9A5A5C60, xD07AF8F8, x87698DB4, xE13C1EE1; + vtype x000CFFCF, x9A485CCE, x0521DDF4, x9E49915E; + vtype xD069F8B4, x030FF0C3, xD2699876; + vtype xD579DDF4, xD579F0C3, xB32C6396; + vtype x0, x1, x2, x3; + + vsel(x0F330F33, a4, a3, a5); + vxor(x0F33F0CC, a6, x0F330F33); + vxor(x5A66A599, a2, x0F33F0CC); + + vsel(x2111B7BB, a3, a6, x5A66A599); + vsel(x03FF3033, a5, a3, x0F33F0CC); + vsel(x05BB50EE, a5, x0F33F0CC, a2); + vsel(x074F201F, x03FF3033, a4, x05BB50EE); + vxor(x265E97A4, x2111B7BB, x074F201F); + + vsel(x556BA09E, x5A66A599, x05BB50EE, a4); + vsel(x665A93AC, x556BA09E, x265E97A4, a3); + vnot(x99A56C53, x665A93AC); + vsel(x1, x265E97A4, x99A56C53, a1); + vxor(*out2, *out2, x1); + + vxor(x25A1A797, x03FF3033, x265E97A4); + vsel(x5713754C, a2, x0F33F0CC, x074F201F); + vsel(x66559355, x665A93AC, a2, a5); + vsel(x47B135C6, x25A1A797, x5713754C, x66559355); + + vxor(x9A5A5C60, x03FF3033, x99A56C53); + vsel(xD07AF8F8, x9A5A5C60, x556BA09E, x5A66A599); + vxor(x87698DB4, x5713754C, xD07AF8F8); + vxor(xE13C1EE1, x66559355, x87698DB4); + + vsel(x000CFFCF, a4, a6, x0F33F0CC); + vsel(x9A485CCE, x9A5A5C60, x000CFFCF, x05BB50EE); + vsel(x0521DDF4, x87698DB4, a6, x9A5A5C60); + vsel(x9E49915E, x9A485CCE, x66559355, x0521DDF4); + vsel(x0, x9E49915E, xE13C1EE1, a1); + vxor(*out1, *out1, x0); + + vsel(xD069F8B4, xD07AF8F8, x87698DB4, a5); + vsel(x030FF0C3, x000CFFCF, x03FF3033, a4); + vsel(xD2699876, xD069F8B4, x9E49915E, x030FF0C3); + vsel(x3, x5A66A599, xD2699876, a1); + vxor(*out4, *out4, x3); + + vsel(xD579DDF4, xD07AF8F8, a2, x5713754C); + vsel(xD579F0C3, xD579DDF4, x030FF0C3, a6); + vxor(xB32C6396, x66559355, xD579F0C3); + vsel(x2, xB32C6396, x47B135C6, a1); + vxor(*out3, *out3, x2); +} +#endif + +#if regs >= 13 +/* s4-000014, 26 gates, 13 regs, 2/17/42/70/98 stall cycles */ +MAYBE_INLINE static void +s4(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0505AFAF, x0555AF55, x0A5AA05A, x46566456, x0A0A5F5F, x0AF55FA0, + x0AF50F0F, x4CA36B59; + vtype xB35C94A6; + vtype x01BB23BB, x5050FAFA, xA31C26BE, xA91679E1; + vtype x56E9861E; + vtype x50E9FA1E, x0AF55F00, x827D9784, xD2946D9A; + vtype x31F720B3, x11FB21B3, x4712A7AD, x9586CA37; + vtype x0, x1, x2, x3; + + vsel(x0505AFAF, a5, a3, a1); + vsel(x0555AF55, x0505AFAF, a1, a4); + vxor(x0A5AA05A, a3, x0555AF55); + vsel(x46566456, a1, x0A5AA05A, a2); + vsel(x0A0A5F5F, a3, a5, a1); + vxor(x0AF55FA0, a4, x0A0A5F5F); + vsel(x0AF50F0F, x0AF55FA0, a3, a5); + vxor(x4CA36B59, x46566456, x0AF50F0F); + + vnot(xB35C94A6, x4CA36B59); + + vsel(x01BB23BB, a4, a2, x0555AF55); + vxor(x5050FAFA, a1, x0505AFAF); + vsel(xA31C26BE, xB35C94A6, x01BB23BB, x5050FAFA); + vxor(xA91679E1, x0A0A5F5F, xA31C26BE); + + vnot(x56E9861E, xA91679E1); + + vsel(x50E9FA1E, x5050FAFA, x56E9861E, a4); + vsel(x0AF55F00, x0AF50F0F, x0AF55FA0, x0A0A5F5F); + vsel(x827D9784, xB35C94A6, x0AF55F00, a2); + vxor(xD2946D9A, x50E9FA1E, x827D9784); + vsel(x2, xD2946D9A, x4CA36B59, a6); + vxor(*out3, *out3, x2); + vsel(x3, xB35C94A6, xD2946D9A, a6); + vxor(*out4, *out4, x3); + + vsel(x31F720B3, a2, a4, x0AF55FA0); + vsel(x11FB21B3, x01BB23BB, x31F720B3, x5050FAFA); + vxor(x4712A7AD, x56E9861E, x11FB21B3); + vxor(x9586CA37, xD2946D9A, x4712A7AD); + vsel(x0, x56E9861E, x9586CA37, a6); + vxor(*out1, *out1, x0); + vsel(x1, x9586CA37, xA91679E1, a6); + vxor(*out2, *out2, x1); +} +#else +/* s4-000033, 26 gates, 12 regs, 4/22/48/76/104 stall cycles */ +MAYBE_INLINE static void +s4(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0505AFAF, x0555AF55, x0A5AA05A, x46566456, x0A0A5F5F, x0AF55FA0, + x0AF50F0F, x4CA36B59; + vtype xB35C94A6; + vtype x01BB23BB, x5050FAFA, xA31C26BE, xA91679E1; + vtype x56E9861E; + vtype x50E9FA1E, x0AF55F00, x827D9784, xD2946D9A; + vtype xD2F56D00, x46F9870F, x4773A737, x9586CA37; + vtype x0, x1, x2, x3; + + vsel(x0505AFAF, a5, a3, a1); + vsel(x0555AF55, x0505AFAF, a1, a4); + vxor(x0A5AA05A, a3, x0555AF55); + vsel(x46566456, a1, x0A5AA05A, a2); + vsel(x0A0A5F5F, a3, a5, a1); + vxor(x0AF55FA0, a4, x0A0A5F5F); + vsel(x0AF50F0F, x0AF55FA0, a3, a5); + vxor(x4CA36B59, x46566456, x0AF50F0F); + + vnot(xB35C94A6, x4CA36B59); + + vsel(x01BB23BB, a4, a2, x0555AF55); + vxor(x5050FAFA, a1, x0505AFAF); + vsel(xA31C26BE, xB35C94A6, x01BB23BB, x5050FAFA); + vxor(xA91679E1, x0A0A5F5F, xA31C26BE); + + vnot(x56E9861E, xA91679E1); + + vsel(x50E9FA1E, x5050FAFA, x56E9861E, a4); + vsel(x0AF55F00, x0AF50F0F, x0AF55FA0, x0A0A5F5F); + vsel(x827D9784, xB35C94A6, x0AF55F00, a2); + vxor(xD2946D9A, x50E9FA1E, x827D9784); + vsel(x2, xD2946D9A, x4CA36B59, a6); + vxor(*out3, *out3, x2); + vsel(x3, xB35C94A6, xD2946D9A, a6); + vxor(*out4, *out4, x3); + + vsel(xD2F56D00, xD2946D9A, x0AF55F00, a4); + vsel(x46F9870F, x56E9861E, x0AF50F0F, a2); + vsel(x4773A737, x46F9870F, a2, x01BB23BB); + vxor(x9586CA37, xD2F56D00, x4773A737); + vsel(x0, x56E9861E, x9586CA37, a6); + vxor(*out1, *out1, x0); + vsel(x1, x9586CA37, xA91679E1, a6); + vxor(*out2, *out2, x1); +} +#endif + +#if regs <= 18 && latency <= 2 +/* s5-000000, 35 gates, 18 regs, 7/33/68/105/142 stall cycles */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x550F550F, xAAF0AAF0, xA5F5A5F5, x96C696C6, x00FFFF00, x963969C6; + vtype x2E3C2E3C, xB73121F7, x1501DF0F, x00558A5F, x2E69A463; + vtype x0679ED42, x045157FD, xB32077FF, x9D49D39C; + vtype xAC81CFB2, xF72577AF, x5BA4B81D; + vtype x5BA477AF, x4895469F, x3A35273A, x1A35669A; + vtype x12E6283D, x9E47D3D4, x1A676AB4; + vtype x2E3C69C6, x92C7C296, x369CC1D6; + vtype x891556DF, xE5E77F82, x6CF2295D; + vtype x0, x1, x2, x3; + + vsel(x550F550F, a1, a3, a5); + vnot(xAAF0AAF0, x550F550F); + vsel(xA5F5A5F5, xAAF0AAF0, a1, a3); + vxor(x96C696C6, a2, xA5F5A5F5); + vxor(x00FFFF00, a5, a6); + vxor(x963969C6, x96C696C6, x00FFFF00); + + vsel(x2E3C2E3C, a3, xAAF0AAF0, a2); + vsel(xB73121F7, a2, x963969C6, x96C696C6); + vsel(x1501DF0F, a6, x550F550F, xB73121F7); + vsel(x00558A5F, x1501DF0F, a5, a1); + vxor(x2E69A463, x2E3C2E3C, x00558A5F); + + vsel(x0679ED42, x00FFFF00, x2E69A463, x96C696C6); + vsel(x045157FD, a6, a1, x0679ED42); + vsel(xB32077FF, xB73121F7, a6, x045157FD); + vxor(x9D49D39C, x2E69A463, xB32077FF); + vsel(x2, x9D49D39C, x2E69A463, a4); + vxor(*out3, *out3, x2); + + vsel(xAC81CFB2, xAAF0AAF0, x1501DF0F, x0679ED42); + vsel(xF72577AF, xB32077FF, x550F550F, a1); + vxor(x5BA4B81D, xAC81CFB2, xF72577AF); + vsel(x1, x5BA4B81D, x963969C6, a4); + vxor(*out2, *out2, x1); + + vsel(x5BA477AF, x5BA4B81D, xF72577AF, a6); + vsel(x4895469F, x5BA477AF, x00558A5F, a2); + vsel(x3A35273A, x2E3C2E3C, a2, x963969C6); + vsel(x1A35669A, x4895469F, x3A35273A, x5BA4B81D); + + vsel(x12E6283D, a5, x5BA4B81D, x963969C6); + vsel(x9E47D3D4, x96C696C6, x9D49D39C, xAC81CFB2); + vsel(x1A676AB4, x12E6283D, x9E47D3D4, x4895469F); + + vsel(x2E3C69C6, x2E3C2E3C, x963969C6, a6); + vsel(x92C7C296, x96C696C6, x1A676AB4, a1); + vsel(x369CC1D6, x2E3C69C6, x92C7C296, x5BA4B81D); + vsel(x0, x369CC1D6, x1A676AB4, a4); + vxor(*out1, *out1, x0); + + vsel(x891556DF, xB32077FF, x4895469F, x3A35273A); + vsel(xE5E77F82, xF72577AF, x00FFFF00, x12E6283D); + vxor(x6CF2295D, x891556DF, xE5E77F82); + vsel(x3, x1A35669A, x6CF2295D, a4); + vxor(*out4, *out4, x3); +} +#elif regs == 19 || (regs >= 20 && latency >= 3) +/* s5-000005, 35 gates, 19 regs, 7/29/60/95/132 stall cycles */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x550F550F, xAAF0AAF0, xA5F5A5F5, x96C696C6, x00FFFF00, x963969C6; + vtype x2E3C2E3C, xB73121F7, x1501DF0F, x00558A5F, x2E69A463; + vtype x0679ED42, x045157FD, xB32077FF, x9D49D39C; + vtype xAC81CFB2, xF72577AF, x5BA4B81D; + vtype x5BA477AF, x4895469F, x3A35273A, x1A35669A; + vtype x12E6283D, x9E47D3D4, x1A676AB4; + vtype x2E3CD3D4, x9697C1C6, x369CC1D6; + vtype x891556DF, xE5E77F82, x6CF2295D; + vtype x0, x1, x2, x3; + + vsel(x550F550F, a1, a3, a5); + vnot(xAAF0AAF0, x550F550F); + vsel(xA5F5A5F5, xAAF0AAF0, a1, a3); + vxor(x96C696C6, a2, xA5F5A5F5); + vxor(x00FFFF00, a5, a6); + vxor(x963969C6, x96C696C6, x00FFFF00); + + vsel(x2E3C2E3C, a3, xAAF0AAF0, a2); + vsel(xB73121F7, a2, x963969C6, x96C696C6); + vsel(x1501DF0F, a6, x550F550F, xB73121F7); + vsel(x00558A5F, x1501DF0F, a5, a1); + vxor(x2E69A463, x2E3C2E3C, x00558A5F); + + vsel(x0679ED42, x00FFFF00, x2E69A463, x96C696C6); + vsel(x045157FD, a6, a1, x0679ED42); + vsel(xB32077FF, xB73121F7, a6, x045157FD); + vxor(x9D49D39C, x2E69A463, xB32077FF); + vsel(x2, x9D49D39C, x2E69A463, a4); + vxor(*out3, *out3, x2); + + vsel(xAC81CFB2, xAAF0AAF0, x1501DF0F, x0679ED42); + vsel(xF72577AF, xB32077FF, x550F550F, a1); + vxor(x5BA4B81D, xAC81CFB2, xF72577AF); + vsel(x1, x5BA4B81D, x963969C6, a4); + vxor(*out2, *out2, x1); + + vsel(x5BA477AF, x5BA4B81D, xF72577AF, a6); + vsel(x4895469F, x5BA477AF, x00558A5F, a2); + vsel(x3A35273A, x2E3C2E3C, a2, x963969C6); + vsel(x1A35669A, x4895469F, x3A35273A, x5BA4B81D); + + vsel(x12E6283D, a5, x5BA4B81D, x963969C6); + vsel(x9E47D3D4, x96C696C6, x9D49D39C, xAC81CFB2); + vsel(x1A676AB4, x12E6283D, x9E47D3D4, x4895469F); + + vsel(x2E3CD3D4, x2E3C2E3C, x9E47D3D4, a6); + vsel(x9697C1C6, x96C696C6, x963969C6, x045157FD); + vsel(x369CC1D6, x2E3CD3D4, x9697C1C6, x5BA477AF); + vsel(x0, x369CC1D6, x1A676AB4, a4); + vxor(*out1, *out1, x0); + + vsel(x891556DF, xB32077FF, x4895469F, x3A35273A); + vsel(xE5E77F82, xF72577AF, x00FFFF00, x12E6283D); + vxor(x6CF2295D, x891556DF, xE5E77F82); + vsel(x3, x1A35669A, x6CF2295D, a4); + vxor(*out4, *out4, x3); +} +#elif regs <= 18 && latency >= 5 +/* s5-000011, 35 gates, 18 regs, 9/31/62/95/132 stall cycles */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x550F550F, xAAF0AAF0, xA5F5A5F5, x96C696C6, x00FFFF00, x963969C6; + vtype x2E3C2E3C, xB73121F7, x1501DF0F, x00558A5F, x2E69A463; + vtype x0679ED42, x045157FD, xB32077FF, x9D49D39C; + vtype xAC81CFB2, xF72577AF, x5BA4B81D; + vtype x5BA477AF, x4895469F, x3A35273A, x1A35669A; + vtype x12E6283D, x9E47D3D4, x1A676AB4; + vtype x2E3CD3D4, x96DF41C6, x369CC1D6; + vtype x891556DF, xE5E77F82, x6CF2295D; + vtype x0, x1, x2, x3; + + vsel(x550F550F, a1, a3, a5); + vnot(xAAF0AAF0, x550F550F); + vsel(xA5F5A5F5, xAAF0AAF0, a1, a3); + vxor(x96C696C6, a2, xA5F5A5F5); + vxor(x00FFFF00, a5, a6); + vxor(x963969C6, x96C696C6, x00FFFF00); + + vsel(x2E3C2E3C, a3, xAAF0AAF0, a2); + vsel(xB73121F7, a2, x963969C6, x96C696C6); + vsel(x1501DF0F, a6, x550F550F, xB73121F7); + vsel(x00558A5F, x1501DF0F, a5, a1); + vxor(x2E69A463, x2E3C2E3C, x00558A5F); + + vsel(x0679ED42, x00FFFF00, x2E69A463, x96C696C6); + vsel(x045157FD, a6, a1, x0679ED42); + vsel(xB32077FF, xB73121F7, a6, x045157FD); + vxor(x9D49D39C, x2E69A463, xB32077FF); + vsel(x2, x9D49D39C, x2E69A463, a4); + vxor(*out3, *out3, x2); + + vsel(xAC81CFB2, xAAF0AAF0, x1501DF0F, x0679ED42); + vsel(xF72577AF, xB32077FF, x550F550F, a1); + vxor(x5BA4B81D, xAC81CFB2, xF72577AF); + vsel(x1, x5BA4B81D, x963969C6, a4); + vxor(*out2, *out2, x1); + + vsel(x5BA477AF, x5BA4B81D, xF72577AF, a6); + vsel(x4895469F, x5BA477AF, x00558A5F, a2); + vsel(x3A35273A, x2E3C2E3C, a2, x963969C6); + vsel(x1A35669A, x4895469F, x3A35273A, x5BA4B81D); + + vsel(x12E6283D, a5, x5BA4B81D, x963969C6); + vsel(x9E47D3D4, x96C696C6, x9D49D39C, xAC81CFB2); + vsel(x1A676AB4, x12E6283D, x9E47D3D4, x4895469F); + + vsel(x2E3CD3D4, x2E3C2E3C, x9E47D3D4, a6); + vsel(x96DF41C6, x963969C6, x96C696C6, x12E6283D); + vsel(x369CC1D6, x2E3CD3D4, x96DF41C6, x5BA477AF); + vsel(x0, x369CC1D6, x1A676AB4, a4); + vxor(*out1, *out1, x0); + + vsel(x891556DF, xB32077FF, x4895469F, x3A35273A); + vsel(xE5E77F82, xF72577AF, x00FFFF00, x12E6283D); + vxor(x6CF2295D, x891556DF, xE5E77F82); + vsel(x3, x1A35669A, x6CF2295D, a4); + vxor(*out4, *out4, x3); +} +#elif regs >= 20 +/* s5-000016, 35 gates, 20 regs, 6/30/62/98/135 stall cycles */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x550F550F, xAAF0AAF0, xA5F5A5F5, x96C696C6, x00FFFF00, x963969C6; + vtype x2E3C2E3C, xB73121F7, x1501DF0F, x00558A5F, x2E69A463; + vtype x0679ED42, x045157FD, xB32077FF, x9D49D39C; + vtype xAC81CFB2, xF72577AF, x5BA4B81D; + vtype x5BA477AF, x4895469F, x3A35273A, x1A35669A; + vtype x12E6283D, x9E47D3D4, x1A676AB4; + vtype x891556DF, xE5E77F82, x6CF2295D; + vtype x2E3CA5F5, x9697C1C6, x369CC1D6; + vtype x0, x1, x2, x3; + + vsel(x550F550F, a1, a3, a5); + vnot(xAAF0AAF0, x550F550F); + vsel(xA5F5A5F5, xAAF0AAF0, a1, a3); + vxor(x96C696C6, a2, xA5F5A5F5); + vxor(x00FFFF00, a5, a6); + vxor(x963969C6, x96C696C6, x00FFFF00); + + vsel(x2E3C2E3C, a3, xAAF0AAF0, a2); + vsel(xB73121F7, a2, x963969C6, x96C696C6); + vsel(x1501DF0F, a6, x550F550F, xB73121F7); + vsel(x00558A5F, x1501DF0F, a5, a1); + vxor(x2E69A463, x2E3C2E3C, x00558A5F); + + vsel(x0679ED42, x00FFFF00, x2E69A463, x96C696C6); + vsel(x045157FD, a6, a1, x0679ED42); + vsel(xB32077FF, xB73121F7, a6, x045157FD); + vxor(x9D49D39C, x2E69A463, xB32077FF); + vsel(x2, x9D49D39C, x2E69A463, a4); + vxor(*out3, *out3, x2); + + vsel(xAC81CFB2, xAAF0AAF0, x1501DF0F, x0679ED42); + vsel(xF72577AF, xB32077FF, x550F550F, a1); + vxor(x5BA4B81D, xAC81CFB2, xF72577AF); + vsel(x1, x5BA4B81D, x963969C6, a4); + vxor(*out2, *out2, x1); + + vsel(x5BA477AF, x5BA4B81D, xF72577AF, a6); + vsel(x4895469F, x5BA477AF, x00558A5F, a2); + vsel(x3A35273A, x2E3C2E3C, a2, x963969C6); + vsel(x1A35669A, x4895469F, x3A35273A, x5BA4B81D); + + vsel(x12E6283D, a5, x5BA4B81D, x963969C6); + vsel(x9E47D3D4, x96C696C6, x9D49D39C, xAC81CFB2); + vsel(x1A676AB4, x12E6283D, x9E47D3D4, x4895469F); + + vsel(x891556DF, xB32077FF, x4895469F, x3A35273A); + vsel(xE5E77F82, xF72577AF, x00FFFF00, x12E6283D); + vxor(x6CF2295D, x891556DF, xE5E77F82); + vsel(x3, x1A35669A, x6CF2295D, a4); + vxor(*out4, *out4, x3); + + vsel(x2E3CA5F5, x2E3C2E3C, xA5F5A5F5, a6); + vsel(x9697C1C6, x96C696C6, x963969C6, x045157FD); + vsel(x369CC1D6, x2E3CA5F5, x9697C1C6, x5BA477AF); + vsel(x0, x369CC1D6, x1A676AB4, a4); + vxor(*out1, *out1, x0); +} +#else +/* s5-000023, 35 gates, 18 regs, 9/30/61/96/133 stall cycles */ +MAYBE_INLINE static void +s5(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x550F550F, xAAF0AAF0, xA5F5A5F5, x96C696C6, x00FFFF00, x963969C6; + vtype x2E3C2E3C, xB73121F7, x1501DF0F, x00558A5F, x2E69A463; + vtype x0679ED42, x045157FD, xB32077FF, x9D49D39C; + vtype xAC81CFB2, xF72577AF, x5BA4B81D; + vtype x5BA477AF, x4895469F, x3A35273A, x1A35669A; + vtype x12E6283D, x9E47D3D4, x1A676AB4; + vtype x891556DF, xE5E77F82, x6CF2295D; + vtype x2E3CD3D4, x96DF41C6, x369CC1D6; + vtype x0, x1, x2, x3; + + vsel(x550F550F, a1, a3, a5); + vnot(xAAF0AAF0, x550F550F); + vsel(xA5F5A5F5, xAAF0AAF0, a1, a3); + vxor(x96C696C6, a2, xA5F5A5F5); + vxor(x00FFFF00, a5, a6); + vxor(x963969C6, x96C696C6, x00FFFF00); + + vsel(x2E3C2E3C, a3, xAAF0AAF0, a2); + vsel(xB73121F7, a2, x963969C6, x96C696C6); + vsel(x1501DF0F, a6, x550F550F, xB73121F7); + vsel(x00558A5F, x1501DF0F, a5, a1); + vxor(x2E69A463, x2E3C2E3C, x00558A5F); + + vsel(x0679ED42, x00FFFF00, x2E69A463, x96C696C6); + vsel(x045157FD, a6, a1, x0679ED42); + vsel(xB32077FF, xB73121F7, a6, x045157FD); + vxor(x9D49D39C, x2E69A463, xB32077FF); + vsel(x2, x9D49D39C, x2E69A463, a4); + vxor(*out3, *out3, x2); + + vsel(xAC81CFB2, xAAF0AAF0, x1501DF0F, x0679ED42); + vsel(xF72577AF, xB32077FF, x550F550F, a1); + vxor(x5BA4B81D, xAC81CFB2, xF72577AF); + vsel(x1, x5BA4B81D, x963969C6, a4); + vxor(*out2, *out2, x1); + + vsel(x5BA477AF, x5BA4B81D, xF72577AF, a6); + vsel(x4895469F, x5BA477AF, x00558A5F, a2); + vsel(x3A35273A, x2E3C2E3C, a2, x963969C6); + vsel(x1A35669A, x4895469F, x3A35273A, x5BA4B81D); + + vsel(x12E6283D, a5, x5BA4B81D, x963969C6); + vsel(x9E47D3D4, x96C696C6, x9D49D39C, xAC81CFB2); + vsel(x1A676AB4, x12E6283D, x9E47D3D4, x4895469F); + + vsel(x891556DF, xB32077FF, x4895469F, x3A35273A); + vsel(xE5E77F82, xF72577AF, x00FFFF00, x12E6283D); + vxor(x6CF2295D, x891556DF, xE5E77F82); + vsel(x3, x1A35669A, x6CF2295D, a4); + vxor(*out4, *out4, x3); + + vsel(x2E3CD3D4, x2E3C2E3C, x9E47D3D4, a6); + vsel(x96DF41C6, x963969C6, x96C696C6, x12E6283D); + vsel(x369CC1D6, x2E3CD3D4, x96DF41C6, x5BA477AF); + vsel(x0, x369CC1D6, x1A676AB4, a4); + vxor(*out1, *out1, x0); +} +#endif + +#if regs >= 16 && latency <= 2 +/* s6-000000, 34 gates, 16 regs, 5/34/70/107/144 stall cycles */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x555500FF, x666633CC, x606F30CF, x353A659A, x353A9A65, xCAC5659A; + vtype x353A6565, x0A3F0A6F, x6C5939A3, x5963A3C6; + vtype x35FF659A, x3AF06A95, x05CF0A9F, x16E94A97; + vtype x86CD4C9B, x12E0FFFD, x942D9A67; + vtype x142956AB, x455D45DF, x1C3EE619; + vtype x2AEA70D5, x20CF7A9F, x3CF19C86, x69A49C79; + vtype x840DBB67, x6DA19C1E, x925E63E1; + vtype x9C3CA761, x257A75D5, xB946D2B4; + vtype x0, x1, x2, x3; + + vsel(x555500FF, a1, a4, a5); + vxor(x666633CC, a2, x555500FF); + vsel(x606F30CF, x666633CC, a4, a3); + vxor(x353A659A, a1, x606F30CF); + vxor(x353A9A65, a5, x353A659A); + vnot(xCAC5659A, x353A9A65); + + vsel(x353A6565, x353A659A, x353A9A65, a4); + vsel(x0A3F0A6F, a3, a4, x353A6565); + vxor(x6C5939A3, x666633CC, x0A3F0A6F); + vxor(x5963A3C6, x353A9A65, x6C5939A3); + + vsel(x35FF659A, a4, x353A659A, x353A6565); + vxor(x3AF06A95, a3, x35FF659A); + vsel(x05CF0A9F, a4, a3, x353A9A65); + vsel(x16E94A97, x3AF06A95, x05CF0A9F, x6C5939A3); + + vsel(x86CD4C9B, xCAC5659A, x05CF0A9F, x6C5939A3); + vsel(x12E0FFFD, a5, x3AF06A95, x16E94A97); + vsel(x942D9A67, x86CD4C9B, x353A9A65, x12E0FFFD); + vsel(x0, xCAC5659A, x942D9A67, a6); + vxor(*out1, *out1, x0); + + vsel(x142956AB, x353A659A, x942D9A67, a2); + vsel(x455D45DF, a1, x86CD4C9B, x142956AB); + vxor(x1C3EE619, x5963A3C6, x455D45DF); + vsel(x3, x5963A3C6, x1C3EE619, a6); + vxor(*out4, *out4, x3); + + vsel(x2AEA70D5, x3AF06A95, x606F30CF, x353A9A65); + vsel(x20CF7A9F, x2AEA70D5, x05CF0A9F, x0A3F0A6F); + vxor(x3CF19C86, x1C3EE619, x20CF7A9F); + vxor(x69A49C79, x555500FF, x3CF19C86); + + vsel(x840DBB67, a5, x942D9A67, x86CD4C9B); + vsel(x6DA19C1E, x69A49C79, x3CF19C86, x840DBB67); + vnot(x925E63E1, x6DA19C1E); + vsel(x1, x925E63E1, x69A49C79, a6); + vxor(*out2, *out2, x1); + + vsel(x9C3CA761, x840DBB67, x1C3EE619, x3CF19C86); + vsel(x257A75D5, x455D45DF, x2AEA70D5, x606F30CF); + vxor(xB946D2B4, x9C3CA761, x257A75D5); + vsel(x2, x16E94A97, xB946D2B4, a6); + vxor(*out3, *out3, x2); +} +#elif regs == 15 +/* s6-000008, 34 gates, 15 regs, 6/25/57/94/131 stall cycles */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x555500FF, x666633CC, x606F30CF, x353A659A, x353A9A65, xCAC5659A; + vtype x353A6565, x0A3F0A6F, x6C5939A3, x5963A3C6; + vtype x35FF659A, x3AF06A95, x05CF0A9F, x16E94A97; + vtype x86CD4C9B, x12E0FFFD, x942D9A67; + vtype x142956AB, x455D45DF, x1C3EE619; + vtype xC3C36393, x2D1B471E, xC70B631E, x925E63E1; + vtype x8C2F1A67, x965B6386, x69A49C79; + vtype x1C2E8201, xA56850B5, xB946D2B4; + vtype x0, x1, x2, x3; + + vsel(x555500FF, a1, a4, a5); + vxor(x666633CC, a2, x555500FF); + vsel(x606F30CF, x666633CC, a4, a3); + vxor(x353A659A, a1, x606F30CF); + vxor(x353A9A65, a5, x353A659A); + vnot(xCAC5659A, x353A9A65); + + vsel(x353A6565, x353A659A, x353A9A65, a4); + vsel(x0A3F0A6F, a3, a4, x353A6565); + vxor(x6C5939A3, x666633CC, x0A3F0A6F); + vxor(x5963A3C6, x353A9A65, x6C5939A3); + + vsel(x35FF659A, a4, x353A659A, x353A6565); + vxor(x3AF06A95, a3, x35FF659A); + vsel(x05CF0A9F, a4, a3, x353A9A65); + vsel(x16E94A97, x3AF06A95, x05CF0A9F, x6C5939A3); + + vsel(x86CD4C9B, xCAC5659A, x05CF0A9F, x6C5939A3); + vsel(x12E0FFFD, a5, x3AF06A95, x16E94A97); + vsel(x942D9A67, x86CD4C9B, x353A9A65, x12E0FFFD); + vsel(x0, xCAC5659A, x942D9A67, a6); + vxor(*out1, *out1, x0); + + vsel(x142956AB, x353A659A, x942D9A67, a2); + vsel(x455D45DF, a1, x86CD4C9B, x142956AB); + vxor(x1C3EE619, x5963A3C6, x455D45DF); + vsel(x3, x5963A3C6, x1C3EE619, a6); + vxor(*out4, *out4, x3); + + vsel(xC3C36393, xCAC5659A, a2, a3); + vsel(x2D1B471E, x353A659A, a3, x5963A3C6); + vsel(xC70B631E, xC3C36393, x2D1B471E, x05CF0A9F); + vxor(x925E63E1, x555500FF, xC70B631E); + + vsel(x8C2F1A67, x942D9A67, x0A3F0A6F, x5963A3C6); + vsel(x965B6386, x925E63E1, xC70B631E, x8C2F1A67); + vnot(x69A49C79, x965B6386); + vsel(x1, x925E63E1, x69A49C79, a6); + vxor(*out2, *out2, x1); + + vsel(x1C2E8201, x942D9A67, x1C3EE619, x8C2F1A67); + vxor(xA56850B5, a2, x965B6386); + vxor(xB946D2B4, x1C2E8201, xA56850B5); + vsel(x2, x16E94A97, xB946D2B4, a6); + vxor(*out3, *out3, x2); +} +#elif regs <= 14 +/* s6-000082, 34 gates, 14 regs, 8/31/65/102/139 stall cycles */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x555500FF, x666633CC, x606F30CF, x353A659A, x353A9A65, xCAC5659A; + vtype x353A6565, x0A3F0A6F, x6C5939A3, x5963A3C6; + vtype x35FF659A, x3AF06A95, x066F0CCF, x16E94A97; + vtype x1872E297, x35BE6539, x1C3EE619; + vtype x86CD4C9B, x12E0FFFD, x942D9A67; + vtype x0A63C087, x9E4E5AE0, x02FA65FD, x925E63E1; + vtype xAB756193, x8A75E187, xB946D2B4; + vtype x375A7BA0, x965B6386, x69A49C79; + vtype x0, x1, x2, x3; + + vsel(x555500FF, a1, a4, a5); + vxor(x666633CC, a2, x555500FF); + vsel(x606F30CF, x666633CC, a4, a3); + vxor(x353A659A, a1, x606F30CF); + vxor(x353A9A65, a5, x353A659A); + vnot(xCAC5659A, x353A9A65); + + vsel(x353A6565, x353A659A, x353A9A65, a4); + vsel(x0A3F0A6F, a3, a4, x353A6565); + vxor(x6C5939A3, x666633CC, x0A3F0A6F); + vxor(x5963A3C6, x353A9A65, x6C5939A3); + + vsel(x35FF659A, a4, x353A659A, x353A6565); + vxor(x3AF06A95, a3, x35FF659A); + vsel(x066F0CCF, a3, a4, x5963A3C6); + vsel(x16E94A97, x3AF06A95, x066F0CCF, x6C5939A3); + + vsel(x1872E297, x5963A3C6, x3AF06A95, a1); + vsel(x35BE6539, x35FF659A, x353A6565, x6C5939A3); + vsel(x1C3EE619, x1872E297, x35BE6539, x066F0CCF); + vsel(x3, x5963A3C6, x1C3EE619, a6); + vxor(*out4, *out4, x3); + + vsel(x86CD4C9B, xCAC5659A, x066F0CCF, x6C5939A3); + vsel(x12E0FFFD, a5, x3AF06A95, x16E94A97); + vsel(x942D9A67, x86CD4C9B, x353A9A65, x12E0FFFD); + vsel(x0, xCAC5659A, x942D9A67, a6); + vxor(*out1, *out1, x0); + + vsel(x0A63C087, x1872E297, x066F0CCF, a2); + vxor(x9E4E5AE0, x942D9A67, x0A63C087); + vsel(x02FA65FD, x12E0FFFD, a4, x353A9A65); + vsel(x925E63E1, x9E4E5AE0, x02FA65FD, x6C5939A3); + + vsel(xAB756193, a2, xCAC5659A, x9E4E5AE0); + vsel(x8A75E187, x0A63C087, xAB756193, x925E63E1); + vxor(xB946D2B4, a2, x8A75E187); + vsel(x2, x16E94A97, xB946D2B4, a6); + vxor(*out3, *out3, x2); + + vsel(x375A7BA0, a2, x9E4E5AE0, x16E94A97); + vsel(x965B6386, x8A75E187, x375A7BA0, x1C3EE619); + vnot(x69A49C79, x965B6386); + vsel(x1, x925E63E1, x69A49C79, a6); + vxor(*out2, *out2, x1); +} +#else +/* s6-000461, 34 gates, 16 regs, 7/23/48/82/118 stall cycles */ +MAYBE_INLINE static void +s6(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x555500FF, x666633CC, x606F30CF, x353A659A, x353A9A65, xCAC5659A; + vtype x553A5565, x0A3F0A6F, x6C5939A3, x5963A3C6; + vtype x15FF459A, x1AF04A95, x066F0CCF, x16E94A97; + vtype x1872E297, x55BE5539, x1C3EE619; + vtype x86CD4C9B, x12E0FFFD, x942D9A67; + vtype x2FCAD0F0, x1BF21BB1, x466E4C89, x69A49C79; + vtype x965B6386, x12769BE1, x925E63E1; + vtype x9867CA97, x69339C33, xB946D2B4; + vtype x0, x1, x2, x3; + + vsel(x555500FF, a1, a4, a5); + vxor(x666633CC, a2, x555500FF); + vsel(x606F30CF, x666633CC, a4, a3); + vxor(x353A659A, a1, x606F30CF); + vxor(x353A9A65, a5, x353A659A); + vnot(xCAC5659A, x353A9A65); + + vsel(x553A5565, a1, x353A9A65, a4); + vsel(x0A3F0A6F, a3, a4, x553A5565); + vxor(x6C5939A3, x666633CC, x0A3F0A6F); + vxor(x5963A3C6, x353A9A65, x6C5939A3); + + vsel(x15FF459A, a4, x353A659A, x553A5565); + vxor(x1AF04A95, a3, x15FF459A); + vsel(x066F0CCF, a3, a4, x5963A3C6); + vsel(x16E94A97, x1AF04A95, x066F0CCF, x6C5939A3); + + vsel(x1872E297, x5963A3C6, x1AF04A95, a1); + vsel(x55BE5539, x15FF459A, x553A5565, x6C5939A3); + vsel(x1C3EE619, x1872E297, x55BE5539, x066F0CCF); + vsel(x3, x5963A3C6, x1C3EE619, a6); + vxor(*out4, *out4, x3); + + vsel(x86CD4C9B, xCAC5659A, x066F0CCF, x6C5939A3); + vsel(x12E0FFFD, a5, x1AF04A95, x16E94A97); + vsel(x942D9A67, x86CD4C9B, x353A9A65, x12E0FFFD); + vsel(x0, xCAC5659A, x942D9A67, a6); + vxor(*out1, *out1, x0); + + vxor(x2FCAD0F0, x353A9A65, x1AF04A95); + vsel(x1BF21BB1, x1AF04A95, a2, x553A5565); + vsel(x466E4C89, x55BE5539, x066F0CCF, x1BF21BB1); + vxor(x69A49C79, x2FCAD0F0, x466E4C89); + + vnot(x965B6386, x69A49C79); + vsel(x12769BE1, x1BF21BB1, x942D9A67, x69A49C79); + vsel(x925E63E1, x965B6386, x12769BE1, x555500FF); + vsel(x1, x925E63E1, x69A49C79, a6); + vxor(*out2, *out2, x1); + + vsel(x9867CA97, x942D9A67, x1872E297, x2FCAD0F0); + vsel(x69339C33, x69A49C79, a2, a4); + vsel(xB946D2B4, x9867CA97, x2FCAD0F0, x69339C33); + vsel(x2, x16E94A97, xB946D2B4, a6); + vxor(*out3, *out3, x2); +} +#endif + +#if regs <= 16 || latency >= 3 +/* s7-000013, 34 gates, 15 regs, 9/27/56/88/119 stall cycles */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44447777, x4B4B7878, x22772277, x0505F5F5, x220522F5, x694E5A8D; + vtype x00FFFF00, x66666666, x32353235, x26253636, x26DAC936; + vtype x738F9C63, x11EF9867, x26DA9867; + vtype x4B4B9C63, x4B666663, x4E639396; + vtype x4E4B393C, xFF00FF00, xFF05DD21, xB14EE41D; + vtype xD728827B, x6698807B, x699C585B; + vtype x738C847B, xA4A71E18, x74878E78; + vtype x333D9639, x74879639, x8B7869C6; + vtype x0, x1, x2, x3; + + vsel(x44447777, a2, a6, a3); + vxor(x4B4B7878, a4, x44447777); + vsel(x22772277, a3, a5, a2); + vsel(x0505F5F5, a6, a2, a4); + vsel(x220522F5, x22772277, x0505F5F5, a5); + vxor(x694E5A8D, x4B4B7878, x220522F5); + + vxor(x00FFFF00, a5, a6); + vxor(x66666666, a2, a3); + vsel(x32353235, a3, x220522F5, a4); + vsel(x26253636, x66666666, x32353235, x4B4B7878); + vxor(x26DAC936, x00FFFF00, x26253636); + vsel(x0, x26DAC936, x694E5A8D, a1); + vxor(*out1, *out1, x0); + + vxor(x738F9C63, a2, x26DAC936); + vsel(x11EF9867, x738F9C63, a5, x66666666); + vsel(x26DA9867, x26DAC936, x11EF9867, a6); + + vsel(x4B4B9C63, x4B4B7878, x738F9C63, a6); + vsel(x4B666663, x4B4B9C63, x66666666, x00FFFF00); + vxor(x4E639396, x0505F5F5, x4B666663); + + vsel(x4E4B393C, x4B4B7878, x4E639396, a2); + vnot(xFF00FF00, a5); + vsel(xFF05DD21, xFF00FF00, x738F9C63, x32353235); + vxor(xB14EE41D, x4E4B393C, xFF05DD21); + vsel(x1, xB14EE41D, x26DA9867, a1); + vxor(*out2, *out2, x1); + + vxor(xD728827B, x66666666, xB14EE41D); + vsel(x6698807B, x26DA9867, xD728827B, x4E4B393C); + vsel(x699C585B, x6698807B, x694E5A8D, xFF05DD21); + vsel(x2, x699C585B, x4E639396, a1); + vxor(*out3, *out3, x2); + + vsel(x738C847B, x738F9C63, xD728827B, x4B4B7878); + vxor(xA4A71E18, x738F9C63, xD728827B); + vsel(x74878E78, x738C847B, xA4A71E18, a4); + + vsel(x333D9639, x32353235, x738C847B, xB14EE41D); + vsel(x74879639, x74878E78, x333D9639, a6); + vnot(x8B7869C6, x74879639); + vsel(x3, x74878E78, x8B7869C6, a1); + vxor(*out4, *out4, x3); +} +#else +/* s7-000019, 34 gates, 17 regs, 5/28/57/88/119 stall cycles */ +MAYBE_INLINE static void +s7(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x44447777, x4B4B7878, x22772277, x0505F5F5, x220522F5, x694E5A8D; + vtype x00FFFF00, x66666666, x32353235, x26253636, x26DAC936; + vtype x738F9C63, x11EF9867, x26DA9867; + vtype x4B4B9C63, x4B666663, x4E639396; + vtype x4E4B393C, xFF00FF00, xFF05DD21, xB14EE41D; + vtype xD728827B, x6698807B, x699C585B; + vtype x778A8877, xA4A71E18, x74878E78; + vtype x204A5845, x74879639, x8B7869C6; + vtype x0, x1, x2, x3; + + vsel(x44447777, a2, a6, a3); + vxor(x4B4B7878, a4, x44447777); + vsel(x22772277, a3, a5, a2); + vsel(x0505F5F5, a6, a2, a4); + vsel(x220522F5, x22772277, x0505F5F5, a5); + vxor(x694E5A8D, x4B4B7878, x220522F5); + + vxor(x00FFFF00, a5, a6); + vxor(x66666666, a2, a3); + vsel(x32353235, a3, x220522F5, a4); + vsel(x26253636, x66666666, x32353235, x4B4B7878); + vxor(x26DAC936, x00FFFF00, x26253636); + vsel(x0, x26DAC936, x694E5A8D, a1); + vxor(*out1, *out1, x0); + + vxor(x738F9C63, a2, x26DAC936); + vsel(x11EF9867, x738F9C63, a5, x66666666); + vsel(x26DA9867, x26DAC936, x11EF9867, a6); + + vsel(x4B4B9C63, x4B4B7878, x738F9C63, a6); + vsel(x4B666663, x4B4B9C63, x66666666, x00FFFF00); + vxor(x4E639396, x0505F5F5, x4B666663); + + vsel(x4E4B393C, x4B4B7878, x4E639396, a2); + vnot(xFF00FF00, a5); + vsel(xFF05DD21, xFF00FF00, x738F9C63, x32353235); + vxor(xB14EE41D, x4E4B393C, xFF05DD21); + vsel(x1, xB14EE41D, x26DA9867, a1); + vxor(*out2, *out2, x1); + + vxor(xD728827B, x66666666, xB14EE41D); + vsel(x6698807B, x26DA9867, xD728827B, x4E4B393C); + vsel(x699C585B, x6698807B, x694E5A8D, xFF05DD21); + vsel(x2, x699C585B, x4E639396, a1); + vxor(*out3, *out3, x2); + + vsel(x778A8877, x738F9C63, x26DAC936, x26253636); + vxor(xA4A71E18, x738F9C63, xD728827B); + vsel(x74878E78, x778A8877, xA4A71E18, a4); + + vsel(x204A5845, x26DA9867, x694E5A8D, x26DAC936); + vsel(x74879639, x74878E78, a3, x204A5845); + vnot(x8B7869C6, x74879639); + vsel(x3, x74878E78, x8B7869C6, a1); + vxor(*out4, *out4, x3); +} +#endif + +#if latency >= 3 +/* s8-000035, 32 gates, 15 regs, 6/15/47/79/111 stall cycles */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0505F5F5, x05FAF50A, x0F0F00FF, x22227777, x07DA807F, x34E9B34C; + vtype x00FFF00F, x0033FCCF, x5565B15C, x0C0C3F3F, x59698E63; + vtype x3001F74E, x30555745, x693CD926; + vtype x0C0CD926, x0C3F25E9, x38D696A5; + vtype xC729695A; + vtype x03D2117B, xC778395B, xCB471CB2; + vtype x5425B13F, x56B3803F, x919AE965; + vtype x03DA807F, x613CD515, x62E6556A, xA59E6C31; + vtype x0, x1, x2, x3; + + vsel(x0505F5F5, a5, a1, a3); + vxor(x05FAF50A, a4, x0505F5F5); + vsel(x0F0F00FF, a3, a4, a5); + vsel(x22227777, a2, a5, a1); + vsel(x07DA807F, x05FAF50A, x0F0F00FF, x22227777); + vxor(x34E9B34C, a2, x07DA807F); + + vsel(x00FFF00F, x05FAF50A, a4, a3); + vsel(x0033FCCF, a5, x00FFF00F, a2); + vsel(x5565B15C, a1, x34E9B34C, x0033FCCF); + vsel(x0C0C3F3F, a3, a5, a2); + vxor(x59698E63, x5565B15C, x0C0C3F3F); + + vsel(x3001F74E, x34E9B34C, a5, x05FAF50A); + vsel(x30555745, x3001F74E, a1, x00FFF00F); + vxor(x693CD926, x59698E63, x30555745); + vsel(x2, x693CD926, x59698E63, a6); + vxor(*out3, *out3, x2); + + vsel(x0C0CD926, x0C0C3F3F, x693CD926, a5); + vxor(x0C3F25E9, x0033FCCF, x0C0CD926); + vxor(x38D696A5, x34E9B34C, x0C3F25E9); + + vnot(xC729695A, x38D696A5); + + vsel(x03D2117B, x07DA807F, a2, x0C0CD926); + vsel(xC778395B, xC729695A, x03D2117B, x30555745); + vxor(xCB471CB2, x0C3F25E9, xC778395B); + vsel(x1, xCB471CB2, x34E9B34C, a6); + vxor(*out2, *out2, x1); + + vsel(x5425B13F, x5565B15C, x0C0C3F3F, x03D2117B); + vsel(x56B3803F, x07DA807F, x5425B13F, x59698E63); + vxor(x919AE965, xC729695A, x56B3803F); + vsel(x3, xC729695A, x919AE965, a6); + vxor(*out4, *out4, x3); + + vsel(x03DA807F, x03D2117B, x07DA807F, x693CD926); + vsel(x613CD515, a1, x693CD926, x34E9B34C); + vxor(x62E6556A, x03DA807F, x613CD515); + vxor(xA59E6C31, xC778395B, x62E6556A); + vsel(x0, xA59E6C31, x38D696A5, a6); + vxor(*out1, *out1, x0); +} +#else +/* s8-000037, 32 gates, 15 regs, 3/17/49/81/113 stall cycles */ +MAYBE_INLINE static void +s8(vtype a1, vtype a2, vtype a3, vtype a4, vtype a5, vtype a6, + vtype * out1, vtype * out2, vtype * out3, vtype * out4) +{ + vtype x0505F5F5, x05FAF50A, x0F0F00FF, x22227777, x07DA807F, x34E9B34C; + vtype x00FFF00F, x0033FCCF, x5565B15C, x0C0C3F3F, x59698E63; + vtype x3001F74E, x30555745, x693CD926; + vtype x0C0CD926, x0C3F25E9, x38D696A5; + vtype xC729695A; + vtype x03D2117B, xC778395B, xCB471CB2; + vtype x5425B13F, x56B3803F, x919AE965; + vtype x17B3023F, x75555755, x62E6556A, xA59E6C31; + vtype x0, x1, x2, x3; + + vsel(x0505F5F5, a5, a1, a3); + vxor(x05FAF50A, a4, x0505F5F5); + vsel(x0F0F00FF, a3, a4, a5); + vsel(x22227777, a2, a5, a1); + vsel(x07DA807F, x05FAF50A, x0F0F00FF, x22227777); + vxor(x34E9B34C, a2, x07DA807F); + + vsel(x00FFF00F, x05FAF50A, a4, a3); + vsel(x0033FCCF, a5, x00FFF00F, a2); + vsel(x5565B15C, a1, x34E9B34C, x0033FCCF); + vsel(x0C0C3F3F, a3, a5, a2); + vxor(x59698E63, x5565B15C, x0C0C3F3F); + + vsel(x3001F74E, x34E9B34C, a5, x05FAF50A); + vsel(x30555745, x3001F74E, a1, x00FFF00F); + vxor(x693CD926, x59698E63, x30555745); + vsel(x2, x693CD926, x59698E63, a6); + vxor(*out3, *out3, x2); + + vsel(x0C0CD926, x0C0C3F3F, x693CD926, a5); + vxor(x0C3F25E9, x0033FCCF, x0C0CD926); + vxor(x38D696A5, x34E9B34C, x0C3F25E9); + + vnot(xC729695A, x38D696A5); + + vsel(x03D2117B, x07DA807F, a2, x0C0CD926); + vsel(xC778395B, xC729695A, x03D2117B, x30555745); + vxor(xCB471CB2, x0C3F25E9, xC778395B); + vsel(x1, xCB471CB2, x34E9B34C, a6); + vxor(*out2, *out2, x1); + + vsel(x5425B13F, x5565B15C, x0C0C3F3F, x03D2117B); + vsel(x56B3803F, x07DA807F, x5425B13F, x59698E63); + vxor(x919AE965, xC729695A, x56B3803F); + vsel(x3, xC729695A, x919AE965, a6); + vxor(*out4, *out4, x3); + + vsel(x17B3023F, x07DA807F, a2, x59698E63); + vor(x75555755, a1, x30555745); + vxor(x62E6556A, x17B3023F, x75555755); + vxor(xA59E6C31, xC778395B, x62E6556A); + vsel(x0, xA59E6C31, x38D696A5, a6); + vxor(*out1, *out1, x0); +} +#endif diff --git a/src/sboxes.c b/src/sboxes.c new file mode 100644 index 0000000..b723a5c --- /dev/null +++ b/src/sboxes.c @@ -0,0 +1,3 @@ +#undef andn +#define andn 0 +#include "nonstd.c" diff --git a/src/signals.c b/src/signals.c new file mode 100644 index 0000000..7043ed8 --- /dev/null +++ b/src/signals.c @@ -0,0 +1,371 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2003,2006,2010,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _XOPEN_SOURCE 500 /* for setitimer(2) and siginterrupt(3) */ + +#ifdef __ultrix__ +#define __POSIX +#define _POSIX_SOURCE +#endif + +#define NEED_OS_TIMER +#define NEED_OS_FORK +#include "os.h" + +#ifdef _SCO_C_DIALECT +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifdef __DJGPP__ +#include +#endif + +#ifdef __CYGWIN32__ +#include +#endif + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "tty.h" +#include "options.h" +#include "config.h" +#include "bench.h" +#include "john.h" + +volatile int event_pending = 0; +volatile int event_abort = 0, event_save = 0, event_status = 0; +volatile int event_ticksafety = 0; + +static int timer_save_interval, timer_save_value; +static clock_t timer_ticksafety_interval, timer_ticksafety_value; + +#if !OS_TIMER + +#include +#include + +static clock_t timer_emu_interval = 0; +static unsigned int timer_emu_count = 0, timer_emu_max = 0; + +void sig_timer_emu_init(clock_t interval) +{ + timer_emu_interval = interval; + timer_emu_count = 0; timer_emu_max = 0; +} + +void sig_timer_emu_tick(void) +{ + static clock_t last = 0; + clock_t current; + struct tms buf; + + if (++timer_emu_count < timer_emu_max) return; + + current = times(&buf); + + if (!last) { + last = current; + return; + } + + if (current - last < timer_emu_interval && current >= last) { + timer_emu_max += timer_emu_max + 1; + return; + } + + last = current; + timer_emu_count = 0; + timer_emu_max >>= 1; + + raise(SIGALRM); +} + +#endif + +static void sig_install_update(void); + +static void sig_handle_update(int signum) +{ + event_save = event_pending = 1; + +#ifndef SA_RESTART + sig_install_update(); +#endif +} + +static void sig_install_update(void) +{ +#ifdef SA_RESTART + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_handle_update; + sa.sa_flags = SA_RESTART; + sigaction(SIGHUP, &sa, NULL); +#else + signal(SIGHUP, sig_handle_update); +#endif +} + +static void sig_remove_update(void) +{ + signal(SIGHUP, SIG_IGN); +} + +void check_abort(int be_async_signal_safe) +{ + if (!event_abort) return; + + tty_done(); + + if (be_async_signal_safe) { + if (john_main_process) + write_loop(2, "Session aborted\n", 16); + _exit(1); + } + + if (john_main_process) + fprintf(stderr, "Session aborted\n"); + error(); +} + +static void sig_install_abort(void); + +static void sig_handle_abort(int signum) +{ + int saved_errno = errno; + + check_abort(1); + + event_abort = event_pending = 1; + + write_loop(2, "Wait...\r", 8); + + sig_install_abort(); + + errno = saved_errno; +} + +#ifdef __CYGWIN32__ +static CALLBACK BOOL sig_handle_abort_ctrl(DWORD ctrltype) +{ + sig_handle_abort(SIGINT); + return TRUE; +} +#endif + +static void sig_install_abort(void) +{ +#ifdef __DJGPP__ + setcbrk(1); +#endif + +#ifdef __CYGWIN32__ + SetConsoleCtrlHandler(sig_handle_abort_ctrl, TRUE); +#endif + + signal(SIGINT, sig_handle_abort); + signal(SIGTERM, sig_handle_abort); +#ifdef SIGXCPU + signal(SIGXCPU, sig_handle_abort); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ, sig_handle_abort); +#endif +} + +static void sig_remove_abort(void) +{ +#ifdef __CYGWIN32__ + SetConsoleCtrlHandler(sig_handle_abort_ctrl, FALSE); +#endif + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +#ifdef SIGXCPU + signal(SIGXCPU, SIG_DFL); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_DFL); +#endif +} + +#if OS_FORK +static void signal_children(int signum) +{ + int i; + for (i = 0; i < john_child_count; i++) + if (john_child_pids[i]) + kill(john_child_pids[i], signum); +} +#endif + +static void sig_install_timer(void); + +static void sig_handle_timer(int signum) +{ + int saved_errno = errno; + + if (!--timer_save_value) { + timer_save_value = timer_save_interval; + + event_save = event_pending = 1; + } + + if (!--timer_ticksafety_value) { + timer_ticksafety_value = timer_ticksafety_interval; + + event_ticksafety = event_pending = 1; + } + + if (john_main_process) { + int c; +#if OS_FORK + int new_abort = 0, new_status = 0; +#endif + while ((c = tty_getchar()) >= 0) { + if (c == 3 || c == 'q') { +#if OS_FORK + new_abort = 1; +#endif + sig_handle_abort(0); + } else { +#if OS_FORK + new_status = 1; +#endif + event_status = event_pending = 1; + } + } + +#if OS_FORK + if (new_abort || new_status) + signal_children(new_abort ? SIGTERM : SIGUSR2); +#endif + } + +#if !OS_TIMER + signal(SIGALRM, sig_handle_timer); +#elif !defined(SA_RESTART) && !defined(__DJGPP__) + sig_install_timer(); +#endif + + errno = saved_errno; +} + +#if OS_TIMER +static void sig_init_timer(void) +{ + struct itimerval it; + + it.it_value.tv_sec = TIMER_INTERVAL; + it.it_value.tv_usec = 0; +#if defined(SA_RESTART) || defined(__DJGPP__) + it.it_interval = it.it_value; +#else + memset(&it.it_interval, 0, sizeof(it.it_interval)); +#endif + if (setitimer(ITIMER_REAL, &it, NULL)) + pexit("setitimer"); +} +#endif + +static void sig_install_timer(void) +{ +#if !OS_TIMER + signal(SIGALRM, sig_handle_timer); + sig_timer_emu_init(TIMER_INTERVAL * clk_tck); +#else + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_handle_timer; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sigaction(SIGALRM, &sa, NULL); +#if !defined(SA_RESTART) && !defined(__DJGPP__) + siginterrupt(SIGALRM, 0); +#endif + + sig_init_timer(); +#endif +} + +static void sig_remove_timer(void) +{ +#if OS_TIMER + struct itimerval it; + + memset(&it, 0, sizeof(it)); + if (setitimer(ITIMER_REAL, &it, NULL)) perror("setitimer"); +#endif + + signal(SIGALRM, SIG_DFL); +} + +#if OS_FORK +static void sig_handle_status(int signum) +{ + event_status = event_pending = 1; + signal(SIGUSR2, sig_handle_status); +} +#endif + +static void sig_done(void); + +void sig_init(void) +{ + clk_tck_init(); + + timer_save_interval = cfg_get_int(SECTION_OPTIONS, NULL, "Save"); + if (timer_save_interval < 0) + timer_save_interval = TIMER_SAVE_DELAY; + else + if ((timer_save_interval /= TIMER_INTERVAL) <= 0) + timer_save_interval = 1; + timer_save_value = timer_save_interval; + + timer_ticksafety_interval = (clock_t)1 << (sizeof(clock_t) * 8 - 4); + timer_ticksafety_interval /= clk_tck; + if ((timer_ticksafety_interval /= TIMER_INTERVAL) <= 0) + timer_ticksafety_interval = 1; + timer_ticksafety_value = timer_ticksafety_interval; + + atexit(sig_done); + + sig_install_update(); + sig_install_abort(); + sig_install_timer(); +#if OS_FORK + signal(SIGUSR2, sig_handle_status); +#endif +} + +void sig_init_child(void) +{ +#if OS_TIMER + sig_init_timer(); +#endif +} + +static void sig_done(void) +{ + sig_remove_update(); + sig_remove_abort(); + sig_remove_timer(); +} diff --git a/src/signals.h b/src/signals.h new file mode 100644 index 0000000..6a671e5 --- /dev/null +++ b/src/signals.h @@ -0,0 +1,59 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2006,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Signal handling. + */ + +#ifndef _JOHN_SIGNALS_H +#define _JOHN_SIGNALS_H + +#include "arch.h" + +/* + * Event flags. + * + * Why aren't these put into a bitmask? The reason is that it's not possible + * to clear individual flags in a bitmask without a race condition on RISC, + * or having to block the signals. + */ +extern volatile int event_pending; /* An event is pending */ +extern volatile int event_abort; /* Abort requested */ +extern volatile int event_save; /* Save the crash recovery file */ +extern volatile int event_status; /* Status display requested */ +extern volatile int event_ticksafety; /* System time in ticks may overflow */ + +#if !OS_TIMER +/* + * Timer emulation for systems with no setitimer(2). + */ +#include + +extern void sig_timer_emu_init(clock_t interval); +extern void sig_timer_emu_tick(void); +#endif + +/* + * Installs the signal handlers. + */ +extern void sig_init(void); + +/* + * Performs additional (re-)initialization after fork(). Assumes that + * sig_init() has already been called. + */ +extern void sig_init_child(void); + +/* + * Terminates the process if event_abort is set. + */ +extern void check_abort(int be_async_signal_safe); + +#endif diff --git a/src/single.c b/src/single.c new file mode 100644 index 0000000..2bd6051 --- /dev/null +++ b/src/single.c @@ -0,0 +1,509 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2004,2006,2010,2012,2013 by Solar Designer + */ + +#include +#include + +#include "misc.h" +#include "params.h" +#include "common.h" +#include "memory.h" +#include "signals.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "rpp.h" +#include "rules.h" +#include "external.h" +#include "cracker.h" +#include "john.h" + +static int progress = 0; +static int rec_rule; + +static struct db_main *single_db; +static int rule_number, rule_count; +static int length, key_count; +static struct db_keys *guessed_keys; +static struct rpp_context *rule_ctx; + +static void save_state(FILE *file) +{ + fprintf(file, "%d\n", rec_rule); +} + +static int restore_rule_number(void) +{ + if (rule_ctx) + for (rule_number = 0; rule_number < rec_rule; rule_number++) + if (!rpp_next(rule_ctx)) return 1; + + return 0; +} + +static int restore_state(FILE *file) +{ + if (fscanf(file, "%d\n", &rec_rule) != 1) return 1; + + return restore_rule_number(); +} + +static int get_progress(void) +{ + if (progress) return progress; + + return rule_number * 100 / (rule_count + 1); +} + +static void single_alloc_keys(struct db_keys **keys) +{ + int hash_size = sizeof(struct db_keys_hash) + + sizeof(struct db_keys_hash_entry) * (key_count - 1); + + if (!*keys) { + *keys = mem_alloc_tiny( + sizeof(struct db_keys) - 1 + length * key_count, + MEM_ALIGN_WORD); + (*keys)->hash = mem_alloc_tiny(hash_size, MEM_ALIGN_WORD); + } + + (*keys)->count = (*keys)->count_from_guesses = 0; + (*keys)->ptr = (*keys)->buffer; + (*keys)->have_words = 1; /* assume yes; we'll see for real later */ + (*keys)->rule = rule_number; + (*keys)->lock = 0; + memset((*keys)->hash, -1, hash_size); +} + +static void single_init(void) +{ + struct db_salt *salt; + + log_event("Proceeding with \"single crack\" mode"); + + progress = 0; + + length = single_db->format->params.plaintext_length; + key_count = single_db->format->params.min_keys_per_crypt; + if (key_count < SINGLE_HASH_MIN) + key_count = SINGLE_HASH_MIN; +/* + * We use "short" for buffered key indices and "unsigned short" for buffered + * key offsets - make sure these don't overflow. + */ + if (key_count > 0x8000) + key_count = 0x8000; + while (key_count > 0xffff / length + 1) + key_count >>= 1; + + if (rpp_init(rule_ctx, SUBSECTION_SINGLE)) { + log_event("! No \"single crack\" mode rules found"); + if (john_main_process) + fprintf(stderr, + "No \"single crack\" mode rules found in %s\n", + cfg_name); + error(); + } + + rules_init(length); + rec_rule = rule_number = 0; + rule_count = rules_count(rule_ctx, 0); + + log_event("- %d preprocessed word mangling rules", rule_count); + + status_init(get_progress, 0); + + rec_restore_mode(restore_state); + rec_init(single_db, save_state); + + salt = single_db->salts; + do { + single_alloc_keys(&salt->keys); + } while ((salt = salt->next)); + + if (key_count > 1) + log_event("- Allocated %d buffer%s of %d candidate passwords%s", + single_db->salt_count, + single_db->salt_count != 1 ? "s" : "", + key_count, + single_db->salt_count != 1 ? " each" : ""); + + guessed_keys = NULL; + single_alloc_keys(&guessed_keys); + + crk_init(single_db, NULL, guessed_keys); +} + +static MAYBE_INLINE int single_key_hash(char *key) +{ + unsigned int hash, extra, pos; + + hash = (unsigned char)key[0]; + if (!hash) + goto out; + extra = (unsigned char)key[1]; + if (!extra) + goto out_and; + + pos = 3; + if (length & 1) { + while (key[2]) { + hash += (unsigned char)key[2]; + if (!key[3] || pos >= length) break; + extra += (unsigned char)key[3]; + key += 2; + pos += 2; + } + } else { + while (key[2] && pos < length) { + hash += (unsigned char)key[2]; + if (!key[3]) break; + extra += (unsigned char)key[3]; + key += 2; + pos += 2; + } + } + + hash -= extra + pos; +#if SINGLE_HASH_LOG > 6 + hash ^= extra << 6; +#endif + +out_and: + hash &= SINGLE_HASH_SIZE - 1; +out: + return hash; +} + +static int single_process_buffer(struct db_salt *salt); + +static int single_add_key(struct db_salt *salt, char *key, int is_from_guesses) +{ + struct db_keys *keys = salt->keys; + int index, new_hash, reuse_hash; + struct db_keys_hash_entry *entry; + +/* Check if this is a known duplicate, and reject it if so */ + if ((index = keys->hash->hash[new_hash = single_key_hash(key)]) >= 0) + do { + entry = &keys->hash->list[index]; + if (!strncmp(key, &keys->buffer[entry->offset], length)) + return 0; + } while ((index = entry->next) >= 0); + +/* Update the hash table removing the list entry we're about to reuse */ + index = keys->hash->hash[reuse_hash = single_key_hash(keys->ptr)]; + if (index == keys->count) + keys->hash->hash[reuse_hash] = keys->hash->list[index].next; + else + if (index >= 0) { + entry = &keys->hash->list[index]; + while ((index = entry->next) >= 0) { + if (index == keys->count) { + entry->next = keys->hash->list[index].next; + break; + } + entry = &keys->hash->list[index]; + } + } + +/* Add the new entry */ + index = keys->hash->hash[new_hash]; + entry = &keys->hash->list[keys->count]; + entry->next = index; + entry->offset = keys->ptr - keys->buffer; + keys->hash->hash[new_hash] = keys->count; + + strnfcpy(keys->ptr, key, length); + keys->ptr += length; + + keys->count_from_guesses += is_from_guesses; + + if (++(keys->count) >= key_count) + return single_process_buffer(salt); + + return 0; +} + +static int single_process_buffer(struct db_salt *salt) +{ + struct db_salt *current; + struct db_keys *keys; + size_t size; + + if (crk_process_salt(salt)) + return 1; + +/* + * Flush the keys list (since we've just processed the keys), but not the hash + * table to allow for more effective checking for duplicates. We could flush + * the hash table too, such as by calling single_alloc_keys() here, which would + * allow us to drop the update-hash-before-list-entry-reuse code from + * single_add_key(). This would speed things up in terms of this source file's + * code overhead, however it would allow more duplicates to pass. The apparent + * c/s rate (counting duplicates as if they were distinct combinations) would + * be higher, but the number of passwords cracked per unit of time might be + * lower or higher depending on many things including the relative speed of + * password hash computations vs. the "overhead". + */ + keys = salt->keys; + keys->count = keys->count_from_guesses = 0; + keys->ptr = keys->buffer; + keys->lock++; + + if (guessed_keys->count) { + keys = mem_alloc(size = sizeof(struct db_keys) - 1 + + length * guessed_keys->count); + memcpy(keys, guessed_keys, size); + + keys->ptr = keys->buffer; + do { + current = single_db->salts; + do { + if (current == salt || !current->list) + continue; + + if (single_add_key(current, keys->ptr, 1)) + return 1; + } while ((current = current->next)); + keys->ptr += length; + } while (--keys->count); + + MEM_FREE(keys); + } + + keys = salt->keys; + keys->lock--; + if (!keys->count && !keys->lock) + keys->rule = rule_number; + + return 0; +} + +static int single_process_pw(struct db_salt *salt, struct db_password *pw, + char *rule) +{ + struct list_entry *first, *second; + int first_number, second_number; + char pair[RULE_WORD_SIZE]; + int split; + char *key; + unsigned int c; + + if (!(first = pw->words->head)) + return -1; + + first_number = 0; + do { + if ((key = rules_apply(first->data, rule, 0, NULL))) + if (ext_filter(key)) + if (single_add_key(salt, key, 0)) + return 1; + if (!salt->list) + return 2; + if (!pw->binary) + return 0; + + if (++first_number > SINGLE_WORDS_PAIR_MAX) + continue; + + c = (unsigned int)first->data[0] | 0x20; + if (c < 'a' || c > 'z') + continue; + + second_number = 0; + second = pw->words->head; + + do + if (first != second) { + if ((split = strlen(first->data)) < length) { + strnzcpy(pair, first->data, RULE_WORD_SIZE); + strnzcat(pair, second->data, RULE_WORD_SIZE); + + if ((key = rules_apply(pair, rule, split, NULL))) + if (ext_filter(key)) + if (single_add_key(salt, key, 0)) + return 1; + if (!salt->list) + return 2; + if (!pw->binary) + return 0; + } + + if (first->data[1]) { + pair[0] = first->data[0]; + pair[1] = 0; + strnzcat(pair, second->data, RULE_WORD_SIZE); + + if ((key = rules_apply(pair, rule, 1, NULL))) + if (ext_filter(key)) + if (single_add_key(salt, key, 0)) + return 1; + if (!salt->list) + return 2; + if (!pw->binary) + return 0; + } + } while (++second_number <= SINGLE_WORDS_PAIR_MAX && + (second = second->next)); + } while ((first = first->next)); + + return 0; +} + +static int single_process_salt(struct db_salt *salt, char *rule) +{ + struct db_keys *keys; + struct db_password *pw, **last; + int status, have_words = 0; + + keys = salt->keys; + + if (!keys->have_words) + goto no_own_words; + + last = &salt->list; + pw = *last; + do { +/* + * "binary" is set to NULL on entries marked for removal (so we remove them + * here) or already removed (yet we might hit them once in some obscure cases). + */ + if (pw->binary) { + if (!(status = single_process_pw(salt, pw, rule))) { + have_words = 1; + goto next; + } + if (status < 0) /* no words for this hash */ + goto next; + if (status == 2) /* no hashes left for this salt */ + return 0; + return 1; /* no hashes left to crack for all salts */ + } else { + *last = pw->next; /* remove */ + } +next: + last = &pw->next; + } while ((pw = pw->next)); + + if (keys->count && rule_number - keys->rule > (key_count << 1)) + if (single_process_buffer(salt)) + return 1; + + if (!keys->count) + keys->rule = rule_number; + + if (!have_words) { + keys->have_words = 0; +no_own_words: + if (keys->count && single_process_buffer(salt)) + return 1; + } + + return 0; +} + +static void single_run(void) +{ + char *prerule, *rule; + struct db_salt *salt; + int min, saved_min; + int have_words; + + saved_min = rec_rule; + while ((prerule = rpp_next(rule_ctx))) { + if (options.node_count) { + int for_node = rule_number % options.node_count + 1; + if (for_node < options.node_min || + for_node > options.node_max) { + rule_number++; + continue; + } + } + + if (!(rule = rules_reject(prerule, 0, NULL, single_db))) { + log_event("- Rule #%d: '%.100s' rejected", + ++rule_number, prerule); + continue; + } + + if (strcmp(prerule, rule)) + log_event("- Rule #%d: '%.100s' accepted as '%.100s'", + rule_number + 1, prerule, rule); + else + log_event("- Rule #%d: '%.100s' accepted", + rule_number + 1, prerule); + + if (saved_min != rec_rule) { + log_event("- Oldest still in use is now rule #%d", + rec_rule + 1); + saved_min = rec_rule; + } + + have_words = 0; + + min = rule_number; + + salt = single_db->salts; + do { + if (!salt->list) + continue; + if (single_process_salt(salt, rule)) + return; + if (!salt->keys->have_words) + continue; + have_words = 1; + if (salt->keys->rule < min) + min = salt->keys->rule; + } while ((salt = salt->next)); + + rec_rule = min; + rule_number++; + + if (have_words) + continue; + + log_event("- No information to base%s candidate passwords on", + rule_number > 1 ? " further" : ""); + return; + } +} + +static void single_done(void) +{ + struct db_salt *salt; + + if (!event_abort) { + if ((salt = single_db->salts)) { + log_event("- Processing the remaining buffered " + "candidate passwords, if any"); + + do { + if (!salt->list) + continue; + if (salt->keys->count) + if (single_process_buffer(salt)) + break; + } while ((salt = salt->next)); + } + + progress = 100; + } + + rec_done(event_abort || (status.pass && single_db->salts)); +} + +void do_single_crack(struct db_main *db) +{ + struct rpp_context ctx; + + single_db = db; + rule_ctx = &ctx; + single_init(); + single_run(); + single_done(); +} diff --git a/src/single.h b/src/single.h new file mode 100644 index 0000000..c203df2 --- /dev/null +++ b/src/single.h @@ -0,0 +1,20 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + */ + +/* + * "Single crack" mode. + */ + +#ifndef _JOHN_SINGLE_H +#define _JOHN_SINGLE_H + +#include "loader.h" + +/* + * Runs the cracker. + */ +extern void do_single_crack(struct db_main *db); + +#endif diff --git a/src/sparc32.h b/src/sparc32.h new file mode 100644 index 0000000..9cd4dc4 --- /dev/null +++ b/src/sparc32.h @@ -0,0 +1,56 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2005,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for SPARC V8, 32-bit. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +/* + * Let's not bother trying 128 KB SPE tables with the old-fashioned DES + * implementation, despite them resulting in better performance on some + * systems. We're using bitslice DES for the most important (most common) + * DES-based hash types anyway. + */ +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/sparc64.h b/src/sparc64.h new file mode 100644 index 0000000..f06d1be --- /dev/null +++ b/src/sparc64.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2003,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for SPARC V9, 64-bit. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 0 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 0 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 0 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/status.c b/src/status.c new file mode 100644 index 0000000..aee433e --- /dev/null +++ b/src/status.c @@ -0,0 +1,301 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2004,2006,2010-2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#ifdef __ultrix__ +#define __POSIX +#define _POSIX_SOURCE +#endif + +#ifdef _SCO_C_DIALECT +#include +#endif +#include +#include +#include +#include + +#include "times.h" + +#include "misc.h" +#include "math.h" +#include "params.h" +#include "cracker.h" +#include "options.h" +#include "status.h" +#include "bench.h" + +struct status_main status; +unsigned int status_restored_time = 0; +int (*status_get_progress)(void) = NULL; + +static clock_t get_time(void) +{ + struct tms buf; + + return times(&buf); +} + +void status_init(int (*get_progress)(void), int start) +{ + if (start) { + if (!status_restored_time) + memset(&status, 0, sizeof(status)); + status.start_time = get_time(); + } + + status_get_progress = get_progress; + + clk_tck_init(); +} + +void status_ticks_overflow_safety(void) +{ + unsigned int time; + clock_t ticks; + + ticks = get_time() - status.start_time; + if (ticks > ((clock_t)1 << (sizeof(clock_t) * 8 - 2))) { + time = ticks / clk_tck; + status_restored_time += time; + status.start_time += (clock_t)time * clk_tck; + } +} + +void status_update_crypts(int64 *combs, unsigned int crypts) +{ + { + unsigned int saved_hi = status.combs.hi; + add64to64(&status.combs, combs); + if (status.combs.hi < saved_hi) + status.combs_ehi++; + } + + { + unsigned int saved_lo = status.crypts.lo; + add32to64(&status.crypts, crypts); + if ((status.crypts.lo ^ saved_lo) & 0xfff00000U) + status_ticks_overflow_safety(); + } +} + +void status_update_cands(unsigned int cands) +{ + unsigned int saved_lo = status.cands.lo; + add32to64(&status.cands, cands); + if ((status.cands.lo ^ saved_lo) & 0xfff00000U) + status_ticks_overflow_safety(); +} + +static char *status_get_c(char *buffer, int64 *c, unsigned int c_ehi) +{ + int64 current, next, rem; + char *p; + + if (c_ehi) { + strcpy(buffer, "OVERFLOW"); + return buffer; + } + + p = buffer + 31; + *p = 0; + + current = *c; + do { + next = current; + div64by32(&next, 10); + rem = next; + mul64by32(&rem, 10); + neg64(&rem); + add64to64(&rem, ¤t); + *--p = rem.lo + '0'; + current = next; + } while (current.lo || current.hi); + + return p; +} + +unsigned int status_get_time(void) +{ + return status_restored_time + + (get_time() - status.start_time) / clk_tck; +} + +static char *status_get_cps(char *buffer, int64 *c, unsigned int c_ehi) +{ + int use_ticks; + clock_t ticks; + unsigned long time; + int64 tmp, cps; + + if (!(c->lo | c->hi | c_ehi)) + return "0"; + + use_ticks = !(c->hi | c_ehi | status_restored_time); + + ticks = get_time() - status.start_time; + if (use_ticks) + time = ticks; + else + time = status_restored_time + ticks / clk_tck; + if (!time) time = 1; + + cps = *c; + if (c_ehi) { + cps.lo = cps.hi; + cps.hi = c_ehi; + } + if (use_ticks) + mul64by32(&cps, clk_tck); + div64by32(&cps, time); + if (c_ehi) { + cps.hi = cps.lo; + cps.lo = 0; + } + + if (cps.hi > 232 || (cps.hi == 232 && cps.lo >= 3567587328U)) + sprintf(buffer, "%uG", div64by32lo(&cps, 1000000000)); + else + if (cps.hi || cps.lo >= 1000000000) + sprintf(buffer, "%uM", div64by32lo(&cps, 1000000)); + else + if (cps.lo >= 1000000) + sprintf(buffer, "%uK", div64by32lo(&cps, 1000)); + else + if (cps.lo >= 1000) + sprintf(buffer, "%u", cps.lo); + else { + const char *fmt; + unsigned int div, frac; + fmt = "%u.%06u"; div = 1000000; + if (cps.lo >= 100) { + fmt = "%u.%u"; div = 10; + } else if (cps.lo >= 10) { + fmt = "%u.%02u"; div = 100; + } else if (cps.lo >= 1) { + fmt = "%u.%03u"; div = 1000; + } + tmp = *c; + if (use_ticks) + mul64by32(&tmp, clk_tck); + mul64by32(&tmp, div); + frac = div64by32lo(&tmp, time); + if (div == 1000000) { + if (frac >= 100000) { + fmt = "%u.%04u"; div = 10000; frac /= 100; + } else if (frac >= 10000) { + fmt = "%u.%05u"; div = 100000; frac /= 10; + } + } + frac %= div; + sprintf(buffer, fmt, cps.lo, frac); + } + + return buffer; +} + +static void status_print_cracking(char *percent) +{ + unsigned int time = status_get_time(); + char *key1, key2[PLAINTEXT_BUFFER_SIZE]; + int64 g; + char s_gps[32], s_pps[32], s_crypts_ps[32], s_combs_ps[32]; + char s[1024], *p; + int n; + + key1 = NULL; + key2[0] = 0; + if (!(options.flags & FLG_STATUS_CHK) && + (status.crypts.lo | status.crypts.hi)) { + char *key = crk_get_key2(); + if (key) + strnzcpy(key2, key, sizeof(key2)); + key1 = crk_get_key1(); + } + + p = s; + if (options.fork) { + n = sprintf(p, "%u ", options.node_min); + if (n > 0) + p += n; + } + + g.lo = status.guess_count; g.hi = 0; + n = sprintf(p, + "%ug %u:%02u:%02u:%02u%.100s %.31sg/s ", + status.guess_count, + time / 86400, time % 86400 / 3600, time % 3600 / 60, time % 60, + percent, + status_get_cps(s_gps, &g, 0)); + if (n > 0) + p += n; + + if (!status.compat) { + n = sprintf(p, + "%.31sp/s %.31sc/s ", + status_get_cps(s_pps, &status.cands, 0), + status_get_cps(s_crypts_ps, &status.crypts, 0)); + if (n > 0) + p += n; + } + + n = sprintf(p, "%.31sC/s%s%.200s%s%.200s\n", + status_get_cps(s_combs_ps, &status.combs, status.combs_ehi), + key1 ? " " : "", key1 ? key1 : "", key2[0] ? ".." : "", key2); + if (n > 0) + p += n; + + fwrite(s, p - s, 1, stderr); +} + +static void status_print_stdout(char *percent) +{ + unsigned int time = status_get_time(); + char *key; + char s_pps[32], s_p[32]; + + key = NULL; + if (!(options.flags & FLG_STATUS_CHK) && + (status.cands.lo | status.cands.hi)) + key = crk_get_key1(); + + fprintf(stderr, + "%sp %u:%02u:%02u:%02u%s %sp/s%s%s\n", + status_get_c(s_p, &status.cands, 0), + time / 86400, time % 86400 / 3600, time % 3600 / 60, time % 60, + percent, + status_get_cps(s_pps, &status.cands, 0), + key ? " " : "", key ? key : ""); +} + +void status_print(void) +{ + int percent_value; + char s_percent[32]; + + percent_value = -1; + if (options.flags & FLG_STATUS_CHK) + percent_value = status.progress; + else + if (status_get_progress) + percent_value = status_get_progress(); + + s_percent[0] = 0; + if (percent_value >= 0) + sprintf(s_percent, status.pass ? " %d%% %d/3" : " %d%%", + percent_value, status.pass); + else + if (status.pass) + sprintf(s_percent, " %d/3", status.pass); + + if (options.flags & FLG_STDOUT) + status_print_stdout(s_percent); + else + status_print_cracking(s_percent); +} diff --git a/src/status.h b/src/status.h new file mode 100644 index 0000000..912433d --- /dev/null +++ b/src/status.h @@ -0,0 +1,83 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2006,2011,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Status information management routines. + */ + +#ifndef _JOHN_STATUS_H +#define _JOHN_STATUS_H + +#include + +#include "math.h" + +/* + * Current status. + */ +struct status_main { + clock_t start_time; + unsigned int guess_count; + int64 combs, crypts, cands; + unsigned int combs_ehi; + int compat; + int pass; + int progress; +}; + +extern struct status_main status; + +extern int (*status_get_progress)(void); + +/* + * Elapsed time of previous sessions and excess ticks (if any), in seconds. + */ +extern unsigned int status_restored_time; + +/* + * If start is non-zero, sets start_time to current time and the rest of + * fields to zero. Always initializes the get_progress() handler (can be + * NULL). + */ +extern void status_init(int (*get_progress)(void), int start); + +/* + * Checks the number of ticks elapsed since start_time and moves some excess + * ticks onto status_restored_time (by increasing both it and start_time) + * such that the difference between the current system time in ticks (which + * may overflow) and start_time always correctly represents the number of + * ticks elapsed since status_restored_time. + */ +extern void status_ticks_overflow_safety(void); + +/* + * Updates the combinations and crypts counters by adding the supplied numbers + * to them. + * Calls status_ticks_overflow_safety() once in a while. + */ +extern void status_update_crypts(int64 *combs, unsigned int crypts); + +/* + * Updates the candidates counter by adding the supplied number to it. + * Calls status_ticks_overflow_safety() once in a while. + */ +extern void status_update_cands(unsigned int cands); + +/* + * Returns the elapsed time in seconds. + */ +extern unsigned int status_get_time(void); + +/* + * Prints current status to stdout. + */ +extern void status_print(void); + +#endif diff --git a/src/symlink.c b/src/symlink.c new file mode 100644 index 0000000..3607200 --- /dev/null +++ b/src/symlink.c @@ -0,0 +1,36 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Symlink emulation for Win32. + */ + +#include +#include + +#define MAIN_NAME "john.exe" + +int main(int argc, char **argv) +{ + char path[strlen(argv[0] ? argv[0] : "") + sizeof(MAIN_NAME)]; + char *name; + + if (!argv[0]) + name = path; + else + if ((name = strrchr(strcpy(path, argv[0]), '/'))) + name++; + else + name = path; + strcpy(name, MAIN_NAME); + + execv(path, argv); + return 1; +} diff --git a/src/times.h b/src/times.h new file mode 100644 index 0000000..962fd27 --- /dev/null +++ b/src/times.h @@ -0,0 +1,37 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Workaround a DJGPP time functions problem which could cause the system + * date not to advance at midnight when a BIOS time query function resets + * the overflow flag before DOS has a chance to see it. Note that there's + * still a race condition in the code below, it's just far less likely to + * cause any harm. The real fix would be more complicated... + */ + +#if !defined(_JOHN_TIMES_H) && defined(__DJGPP__) +#define _JOHN_TIMES_H + +#include +#include + +static inline clock_t safe_times(struct tms *buffer) +{ + __dpmi_regs r; + + r.h.ah = 0x2C; + __dpmi_int(0x21, &r); + + return times(buffer); +} + +#define times safe_times + +#endif diff --git a/src/trip_fmt.c b/src/trip_fmt.c new file mode 100644 index 0000000..051e95d --- /dev/null +++ b/src/trip_fmt.c @@ -0,0 +1,638 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2011,2012 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "arch.h" +#include "DES_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "tripcode" +#define FORMAT_NAME "" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 8 +#define CIPHERTEXT_LENGTH 10 + +#define SALT_SIZE 0 +#define SALT_ALIGN 1 + +static struct fmt_tests tests[] = { + {"Rk7VUsDT2U", "simpson"}, + {"3GqYIJ3Obs", "tripcode"}, + {"Id1gMYGA52", "ponytail"}, + {NULL} +}; + +#if DES_BS + +#include "DES_bs.h" + +#define ALGORITHM_NAME DES_BS_ALGORITHM_NAME + +#define BINARY_SIZE sizeof(ARCH_WORD_32) +#define BINARY_ALIGN sizeof(ARCH_WORD_32) + +#define TRIPCODE_SCALE 0x40 + +#define MIN_KEYS_PER_CRYPT DES_BS_DEPTH +#define MAX_KEYS_PER_CRYPT (DES_BS_DEPTH * TRIPCODE_SCALE) + +static DES_bs_vector (*crypt_out)[64]; +static int block_count; +static int worst_case_block_count; + +#if DES_bs_mt +static int *l2g; +#endif + +static int (*hash_func)(int index); +static int (*next_hash_func)(int index); + +#else + +#define ALGORITHM_NAME DES_STD_ALGORITHM_NAME + +#define BINARY_SIZE ARCH_SIZE +#define BINARY_ALIGN ARCH_SIZE + +#define MIN_KEYS_PER_CRYPT 0x40 +#define MAX_KEYS_PER_CRYPT 0x1000 + +static DES_binary binary_mask; + +#endif + +static struct { +#if DES_BS + int block, index, hash; +#else + union { + double dummy; + DES_binary binary; + } aligned; +#endif + int next; /* index of next entry with the same salt */ + unsigned int salt; + char key[PLAINTEXT_LENGTH]; +} *buffer; + +static unsigned char salt_map[0x100]; + +struct fmt_main fmt_trip; + +static void init(struct fmt_main *self) +{ +#if !DES_BS + char fake_crypt[14]; + ARCH_WORD *alt_binary; +#endif + int i; + +#if DES_BS + DES_bs_init(0, DES_bs_cpt); +#if DES_bs_mt + fmt_trip.params.min_keys_per_crypt = DES_bs_min_kpc; + fmt_trip.params.max_keys_per_crypt = DES_bs_min_kpc * TRIPCODE_SCALE; +#endif + +#undef howmany +#define howmany(x, y) (((x) + ((y) - 1)) / (y)) + worst_case_block_count = 0xFFF + + howmany(fmt_trip.params.max_keys_per_crypt - 0xFFF, DES_BS_DEPTH); + crypt_out = mem_alloc_tiny(sizeof(*crypt_out) * worst_case_block_count, + MEM_ALIGN_CACHE); + memset(crypt_out, 0, sizeof(*crypt_out) * worst_case_block_count); + +#if DES_bs_mt + l2g = mem_alloc_tiny(sizeof(*l2g) * DES_bs_max_kpc, MEM_ALIGN_CACHE); +#endif + + hash_func = NULL; + next_hash_func = NULL; +#else + DES_std_init(); + + memset(fake_crypt, '.', 13); + fake_crypt[13] = 0; + memcpy(binary_mask, DES_std_get_binary(fake_crypt), + sizeof(binary_mask)); + + fake_crypt[2] = 'z'; + alt_binary = DES_std_get_binary(fake_crypt); + + for (i = 0; i < 16 / DES_SIZE; i++) { + binary_mask[i] ^= ~alt_binary[i]; + binary_mask[i] &= DES_BINARY_MASK; + } +#endif + + buffer = mem_alloc_tiny(sizeof(*buffer) * + fmt_trip.params.max_keys_per_crypt, + MEM_ALIGN_CACHE); + + for (i = 0; i < 0x100; i++) { + char *from = ":;<=>?@[\\]^_`"; + char *to = "ABCDEFGabcdef"; + char *p; + if (atoi64[i] != 0x7F) + salt_map[i] = i; + else if ((p = strchr(from, i))) + salt_map[i] = to[p - from]; + else + salt_map[i] = '.'; + } +} + +static int valid(char *ciphertext, struct fmt_main *self) +{ + char *pos; + + for (pos = ciphertext; atoi64[ARCH_INDEX(*pos)] != 0x7F; pos++) + ; + if (*pos || pos - ciphertext != CIPHERTEXT_LENGTH) + return 0; + + if (atoi64[ARCH_INDEX(*(pos - 1))] & 3) + return 0; + + return 1; +} + +static void *get_binary(char *ciphertext) +{ + char fake_crypt[14]; + + fake_crypt[0] = '.'; + fake_crypt[1] = '.'; + fake_crypt[2] = '.'; + memcpy(&fake_crypt[3], ciphertext, 11); + +#if DES_BS + return DES_bs_get_binary(fake_crypt); +#else + return DES_std_get_binary(fake_crypt); +#endif +} + +#if DES_BS + +static int binary_hash_0(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 1) & 0x80) | (w & 0x7F); +} + +static int binary_hash_2(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 1) & 0xF80) | (w & 0x7F); +} + +static int binary_hash_3(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 2) & 0xC000) | ((w >> 1) & 0x3F80) | (w & 0x7F); +} + +static int binary_hash_4(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 2) & 0xFC000) | ((w >> 1) & 0x3F80) | (w & 0x7F); +} + +static int binary_hash_5(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 3) & 0xE00000) | + ((w >> 2) & 0x1FC000) | ((w >> 1) & 0x3F80) | (w & 0x7F); +} + +static int binary_hash_6(void *binary) +{ + unsigned int w = *(ARCH_WORD_32 *)binary; + return ((w >> 3) & 0x7E00000) | + ((w >> 2) & 0x1FC000) | ((w >> 1) & 0x3F80) | (w & 0x7F); +} + +static MAYBE_INLINE void blkcpy(DES_bs_vector *dst, DES_bs_vector *src, int n) +{ + memcpy(dst, src, n * sizeof(*dst)); +} + +static MAYBE_INLINE void blkcpy58(DES_bs_vector *dst, DES_bs_vector *src) +{ + memcpy(dst, src, 7 * sizeof(*dst)); + memcpy(&dst[8], &src[8], 7 * sizeof(*dst)); + memcpy(&dst[16], &src[16], 7 * sizeof(*dst)); + memcpy(&dst[24], &src[24], 15 * sizeof(*dst)); + memcpy(&dst[40], &src[40], 7 * sizeof(*dst)); + memcpy(&dst[48], &src[48], 7 * sizeof(*dst)); + memcpy(&dst[56], &src[56], 8 * sizeof(*dst)); +} + +#if DES_bs_mt +#define MAYBE_T0 \ + const int t = 0; +#else +#define MAYBE_T0 +#endif + +#define define_get_hash(NAME, CALL) \ +static int NAME(int index) \ +{ \ + if (hash_func == CALL) \ + return buffer[index].hash; \ + { \ + int block = buffer[index].block; \ + MAYBE_T0; \ + blkcpy(DES_bs_all.B, crypt_out[block], 27 + 3); \ + return (next_hash_func = CALL)(buffer[index].index); \ + } \ +} + +define_get_hash(get_hash_0, DES_bs_get_hash_0) +define_get_hash(get_hash_1, DES_bs_get_hash_1t) +define_get_hash(get_hash_2, DES_bs_get_hash_2t) +define_get_hash(get_hash_3, DES_bs_get_hash_3t) +define_get_hash(get_hash_4, DES_bs_get_hash_4t) +define_get_hash(get_hash_5, DES_bs_get_hash_5t) +define_get_hash(get_hash_6, DES_bs_get_hash_6t) + +#else + +static int binary_hash_0(void *binary) +{ + return DES_STD_HASH_0(*(ARCH_WORD *)binary); +} + +static int binary_hash_1(void *binary) +{ + return DES_STD_HASH_1(*(ARCH_WORD *)binary); +} + +static int binary_hash_2(void *binary) +{ + return DES_STD_HASH_2(*(ARCH_WORD *)binary); +} + +#define binary_hash_3 NULL +#define binary_hash_4 NULL +#define binary_hash_5 NULL +#define binary_hash_6 NULL + +static int get_hash_0(int index) +{ + return DES_STD_HASH_0(buffer[index].aligned.binary[0]); +} + +static int get_hash_1(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].aligned.binary[0]; + return DES_STD_HASH_1(binary); +} + +static int get_hash_2(int index) +{ + ARCH_WORD binary; + + binary = buffer[index].aligned.binary[0]; + return DES_STD_HASH_2(binary); +} + +#define get_hash_3 NULL +#define get_hash_4 NULL +#define get_hash_5 NULL +#define get_hash_6 NULL + +#endif + +static MAYBE_INLINE void crypt_link_by_salt(int count) +{ + int index; + int salt_bucket[0x1000]; + + memset(salt_bucket, -1, sizeof(salt_bucket)); + for (index = count - 1; index >= 0; index--) { + char fake_crypt[14]; + + if (!buffer[index].key[0]) { + fake_crypt[0] = '.'; + fake_crypt[1] = '.'; + } else + if (!buffer[index].key[1]) { + fake_crypt[0] = 'H'; + fake_crypt[1] = '.'; + } else + if (!buffer[index].key[2]) { + fake_crypt[0] = + salt_map[ARCH_INDEX(buffer[index].key[1])]; + fake_crypt[1] = 'H'; + } else { + fake_crypt[0] = + salt_map[ARCH_INDEX(buffer[index].key[1])]; + fake_crypt[1] = + salt_map[ARCH_INDEX(buffer[index].key[2])]; + } + fake_crypt[13] = 0; + + { + unsigned int salt = DES_raw_get_salt(fake_crypt); +#if DES_BS + buffer[index].salt = salt; + buffer[index].next = salt_bucket[salt]; +#else + if ((buffer[index].next = salt_bucket[salt]) >= 0) + buffer[index].salt = + buffer[salt_bucket[salt]].salt; + else + buffer[index].salt = + DES_std_get_salt(fake_crypt); +#endif + salt_bucket[salt] = index; + } + } +} + +static MAYBE_INLINE void crypt_traverse_by_salt(int count) +{ + int index; +#if DES_bs_mt + int block_index; +#endif + +#if DES_BS + block_count = 0; +#endif + for (index = 0; index < count; index++) { + int gindex; +#if DES_BS + int lindex; +#if DES_bs_mt + int lindex_mod; +#else + int l2g[DES_BS_DEPTH]; +#endif +#endif + + if (buffer[index].salt == 0xFFFFFFFF) /* already processed */ + continue; + + gindex = index; +#if DES_BS + DES_bs_set_salt(buffer[gindex].salt); + lindex = 0; +#if DES_bs_mt + lindex_mod = 0; + block_index = block_count; +#endif +#else + DES_std_set_salt(buffer[gindex].salt); +#endif + + do { +#if DES_BS +#if DES_bs_mt + buffer[gindex].block = block_index; + buffer[gindex].index = lindex_mod; + if (++lindex_mod >= DES_BS_DEPTH) { + lindex_mod = 0; + block_index++; + } +#else + buffer[gindex].block = block_count; + buffer[gindex].index = lindex; +#endif + l2g[lindex] = gindex; + DES_bs_set_key(buffer[gindex].key, lindex++); +#if DES_bs_mt + if (lindex >= DES_bs_max_kpc || + buffer[gindex].next < 0) { + int n = howmany(lindex, DES_BS_DEPTH); + int t; +#else + if (lindex >= DES_BS_DEPTH || + buffer[gindex].next < 0) { +#endif + int tindex; + DES_bs_crypt_25(lindex); + for_each_t(n) { + blkcpy58(crypt_out[block_count++], + DES_bs_all.B); + assert(block_count <= + worst_case_block_count); + } + if (next_hash_func) + for (tindex = 0; tindex < lindex; tindex++) { + buffer[l2g[tindex]].hash = + next_hash_func(tindex); + } + hash_func = next_hash_func; + lindex = 0; + } +#else + unsigned ARCH_WORD *out; + + DES_std_set_key(buffer[gindex].key); + + DES_std_crypt(DES_KS_current, + out = buffer[gindex].aligned.binary); + + { + ARCH_WORD mask; +#if ARCH_BITS < 64 + mask = (out[0] ^ out[1]) & buffer[gindex].salt; + out[0] ^= mask; + out[1] ^= mask; + mask = (out[2] ^ out[3]) & buffer[gindex].salt; + out[2] ^= mask; + out[3] ^= mask; +#else + mask = (out[0] ^ (out[0] >> 32)) & + buffer[gindex].salt; + out[0] ^= mask ^ (mask << 32); + mask = (out[1] ^ (out[1] >> 32)) & + buffer[gindex].salt; + out[1] ^= mask ^ (mask << 32); +#endif + } + out[0] &= binary_mask[0]; +#endif + + buffer[gindex].salt = 0xFFFFFFFF; + } while ((gindex = buffer[gindex].next) >= 0); + } + +#if 0 + printf("%d / %d = %d\n", count, block_count, count / block_count); +#endif +} + +static int crypt_all(int *pcount, struct db_salt *salt) +{ + int count = *pcount; + crypt_link_by_salt(count); + crypt_traverse_by_salt(count); + return count; +} + +#if DES_BS +static int cmp_all(void *binary, int count) +{ + int block_index; + + next_hash_func = NULL; + + for (block_index = 0; block_index < block_count; block_index++) { + MAYBE_T0; + blkcpy(DES_bs_all.B, crypt_out[block_index], 32); + if (DES_bs_cmp_all(binary, DES_BS_DEPTH)) + return 1; + } + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + int block = buffer[index].block; + MAYBE_T0; + blkcpy(DES_bs_all.B, crypt_out[block], 32); + return DES_bs_cmp_one((ARCH_WORD_32 *)binary, 32, buffer[index].index); +} + +static int cmp_exact(char *source, int index) +{ + int block = buffer[index].block; + MAYBE_T0; + blkcpy(DES_bs_all.B, crypt_out[block], 64); + return DES_bs_cmp_one(get_binary(source), 64, buffer[index].index); +} +#else +static int cmp_all(void *binary, int count) +{ + int index; + + for (index = 0; index < count; index++) + if (*(unsigned ARCH_WORD *)binary == buffer[index].aligned.binary[0]) + return 1; + + return 0; +} + +static int cmp_one(void *binary, int index) +{ + return *(unsigned ARCH_WORD *)binary == buffer[index].aligned.binary[0]; +} + +static int cmp_exact(char *source, int index) +{ + ARCH_WORD *binary; + int word; + + binary = get_binary(source); + + for (word = 0; word < 16 / DES_SIZE; word++) + if ((unsigned ARCH_WORD)binary[word] != + (buffer[index].aligned.binary[word] & binary_mask[word])) + return 0; + + return 1; +} +#endif + +static void set_key(char *key, int index) +{ + memcpy(buffer[index].key, key, PLAINTEXT_LENGTH); +} + +static char *get_key(int index) +{ + static char out[PLAINTEXT_LENGTH + 1]; + + memcpy(out, buffer[index].key, PLAINTEXT_LENGTH); + out[PLAINTEXT_LENGTH] = 0; + + return out; +} + +struct fmt_main fmt_trip = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + BINARY_ALIGN, + SALT_SIZE, + SALT_ALIGN, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, +#if DES_BS && DES_bs_mt + FMT_OMP | +#endif +#if DES_BS + FMT_CASE | FMT_BS, +#else + FMT_CASE, +#endif + tests + }, { + init, + fmt_default_done, + fmt_default_reset, + fmt_default_prepare, + valid, + fmt_default_split, + get_binary, + fmt_default_salt, + fmt_default_source, + { + binary_hash_0, + binary_hash_1, + binary_hash_2, + binary_hash_3, + binary_hash_4, + binary_hash_5, + binary_hash_6 + }, + fmt_default_salt_hash, + fmt_default_set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2, + get_hash_3, + get_hash_4, + get_hash_5, + get_hash_6 + }, + cmp_all, + cmp_one, + cmp_exact + } +}; diff --git a/src/tty.c b/src/tty.c new file mode 100644 index 0000000..4f3f9bd --- /dev/null +++ b/src/tty.c @@ -0,0 +1,119 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#ifndef __DJGPP__ +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#if !defined(O_NONBLOCK) && defined(O_NDELAY) +#define O_NONBLOCK O_NDELAY +#endif + +#ifdef __CYGWIN32__ +#include +#include +#ifndef __CYGWIN__ +extern int tcgetattr(int fd, struct termios *termios_p); +extern int tcsetattr(int fd, int actions, struct termios *termios_p); +#endif +#endif + +#include "tty.h" + +#ifndef __DJGPP__ +static int tty_fd = -1; +static struct termios saved_ti; +#endif + +void tty_init(int stdin_mode) +{ +#ifndef __DJGPP__ + int fd; + struct termios ti; + + if (tty_fd >= 0) return; + +/* + * If we're in "--stdin" mode (reading candidate passwords from stdin), then + * only initialize the tty if stdin is not a tty. Otherwise it could be the + * same tty, in which case we'd interfere with the user's ability to type + * candidate passwords directly to John. + */ + if (stdin_mode && !tcgetattr(0, &ti)) + return; + + if ((fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return; + +#ifndef __CYGWIN32__ + if (tcgetpgrp(fd) != getpid()) { + close(fd); return; + } +#endif + + tcgetattr(fd, &ti); + saved_ti = ti; + ti.c_lflag &= ~(ICANON | ECHO); + ti.c_cc[VMIN] = 1; + ti.c_cc[VTIME] = 0; + tcsetattr(fd, TCSANOW, &ti); + + tty_fd = fd; + + atexit(tty_done); +#endif +} + +int tty_getchar(void) +{ +#ifndef __DJGPP__ + int c; +#ifdef __CYGWIN32__ + fd_set set; + struct timeval tv; +#endif + + if (tty_fd >= 0) { +#ifdef __CYGWIN32__ + FD_ZERO(&set); FD_SET(tty_fd, &set); + tv.tv_sec = 0; tv.tv_usec = 0; + if (select(tty_fd + 1, &set, NULL, NULL, &tv) <= 0) + return -1; +#endif + c = 0; + if (read(tty_fd, &c, 1) > 0) return c; + } +#else + if (_bios_keybrd(_KEYBRD_READY)) + return _bios_keybrd(_KEYBRD_READ); +#endif + + return -1; +} + +void tty_done(void) +{ +#ifndef __DJGPP__ + int fd; + + if (tty_fd < 0) return; + + fd = tty_fd; tty_fd = -1; + tcsetattr(fd, TCSANOW, &saved_ti); + + close(fd); +#endif +} diff --git a/src/tty.h b/src/tty.h new file mode 100644 index 0000000..51f91eb --- /dev/null +++ b/src/tty.h @@ -0,0 +1,36 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2010 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Terminal support routines. + */ + +#ifndef _JOHN_TTY_H +#define _JOHN_TTY_H + +/* + * Initializes the terminal for unbuffered non-blocking input. Also registers + * tty_done() via atexit(). + * stdin_mode indicates whether we're running with "--stdin" (reading candidate + * passwords from stdin) or not. + */ +extern void tty_init(int stdin_mode); + +/* + * Reads a character, returns -1 if no data available or on error. + */ +extern int tty_getchar(void); + +/* + * Restores the terminal parameters and closes the file descriptor. + */ +extern void tty_done(void); + +#endif diff --git a/src/unafs.c b/src/unafs.c new file mode 100644 index 0000000..a5d4fee --- /dev/null +++ b/src/unafs.c @@ -0,0 +1,93 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1998,2005,2006 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include + +#include "misc.h" + +#define DB_ENTRY_SIZE 200 + +static void process_entry(unsigned char *entry, char *cell) +{ + char *name = (char *)&entry[40]; + char *instance = (char *)&entry[104]; + unsigned char *key = &entry[168]; + int index; + + if (!name[0]) return; + + name[63] = 0; + printf("%s", name); + if (instance[0]) { + instance[63] = 0; + printf(".%s", instance); + } + printf(":$K4$"); + + for (index = 0; index < 8; index++) + printf("%02x", (int)key[index]); + + printf(",%s\n", cell); +} + +static int process_db(FILE *file, char *cell) +{ + unsigned char buffer[DB_ENTRY_SIZE]; + long size; + + if (fread(buffer, 8, 1, file) != 1) return 1; + size = + ((long)buffer[6] << 8) | + (long)buffer[7]; + if (size == 0) size = 64; /* OpenAFS */ + if (fseek(file, size, SEEK_SET)) pexit("fseek"); + + if (fread(buffer, 8, 1, file) != 1) return 1; + size += + ((long)buffer[4] << 24) | + ((long)buffer[5] << 16) | + ((long)buffer[6] << 8) | + (long)buffer[7]; + if (fseek(file, size, SEEK_SET)) pexit("fseek"); + + while (fread(buffer, 1, DB_ENTRY_SIZE, file) == DB_ENTRY_SIZE) + process_entry(buffer, cell); + + return 0; +} + +int unafs(int argc, char **argv) +{ + FILE *file; + + if (argc != 3) { + puts("Usage: unafs DATABASE-FILE CELL-NAME"); + + if (argc <= 1) + return 0; + else + error(); + } + + if (!(file = fopen(argv[1], "rb"))) + pexit("fopen: %s", argv[1]); + + if (process_db(file, argv[2])) + if (!ferror(file)) { + fprintf(stderr, "fread: Unexpected EOF\n"); + error(); + } + + if (ferror(file)) pexit("fread"); + + if (fclose(file)) pexit("fclose"); + + return 0; +} diff --git a/src/unique.c b/src/unique.c new file mode 100644 index 0000000..ca0f8d1 --- /dev/null +++ b/src/unique.c @@ -0,0 +1,262 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1998,1999,2002,2003,2005,2006,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _POSIX_SOURCE /* for fdopen(3) */ +#include +#include +#include +#include +#include + +#include "arch.h" +#include "misc.h" +#include "params.h" +#include "memory.h" + +#define ENTRY_END_HASH 0xFFFFFFFF /* also hard-coded */ +#define ENTRY_END_LIST 0xFFFFFFFE +#define ENTRY_DUPE 0xFFFFFFFD + +static struct { + unsigned int *hash; + char *data; +} buffer; + +static FILE *output; + +#if ARCH_ALLOWS_UNALIGNED && !ARCH_INT_GT_32 + +#define get_int(ptr) \ + (*(ptr)) + +#define put_int(ptr, value) \ + *(ptr) = (value); + +#else + +static unsigned int get_int(unsigned int *ptr) +{ + unsigned char *bytes = (unsigned char *)ptr; + + return + (unsigned int)bytes[0] | + ((unsigned int)bytes[1] << 8) | + ((unsigned int)bytes[2] << 16) | + ((unsigned int)bytes[3] << 24); +} + +static void put_int(unsigned int *ptr, unsigned int value) +{ + unsigned char *bytes = (unsigned char *)ptr; + + bytes[0] = value; + bytes[1] = value >> 8; + bytes[2] = value >> 16; + bytes[3] = value >> 24; +} + +#endif + +#define get_data(ptr) \ + get_int((unsigned int *)&buffer.data[ptr]) + +#define put_data(ptr, value) \ + put_int((unsigned int *)&buffer.data[ptr], value) + +static unsigned int line_hash(char *line) +{ + unsigned int hash, extra; + char *p; + + p = line + 2; + hash = (unsigned char)line[0]; + if (!hash) + goto out; + extra = (unsigned char)line[1]; + if (!extra) +#if UNIQUE_HASH_SIZE >= 0x100 + goto out; +#else + goto out_and; +#endif + + while (*p) { + hash <<= 3; extra <<= 2; + hash += (unsigned char)p[0]; + if (!p[1]) break; + extra += (unsigned char)p[1]; + p += 2; + if (hash & 0xe0000000) { + hash ^= hash >> UNIQUE_HASH_LOG; + extra ^= extra >> UNIQUE_HASH_LOG; + hash &= UNIQUE_HASH_SIZE - 1; + } + } + + hash -= extra; + hash ^= extra << (UNIQUE_HASH_LOG / 2); + + hash ^= hash >> UNIQUE_HASH_LOG; + +#if UNIQUE_HASH_SIZE < 0x100 +out_and: +#endif + hash &= UNIQUE_HASH_SIZE - 1; +out: + return hash; +} + +static void init_hash(void) +{ +#if 0 + int index; + + for (index = 0; index < UNIQUE_HASH_SIZE; index++) + buffer.hash[index] = ENTRY_END_HASH; +#else +/* ENTRY_END_HASH is 0xFFFFFFFF */ + memset(buffer.hash, 0xff, UNIQUE_HASH_SIZE * sizeof(unsigned int)); +#endif +} + +static void read_buffer(void) +{ + char line[LINE_BUFFER_SIZE]; + unsigned int ptr, current, *last; + + init_hash(); + + ptr = 0; + while (fgetl(line, sizeof(line), stdin)) { + last = &buffer.hash[line_hash(line)]; +#if ARCH_LITTLE_ENDIAN && !ARCH_INT_GT_32 + current = *last; +#else + current = get_int(last); +#endif + while (current != ENTRY_END_HASH) { + if (!strcmp(line, &buffer.data[current + 4])) break; + last = (unsigned int *)&buffer.data[current]; + current = get_int(last); + } + if (current != ENTRY_END_HASH) continue; + + put_int(last, ptr); + + put_data(ptr, ENTRY_END_HASH); + ptr += 4; + + strcpy(&buffer.data[ptr], line); + ptr += strlen(line) + 1; + + if (ptr > UNIQUE_BUFFER_SIZE - sizeof(line) - 8) break; + } + + if (ferror(stdin)) pexit("fgets"); + + put_data(ptr, ENTRY_END_LIST); +} + +static void write_buffer(void) +{ + unsigned int ptr, hash; + + ptr = 0; + while ((hash = get_data(ptr)) != ENTRY_END_LIST) { + unsigned int length, size; + ptr += 4; + length = strlen(&buffer.data[ptr]); + size = length + 1; + if (hash != ENTRY_DUPE) { + buffer.data[ptr + length] = '\n'; + if (fwrite(&buffer.data[ptr], size, 1, output) != 1) + pexit("fwrite"); + } + ptr += size; + } +} + +static void clean_buffer(void) +{ + char line[LINE_BUFFER_SIZE]; + unsigned int current, *last; + + if (fseek(output, 0, SEEK_SET) < 0) pexit("fseek"); + + while (fgetl(line, sizeof(line), output)) { + last = &buffer.hash[line_hash(line)]; +#if ARCH_LITTLE_ENDIAN && !ARCH_INT_GT_32 + current = *last; +#else + current = get_int(last); +#endif + while (current != ENTRY_END_HASH && current != ENTRY_DUPE) { + if (!strcmp(line, &buffer.data[current + 4])) { + put_int(last, get_data(current)); + put_data(current, ENTRY_DUPE); + break; + } + last = (unsigned int *)&buffer.data[current]; + current = get_int(last); + } + } + + if (ferror(output)) pexit("fgets"); + +/* Workaround a Solaris stdio bug */ + if (fseek(output, 0, SEEK_END) < 0) pexit("fseek"); +} + +static void unique_init(char *name) +{ + int fd; + + buffer.hash = mem_alloc(UNIQUE_HASH_SIZE * sizeof(unsigned int)); + buffer.data = mem_alloc(UNIQUE_BUFFER_SIZE); + + if ((fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) + pexit("open: %s", name); + if (!(output = fdopen(fd, "w+"))) pexit("fdopen"); +} + +static void unique_run(void) +{ + read_buffer(); + write_buffer(); + + while (!feof(stdin)) { + read_buffer(); + clean_buffer(); + write_buffer(); + } +} + +static void unique_done(void) +{ + if (fclose(output)) pexit("fclose"); +} + +int unique(int argc, char **argv) +{ + if (argc != 2) { + puts("Usage: unique OUTPUT-FILE"); + + if (argc <= 1) + return 0; + else + error(); + } + + unique_init(argv[1]); + unique_run(); + unique_done(); + + return 0; +} diff --git a/src/unshadow.c b/src/unshadow.c new file mode 100644 index 0000000..58a35ed --- /dev/null +++ b/src/unshadow.c @@ -0,0 +1,180 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2005,2006,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#include +#include + +#include "misc.h" +#include "params.h" +#include "memory.h" + +struct shadow_entry { + struct shadow_entry *next; + char *login, *passwd; +}; + +static struct shadow_entry **shadow_table; + +static void alloc_hash(void) +{ + int size; + + size = SHADOW_HASH_SIZE * sizeof(struct shadow_entry *); + shadow_table = (struct shadow_entry **)mem_alloc(size); + memset(shadow_table, 0, size); +} + +static unsigned int login_hash(char *login) +{ + unsigned int hash, extra; + char *p; + + p = login + 2; + hash = (unsigned char)login[0]; + if (!hash) + goto out; + extra = (unsigned char)login[1]; + if (!extra) +#if SHADOW_HASH_SIZE >= 0x100 + goto out; +#else + goto out_and; +#endif + + while (*p) { + hash <<= 3; extra <<= 2; + hash += (unsigned char)p[0]; + if (!p[1]) break; + extra += (unsigned char)p[1]; + p += 2; + if (hash & 0xe0000000) { + hash ^= hash >> SHADOW_HASH_LOG; + extra ^= extra >> SHADOW_HASH_LOG; + hash &= SHADOW_HASH_SIZE - 1; + } + } + + hash -= extra; + hash ^= extra << (SHADOW_HASH_LOG / 2); + + hash ^= hash >> SHADOW_HASH_LOG; +#if SHADOW_HASH_LOG <= 15 + hash ^= hash >> (2 * SHADOW_HASH_LOG); +#endif +#if SHADOW_HASH_LOG <= 10 + hash ^= hash >> (3 * SHADOW_HASH_LOG); +#endif + +#if SHADOW_HASH_SIZE < 0x100 +out_and: +#endif + hash &= SHADOW_HASH_SIZE - 1; +out: + return hash; +} + +static void read_file(char *name, void (*process_line)(char *line)) +{ + FILE *file; + char line[LINE_BUFFER_SIZE]; + + if (!(file = fopen(name, "r"))) + pexit("fopen: %s", name); + + while (fgetl(line, sizeof(line), file)) + process_line(line); + + if (ferror(file)) pexit("fgets"); + + if (fclose(file)) pexit("fclose"); +} + +static void process_shadow_line(char *line) +{ + static struct shadow_entry **entry = NULL; + struct shadow_entry *last; + char *login, *passwd, *tail; + + if (!(passwd = strchr(line, ':'))) { + while (*line == ' ' || *line == '\t') line++; + /* AIX */ + if (!strncmp(line, "password = ", 11) && entry) + (*entry)->passwd = str_alloc_copy(line + 11); + return; + } + + login = line; + *passwd++ = 0; + + /* DU / Tru64 C2, HP-UX tcb */ + if (!strncmp(passwd, "u_name=", 7)) { + if ((passwd = strstr(passwd, ":u_pwd="))) + passwd += 7; + } else + /* HP-UX tcb */ + if (!strncmp(passwd, "u_pwd=", 6) && entry) { + passwd += 6; + if ((tail = strchr(passwd, ':'))) + *tail = 0; + (*entry)->passwd = str_alloc_copy(passwd); + return; + } + + if (passwd && (tail = strchr(passwd, ':'))) + *tail = 0; + + entry = &shadow_table[login_hash(login)]; + last = *entry; + *entry = mem_alloc_tiny(sizeof(struct shadow_entry), MEM_ALIGN_WORD); + (*entry)->next = last; + (*entry)->login = str_alloc_copy(login); + (*entry)->passwd = passwd ? str_alloc_copy(passwd) : "*"; +} + +static void process_passwd_line(char *line) +{ + char *pos1, *pos2; + struct shadow_entry *current; + + if (!(pos1 = strchr(line, ':'))) return; + *pos1++ = 0; + + if (!(pos2 = strchr(pos1, ':'))) + pos2 = pos1 + strlen(pos1); + + if (pos2 > pos1 && (current = shadow_table[login_hash(line)])) + do { + if (!strcmp(current->login, line)) { + printf("%s:%s%s\n", line, current->passwd, pos2); + return; + } + } while ((current = current->next)); + + printf("%s:%s\n", line, pos1); +} + +int unshadow(int argc, char **argv) +{ + if (argc != 3) { + puts("Usage: unshadow PASSWORD-FILE SHADOW-FILE"); + + if (argc <= 1) + return 0; + else + error(); + } + + alloc_hash(); + + read_file(argv[2], process_shadow_line); + read_file(argv[1], process_passwd_line); + + return 0; +} diff --git a/src/vax.h b/src/vax.h new file mode 100644 index 0000000..263e159 --- /dev/null +++ b/src/vax.h @@ -0,0 +1,50 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2000,2008 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for VAX. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 1 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#define DES_ASM 0 +#define DES_128K 1 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 1 +#define DES_COPY 1 +#define DES_BS_ASM 0 +#define DES_BS 1 +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 1 + +#define MD5_ASM 0 +#define MD5_X2 0 +#define MD5_IMM 1 + +#define BF_ASM 0 +#define BF_SCALE 0 +#define BF_X2 0 + +#endif diff --git a/src/wordlist.c b/src/wordlist.c new file mode 100644 index 0000000..064b33d --- /dev/null +++ b/src/wordlist.c @@ -0,0 +1,378 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-99,2003,2004,2006,2009,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +#define _POSIX_SOURCE /* for fileno(3) */ +#include +#include +#include +#include + +#include "misc.h" +#include "math.h" +#include "params.h" +#include "common.h" +#include "path.h" +#include "signals.h" +#include "loader.h" +#include "logger.h" +#include "status.h" +#include "recovery.h" +#include "options.h" +#include "rpp.h" +#include "rules.h" +#include "external.h" +#include "cracker.h" +#include "john.h" + +static FILE *word_file = NULL; +static int progress = 0; + +static int rec_rule; +static long rec_pos; /* ftell(3) is defined to return a long */ +static unsigned long rec_line; + +static int rule_number, rule_count; +static unsigned long line_number; +static int length; +static struct rpp_context *rule_ctx; + +static void save_state(FILE *file) +{ + fprintf(file, "%d\n%ld\n%lu\n", rec_rule, rec_pos, rec_line); +} + +static int restore_rule_number(void) +{ + if (rule_ctx) + for (rule_number = 0; rule_number < rec_rule; rule_number++) + if (!rpp_next(rule_ctx)) { + fprintf(stderr, "Restored rule number is out of range - " + "has the configuration file changed?\n"); + return 1; + } + + return 0; +} + +static MAYBE_INLINE int skip_lines(unsigned long n, char *line) +{ + if (n) { + line_number += n; + + do { + if (!fgetl(line, LINE_BUFFER_SIZE, word_file)) + return 1; + } while (--n); + } + + return 0; +} + +static void restore_line_number(void) +{ + char line[LINE_BUFFER_SIZE]; + if (skip_lines(rec_pos, line)) { + if (ferror(word_file)) + pexit("fgets"); + fprintf(stderr, "fgets: Unexpected EOF\n"); + error(); + } +} + +static int restore_state(FILE *file) +{ + if (fscanf(file, "%d\n%ld\n", &rec_rule, &rec_pos) != 2) + return 1; + rec_line = 0; + if (rec_version >= 4 && fscanf(file, "%lu\n", &rec_line) != 1) + return 1; + if (rec_rule < 0 || rec_pos < 0) + return 1; + + if (restore_rule_number()) + return 1; + + if (word_file == stdin) { + restore_line_number(); + } else { + if (fseek(word_file, rec_pos, SEEK_SET)) + pexit("fseek"); + line_number = rec_line; + } + + return 0; +} + +static void fix_state(void) +{ + rec_rule = rule_number; + rec_line = line_number; + + if (word_file == stdin) + rec_pos = line_number; + else + if ((rec_pos = ftell(word_file)) < 0) { +#ifdef __DJGPP__ + if (rec_pos != -1) + rec_pos = 0; + else +#endif + pexit("ftell"); + } +} + +static int get_progress(void) +{ + struct stat file_stat; + long pos; + int64 x100; + + if (!word_file) return progress; + + if (word_file == stdin) return -1; + + if (fstat(fileno(word_file), &file_stat)) pexit("fstat"); + + if ((pos = ftell(word_file)) < 0) { +#ifdef __DJGPP__ + if (pos != -1) + pos = 0; + else +#endif + pexit("ftell"); + } + + mul32by32(&x100, pos, 100); + return + (rule_number * 100 + + div64by32lo(&x100, file_stat.st_size + 1)) / rule_count; +} + +static char *dummy_rules_apply(char *word, char *rule, int split, char *last) +{ + word[length] = 0; + if (strcmp(word, last)) + return strcpy(last, word); + return NULL; +} + +void do_wordlist_crack(struct db_main *db, char *name, int rules) +{ + union { + char buffer[2][LINE_BUFFER_SIZE + CACHE_BANK_SHIFT]; + ARCH_WORD dummy; + } aligned; + char *line = aligned.buffer[0], *last = aligned.buffer[1]; + struct rpp_context ctx; + char *prerule, *rule, *word; + char *(*apply)(char *word, char *rule, int split, char *last); + int dist_rules, dist_switch; + unsigned long my_words, their_words, my_words_left; + + log_event("Proceeding with wordlist mode"); + + if (name) { + if (!(word_file = fopen(path_expand(name), "r"))) + pexit("fopen: %s", path_expand(name)); + log_event("- Wordlist file: %.100s", path_expand(name)); + } else { + word_file = stdin; + log_event("- Reading candidate passwords from stdin"); + } + + length = db->format->params.plaintext_length; + + if (rules) { + if (rpp_init(rule_ctx = &ctx, SUBSECTION_WORDLIST)) { + log_event("! No wordlist mode rules found"); + if (john_main_process) + fprintf(stderr, + "No wordlist mode rules found in %s\n", + cfg_name); + error(); + } + + rules_init(length); + rule_count = rules_count(&ctx, -1); + + log_event("- %d preprocessed word mangling rules", rule_count); + + apply = rules_apply; + } else { + rule_ctx = NULL; + rule_count = 1; + + log_event("- No word mangling rules"); + + apply = dummy_rules_apply; + } + + rule_number = 0; + line_number = 0; + + status_init(get_progress, 0); + + rec_restore_mode(restore_state); + rec_init(db, save_state); + + crk_init(db, fix_state, NULL); + + prerule = rule = ""; + if (rules) + prerule = rpp_next(&ctx); + +/* A string that can't be produced by fgetl(). */ + last[0] = '\n'; + last[1] = 0; + + dist_rules = 0; + dist_switch = rule_count; /* never */ + my_words = ~0UL; /* all */ + their_words = 0; + if (options.node_count) { + int rule_rem = rule_count % options.node_count; + const char *now, *later = ""; + dist_switch = rule_count - rule_rem; + if (!rule_rem || rule_number < dist_switch) { + dist_rules = 1; + now = "rules"; + if (rule_rem) + later = ", then switch to distributing words"; + } else { + dist_switch = rule_count; /* never */ + my_words = options.node_max - options.node_min + 1; + their_words = options.node_count - my_words; + now = "words"; + } + log_event("- Will distribute %s across nodes%s", now, later); + } + + my_words_left = my_words; + if (their_words) { + if (line_number) { +/* Restored session. line_number is right after a word we've actually used. */ + int for_node = line_number % options.node_count + 1; + if (for_node < options.node_min || + for_node > options.node_max) { +/* We assume that line_number is at the beginning of other nodes' block */ + if (skip_lines(their_words, line) && +/* Check for error since a mere EOF means next rule (the loop below should see + * the EOF again, and it will skip to next rule if applicable) */ + ferror(word_file)) + prerule = NULL; + } else { + my_words_left = + options.node_max - for_node + 1; + } + } else { +/* New session. Skip lower-numbered nodes' lines. */ + if (skip_lines(options.node_min - 1, line)) + prerule = NULL; + } + } + + if (prerule) + do { + if (rules) { + if (dist_rules) { + int for_node = + rule_number % options.node_count + 1; + if (for_node < options.node_min || + for_node > options.node_max) + goto next_rule; + } + if ((rule = rules_reject(prerule, -1, last, db))) { + if (strcmp(prerule, rule)) + log_event("- Rule #%d: '%.100s'" + " accepted as '%.100s'", + rule_number + 1, prerule, rule); + else + log_event("- Rule #%d: '%.100s'" + " accepted", + rule_number + 1, prerule); + } else { + log_event("- Rule #%d: '%.100s' rejected", + rule_number + 1, prerule); + goto next_rule; + } + } + + while (fgetl(line, LINE_BUFFER_SIZE, word_file)) { + line_number++; + + if (line[0] != '#') { +process_word: + if ((word = apply(line, rule, -1, last))) { + last = word; + + if (ext_filter(word)) + if (crk_process_key(word)) { + rules = 0; + break; + } + } +next_word: + if (--my_words_left) + continue; + if (skip_lines(their_words, line)) + break; + my_words_left = my_words; + continue; + } + + if (strncmp(line, "#!comment", 9)) + goto process_word; + goto next_word; + } + + if (ferror(word_file)) + break; + + if (rules) { +next_rule: + if (!(rule = rpp_next(&ctx))) break; + rule_number++; + + if (rule_number >= dist_switch) { + log_event("- Switching to distributing words"); + dist_rules = 0; + dist_switch = rule_count; /* not anymore */ + my_words = + options.node_max - options.node_min + 1; + their_words = options.node_count - my_words; + } + + line_number = 0; + if (fseek(word_file, 0, SEEK_SET)) + pexit("fseek"); + + if (their_words && + skip_lines(options.node_min - 1, line)) + break; + } + + my_words_left = my_words; + } while (rules); + + crk_done(); + rec_done(event_abort || (status.pass && db->salts)); + + if (ferror(word_file)) pexit("fgets"); + + if (name) { + if (event_abort) + progress = get_progress(); + else + progress = 100; + + if (fclose(word_file)) pexit("fclose"); + word_file = NULL; + } +} diff --git a/src/wordlist.h b/src/wordlist.h new file mode 100644 index 0000000..cacd29f --- /dev/null +++ b/src/wordlist.h @@ -0,0 +1,26 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Wordlist cracker. + */ + +#ifndef _JOHN_WORDLIST_H +#define _JOHN_WORDLIST_H + +#include "loader.h" + +/* + * Runs the wordlist cracker reading words from the supplied file name, or + * stdin if name is NULL. + */ +extern void do_wordlist_crack(struct db_main *db, char *name, int rules); + +#endif diff --git a/src/x86-64.S b/src/x86-64.S new file mode 100644 index 0000000..b0044b2 --- /dev/null +++ b/src/x86-64.S @@ -0,0 +1,1388 @@ +/* + * This file contains the core of a bitslice DES implementation for x86-64/SSE2. + * It is part of John the Ripper password cracker, + * Copyright (c) 2000-2001,2005,2006,2008,2011,2012 by Solar Designer + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. (This is a heavily cut-down "BSD license".) + * + * Gate counts per S-box: 49 44 46 33 48 46 46 41 + * Average: 44.125 + * + * The Boolean expressions corresponding to DES S-boxes have been generated + * by Roman Rusakov for use in Openwall's + * John the Ripper password cracker: http://www.openwall.com/john/ + * Being mathematical formulas, they are not copyrighted and are free for reuse + * by anyone. + * + * The x86-64/SSE2 code for the S-boxes was generated by Solar Designer using a + * Perl script. The script performed various optimizations, including the + * x86-64 specific optimization of preferring registers 0-7 over 8-15 to reduce + * the number of instruction prefixes (and thus code size). The instruction + * scheduling has been tuned for Core 2. + * + * The effort has been sponsored by Rapid7: http://www.rapid7.com + */ + +#include "arch.h" + +#if DES_BS_ASM + +#ifdef UNDERSCORES +#define DES_bs_all _DES_bs_all +#define DES_bs_init_asm _DES_bs_init_asm +#define DES_bs_crypt _DES_bs_crypt +#define DES_bs_crypt_25 _DES_bs_crypt_25 +#define DES_bs_crypt_LM _DES_bs_crypt_LM +#endif + +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align log +#else +#define DO_ALIGN(log) .align 1 << log +#endif + +#ifdef __sun +/* Sun's assembler doesn't recognize .space */ +#define DO_SPACE(size) .zero size +#else +/* Mac OS X assembler doesn't recognize .zero */ +#define DO_SPACE(size) .space size +#endif + +/* Sun's assembler can't multiply, but at least it can add... */ +#define nptr(n) n+n+n+n+n+n+n+n +#define nvec(n) n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n + +#ifdef BSD +.data +#else +.bss +#endif + +.globl DES_bs_all +DO_ALIGN(6) +DES_bs_all: +DES_bs_all_KSp: +DO_SPACE(nptr(0x300)) +DES_bs_all_KS_p: +DES_bs_all_KS_v: +DO_SPACE(nvec(0x300)) +DES_bs_all_E: +DO_SPACE(nptr(96)) +DES_bs_all_K: +DO_SPACE(nvec(56)) +DES_bs_all_B: +DO_SPACE(nvec(64)) +DES_bs_all_tmp: +DO_SPACE(nvec(16)) +DES_bs_all_xkeys: +DO_SPACE(nvec(64)) +DES_bs_all_pxkeys: +DO_SPACE(nptr(128)) +DES_bs_all_keys_changed: +DO_SPACE(4) +DES_bs_all_salt: +DO_SPACE(4) +DES_bs_all_Ens: +DO_SPACE(nptr(48)) + +#define E(i) DES_bs_all_E+nptr(i)(%rip) +#define B(i) DES_bs_all_B+nvec(i)(%rip) +#define tmp_at(i) DES_bs_all_tmp+nvec(i)(%rip) + +#define pnot tmp_at(0) + +#define a1 %xmm0 +#define a2 %xmm1 +#define a3 %xmm2 +#define a4 %xmm3 +#define a5 %xmm4 +#define a6 %xmm5 + +#define S1(out1, out2, out3, out4) \ + movdqa %xmm4,%xmm7; \ + movdqa %xmm5,%xmm10; \ + pandn %xmm0,%xmm4; \ + movdqa %xmm2,%xmm13; \ + movdqa %xmm4,%xmm14; \ + por %xmm2,%xmm10; \ + movdqa %xmm5,%xmm11; \ + pxor %xmm0,%xmm13; \ + pxor %xmm7,%xmm11; \ + pxor %xmm3,%xmm14; \ + movdqa %xmm13,%xmm12; \ + movdqa %xmm11,%xmm15; \ + pand %xmm10,%xmm13; \ + movdqa %xmm14,%xmm9; \ + movdqa %xmm13,%xmm8; \ + pxor %xmm2,%xmm15; \ + pxor %xmm3,%xmm8; \ + pandn %xmm11,%xmm12; \ + pandn %xmm8,%xmm9; \ + por %xmm5,%xmm13; \ + por %xmm0,%xmm5; \ + pandn %xmm7,%xmm8; \ + pandn %xmm14,%xmm15; \ + movdqa %xmm5,%xmm6; \ + pxor %xmm15,%xmm13; \ + movdqa %xmm9,%xmm15; \ + por %xmm13,%xmm6; \ + pandn %xmm3,%xmm5; \ + movdqa %xmm8,%xmm3; \ + pandn %xmm13,%xmm15; \ + pxor %xmm6,%xmm8; \ + pxor %xmm3,%xmm5; \ + pand %xmm10,%xmm13; \ + pandn %xmm2,%xmm4; \ + movdqa %xmm6,%xmm2; \ + pxor %xmm10,%xmm6; \ + pxor %xmm14,%xmm2; \ + pandn %xmm2,%xmm4; \ + movdqa %xmm4,%xmm2; \ + pxor pnot,%xmm2; \ + pxor %xmm11,%xmm4; \ + pxor %xmm2,%xmm13; \ + movdqa %xmm1,%xmm2; \ + por %xmm3,%xmm4; \ + pandn %xmm8,%xmm2; \ + por %xmm7,%xmm14; \ + pxor %xmm10,%xmm4; \ + por %xmm1,%xmm9; \ + pxor %xmm13,%xmm2; \ + pxor %xmm0,%xmm4; \ + movdqa %xmm1,%xmm0; \ + pxor %xmm4,%xmm13; \ + pxor %xmm13,%xmm9; \ + por %xmm12,%xmm5; \ + pxor out1,%xmm9; \ + por %xmm5,%xmm6; \ + por %xmm11,%xmm13; \ + pxor %xmm4,%xmm6; \ + movdqa %xmm9,out1; \ + por %xmm15,%xmm0; \ + pxor %xmm6,%xmm13; \ + pxor out3,%xmm2; \ + pxor out2,%xmm13; \ + pand %xmm15,%xmm4; \ + pandn %xmm14,%xmm6; \ + pxor %xmm0,%xmm13; \ + pxor %xmm6,%xmm4; \ + movdqa %xmm2,out3; \ + por %xmm1,%xmm4; \ + pxor %xmm5,%xmm4; \ + movdqa %xmm13,out2; \ + pxor out4,%xmm4; \ + movdqa %xmm4,out4 + +#define S2(out1, out2, out3, out4) \ + movdqa %xmm4,%xmm13; \ + movdqa %xmm5,%xmm6; \ + pxor %xmm1,%xmm13; \ + movdqa %xmm5,%xmm8; \ + pandn %xmm0,%xmm6; \ + movdqa %xmm13,%xmm7; \ + pandn %xmm4,%xmm6; \ + movdqa %xmm5,%xmm9; \ + movdqa %xmm6,%xmm14; \ + pandn %xmm13,%xmm8; \ + pand %xmm0,%xmm7; \ + pxor pnot,%xmm0; \ + por %xmm1,%xmm14; \ + movdqa %xmm8,%xmm12; \ + pxor %xmm4,%xmm7; \ + pand %xmm2,%xmm9; \ + pxor %xmm5,%xmm13; \ + pxor %xmm8,%xmm6; \ + movdqa %xmm9,%xmm10; \ + pand %xmm14,%xmm6; \ + pandn %xmm6,%xmm10; \ + pand %xmm2,%xmm6; \ + pandn %xmm7,%xmm12; \ + pxor %xmm6,%xmm0; \ + movdqa %xmm9,%xmm5; \ + pandn %xmm3,%xmm10; \ + pandn %xmm13,%xmm5; \ + movdqa %xmm5,%xmm11; \ + pandn %xmm1,%xmm5; \ + pxor %xmm0,%xmm11; \ + pxor %xmm13,%xmm2; \ + por %xmm3,%xmm12; \ + pxor %xmm5,%xmm7; \ + movdqa %xmm7,%xmm1; \ + pxor out2,%xmm10; \ + pandn %xmm0,%xmm1; \ + movdqa %xmm3,%xmm0; \ + pxor %xmm2,%xmm1; \ + pandn %xmm14,%xmm0; \ + pxor %xmm11,%xmm14; \ + pxor %xmm5,%xmm6; \ + pxor %xmm1,%xmm0; \ + por %xmm6,%xmm2; \ + por %xmm14,%xmm9; \ + pxor %xmm1,%xmm6; \ + pxor %xmm11,%xmm10; \ + pand %xmm9,%xmm6; \ + pxor out3,%xmm2; \ + pxor %xmm4,%xmm6; \ + pandn %xmm6,%xmm8; \ + pxor %xmm9,%xmm2; \ + pxor %xmm11,%xmm8; \ + por %xmm8,%xmm3; \ + por %xmm13,%xmm14; \ + pxor %xmm3,%xmm2; \ + pandn %xmm8,%xmm7; \ + movdqa %xmm2,out3; \ + pxor out4,%xmm7; \ + movdqa %xmm10,out2; \ + pxor %xmm14,%xmm7; \ + pxor out1,%xmm0; \ + pxor %xmm12,%xmm7; \ + movdqa %xmm0,out1; \ + movdqa %xmm7,out4 + +#define S3(out1, out2, out3, out4) \ + movdqa %xmm1,%xmm6; \ + movdqa %xmm5,%xmm13; \ + pandn %xmm0,%xmm6; \ + movdqa %xmm5,%xmm8; \ + pxor %xmm2,%xmm13; \ + movdqa %xmm0,%xmm11; \ + por %xmm13,%xmm6; \ + movdqa %xmm13,%xmm9; \ + pxor %xmm3,%xmm8; \ + movdqa %xmm3,%xmm15; \ + pandn %xmm8,%xmm11; \ + pxor %xmm1,%xmm9; \ + movdqa %xmm11,%xmm10; \ + movdqa %xmm4,%xmm12; \ + movdqa %xmm5,%xmm14; \ + pxor %xmm6,%xmm10; \ + pandn %xmm9,%xmm14; \ + movdqa %xmm10,%xmm7; \ + pxor %xmm14,%xmm6; \ + movdqa %xmm6,%xmm14; \ + pand %xmm5,%xmm7; \ + pand %xmm3,%xmm5; \ + pandn %xmm10,%xmm14; \ + por %xmm3,%xmm7; \ + pandn %xmm10,%xmm12; \ + pand %xmm0,%xmm7; \ + pxor out4,%xmm12; \ + pxor %xmm9,%xmm7; \ + pand %xmm13,%xmm8; \ + pxor %xmm0,%xmm15; \ + pxor %xmm7,%xmm12; \ + pxor %xmm15,%xmm6; \ + pand %xmm3,%xmm13; \ + por %xmm2,%xmm6; \ + por %xmm11,%xmm15; \ + pandn %xmm6,%xmm8; \ + movdqa %xmm15,%xmm6; \ + pand %xmm4,%xmm8; \ + pandn %xmm7,%xmm6; \ + movdqa %xmm1,%xmm7; \ + pandn %xmm10,%xmm1; \ + pandn %xmm5,%xmm7; \ + por %xmm9,%xmm5; \ + pxor %xmm7,%xmm6; \ + movdqa %xmm2,%xmm7; \ + pxor %xmm9,%xmm15; \ + pandn %xmm6,%xmm7; \ + pandn %xmm1,%xmm2; \ + pandn %xmm5,%xmm7; \ + pxor pnot,%xmm15; \ + pxor out2,%xmm7; \ + pxor %xmm2,%xmm15; \ + pandn %xmm4,%xmm14; \ + movdqa %xmm12,out4; \ + por %xmm15,%xmm9; \ + pxor %xmm0,%xmm7; \ + pandn %xmm9,%xmm13; \ + por %xmm11,%xmm1; \ + pxor %xmm8,%xmm7; \ + pxor %xmm1,%xmm13; \ + por %xmm4,%xmm6; \ + pxor out1,%xmm14; \ + pxor %xmm13,%xmm6; \ + pxor %xmm15,%xmm14; \ + pxor out3,%xmm6; \ + movdqa %xmm7,out2; \ + movdqa %xmm14,out1; \ + movdqa %xmm6,out3 + +#define S4(out1, out2, out3, out4) \ + movdqa %xmm3,%xmm7; \ + movdqa %xmm1,%xmm8; \ + pxor %xmm2,%xmm0; \ + pxor %xmm4,%xmm2; \ + por %xmm1,%xmm3; \ + pandn %xmm2,%xmm1; \ + pxor %xmm4,%xmm3; \ + movdqa %xmm1,%xmm10; \ + pxor %xmm7,%xmm1; \ + pandn %xmm2,%xmm3; \ + movdqa %xmm1,%xmm11; \ + movdqa %xmm3,%xmm6; \ + pxor %xmm8,%xmm7; \ + por %xmm0,%xmm1; \ + pandn %xmm1,%xmm3; \ + movdqa %xmm3,%xmm1; \ + movdqa %xmm5,%xmm12; \ + pxor %xmm8,%xmm3; \ + pand %xmm3,%xmm11; \ + movdqa %xmm11,%xmm9; \ + por %xmm4,%xmm10; \ + pxor %xmm3,%xmm0; \ + pandn %xmm2,%xmm11; \ + pandn %xmm0,%xmm11; \ + pxor %xmm0,%xmm10; \ + movdqa %xmm7,%xmm0; \ + pxor %xmm11,%xmm6; \ + movdqa %xmm6,%xmm4; \ + pandn %xmm5,%xmm6; \ + pandn %xmm10,%xmm7; \ + pxor out1,%xmm6; \ + pandn %xmm4,%xmm5; \ + pxor %xmm1,%xmm7; \ + pxor %xmm7,%xmm6; \ + pxor pnot,%xmm7; \ + pxor %xmm7,%xmm5; \ + pxor %xmm4,%xmm7; \ + pxor out2,%xmm5; \ + movdqa %xmm5,out2; \ + pandn %xmm7,%xmm0; \ + movdqa %xmm12,%xmm7; \ + por %xmm9,%xmm0; \ + movdqa %xmm6,out1; \ + pxor %xmm10,%xmm0; \ + por %xmm3,%xmm12; \ + pxor %xmm0,%xmm12; \ + pxor out4,%xmm0; \ + pand %xmm7,%xmm3; \ + pxor out3,%xmm12; \ + movdqa %xmm12,out3; \ + pxor %xmm3,%xmm0; \ + movdqa %xmm0,out4 + +#define S5(out1, out2, out3, out4) \ + movdqa %xmm2,%xmm6; \ + por %xmm0,%xmm2; \ + movdqa %xmm5,%xmm7; \ + pandn %xmm2,%xmm5; \ + movdqa %xmm3,%xmm14; \ + pandn %xmm5,%xmm3; \ + pxor %xmm0,%xmm5; \ + pxor %xmm6,%xmm3; \ + movdqa %xmm5,%xmm15; \ + pxor %xmm6,%xmm5; \ + movdqa %xmm3,%xmm10; \ + pand %xmm4,%xmm3; \ + movdqa %xmm5,%xmm8; \ + por %xmm0,%xmm5; \ + pxor %xmm14,%xmm3; \ + pxor %xmm5,%xmm3; \ + movdqa %xmm5,%xmm12; \ + por %xmm14,%xmm8; \ + pxor %xmm0,%xmm2; \ + pxor %xmm3,%xmm7; \ + pand %xmm14,%xmm12; \ + movdqa %xmm7,%xmm9; \ + por %xmm15,%xmm7; \ + pxor %xmm15,%xmm12; \ + pandn %xmm7,%xmm0; \ + pand %xmm4,%xmm7; \ + pxor %xmm8,%xmm4; \ + pxor %xmm7,%xmm12; \ + movdqa %xmm0,%xmm6; \ + pxor %xmm4,%xmm0; \ + pxor %xmm10,%xmm6; \ + movdqa %xmm1,%xmm13; \ + pandn %xmm4,%xmm6; \ + pand %xmm10,%xmm5; \ + pxor pnot,%xmm6; \ + por %xmm12,%xmm0; \ + pandn %xmm6,%xmm13; \ + movdqa %xmm7,%xmm6; \ + pandn %xmm10,%xmm7; \ + pxor %xmm8,%xmm10; \ + pandn %xmm0,%xmm7; \ + pxor %xmm13,%xmm3; \ + pand %xmm7,%xmm9; \ + movdqa %xmm7,%xmm0; \ + pxor %xmm4,%xmm9; \ + pandn %xmm8,%xmm0; \ + pand %xmm1,%xmm8; \ + por %xmm1,%xmm0; \ + pand %xmm9,%xmm14; \ + pxor %xmm2,%xmm7; \ + por %xmm9,%xmm5; \ + pxor %xmm14,%xmm7; \ + pxor %xmm6,%xmm5; \ + pxor %xmm7,%xmm0; \ + pxor %xmm15,%xmm9; \ + pandn %xmm10,%xmm7; \ + pand %xmm1,%xmm5; \ + pxor %xmm9,%xmm7; \ + pxor %xmm12,%xmm5; \ + pxor %xmm8,%xmm7; \ + pxor out3,%xmm3; \ + pxor out4,%xmm5; \ + pxor out1,%xmm0; \ + pxor out2,%xmm7; \ + movdqa %xmm3,out3; \ + movdqa %xmm5,out4; \ + movdqa %xmm0,out1; \ + movdqa %xmm7,out2 + +#define S6(out1, out2, out3, out4) \ + movdqa %xmm5,%xmm8; \ + por %xmm1,%xmm5; \ + movdqa %xmm4,%xmm7; \ + movdqa %xmm4,tmp_at(2); \ + movdqa %xmm2,%xmm11; \ + pxor %xmm1,%xmm4; \ + pand %xmm0,%xmm5; \ + movdqa %xmm3,%xmm15; \ + pxor %xmm5,%xmm4; \ + movdqa %xmm4,%xmm9; \ + pxor %xmm0,%xmm11; \ + pxor %xmm8,%xmm4; \ + movdqa %xmm0,tmp_at(1); \ + movdqa %xmm4,%xmm12; \ + pand %xmm0,%xmm4; \ + movdqa %xmm11,%xmm0; \ + pandn %xmm7,%xmm12; \ + movdqa %xmm4,%xmm10; \ + pxor %xmm1,%xmm4; \ + por %xmm1,%xmm11; \ + por %xmm4,%xmm0; \ + movdqa %xmm0,%xmm6; \ + por %xmm12,%xmm4; \ + pxor %xmm9,%xmm0; \ + pxor %xmm1,%xmm6; \ + movdqa %xmm4,%xmm14; \ + movdqa %xmm6,%xmm7; \ + pandn %xmm8,%xmm6; \ + pxor %xmm8,%xmm10; \ + pxor %xmm2,%xmm6; \ + pand %xmm0,%xmm2; \ + movdqa %xmm3,%xmm1; \ + pandn %xmm2,%xmm8; \ + movdqa %xmm2,%xmm13; \ + pxor %xmm8,%xmm14; \ + pxor %xmm11,%xmm7; \ + pand %xmm14,%xmm15; \ + pandn tmp_at(2),%xmm2; \ + pxor %xmm0,%xmm15; \ + por tmp_at(1),%xmm0; \ + pxor out4,%xmm15; \ + pand %xmm4,%xmm0; \ + por %xmm6,%xmm2; \ + pxor %xmm6,%xmm0; \ + pxor pnot,%xmm7; \ + pandn %xmm0,%xmm8; \ + pxor %xmm9,%xmm0; \ + por %xmm3,%xmm12; \ + pandn tmp_at(2),%xmm0; \ + por %xmm2,%xmm5; \ + pxor %xmm7,%xmm0; \ + pxor tmp_at(1),%xmm6; \ + pandn %xmm0,%xmm1; \ + pandn %xmm2,%xmm3; \ + pand %xmm10,%xmm6; \ + pxor %xmm3,%xmm7; \ + pxor out3,%xmm8; \ + pxor %xmm6,%xmm7; \ + pxor %xmm12,%xmm8; \ + pxor %xmm1,%xmm5; \ + pxor %xmm13,%xmm7; \ + pxor %xmm11,%xmm14; \ + pxor out2,%xmm5; \ + pxor %xmm14,%xmm5; \ + movdqa %xmm15,out4; \ + pxor out1,%xmm7; \ + movdqa %xmm8,out3; \ + movdqa %xmm5,out2; \ + movdqa %xmm7,out1 + +#define S7(out1, out2, out3, out4) \ + movdqa %xmm4,%xmm14; \ + pxor %xmm3,%xmm4; \ + movdqa %xmm3,%xmm11; \ + movdqa %xmm4,%xmm12; \ + pand %xmm4,%xmm11; \ + pxor %xmm2,%xmm4; \ + movdqa %xmm11,%xmm6; \ + movdqa %xmm4,%xmm7; \ + movdqa %xmm11,%xmm15; \ + pand %xmm5,%xmm6; \ + pxor %xmm1,%xmm11; \ + movdqa %xmm7,%xmm13; \ + pand %xmm5,%xmm4; \ + movdqa %xmm11,%xmm10; \ + pxor %xmm5,%xmm12; \ + pxor %xmm2,%xmm6; \ + movdqa %xmm6,%xmm8; \ + por %xmm10,%xmm6; \ + pand %xmm4,%xmm11; \ + pandn %xmm0,%xmm11; \ + pxor %xmm12,%xmm6; \ + pxor %xmm4,%xmm8; \ + pandn %xmm14,%xmm7; \ + movdqa %xmm7,%xmm9; \ + pxor %xmm6,%xmm11; \ + pxor %xmm12,%xmm4; \ + por %xmm10,%xmm7; \ + pxor %xmm8,%xmm7; \ + pandn %xmm3,%xmm4; \ + pxor %xmm14,%xmm8; \ + pandn %xmm10,%xmm4; \ + pxor %xmm4,%xmm8; \ + pandn %xmm13,%xmm12; \ + pand %xmm8,%xmm2; \ + por %xmm15,%xmm6; \ + por %xmm2,%xmm6; \ + pxor %xmm12,%xmm6; \ + movdqa %xmm0,%xmm3; \ + pandn %xmm6,%xmm0; \ + movdqa %xmm6,%xmm4; \ + por %xmm8,%xmm6; \ + pand %xmm5,%xmm6; \ + pxor %xmm7,%xmm0; \ + por %xmm14,%xmm2; \ + pand %xmm6,%xmm1; \ + pxor %xmm4,%xmm7; \ + pxor %xmm6,%xmm2; \ + pxor %xmm7,%xmm1; \ + pxor %xmm14,%xmm7; \ + movdqa %xmm3,%xmm5; \ + por %xmm2,%xmm7; \ + pxor out1,%xmm0; \ + pand %xmm7,%xmm3; \ + pxor pnot,%xmm4; \ + pxor %xmm6,%xmm7; \ + por %xmm9,%xmm7; \ + pxor out4,%xmm11; \ + pxor %xmm3,%xmm8; \ + pxor %xmm4,%xmm7; \ + pandn %xmm7,%xmm5; \ + movdqa %xmm11,out4; \ + pxor out2,%xmm1; \ + movdqa %xmm0,out1; \ + pxor %xmm5,%xmm1; \ + pxor out3,%xmm8; \ + movdqa %xmm8,out3; \ + movdqa %xmm1,out2 + +#define S8(out1, out2, out3, out4) \ + movdqa %xmm1,%xmm13; \ + pandn %xmm2,%xmm1; \ + movdqa %xmm2,%xmm11; \ + movdqa %xmm2,%xmm8; \ + pandn %xmm4,%xmm2; \ + movdqa %xmm1,%xmm6; \ + pxor %xmm3,%xmm2; \ + pandn %xmm13,%xmm11; \ + movdqa %xmm2,%xmm9; \ + pand %xmm0,%xmm2; \ + movdqa %xmm9,%xmm7; \ + pandn %xmm2,%xmm1; \ + pandn %xmm13,%xmm9; \ + pxor %xmm4,%xmm11; \ + movdqa %xmm9,%xmm12; \ + por %xmm0,%xmm9; \ + movdqa %xmm11,%xmm10; \ + pand %xmm9,%xmm11; \ + pxor pnot,%xmm7; \ + por %xmm11,%xmm2; \ + pxor %xmm11,%xmm7; \ + pandn %xmm8,%xmm9; \ + movdqa %xmm5,%xmm15; \ + pxor %xmm9,%xmm7; \ + por %xmm1,%xmm5; \ + pxor %xmm7,%xmm6; \ + pxor %xmm6,%xmm5; \ + pxor %xmm0,%xmm6; \ + movdqa %xmm6,%xmm14; \ + pxor %xmm13,%xmm7; \ + pand %xmm4,%xmm6; \ + pxor out2,%xmm5; \ + pxor %xmm7,%xmm6; \ + pxor %xmm6,%xmm12; \ + movdqa %xmm5,out2; \ + pxor %xmm2,%xmm6; \ + pxor %xmm4,%xmm14; \ + por %xmm13,%xmm6; \ + pand %xmm15,%xmm2; \ + por %xmm3,%xmm7; \ + pxor %xmm12,%xmm10; \ + pxor %xmm10,%xmm7; \ + pxor %xmm14,%xmm6; \ + pxor %xmm6,%xmm2; \ + pxor %xmm7,%xmm0; \ + pandn %xmm10,%xmm3; \ + pand %xmm15,%xmm0; \ + pand %xmm3,%xmm6; \ + pxor out3,%xmm2; \ + pxor %xmm6,%xmm7; \ + pxor %xmm1,%xmm7; \ + pxor out4,%xmm0; \ + movdqa %xmm2,out3; \ + por %xmm15,%xmm7; \ + pxor out1,%xmm7; \ + pxor %xmm12,%xmm0; \ + pxor %xmm12,%xmm7; \ + movdqa %xmm0,out4; \ + movdqa %xmm7,out1 + +#define zero %xmm0 + +#define DES_bs_clear_block_8(i) \ + movdqa zero,B(i); \ + movdqa zero,B(i + 1); \ + movdqa zero,B(i + 2); \ + movdqa zero,B(i + 3); \ + movdqa zero,B(i + 4); \ + movdqa zero,B(i + 5); \ + movdqa zero,B(i + 6); \ + movdqa zero,B(i + 7) + +#define DES_bs_clear_block \ + DES_bs_clear_block_8(0); \ + DES_bs_clear_block_8(8); \ + DES_bs_clear_block_8(16); \ + DES_bs_clear_block_8(24); \ + DES_bs_clear_block_8(32); \ + DES_bs_clear_block_8(40); \ + DES_bs_clear_block_8(48); \ + DES_bs_clear_block_8(56) + +#define k_ptr %rdx +#define K(i) nvec(i)(k_ptr) +#define k(i) nptr(i)(k_ptr) + +#define tmp1 %rcx +#define tmp2 %rsi + +#define xor_E(i) \ + movq E(i),tmp1; \ + movdqa K(i),a1; \ + movq E(i + 1),tmp2; \ + movdqa K(i + 1),a2; \ + pxor (tmp1),a1; \ + pxor (tmp2),a2; \ + movq E(i + 2),tmp1; \ + movdqa K(i + 2),a3; \ + movq E(i + 3),tmp2; \ + movdqa K(i + 3),a4; \ + pxor (tmp1),a3; \ + pxor (tmp2),a4; \ + movq E(i + 4),tmp1; \ + movdqa K(i + 4),a5; \ + movq E(i + 5),tmp2; \ + movdqa K(i + 5),a6; \ + pxor (tmp1),a5; \ + pxor (tmp2),a6 + +#define xor_B(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6, k6) \ + movdqa B(b1),a1; \ + movdqa B(b2),a2; \ + pxor K(k1),a1; \ + movdqa B(b3),a3; \ + pxor K(k2),a2; \ + movdqa B(b4),a4; \ + pxor K(k3),a3; \ + movdqa B(b5),a5; \ + pxor K(k4),a4; \ + movdqa B(b6),a6; \ + pxor K(k5),a5; \ + pxor K(k6),a6 + +#define xor_B_KS_p(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6, k6) \ + movq k(k1),tmp1; \ + movq k(k2),tmp2; \ + movdqa B(b1),a1; \ + movdqa B(b2),a2; \ + pxor (tmp1),a1; \ + movq k(k3),tmp1; \ + pxor (tmp2),a2; \ + movq k(k4),tmp2; \ + movdqa B(b3),a3; \ + movdqa B(b4),a4; \ + pxor (tmp1),a3; \ + movq k(k5),tmp1; \ + pxor (tmp2),a4; \ + movdqa B(b5),a5; \ + movq k(k6),tmp2; \ + movdqa B(b6),a6; \ + pxor (tmp1),a5; \ + pxor (tmp2),a6 + +#define mask01 tmp_at(8) +#define mask02 tmp_at(9) +#define mask04 tmp_at(10) +#define mask08 tmp_at(11) +#define mask10 tmp_at(12) +#define mask20 tmp_at(13) +#define mask40 tmp_at(14) +#define mask80 tmp_at(15) + +#define v_ptr %rax +#define V(i) nvec(i)(v_ptr) + +#if 1 +#define SHLB1(reg) paddb reg,reg +#else +#define SHLB1(reg) psllq $1,reg +#endif + +#define FINALIZE_NEXT_KEY_BITS_0_6 \ + movdqa V(0),%xmm0; \ + movdqa V(1),%xmm1; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + SHLB1(%xmm1); \ + psllq $2,%xmm2; \ + psllq $3,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $4,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psllq $5,%xmm5; \ + psllq $6,%xmm6; \ + psllq $7,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(0); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm8,%xmm1; \ + pand %xmm8,%xmm2; \ + pand %xmm8,%xmm0; \ + pand %xmm8,%xmm3; \ + psrlq $1,%xmm0; \ + SHLB1(%xmm2); \ + psllq $2,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm8,%xmm4; \ + pand %xmm8,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $3,%xmm4; \ + pand %xmm8,%xmm6; \ + pand %xmm8,%xmm0; \ + psllq $4,%xmm5; \ + psllq $5,%xmm6; \ + psllq $6,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(1); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm9,%xmm1; \ + pand %xmm9,%xmm2; \ + pand %xmm9,%xmm0; \ + pand %xmm9,%xmm3; \ + psrlq $1,%xmm1; \ + psrlq $2,%xmm0; \ + SHLB1(%xmm3); \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm9,%xmm4; \ + pand %xmm9,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $2,%xmm4; \ + pand %xmm9,%xmm6; \ + pand %xmm9,%xmm0; \ + psllq $3,%xmm5; \ + psllq $4,%xmm6; \ + psllq $5,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(2); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm10,%xmm1; \ + pand %xmm10,%xmm2; \ + pand %xmm10,%xmm0; \ + pand %xmm10,%xmm3; \ + psrlq $2,%xmm1; \ + psrlq $3,%xmm0; \ + psrlq $1,%xmm2; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm10,%xmm4; \ + pand %xmm10,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + SHLB1(%xmm4); \ + pand %xmm10,%xmm6; \ + pand %xmm10,%xmm0; \ + psllq $2,%xmm5; \ + psllq $3,%xmm6; \ + psllq $4,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(3); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm11,%xmm1; \ + pand %xmm11,%xmm2; \ + pand %xmm11,%xmm0; \ + pand %xmm11,%xmm3; \ + psrlq $3,%xmm1; \ + psrlq $4,%xmm0; \ + psrlq $2,%xmm2; \ + psrlq $1,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm11,%xmm4; \ + pand %xmm11,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + pand %xmm11,%xmm6; \ + pand %xmm11,%xmm0; \ + SHLB1(%xmm5); \ + psllq $2,%xmm6; \ + psllq $3,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(4); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm12,%xmm1; \ + pand %xmm12,%xmm2; \ + pand %xmm12,%xmm0; \ + pand %xmm12,%xmm3; \ + psrlq $4,%xmm1; \ + psrlq $5,%xmm0; \ + psrlq $3,%xmm2; \ + psrlq $2,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm12,%xmm4; \ + pand %xmm12,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psrlq $1,%xmm4; \ + pand %xmm12,%xmm6; \ + pand %xmm12,%xmm0; \ + SHLB1(%xmm6); \ + psllq $2,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa %xmm0,K(5); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(3),%xmm3; \ + pand %xmm13,%xmm1; \ + pand %xmm13,%xmm2; \ + pand %xmm13,%xmm0; \ + pand %xmm13,%xmm3; \ + psrlq $5,%xmm1; \ + psrlq $6,%xmm0; \ + psrlq $4,%xmm2; \ + psrlq $3,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm13,%xmm4; \ + pand %xmm13,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psrlq $2,%xmm4; \ + pand %xmm13,%xmm6; \ + pand %xmm13,%xmm0; \ + psrlq $1,%xmm5; \ + SHLB1(%xmm0); \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + por %xmm3,%xmm0; \ + movdqa %xmm0,K(6) + +.text + +DO_ALIGN(6) +.globl DES_bs_init_asm +DES_bs_init_asm: + pcmpeqd %xmm0,%xmm0 + movdqa %xmm0,pnot + paddb %xmm0,%xmm0 + pxor pnot,%xmm0 + movdqa %xmm0,mask01 + SHLB1(%xmm0) + movdqa %xmm0,mask02 + SHLB1(%xmm0) + movdqa %xmm0,mask04 + SHLB1(%xmm0) + movdqa %xmm0,mask08 + SHLB1(%xmm0) + movdqa %xmm0,mask10 + SHLB1(%xmm0) + movdqa %xmm0,mask20 + SHLB1(%xmm0) + movdqa %xmm0,mask40 + SHLB1(%xmm0) + movdqa %xmm0,mask80 + ret + +#define iterations %edi +#define rounds_and_swapped %eax + +DO_ALIGN(6) +.globl DES_bs_crypt +DES_bs_crypt: + cmpl $0,DES_bs_all_keys_changed(%rip) + jz DES_bs_crypt_body + pushq %rdi + call DES_bs_finalize_keys + popq %rdi +DES_bs_crypt_body: + pxor zero,zero + leaq DES_bs_all_KS_v(%rip),k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped +DES_bs_crypt_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62)) + xor_E(6) + S2(B(44), B(59), B(33), B(49)) + xor_E(12) + S3(B(55), B(47), B(61), B(37)) + xor_E(18) + S4(B(57), B(51), B(41), B(32)) + xor_E(24) + S5(B(39), B(45), B(56), B(34)) + xor_E(30) + S6(B(35), B(60), B(42), B(50)) + xor_E(36) + S7(B(63), B(43), B(53), B(38)) + xor_E(42) + S8(B(36), B(58), B(46), B(52)) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_next +DES_bs_crypt_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30)) + xor_E(54) + S2(B(12), B(27), B(1), B(17)) + xor_E(60) + S3(B(23), B(15), B(29), B(5)) + xor_E(66) + S4(B(25), B(19), B(9), B(0)) + xor_E(72) + S5(B(7), B(13), B(24), B(2)) + xor_E(78) + S6(B(3), B(28), B(10), B(18)) + xor_E(84) + S7(B(31), B(11), B(21), B(6)) + xor_E(90) + addq $nvec(96),k_ptr + S8(B(4), B(26), B(14), B(20)) + subl $1,rounds_and_swapped + jnz DES_bs_crypt_start + subq $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + subl $1,iterations + jnz DES_bs_crypt_swap + ret +DES_bs_crypt_next: + subq $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + subl $1,iterations + jnz DES_bs_crypt_start + ret + +DO_ALIGN(6) +.globl DES_bs_crypt_25 +DES_bs_crypt_25: + cmpl $0,DES_bs_all_keys_changed(%rip) + jnz DES_bs_finalize_keys_25 +DES_bs_crypt_25_body: + pxor zero,zero + leaq DES_bs_all_KS_v(%rip),k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped + movl $25,iterations +DES_bs_crypt_25_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62)) + xor_E(6) + S2(B(44), B(59), B(33), B(49)) + xor_B(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12, 17) + S3(B(55), B(47), B(61), B(37)) + xor_B(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16, 23) + S4(B(57), B(51), B(41), B(32)) + xor_E(24) + S5(B(39), B(45), B(56), B(34)) + xor_E(30) + S6(B(35), B(60), B(42), B(50)) + xor_B(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28, 41) + S7(B(63), B(43), B(53), B(38)) + xor_B(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0, 47) + S8(B(36), B(58), B(46), B(52)) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_25_next +DES_bs_crypt_25_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30)) + xor_E(54) + S2(B(12), B(27), B(1), B(17)) + xor_B(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44, 65) + S3(B(23), B(15), B(29), B(5)) + xor_B(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48, 71) + S4(B(25), B(19), B(9), B(0)) + xor_E(72) + S5(B(7), B(13), B(24), B(2)) + xor_E(78) + S6(B(3), B(28), B(10), B(18)) + xor_B(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60, 89) + S7(B(31), B(11), B(21), B(6)) + xor_B(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32, 95) + S8(B(4), B(26), B(14), B(20)) + addq $nvec(96),k_ptr + subl $1,rounds_and_swapped + jnz DES_bs_crypt_25_start + subq $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + subl $1,iterations + jnz DES_bs_crypt_25_swap + ret +DES_bs_crypt_25_next: + subq $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + subl $1,iterations + jmp DES_bs_crypt_25_start + +DES_bs_finalize_keys_25: + leaq DES_bs_crypt_25_body(%rip),tmp1 + pushq tmp1 +DES_bs_finalize_keys: + movdqa mask01,%xmm7 + movdqa mask02,%xmm8 + leaq DES_bs_all_xkeys(%rip),v_ptr + movdqa mask04,%xmm9 + movdqa mask08,%xmm10 + leaq DES_bs_all_K(%rip),k_ptr + movl $8,iterations + movdqa mask10,%xmm11 + movdqa mask20,%xmm12 + movl $0,DES_bs_all_keys_changed(%rip) + movdqa mask40,%xmm13 +DES_bs_finalize_keys_main_loop: + FINALIZE_NEXT_KEY_BITS_0_6 + addq $nvec(7),k_ptr + addq $nvec(8),v_ptr + subl $1,iterations + jnz DES_bs_finalize_keys_main_loop + leaq DES_bs_all_KSp(%rip),k_ptr + leaq DES_bs_all_KS_v(%rip),v_ptr + movl $0x60,iterations +DES_bs_finalize_keys_expand_loop: + movq k(0),tmp1 + movq k(1),tmp2 + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movq k(2),tmp1 + movq k(3),tmp2 + movdqa %xmm0,V(0) + movdqa %xmm1,V(1) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movq k(4),tmp1 + movq k(5),tmp2 + movdqa %xmm0,V(2) + movdqa %xmm1,V(3) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movq k(6),tmp1 + movq k(7),tmp2 + movdqa %xmm0,V(4) + movdqa %xmm1,V(5) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + addq $nptr(8),k_ptr + movdqa %xmm0,V(6) + movdqa %xmm1,V(7) + addq $nvec(8),v_ptr + subl $1,iterations + jnz DES_bs_finalize_keys_expand_loop + ret + +#define ones %xmm1 + +#define rounds %eax + +DO_ALIGN(6) +.globl DES_bs_crypt_LM +DES_bs_crypt_LM: + movl (%rdi),%r8d + movdqa mask01,%xmm7 + movdqa mask02,%xmm8 + leaq DES_bs_all_xkeys(%rip),v_ptr + movdqa mask04,%xmm9 + movdqa mask08,%xmm10 + leaq DES_bs_all_K(%rip),k_ptr + movdqa mask10,%xmm11 + movdqa mask20,%xmm12 + movl $7,iterations + movdqa mask40,%xmm13 + movdqa mask80,%xmm14 +DES_bs_finalize_keys_LM_loop: + FINALIZE_NEXT_KEY_BITS_0_6 +# bit 7 + movdqa V(0),%xmm0 + movdqa V(1),%xmm1 + movdqa V(2),%xmm2 + movdqa V(3),%xmm3 + pand %xmm14,%xmm0 + pand %xmm14,%xmm1 + pand %xmm14,%xmm2 + pand %xmm14,%xmm3 + psrlq $7,%xmm0 + psrlq $6,%xmm1 + psrlq $5,%xmm2 + psrlq $4,%xmm3 + por %xmm0,%xmm1 + por %xmm2,%xmm3 + movdqa V(4),%xmm4 + movdqa V(5),%xmm5 + por %xmm1,%xmm3 + pand %xmm14,%xmm4 + pand %xmm14,%xmm5 + movdqa V(6),%xmm6 + movdqa V(7),%xmm0 + psrlq $3,%xmm4 + pand %xmm14,%xmm6 + pand %xmm14,%xmm0 + psrlq $2,%xmm5 + psrlq $1,%xmm6 + por %xmm4,%xmm5 + por %xmm6,%xmm3 + por %xmm5,%xmm0 + addq $nvec(8),v_ptr + por %xmm3,%xmm0 + movdqa %xmm0,K(7) + addq $nvec(8),k_ptr + subl $1,iterations + jnz DES_bs_finalize_keys_LM_loop + + pxor zero,zero + pcmpeqd ones,ones + leaq DES_bs_all_KS_p(%rip),k_ptr + movdqa zero,B(0) + movdqa zero,B(1) + movdqa zero,B(2) + movdqa zero,B(3) + movdqa zero,B(4) + movdqa zero,B(5) + movdqa zero,B(6) + movdqa zero,B(7) + movdqa ones,B(8) + movdqa ones,B(9) + movdqa ones,B(10) + movdqa zero,B(11) + movdqa ones,B(12) + movdqa zero,B(13) + movdqa zero,B(14) + movdqa zero,B(15) + movdqa zero,B(16) + movdqa zero,B(17) + movdqa zero,B(18) + movdqa zero,B(19) + movdqa zero,B(20) + movdqa zero,B(21) + movdqa zero,B(22) + movdqa ones,B(23) + movdqa zero,B(24) + movdqa zero,B(25) + movdqa ones,B(26) + movdqa zero,B(27) + movdqa zero,B(28) + movdqa ones,B(29) + movdqa ones,B(30) + movdqa ones,B(31) + movdqa zero,B(32) + movdqa zero,B(33) + movdqa zero,B(34) + movdqa ones,B(35) + movdqa zero,B(36) + movdqa ones,B(37) + movdqa ones,B(38) + movdqa ones,B(39) + movdqa zero,B(40) + movdqa zero,B(41) + movdqa zero,B(42) + movdqa zero,B(43) + movdqa zero,B(44) + movdqa ones,B(45) + movdqa zero,B(46) + movdqa zero,B(47) + movdqa ones,B(48) + movdqa ones,B(49) + movdqa zero,B(50) + movdqa zero,B(51) + movdqa zero,B(52) + movdqa zero,B(53) + movdqa ones,B(54) + movdqa zero,B(55) + movdqa ones,B(56) + movdqa zero,B(57) + movdqa ones,B(58) + movdqa zero,B(59) + movdqa ones,B(60) + movdqa ones,B(61) + movdqa ones,B(62) + movdqa ones,B(63) + movl $8,rounds +DES_bs_crypt_LM_loop: + xor_B_KS_p(31, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5) + S1(B(40), B(48), B(54), B(62)) + xor_B_KS_p(3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11) + S2(B(44), B(59), B(33), B(49)) + xor_B_KS_p(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12, 17) + S3(B(55), B(47), B(61), B(37)) + xor_B_KS_p(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16, 23) + S4(B(57), B(51), B(41), B(32)) + xor_B_KS_p(15, 24, 16, 25, 17, 26, 18, 27, 19, 28, 20, 29) + S5(B(39), B(45), B(56), B(34)) + xor_B_KS_p(19, 30, 20, 31, 21, 32, 22, 33, 23, 34, 24, 35) + S6(B(35), B(60), B(42), B(50)) + xor_B_KS_p(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28, 41) + S7(B(63), B(43), B(53), B(38)) + xor_B_KS_p(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0, 47) + S8(B(36), B(58), B(46), B(52)) + xor_B_KS_p(63, 48, 32, 49, 33, 50, 34, 51, 35, 52, 36, 53) + S1(B(8), B(16), B(22), B(30)) + xor_B_KS_p(35, 54, 36, 55, 37, 56, 38, 57, 39, 58, 40, 59) + S2(B(12), B(27), B(1), B(17)) + xor_B_KS_p(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44, 65) + S3(B(23), B(15), B(29), B(5)) + xor_B_KS_p(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48, 71) + S4(B(25), B(19), B(9), B(0)) + xor_B_KS_p(47, 72, 48, 73, 49, 74, 50, 75, 51, 76, 52, 77) + S5(B(7), B(13), B(24), B(2)) + xor_B_KS_p(51, 78, 52, 79, 53, 80, 54, 81, 55, 82, 56, 83) + S6(B(3), B(28), B(10), B(18)) + xor_B_KS_p(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60, 89) + S7(B(31), B(11), B(21), B(6)) + xor_B_KS_p(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32, 95) + addq $nptr(96),k_ptr + S8(B(4), B(26), B(14), B(20)) + subl $1,rounds + jnz DES_bs_crypt_LM_loop + xchgq %r8,%rax + ret + +#endif + +#if defined(CPU_REQ_AVX) || defined(CPU_REQ_XOP) +/* + * CPU detection. + */ + +#define CF_XSAVE_OSXSAVE_AVX $0x1C000000 +#define CF_XOP $0x00000800 + +.text + +#ifdef UNDERSCORES +#define CPU_detect _CPU_detect +#endif +.globl CPU_detect +CPU_detect: + pushq %rbx + movl $1,%eax + cpuid + andl CF_XSAVE_OSXSAVE_AVX,%ecx + cmpl CF_XSAVE_OSXSAVE_AVX,%ecx + jne CPU_detect_fail + xorl %ecx,%ecx + xgetbv + andb $0x6,%al + cmpb $0x6,%al + jne CPU_detect_fail +#ifdef CPU_REQ_XOP + movl $0x80000000,%eax + cpuid + movl $0x80000001,%edx + cmpl %edx,%eax + jl CPU_detect_fail + xchgl %edx,%eax + cpuid + testl CF_XOP,%ecx + jz CPU_detect_fail +#endif + movl $1,%eax + popq %rbx + ret +CPU_detect_fail: + xorl %eax,%eax + popq %rbx + ret +#endif + +#if defined(__ELF__) && defined(__linux__) +.section .note.GNU-stack,"",@progbits +#endif diff --git a/src/x86-64.h b/src/x86-64.h new file mode 100644 index 0000000..65d3705 --- /dev/null +++ b/src/x86-64.h @@ -0,0 +1,186 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 2003,2006,2008,2010,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for x86-64. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 8 +#define ARCH_BITS 64 +#define ARCH_BITS_LOG 6 +#define ARCH_BITS_STR "64" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 1 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 0 + +#ifdef __XOP__ +#define JOHN_XOP +#endif +#if defined(__AVX__) || defined(JOHN_XOP) +#define JOHN_AVX +#endif + +#define DES_ASM 0 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 1 +#define DES_EXTB 1 +#define DES_COPY 0 +#define DES_BS 1 +#if 0 +#define DES_BS_VECTOR 0 +#define DES_BS_ALGORITHM_NAME "DES 64/64" +#elif defined(JOHN_AVX) && (defined(__GNUC__) || defined(_OPENMP)) +/* + * Require gcc for AVX/XOP because DES_bs_all is aligned in a gcc-specific way, + * except in OpenMP-enabled builds, where it's aligned by different means. + */ +#undef CPU_DETECT +#define CPU_DETECT 1 +#define CPU_REQ 1 +#define CPU_REQ_AVX +#define CPU_NAME "AVX" +#ifndef CPU_FALLBACK +#define CPU_FALLBACK 0 +#endif +#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY) +#define CPU_FALLBACK_BINARY "john-non-avx" +#define CPU_FALLBACK_BINARY_DEFAULT +#endif +#define DES_BS_ASM 0 +#if 0 +/* 512-bit as 2x256 */ +#define DES_BS_VECTOR 8 +#if defined(JOHN_XOP) && defined(__GNUC__) +/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */ +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 256/256 X2 XOP-16" +#else +#define DES_BS_ALGORITHM_NAME "DES 256/256 X2 AVX-16" +#endif +#elif 0 +/* 384-bit as 256+128 */ +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_VECTOR 6 +#if defined(JOHN_XOP) && defined(__GNUC__) +/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */ +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 256/256 XOP-16 + 128/128 XOP-16" +#else +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 128/128 AVX-16" +#endif +#elif 0 +/* 384-bit as 256+64+64 */ +#define DES_BS_NO_AVX128 +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_VECTOR 6 +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64 MMX + 64/64" +#elif 0 +/* 320-bit as 256+64 MMX */ +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_VECTOR 5 +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64 MMX" +#elif 0 +/* 320-bit as 256+64 */ +#define DES_BS_NO_MMX +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_VECTOR 5 +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64" +#elif 0 +/* 256-bit as 1x256 */ +#define DES_BS_VECTOR 4 +#if defined(JOHN_XOP) && defined(__GNUC__) +/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */ +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 256/256 XOP-16" +#else +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16" +#endif +#elif 0 +/* 256-bit as 2x128 */ +#define DES_BS_NO_AVX256 +#define DES_BS_VECTOR 4 +#ifdef JOHN_XOP +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 XOP-16" +#else +#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 AVX-16" +#endif +#else +/* 128-bit */ +#define DES_BS_VECTOR 2 +#ifdef JOHN_XOP +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 128/128 XOP-16" +#else +#define DES_BS_ALGORITHM_NAME "DES 128/128 AVX-16" +#endif +#endif +#elif defined(__SSE2__) && defined(_OPENMP) +#define DES_BS_ASM 0 +#if 1 +#define DES_BS_VECTOR 2 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16" +#elif 0 +#define DES_BS_VECTOR 3 +#define DES_BS_VECTOR_SIZE 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64 MMX" +#elif 0 +#define DES_BS_NO_MMX +#define DES_BS_VECTOR 3 +#define DES_BS_VECTOR_SIZE 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64" +#elif 0 +#define DES_BS_NO_MMX +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 SSE2-16" +#else +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64 MMX + 64/64" +#endif +#else +#define DES_BS_ASM 1 +#define DES_BS_VECTOR 2 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16" +#endif +#define DES_BS_EXPAND 1 + +#if CPU_DETECT && DES_BS == 3 +#define CPU_REQ_XOP +#undef CPU_NAME +#define CPU_NAME "XOP" +#ifdef CPU_FALLBACK_BINARY_DEFAULT +#undef CPU_FALLBACK_BINARY +#define CPU_FALLBACK_BINARY "john-non-xop" +#endif +#endif + +#define MD5_ASM 0 +#define MD5_X2 1 +#define MD5_IMM 1 + +#define BF_ASM 0 +#define BF_SCALE 1 +#define BF_X2 1 + +#endif diff --git a/src/x86-any.h b/src/x86-any.h new file mode 100644 index 0000000..5906c5d --- /dev/null +++ b/src/x86-any.h @@ -0,0 +1,59 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001,2008,2010,2011 by Solar Designer + */ + +/* + * Architecture specific parameters for x86. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 1 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 1 +#define CPU_REQ 0 + +#define DES_ASM 1 +#define DES_128K 0 +#define DES_X2 0 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_BS_ASM 0 +#ifdef _OPENMP +#define DES_BS 2 +#else +#define DES_BS 0 +#endif +#define DES_BS_VECTOR 0 +#define DES_BS_EXPAND 0 + +#ifdef _OPENMP +#define MD5_ASM 0 +#else +#define MD5_ASM 1 +#endif +#define MD5_X2 0 +#define MD5_IMM 1 + +#ifdef _OPENMP +#define BF_ASM 0 +#define BF_X2 1 +#else +#define BF_ASM 1 +#define BF_X2 0 +#endif +#define BF_SCALE 1 + +#endif diff --git a/src/x86-mmx.S b/src/x86-mmx.S new file mode 100644 index 0000000..5683cef --- /dev/null +++ b/src/x86-mmx.S @@ -0,0 +1,1400 @@ +/* + * This file contains the core of a bitslice DES implementation for x86/MMX. + * It is part of John the Ripper password cracker, + * Copyright (c) 2000-2001,2005,2006,2008,2011,2012 by Solar Designer + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. (This is a heavily cut-down "BSD license".) + * + * Gate counts per S-box: 49 44 46 33 48 46 46 41 + * Average: 44.125 + * + * The Boolean expressions corresponding to DES S-boxes have been generated + * by Roman Rusakov for use in Openwall's + * John the Ripper password cracker: http://www.openwall.com/john/ + * Being mathematical formulas, they are not copyrighted and are free for reuse + * by anyone. + * + * The x86/MMX code for the S-boxes was generated by Solar Designer using a + * Perl script, hand-optimized, and then had its instruction scheduling tuned + * on a Pentium 3 using a brute-force instruction scheduling program running + * the individual S-boxes in a context similar to that of this file. + * + * The effort has been sponsored by Rapid7: http://www.rapid7.com + * + * Note: there's some MMX code in x86.S as well (just not for bitslice DES). + */ + +#include "arch.h" + +#if DES_BS_ASM + +#ifdef UNDERSCORES +#define DES_bs_all _DES_bs_all +#define DES_bs_init_asm _DES_bs_init_asm +#define DES_bs_crypt _DES_bs_crypt +#define DES_bs_crypt_25 _DES_bs_crypt_25 +#define DES_bs_crypt_LM _DES_bs_crypt_LM +#endif + +/* + * Some broken systems don't offer section alignments larger than 4 bytes, + * while for the MMX code we need at least an 8 byte alignment. ALIGN_FIX + * is here to work around this issue when we happen to get bad addresses. + */ +#ifndef ALIGN_FIX +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align log +#else +#define DO_ALIGN(log) .align 1 << log +#endif +#else +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align log; .space 4 +#else +#define DO_ALIGN(log) .align 1 << log; .space 4 +#endif +#endif + +#ifdef __sun +/* Sun's assembler doesn't recognize .space */ +#define DO_SPACE(size) .zero size +#else +/* Mac OS X assembler doesn't recognize .zero */ +#define DO_SPACE(size) .space size +#endif + +/* Sun's assembler can't multiply, but at least it can add... */ +#define nptr(n) n+n+n+n +#define nvec(n) n+n+n+n+n+n+n+n + +#ifdef BSD +.data +#else +.bss +#endif + +.globl DES_bs_all +DO_ALIGN(5) +DES_bs_all: +DES_bs_all_KSp: +DO_SPACE(nptr(0x300)) +DES_bs_all_KS_p: +DES_bs_all_KS_v: +DO_SPACE(nvec(0x300)) +DES_bs_all_E: +DO_SPACE(nptr(96)) +DES_bs_all_K: +DO_SPACE(nvec(56)) +DES_bs_all_B: +DO_SPACE(nvec(64)) +DES_bs_all_tmp: +DO_SPACE(nvec(16)) +DES_bs_all_xkeys: +DO_SPACE(nvec(64)) +DES_bs_all_pxkeys: +DO_SPACE(nptr(64)) +DES_bs_all_keys_changed: +DO_SPACE(4) +DES_bs_all_salt: +DO_SPACE(4) +DES_bs_all_Ens: +DO_SPACE(nptr(48)) + +#define E(i) DES_bs_all_E+nptr(i) +#define B(i) DES_bs_all_B+nvec(i) +#define tmp_at(i) DES_bs_all_tmp+nvec(i) + +#define pnot tmp_at(0) + +#define S1(out1, out2, out3, out4) \ + movq %mm0,tmp_at(1); \ + movq %mm5,%mm7; \ + movq %mm4,tmp_at(4); \ + movq %mm2,%mm6; \ + movq %mm1,tmp_at(2); \ + por %mm2,%mm7; \ + movq %mm3,tmp_at(3); \ + pxor %mm0,%mm6; \ + movq %mm7,tmp_at(5); \ + movq %mm6,%mm1; \ + pandn %mm0,%mm4; \ + pand %mm7,%mm1; \ + movq %mm1,%mm7; \ + por %mm5,%mm7; \ + pxor %mm3,%mm1; \ + pxor %mm4,%mm3; \ + movq %mm1,tmp_at(6); \ + movq %mm3,%mm1; \ + pandn tmp_at(6),%mm3; \ + movq %mm3,tmp_at(7); \ + movq %mm5,%mm3; \ + por %mm0,%mm5; \ + pxor tmp_at(4),%mm3; \ + movq %mm3,tmp_at(8); \ + movq %mm5,%mm0; \ + pandn %mm3,%mm6; \ + pxor %mm2,%mm3; \ + pandn %mm2,%mm4; \ + pandn %mm1,%mm3; \ + pxor %mm3,%mm7; \ + movq tmp_at(7),%mm3; \ + pandn tmp_at(3),%mm5; \ + por %mm7,%mm0; \ + pandn %mm7,%mm3; \ + movq %mm3,tmp_at(9); \ + pand tmp_at(5),%mm7; \ + movq tmp_at(6),%mm3; \ + movq %mm0,%mm2; \ + pxor %mm1,%mm2; \ + pandn tmp_at(4),%mm3; \ + pandn %mm2,%mm4; \ + movq tmp_at(2),%mm2; \ + pxor %mm4,%mm7; \ + pxor tmp_at(8),%mm4; \ + pxor %mm3,%mm5; \ + por %mm3,%mm4; \ + pxor tmp_at(1),%mm4; \ + pxor %mm0,%mm3; \ + pandn %mm3,%mm2; \ + pxor tmp_at(5),%mm0; \ + movq tmp_at(7),%mm3; \ + por tmp_at(2),%mm3; \ + pxor pnot,%mm7; \ + pxor out1,%mm3; \ + pxor %mm7,%mm2; \ + pxor tmp_at(5),%mm4; \ + pxor out3,%mm2; \ + pxor %mm4,%mm7; \ + pxor %mm7,%mm3; \ + movq %mm3,out1; \ + por %mm6,%mm5; \ + por tmp_at(8),%mm7; \ + por %mm5,%mm0; \ + pxor out2,%mm7; \ + pxor %mm4,%mm0; \ + pxor %mm0,%mm7; \ + por tmp_at(4),%mm1; \ + movq tmp_at(2),%mm3; \ + pand tmp_at(9),%mm4; \ + pandn %mm1,%mm0; \ + pxor %mm0,%mm4; \ + por tmp_at(9),%mm3; \ + por tmp_at(2),%mm4; \ + movq %mm2,out3; \ + pxor %mm3,%mm7; \ + pxor %mm5,%mm4; \ + pxor out4,%mm4; \ + movq %mm7,out2; \ + movq %mm4,out4 + +#define S2(out1, out2, out3, out4) \ + movq %mm2,tmp_at(2); \ + movq %mm1,tmp_at(1); \ + movq %mm5,%mm2; \ + movq %mm4,tmp_at(4); \ + pandn %mm0,%mm2; \ + movq %mm3,tmp_at(3); \ + pandn %mm4,%mm2; \ + movq %mm0,%mm6; \ + movq %mm2,%mm7; \ + pxor pnot,%mm0; \ + por %mm1,%mm7; \ + pxor %mm4,%mm1; \ + movq %mm7,tmp_at(5); \ + pand %mm1,%mm6; \ + movq %mm5,%mm7; \ + pxor %mm4,%mm6; \ + pandn %mm1,%mm7; \ + movq %mm3,%mm4; \ + pxor %mm7,%mm2; \ + pandn %mm6,%mm7; \ + pxor %mm5,%mm1; \ + movq %mm7,tmp_at(7); \ + movq %mm5,%mm7; \ + pand tmp_at(2),%mm5; \ + pand tmp_at(5),%mm2; \ + movq %mm5,tmp_at(8); \ + pandn %mm2,%mm5; \ + pand tmp_at(2),%mm2; \ + movq tmp_at(8),%mm7; \ + pandn tmp_at(3),%mm5; \ + pandn %mm1,%mm7; \ + pxor %mm2,%mm0; \ + movq %mm7,%mm3; \ + pxor %mm0,%mm3; \ + pxor out2,%mm5; \ + pandn tmp_at(1),%mm7; \ + pxor %mm6,%mm7; \ + pxor %mm3,%mm5; \ + movq %mm7,%mm6; \ + movq %mm5,out2; \ + movq tmp_at(7),%mm5; \ + pandn tmp_at(5),%mm4; \ + pandn %mm0,%mm6; \ + pxor tmp_at(5),%mm3; \ + movq %mm1,%mm0; \ + pxor %mm4,%mm6; \ + pxor tmp_at(2),%mm0; \ + pxor %mm0,%mm6; \ + movq %mm0,%mm4; \ + pxor out1,%mm6; \ + pandn tmp_at(1),%mm0; \ + pxor tmp_at(4),%mm2; \ + pxor %mm3,%mm0; \ + movq %mm6,out1; \ + por %mm1,%mm3; \ + por tmp_at(8),%mm0; \ + pxor %mm4,%mm0; \ + movq %mm0,%mm4; \ + pandn tmp_at(2),%mm0; \ + movq tmp_at(3),%mm6; \ + pxor tmp_at(7),%mm0; \ + por %mm7,%mm0; \ + por %mm6,%mm5; \ + pxor %mm0,%mm2; \ + pandn %mm2,%mm7; \ + por %mm2,%mm6; \ + pxor out4,%mm7; \ + pxor %mm4,%mm6; \ + pxor out3,%mm6; \ + pxor %mm5,%mm7; \ + pxor %mm3,%mm7; \ + movq %mm6,out3; \ + movq %mm7,out4 + +#define S3(out1, out2, out3, out4) \ + movq %mm0,tmp_at(1); \ + movq %mm1,tmp_at(2); \ + movq %mm0,%mm7; \ + pandn %mm0,%mm1; \ + movq %mm2,tmp_at(3); \ + movq %mm5,%mm0; \ + pxor %mm2,%mm0; \ + movq %mm4,tmp_at(4); \ + movq %mm5,%mm2; \ + por %mm0,%mm1; \ + pxor %mm3,%mm2; \ + movq %mm0,%mm4; \ + movq %mm5,%mm6; \ + pandn %mm2,%mm7; \ + pxor tmp_at(2),%mm4; \ + movq %mm7,tmp_at(5); \ + pxor %mm1,%mm7; \ + pandn %mm4,%mm6; \ + movq %mm7,tmp_at(6); \ + pxor %mm6,%mm1; \ + pand %mm0,%mm2; \ + movq %mm1,%mm6; \ + movq %mm3,%mm0; \ + pandn %mm7,%mm6; \ + pand %mm5,%mm7; \ + pand %mm3,%mm5; \ + por %mm3,%mm7; \ + pand tmp_at(1),%mm7; \ + movq tmp_at(4),%mm3; \ + pandn tmp_at(6),%mm3; \ + pxor %mm4,%mm7; \ + pxor tmp_at(1),%mm0; \ + movq %mm7,tmp_at(7); \ + pxor %mm3,%mm7; \ + movq tmp_at(2),%mm3; \ + pxor out4,%mm7; \ + pxor %mm0,%mm1; \ + movq %mm7,out4; \ + movq tmp_at(3),%mm7; \ + por tmp_at(3),%mm1; \ + pandn %mm1,%mm2; \ + por tmp_at(5),%mm0; \ + movq %mm0,%mm1; \ + pandn %mm5,%mm3; \ + pandn tmp_at(7),%mm1; \ + por %mm4,%mm5; \ + pxor %mm3,%mm1; \ + por tmp_at(2),%mm7; \ + movq tmp_at(3),%mm3; \ + pandn %mm1,%mm3; \ + pxor %mm4,%mm0; \ + pandn %mm5,%mm3; \ + movq tmp_at(4),%mm5; \ + pxor tmp_at(1),%mm3; \ + pand %mm2,%mm5; \ + pxor pnot,%mm0; \ + pxor %mm5,%mm3; \ + movq %mm7,%mm5; \ + pxor out2,%mm3; \ + pandn tmp_at(4),%mm6; \ + pandn tmp_at(6),%mm7; \ + pxor %mm0,%mm6; \ + movq %mm3,out2; \ + pxor tmp_at(1),%mm2; \ + por tmp_at(4),%mm1; \ + por %mm2,%mm0; \ + pxor tmp_at(6),%mm5; \ + pxor %mm1,%mm0; \ + pxor out1,%mm6; \ + pxor out3,%mm5; \ + pxor tmp_at(7),%mm0; \ + pxor %mm7,%mm6; \ + pxor %mm5,%mm0; \ + movq %mm6,out1; \ + movq %mm0,out3 + +#define S4(out1, out2, out3, out4) \ + movq %mm1,%mm7; \ + pxor %mm2,%mm0; \ + por %mm3,%mm1; \ + pxor %mm4,%mm2; \ + movq %mm5,tmp_at(2); \ + pxor %mm4,%mm1; \ + movq %mm7,%mm6; \ + movq %mm7,%mm5; \ + pandn %mm2,%mm7; \ + pandn %mm2,%mm1; \ + por %mm7,%mm4; \ + pxor %mm3,%mm7; \ + movq %mm7,%mm6; \ + por %mm0,%mm7; \ + pxor %mm5,%mm3; \ + movq %mm1,tmp_at(3); \ + pandn %mm7,%mm1; \ + movq %mm1,%mm7; \ + pxor %mm5,%mm1; \ + pand %mm1,%mm6; \ + movq %mm6,%mm5; \ + pxor %mm1,%mm0; \ + pandn %mm2,%mm6; \ + pandn %mm0,%mm6; \ + pxor %mm0,%mm4; \ + movq %mm3,%mm0; \ + pandn %mm4,%mm3; \ + movq tmp_at(2),%mm2; \ + pxor %mm7,%mm3; \ + pxor tmp_at(3),%mm6; \ + movq %mm6,%mm7; \ + pandn %mm2,%mm6; \ + pxor out1,%mm6; \ + pandn %mm7,%mm2; \ + pxor out2,%mm2; \ + pxor %mm3,%mm6; \ + pxor pnot,%mm3; \ + pxor %mm3,%mm2; \ + pxor %mm7,%mm3; \ + movq %mm6,out1; \ + pandn %mm3,%mm0; \ + por %mm5,%mm0; \ + movq %mm2,out2; \ + movq tmp_at(2),%mm3; \ + por %mm1,%mm3; \ + pand tmp_at(2),%mm1; \ + pxor %mm4,%mm0; \ + pxor %mm0,%mm3; \ + pxor out3,%mm3; \ + pxor %mm1,%mm0; \ + movq %mm3,out3; \ + pxor out4,%mm0; \ + movq %mm0,out4 + +#define S5(out1, out2, out3, out4) \ + movq %mm2,tmp_at(3); \ + movq %mm0,tmp_at(1); \ + por %mm0,%mm2; \ + movq %mm5,%mm6; \ + movq %mm2,tmp_at(4); \ + pandn %mm2,%mm5; \ + movq %mm2,%mm7; \ + movq %mm5,%mm2; \ + pxor %mm0,%mm5; \ + movq %mm3,%mm7; \ + movq %mm5,tmp_at(5); \ + pxor tmp_at(3),%mm5; \ + movq %mm1,tmp_at(2); \ + por %mm5,%mm0; \ + por %mm3,%mm5; \ + pandn %mm2,%mm3; \ + pxor tmp_at(3),%mm3; \ + movq %mm3,tmp_at(6); \ + movq %mm0,%mm1; \ + pand %mm4,%mm3; \ + pxor %mm0,%mm3; \ + pand %mm7,%mm0; \ + pxor %mm7,%mm3; \ + movq %mm3,tmp_at(3); \ + pxor %mm3,%mm6; \ + movq %mm6,%mm2; \ + por tmp_at(5),%mm6; \ + movq %mm6,%mm3; \ + pand %mm4,%mm6; \ + movq %mm6,tmp_at(7); \ + pxor tmp_at(5),%mm6; \ + pxor %mm6,%mm0; \ + movq tmp_at(1),%mm6; \ + movq %mm0,tmp_at(8); \ + pandn %mm3,%mm6; \ + movq tmp_at(2),%mm0; \ + movq %mm6,%mm3; \ + pxor tmp_at(6),%mm6; \ + pxor %mm5,%mm4; \ + pandn %mm4,%mm6; \ + pxor pnot,%mm6; \ + pandn %mm6,%mm0; \ + pxor tmp_at(3),%mm0; \ + movq tmp_at(7),%mm6; \ + pandn tmp_at(6),%mm6; \ + pxor out3,%mm0; \ + pxor %mm4,%mm3; \ + movq %mm0,out3; \ + por tmp_at(8),%mm3; \ + movq tmp_at(6),%mm0; \ + pandn %mm3,%mm6; \ + pand tmp_at(6),%mm1; \ + pand %mm6,%mm2; \ + movq %mm6,%mm3; \ + pandn %mm5,%mm6; \ + pxor %mm4,%mm2; \ + por %mm2,%mm1; \ + pxor tmp_at(4),%mm3; \ + pxor tmp_at(7),%mm1; \ + pand %mm2,%mm7; \ + pand tmp_at(2),%mm1; \ + pxor tmp_at(1),%mm7; \ + pxor tmp_at(8),%mm1; \ + pxor %mm7,%mm3; \ + por tmp_at(2),%mm6; \ + pxor out4,%mm1; \ + movq %mm1,out4; \ + pxor %mm5,%mm0; \ + pxor tmp_at(5),%mm2; \ + pxor %mm3,%mm6; \ + pandn %mm0,%mm3; \ + pand tmp_at(2),%mm5; \ + pxor %mm2,%mm3; \ + pxor out2,%mm5; \ + pxor %mm5,%mm3; \ + pxor out1,%mm6; \ + movq %mm3,out2; \ + movq %mm6,out1 + +#define S6(out1, out2, out3, out4) \ + movq %mm4,tmp_at(2); \ + pxor %mm1,%mm4; \ + movq %mm5,tmp_at(3); \ + por %mm1,%mm5; \ + movq %mm2,%mm7; \ + pand %mm0,%mm5; \ + pxor %mm0,%mm2; \ + movq %mm0,tmp_at(1); \ + pxor %mm5,%mm4; \ + movq %mm4,tmp_at(4); \ + pxor tmp_at(3),%mm4; \ + movq %mm4,%mm6; \ + pandn tmp_at(2),%mm4; \ + pand %mm0,%mm6; \ + movq %mm6,tmp_at(5); \ + pxor %mm1,%mm6; \ + movq %mm6,tmp_at(6); \ + por %mm2,%mm6; \ + movq %mm6,tmp_at(7); \ + pxor tmp_at(4),%mm6; \ + movq %mm6,%mm0; \ + pand %mm7,%mm6; \ + movq %mm6,tmp_at(8); \ + movq tmp_at(3),%mm6; \ + por %mm1,%mm2; \ + pandn tmp_at(8),%mm6; \ + movq %mm6,tmp_at(9); \ + movq tmp_at(6),%mm6; \ + por %mm4,%mm6; \ + movq %mm6,tmp_at(6); \ + pxor tmp_at(9),%mm6; \ + movq %mm6,tmp_at(10); \ + pand %mm3,%mm6; \ + pxor out4,%mm6; \ + pxor %mm0,%mm6; \ + por tmp_at(1),%mm0; \ + movq %mm6,out4; \ + movq tmp_at(7),%mm6; \ + pxor %mm1,%mm6; \ + movq %mm3,%mm1; \ + movq %mm6,tmp_at(7); \ + pandn tmp_at(3),%mm6; \ + pxor %mm7,%mm6; \ + movq tmp_at(8),%mm7; \ + movq %mm6,tmp_at(12); \ + pandn tmp_at(2),%mm7; \ + pand tmp_at(6),%mm0; \ + por %mm6,%mm7; \ + pxor %mm6,%mm0; \ + movq tmp_at(9),%mm6; \ + por %mm3,%mm4; \ + pandn %mm0,%mm6; \ + por %mm7,%mm5; \ + pxor %mm4,%mm6; \ + pxor tmp_at(4),%mm0; \ + pxor out3,%mm6; \ + pxor %mm2,%mm5; \ + movq %mm6,out3; \ + movq tmp_at(5),%mm6; \ + pandn tmp_at(2),%mm0; \ + pxor pnot,%mm2; \ + pxor tmp_at(7),%mm2; \ + pxor tmp_at(3),%mm6; \ + pxor out2,%mm5; \ + movq tmp_at(12),%mm4; \ + pxor %mm2,%mm0; \ + pxor tmp_at(1),%mm4; \ + pxor tmp_at(10),%mm5; \ + pand %mm6,%mm4; \ + pandn %mm0,%mm3; \ + pxor out1,%mm4; \ + pandn %mm7,%mm1; \ + pxor tmp_at(8),%mm4; \ + pxor %mm2,%mm1; \ + pxor %mm3,%mm5; \ + movq %mm5,out2; \ + pxor %mm1,%mm4; \ + movq %mm4,out1 + +#define S7(out1, out2, out3, out4) \ + movq %mm0,tmp_at(1); \ + movq %mm4,tmp_at(3); \ + movq %mm4,%mm0; \ + pxor %mm3,%mm4; \ + movq %mm5,tmp_at(4); \ + movq %mm4,%mm7; \ + movq %mm3,tmp_at(2); \ + pxor %mm2,%mm4; \ + movq %mm4,tmp_at(5); \ + pand %mm5,%mm4; \ + movq %mm7,%mm5; \ + pxor tmp_at(4),%mm5; \ + pand %mm3,%mm7; \ + movq %mm7,tmp_at(6); \ + movq %mm7,%mm6; \ + pxor %mm1,%mm7; \ + pand tmp_at(4),%mm6; \ + pxor %mm2,%mm6; \ + movq %mm7,tmp_at(7); \ + movq tmp_at(1),%mm3; \ + movq %mm6,%mm0; \ + por %mm7,%mm6; \ + pand %mm4,%mm7; \ + pxor %mm5,%mm6; \ + pandn %mm3,%mm7; \ + pxor %mm4,%mm0; \ + pxor out4,%mm7; \ + pxor %mm5,%mm4; \ + pxor %mm6,%mm7; \ + movq %mm7,out4; \ + pandn tmp_at(2),%mm4; \ + por tmp_at(6),%mm6; \ + movq tmp_at(5),%mm7; \ + pandn tmp_at(3),%mm7; \ + pandn tmp_at(7),%mm4; \ + movq %mm7,tmp_at(9); \ + por tmp_at(7),%mm7; \ + pandn tmp_at(5),%mm5; \ + pxor %mm0,%mm7; \ + pxor tmp_at(3),%mm0; \ + pxor %mm4,%mm0; \ + movq tmp_at(1),%mm4; \ + pand %mm0,%mm2; \ + por %mm2,%mm6; \ + pxor %mm5,%mm6; \ + pandn %mm6,%mm3; \ + movq %mm6,%mm5; \ + pxor %mm7,%mm3; \ + pxor %mm6,%mm7; \ + por %mm0,%mm6; \ + pxor out1,%mm3; \ + pand tmp_at(4),%mm6; \ + pxor pnot,%mm5; \ + pand %mm6,%mm1; \ + pxor out3,%mm0; \ + pxor %mm7,%mm1; \ + movq %mm3,out1; \ + movq %mm4,%mm3; \ + pxor tmp_at(3),%mm7; \ + por %mm1,%mm2; \ + pxor %mm6,%mm2; \ + por %mm2,%mm7; \ + pand %mm7,%mm4; \ + pxor %mm6,%mm7; \ + por tmp_at(9),%mm7; \ + pxor %mm5,%mm7; \ + pxor out2,%mm1; \ + pandn %mm7,%mm3; \ + pxor %mm4,%mm0; \ + movq %mm0,out3; \ + pxor %mm3,%mm1; \ + movq %mm1,out2 + +#define S8(out1, out2, out3, out4) \ + movq %mm2,%mm7; \ + movq %mm1,tmp_at(1); \ + pandn %mm2,%mm1; \ + movq %mm2,tmp_at(2); \ + pandn %mm4,%mm2; \ + movq %mm5,tmp_at(5); \ + pxor %mm3,%mm2; \ + movq %mm4,tmp_at(4); \ + movq %mm1,%mm5; \ + movq %mm3,tmp_at(3); \ + movq %mm2,%mm4; \ + movq %mm2,%mm3; \ + pandn tmp_at(1),%mm4; \ + pand %mm0,%mm2; \ + pandn tmp_at(1),%mm7; \ + pandn %mm2,%mm1; \ + pxor tmp_at(4),%mm7; \ + movq %mm4,%mm6; \ + por %mm0,%mm4; \ + movq %mm7,tmp_at(6); \ + pand %mm4,%mm7; \ + pxor pnot,%mm3; \ + por %mm7,%mm2; \ + pxor %mm7,%mm3; \ + pandn tmp_at(2),%mm4; \ + movq tmp_at(5),%mm7; \ + pxor %mm4,%mm3; \ + por %mm1,%mm7; \ + pxor %mm3,%mm5; \ + pxor %mm5,%mm7; \ + pxor %mm0,%mm5; \ + pxor out2,%mm7; \ + movq %mm7,out2; \ + pxor tmp_at(1),%mm3; \ + movq %mm5,%mm4; \ + pand tmp_at(4),%mm5; \ + pxor %mm3,%mm5; \ + por tmp_at(3),%mm3; \ + pxor %mm5,%mm6; \ + pxor tmp_at(6),%mm3; \ + pxor %mm2,%mm5; \ + pxor %mm6,%mm3; \ + por tmp_at(1),%mm5; \ + pxor %mm3,%mm0; \ + pxor %mm4,%mm5; \ + por tmp_at(3),%mm4; \ + pxor tmp_at(4),%mm5; \ + pand tmp_at(5),%mm2; \ + pandn %mm5,%mm4; \ + pand tmp_at(5),%mm0; \ + pxor %mm6,%mm0; \ + por %mm1,%mm4; \ + pxor out4,%mm0; \ + pxor %mm4,%mm3; \ + pxor out3,%mm2; \ + por tmp_at(5),%mm3; \ + pxor out1,%mm3; \ + pxor %mm5,%mm2; \ + pxor %mm6,%mm3; \ + movq %mm0,out4; \ + movq %mm2,out3; \ + movq %mm3,out1 + +#define zero %mm0 + +#define DES_bs_clear_block_8(i) \ + movq zero,B(i); \ + movq zero,B(i + 1); \ + movq zero,B(i + 2); \ + movq zero,B(i + 3); \ + movq zero,B(i + 4); \ + movq zero,B(i + 5); \ + movq zero,B(i + 6); \ + movq zero,B(i + 7) + +#define DES_bs_clear_block \ + DES_bs_clear_block_8(0); \ + DES_bs_clear_block_8(8); \ + DES_bs_clear_block_8(16); \ + DES_bs_clear_block_8(24); \ + DES_bs_clear_block_8(32); \ + DES_bs_clear_block_8(40); \ + DES_bs_clear_block_8(48); \ + DES_bs_clear_block_8(56) + +#define k_ptr %edx +#define K(i) nvec(i)(k_ptr) +#define k(i) nptr(i)(k_ptr) + +#define a1 %mm0 +#define a2 %mm1 +#define a3 %mm2 +#define a4 %mm3 +#define a5 %mm4 +#define a6 %mm5 + +#define tmp1 %ecx +#define tmp2 %esi + +#define xor_E(i) \ + movl E(i),tmp1; \ + movq K(i),a1; \ + movl E(i + 1),tmp2; \ + movq K(i + 1),a2; \ + pxor (tmp1),a1; \ + pxor (tmp2),a2; \ + movl E(i + 2),tmp1; \ + movq K(i + 2),a3; \ + movl E(i + 3),tmp2; \ + movq K(i + 3),a4; \ + pxor (tmp1),a3; \ + pxor (tmp2),a4; \ + movl E(i + 4),tmp1; \ + movq K(i + 4),a5; \ + movl E(i + 5),tmp2; \ + movq K(i + 5),a6; \ + pxor (tmp1),a5; \ + pxor (tmp2),a6 + +#define xor_B(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6, k6) \ + movq B(b1),a1; \ + movq B(b2),a2; \ + pxor K(k1),a1; \ + movq B(b3),a3; \ + pxor K(k2),a2; \ + movq B(b4),a4; \ + pxor K(k3),a3; \ + movq B(b5),a5; \ + pxor K(k4),a4; \ + movq B(b6),a6; \ + pxor K(k5),a5; \ + pxor K(k6),a6 + +#define xor_B_KS_p(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6, k6) \ + movl k(k1),tmp1; \ + movl k(k2),tmp2; \ + movq B(b1),a1; \ + movq B(b2),a2; \ + pxor (tmp1),a1; \ + movl k(k3),tmp1; \ + pxor (tmp2),a2; \ + movl k(k4),tmp2; \ + movq B(b3),a3; \ + movq B(b4),a4; \ + pxor (tmp1),a3; \ + movl k(k5),tmp1; \ + pxor (tmp2),a4; \ + movq B(b5),a5; \ + movl k(k6),tmp2; \ + movq B(b6),a6; \ + pxor (tmp1),a5; \ + pxor (tmp2),a6 + +#define mask01 tmp_at(15) + +#define v_ptr %eax +#define V(i) nvec(i)(v_ptr) + +#if 1 +#define SHLB1(reg) paddb reg,reg +#else +#define SHLB1(reg) psllq $1,reg +#endif + +#define FINALIZE_NEXT_KEY_BITS_0_6 \ + movq mask01,%mm7; \ +\ + movq V(0),%mm0; \ + movq V(1),%mm1; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + SHLB1(%mm1); \ + psllq $2,%mm2; \ + psllq $3,%mm3; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + psllq $4,%mm4; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + psllq $5,%mm5; \ + psllq $6,%mm6; \ + psllq $7,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(0); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $1,%mm0; \ + SHLB1(%mm2); \ + psllq $2,%mm3; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + psllq $3,%mm4; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + psllq $4,%mm5; \ + psllq $5,%mm6; \ + psllq $6,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(1); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $2,%mm0; \ + psrlq $1,%mm1; \ + SHLB1(%mm3); \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + psllq $2,%mm4; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + psllq $3,%mm5; \ + psllq $4,%mm6; \ + psllq $5,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(2); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $3,%mm0; \ + psrlq $2,%mm1; \ + psrlq $1,%mm2; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + SHLB1(%mm4); \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + psllq $2,%mm5; \ + psllq $3,%mm6; \ + psllq $4,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(3); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $4,%mm0; \ + psrlq $3,%mm1; \ + psrlq $2,%mm2; \ + psrlq $1,%mm3; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + SHLB1(%mm5); \ + psllq $2,%mm6; \ + psllq $3,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(4); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $5,%mm0; \ + psrlq $4,%mm1; \ + psrlq $3,%mm2; \ + psrlq $2,%mm3; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + psrlq $1,%mm4; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + SHLB1(%mm6); \ + psllq $2,%mm0; \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + movq V(1),%mm1; \ + por %mm3,%mm0; \ + SHLB1(%mm7); \ + movq %mm0,K(5); \ +\ + movq V(0),%mm0; \ + movq V(2),%mm2; \ + movq V(3),%mm3; \ + pand %mm7,%mm0; \ + pand %mm7,%mm1; \ + pand %mm7,%mm2; \ + pand %mm7,%mm3; \ + psrlq $6,%mm0; \ + psrlq $5,%mm1; \ + psrlq $4,%mm2; \ + psrlq $3,%mm3; \ + por %mm0,%mm1; \ + por %mm2,%mm3; \ + movq V(4),%mm4; \ + movq V(5),%mm5; \ + por %mm1,%mm3; \ + pand %mm7,%mm4; \ + pand %mm7,%mm5; \ + movq V(6),%mm6; \ + movq V(7),%mm0; \ + psrlq $2,%mm4; \ + pand %mm7,%mm6; \ + pand %mm7,%mm0; \ + psrlq $1,%mm5; \ + SHLB1(%mm0); \ + por %mm4,%mm5; \ + por %mm6,%mm3; \ + por %mm5,%mm0; \ + por %mm3,%mm0; \ + movq %mm0,K(6) + +.text + +DO_ALIGN(5) +.globl DES_bs_init_asm +DES_bs_init_asm: + pcmpeqd %mm0,%mm0 + movq %mm0,pnot + paddb %mm0,%mm0 + pxor pnot,%mm0 + movq %mm0,mask01 + ret + +#define rounds_and_swapped %ebp +#define iterations %eax + +DO_ALIGN(5) +.globl DES_bs_crypt +DES_bs_crypt: + cmpl $0,DES_bs_all_keys_changed + jz DES_bs_crypt_body + call DES_bs_finalize_keys +DES_bs_crypt_body: + movl 4(%esp),iterations + pxor zero,zero + pushl %ebp + pushl %esi + movl $DES_bs_all_KS_v,k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped +DES_bs_crypt_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62)) + xor_E(6) + S2(B(44), B(59), B(33), B(49)) + xor_E(12) + S3(B(55), B(47), B(61), B(37)) + xor_E(18) + S4(B(57), B(51), B(41), B(32)) + xor_E(24) + S5(B(39), B(45), B(56), B(34)) + xor_E(30) + S6(B(35), B(60), B(42), B(50)) + xor_E(36) + S7(B(63), B(43), B(53), B(38)) + xor_E(42) + S8(B(36), B(58), B(46), B(52)) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_next +DES_bs_crypt_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30)) + xor_E(54) + S2(B(12), B(27), B(1), B(17)) + xor_E(60) + S3(B(23), B(15), B(29), B(5)) + xor_E(66) + S4(B(25), B(19), B(9), B(0)) + xor_E(72) + S5(B(7), B(13), B(24), B(2)) + xor_E(78) + S6(B(3), B(28), B(10), B(18)) + xor_E(84) + S7(B(31), B(11), B(21), B(6)) + xor_E(90) + addl $nvec(96),k_ptr + S8(B(4), B(26), B(14), B(20)) + decl rounds_and_swapped + jnz DES_bs_crypt_start + subl $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_swap + popl %esi + popl %ebp +#ifdef EMMS + emms +#endif + ret +DES_bs_crypt_next: + subl $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_start + popl %esi + popl %ebp +#ifdef EMMS + emms +#endif + ret + +DO_ALIGN(5) +.globl DES_bs_crypt_25 +DES_bs_crypt_25: + cmpl $0,DES_bs_all_keys_changed + jnz DES_bs_finalize_keys_25 +DES_bs_crypt_25_body: + pxor zero,zero + pushl %ebp + pushl %esi + movl $DES_bs_all_KS_v,k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped + movl $25,iterations +DES_bs_crypt_25_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62)) + xor_E(6) + S2(B(44), B(59), B(33), B(49)) + xor_B(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12, 17) + S3(B(55), B(47), B(61), B(37)) + xor_B(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16, 23) + S4(B(57), B(51), B(41), B(32)) + xor_E(24) + S5(B(39), B(45), B(56), B(34)) + xor_E(30) + S6(B(35), B(60), B(42), B(50)) + xor_B(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28, 41) + S7(B(63), B(43), B(53), B(38)) + xor_B(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0, 47) + S8(B(36), B(58), B(46), B(52)) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_25_next +DES_bs_crypt_25_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30)) + xor_E(54) + S2(B(12), B(27), B(1), B(17)) + xor_B(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44, 65) + S3(B(23), B(15), B(29), B(5)) + xor_B(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48, 71) + S4(B(25), B(19), B(9), B(0)) + xor_E(72) + S5(B(7), B(13), B(24), B(2)) + xor_E(78) + S6(B(3), B(28), B(10), B(18)) + xor_B(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60, 89) + S7(B(31), B(11), B(21), B(6)) + xor_B(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32, 95) + S8(B(4), B(26), B(14), B(20)) + addl $nvec(96),k_ptr + decl rounds_and_swapped + jnz DES_bs_crypt_25_start + subl $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_25_swap + popl %esi + popl %ebp +#ifdef EMMS + emms +#endif + ret +DES_bs_crypt_25_next: + subl $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + decl iterations + jmp DES_bs_crypt_25_start + +DES_bs_finalize_keys_25: + pushl $DES_bs_crypt_25_body +DES_bs_finalize_keys: + movl $DES_bs_all_xkeys,v_ptr + movl $DES_bs_all_K,k_ptr + movl $0,DES_bs_all_keys_changed +DES_bs_finalize_keys_main_loop: + FINALIZE_NEXT_KEY_BITS_0_6 + addl $nvec(7),k_ptr + addl $nvec(8),v_ptr + cmpl $DES_bs_all_K+nvec(56),k_ptr + jb DES_bs_finalize_keys_main_loop + pushl %esi + movl $DES_bs_all_KSp,k_ptr + movl $DES_bs_all_KS_v,v_ptr +DES_bs_finalize_keys_expand_loop: + movl k(0),tmp1 + movl k(1),tmp2 + movq (tmp1),%mm0 + movq (tmp2),%mm1 + movl k(2),tmp1 + movl k(3),tmp2 + movq %mm0,V(0) + movq %mm1,V(1) + movq (tmp1),%mm0 + movq (tmp2),%mm1 + movl k(4),tmp1 + movl k(5),tmp2 + movq %mm0,V(2) + movq %mm1,V(3) + movq (tmp1),%mm0 + movq (tmp2),%mm1 + movl k(6),tmp1 + movl k(7),tmp2 + movq %mm0,V(4) + movq %mm1,V(5) + movq (tmp1),%mm0 + movq (tmp2),%mm1 + addl $nptr(8),k_ptr + movq %mm0,V(6) + movq %mm1,V(7) + addl $nvec(8),v_ptr + cmpl $DES_bs_all_KSp+nptr(0x300),k_ptr + jb DES_bs_finalize_keys_expand_loop + popl %esi + ret + +#define ones %mm1 + +#define rounds %eax + +DO_ALIGN(5) +.globl DES_bs_crypt_LM +DES_bs_crypt_LM: + movl $DES_bs_all_xkeys,v_ptr + movl $DES_bs_all_K,k_ptr +DES_bs_finalize_keys_LM_loop: + FINALIZE_NEXT_KEY_BITS_0_6 +# bit 7 + SHLB1(%mm7) + movq V(0),%mm0 + movq V(1),%mm1 + movq V(2),%mm2 + movq V(3),%mm3 + pand %mm7,%mm0 + pand %mm7,%mm1 + pand %mm7,%mm2 + pand %mm7,%mm3 + psrlq $7,%mm0 + psrlq $6,%mm1 + psrlq $5,%mm2 + psrlq $4,%mm3 + por %mm0,%mm1 + por %mm2,%mm3 + movq V(4),%mm4 + movq V(5),%mm5 + por %mm1,%mm3 + pand %mm7,%mm4 + pand %mm7,%mm5 + movq V(6),%mm6 + movq V(7),%mm0 + psrlq $3,%mm4 + pand %mm7,%mm6 + pand %mm7,%mm0 + psrlq $2,%mm5 + psrlq $1,%mm6 + por %mm4,%mm5 + por %mm6,%mm3 + por %mm5,%mm0 + addl $nvec(8),v_ptr + por %mm3,%mm0 + movq %mm0,K(7) + addl $nvec(8),k_ptr + cmpl $DES_bs_all_K+nvec(56),k_ptr + jb DES_bs_finalize_keys_LM_loop + + pxor zero,zero + pushl %esi + pcmpeqd ones,ones + movl $DES_bs_all_KS_p,k_ptr + movq zero,B(0) + movq zero,B(1) + movq zero,B(2) + movq zero,B(3) + movq zero,B(4) + movq zero,B(5) + movq zero,B(6) + movq zero,B(7) + movq ones,B(8) + movq ones,B(9) + movq ones,B(10) + movq zero,B(11) + movq ones,B(12) + movq zero,B(13) + movq zero,B(14) + movq zero,B(15) + movq zero,B(16) + movq zero,B(17) + movq zero,B(18) + movq zero,B(19) + movq zero,B(20) + movq zero,B(21) + movq zero,B(22) + movq ones,B(23) + movq zero,B(24) + movq zero,B(25) + movq ones,B(26) + movq zero,B(27) + movq zero,B(28) + movq ones,B(29) + movq ones,B(30) + movq ones,B(31) + movq zero,B(32) + movq zero,B(33) + movq zero,B(34) + movq ones,B(35) + movq zero,B(36) + movq ones,B(37) + movq ones,B(38) + movq ones,B(39) + movq zero,B(40) + movq zero,B(41) + movq zero,B(42) + movq zero,B(43) + movq zero,B(44) + movq ones,B(45) + movq zero,B(46) + movq zero,B(47) + movq ones,B(48) + movq ones,B(49) + movq zero,B(50) + movq zero,B(51) + movq zero,B(52) + movq zero,B(53) + movq ones,B(54) + movq zero,B(55) + movq ones,B(56) + movq zero,B(57) + movq ones,B(58) + movq zero,B(59) + movq ones,B(60) + movq ones,B(61) + movq ones,B(62) + movq ones,B(63) + movl $8,rounds +DES_bs_crypt_LM_loop: + xor_B_KS_p(31, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5) + S1(B(40), B(48), B(54), B(62)) + xor_B_KS_p(3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11) + S2(B(44), B(59), B(33), B(49)) + xor_B_KS_p(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12, 17) + S3(B(55), B(47), B(61), B(37)) + xor_B_KS_p(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16, 23) + S4(B(57), B(51), B(41), B(32)) + xor_B_KS_p(15, 24, 16, 25, 17, 26, 18, 27, 19, 28, 20, 29) + S5(B(39), B(45), B(56), B(34)) + xor_B_KS_p(19, 30, 20, 31, 21, 32, 22, 33, 23, 34, 24, 35) + S6(B(35), B(60), B(42), B(50)) + xor_B_KS_p(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28, 41) + S7(B(63), B(43), B(53), B(38)) + xor_B_KS_p(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0, 47) + S8(B(36), B(58), B(46), B(52)) + xor_B_KS_p(63, 48, 32, 49, 33, 50, 34, 51, 35, 52, 36, 53) + S1(B(8), B(16), B(22), B(30)) + xor_B_KS_p(35, 54, 36, 55, 37, 56, 38, 57, 39, 58, 40, 59) + S2(B(12), B(27), B(1), B(17)) + xor_B_KS_p(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44, 65) + S3(B(23), B(15), B(29), B(5)) + xor_B_KS_p(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48, 71) + S4(B(25), B(19), B(9), B(0)) + xor_B_KS_p(47, 72, 48, 73, 49, 74, 50, 75, 51, 76, 52, 77) + S5(B(7), B(13), B(24), B(2)) + xor_B_KS_p(51, 78, 52, 79, 53, 80, 54, 81, 55, 82, 56, 83) + S6(B(3), B(28), B(10), B(18)) + xor_B_KS_p(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60, 89) + S7(B(31), B(11), B(21), B(6)) + xor_B_KS_p(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32, 95) + addl $nptr(96),k_ptr + S8(B(4), B(26), B(14), B(20)) + decl rounds + jnz DES_bs_crypt_LM_loop + movl 8(%esp),%eax + popl %esi +#ifdef EMMS + emms +#endif + movl (%eax),%eax + ret + +#endif + +#if defined(__ELF__) && defined(__linux__) +.section .note.GNU-stack,"",@progbits +#endif diff --git a/src/x86-mmx.h b/src/x86-mmx.h new file mode 100644 index 0000000..9c1341e --- /dev/null +++ b/src/x86-mmx.h @@ -0,0 +1,83 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2002,2008,2010,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for x86 with MMX. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 1 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 1 +#define CPU_REQ 1 +#define CPU_NAME "MMX" +#ifndef CPU_FALLBACK +#define CPU_FALLBACK 0 +#endif +#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY) +#define CPU_FALLBACK_BINARY "john-non-mmx" +#endif + +#define DES_ASM 1 +#define DES_128K 0 +#define DES_X2 1 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_STD_ALGORITHM_NAME "DES 48/64 4K MMX" +#if defined(__MMX__) && defined(_OPENMP) +#define DES_BS_ASM 0 +#if 1 +#define DES_BS_VECTOR 2 +#define DES_BS_ALGORITHM_NAME "DES 64/64 MMX" +#else +#define DES_BS_VECTOR 3 +#define DES_BS_VECTOR_SIZE 4 +#define DES_BS_ALGORITHM_NAME "DES 64/64 MMX + 32/32" +#endif +#else +#define DES_BS_ASM 1 +#define DES_BS_VECTOR 2 +#define DES_BS_ALGORITHM_NAME "DES 64/64 MMX" +#endif +#define DES_BS 1 +#define DES_BS_EXPAND 1 + +#ifdef _OPENMP +#define MD5_ASM 0 +#else +#define MD5_ASM 1 +#endif +#define MD5_X2 0 +#define MD5_IMM 1 + +#if defined(_OPENMP) || \ + (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))) +#define BF_ASM 0 +#define BF_X2 1 +#else +#define BF_ASM 1 +#define BF_X2 0 +#endif +#define BF_SCALE 1 + +#endif diff --git a/src/x86-sse.S b/src/x86-sse.S new file mode 100644 index 0000000..e8864da --- /dev/null +++ b/src/x86-sse.S @@ -0,0 +1,1395 @@ +/* + * This file contains the core of a bitslice DES implementation for x86/SSE2. + * It is part of John the Ripper password cracker, + * Copyright (c) 2000-2001,2005,2006,2008,2011,2012 by Solar Designer + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. (This is a heavily cut-down "BSD license".) + * + * Gate counts per S-box: 49 44 46 33 48 46 46 41 + * Average: 44.125 + * + * The Boolean expressions corresponding to DES S-boxes have been generated + * by Roman Rusakov for use in Openwall's + * John the Ripper password cracker: http://www.openwall.com/john/ + * Being mathematical formulas, they are not copyrighted and are free for reuse + * by anyone. + * + * The x86/SSE2 code for the S-boxes was generated by Solar Designer using a + * Perl script and then hand-optimized - originally for MMX, then converted to + * SSE2. Instruction scheduling was not re-done for SSE2-capable CPUs yet; + * doing so may provide further speedup. + * + * The effort has been sponsored by Rapid7: http://www.rapid7.com + */ + +#include "arch.h" + +#if DES_BS_ASM + +#ifdef UNDERSCORES +#define DES_bs_all _DES_bs_all +#define DES_bs_init_asm _DES_bs_init_asm +#define DES_bs_crypt _DES_bs_crypt +#define DES_bs_crypt_25 _DES_bs_crypt_25 +#define DES_bs_crypt_LM _DES_bs_crypt_LM +#endif + +/* + * Some broken systems don't offer section alignments larger than 4 bytes, + * while for the SSE code we need at least a 16 byte alignment. ALIGN_FIX + * is here to work around this issue when we happen to get bad addresses. + */ +#ifndef ALIGN_FIX +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align log +#else +#define DO_ALIGN(log) .align 1 << log +#endif +#else +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align log; .space ALIGN_FIX +#else +#define DO_ALIGN(log) .align 1 << log; .space ALIGN_FIX +#endif +#endif + +#ifdef __sun +/* Sun's assembler doesn't recognize .space */ +#define DO_SPACE(size) .zero size +#else +/* Mac OS X assembler doesn't recognize .zero */ +#define DO_SPACE(size) .space size +#endif + +/* Sun's assembler can't multiply, but at least it can add... */ +#define nptr(n) n+n+n+n +#define nvec(n) n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n + +#ifdef BSD +.data +#else +.bss +#endif + +.globl DES_bs_all +DO_ALIGN(6) +DES_bs_all: +DES_bs_all_KSp: +DO_SPACE(nptr(0x300)) +DES_bs_all_KS_p: +DES_bs_all_KS_v: +DO_SPACE(nvec(0x300)) +DES_bs_all_E: +DO_SPACE(nptr(96)) +DES_bs_all_K: +DO_SPACE(nvec(56)) +DES_bs_all_B: +DO_SPACE(nvec(64)) +DES_bs_all_tmp: +DO_SPACE(nvec(16)) +DES_bs_all_xkeys: +DO_SPACE(nvec(64)) +DES_bs_all_pxkeys: +DO_SPACE(nptr(128)) +DES_bs_all_keys_changed: +DO_SPACE(4) +DES_bs_all_salt: +DO_SPACE(4) +DES_bs_all_Ens: +DO_SPACE(nptr(48)) + +#define E(i) DES_bs_all_E+nptr(i) +#define B(i) DES_bs_all_B+nvec(i) +#define tmp_at(i) DES_bs_all_tmp+nvec(i) + +#define pnot tmp_at(0) + +#define S1(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm0,tmp_at(1); \ + movdqa %xmm5,%xmm7; \ + movdqa %xmm4,tmp_at(4); \ + movdqa %xmm2,%xmm6; \ + movdqa %xmm1,tmp_at(2); \ + por %xmm2,%xmm7; \ + movdqa %xmm3,tmp_at(3); \ + pxor %xmm0,%xmm6; \ + movdqa %xmm7,tmp_at(5); \ + movdqa %xmm6,%xmm1; \ + pandn %xmm0,%xmm4; \ + pand %xmm7,%xmm1; \ + movdqa %xmm1,%xmm7; \ + por %xmm5,%xmm7; \ + pxor %xmm3,%xmm1; \ + pxor %xmm4,%xmm3; \ + movdqa %xmm1,tmp_at(6); \ + movdqa %xmm3,%xmm1; \ + pandn tmp_at(6),%xmm3; \ + movdqa %xmm3,tmp_at(7); \ + movdqa %xmm5,%xmm3; \ + por %xmm0,%xmm5; \ + pxor tmp_at(4),%xmm3; \ + movdqa %xmm3,tmp_at(8); \ + movdqa %xmm5,%xmm0; \ + pandn %xmm3,%xmm6; \ + pxor %xmm2,%xmm3; \ + pandn %xmm2,%xmm4; \ + pandn %xmm1,%xmm3; \ + pxor %xmm3,%xmm7; \ + movdqa tmp_at(7),%xmm3; \ + pandn tmp_at(3),%xmm5; \ + por %xmm7,%xmm0; \ + pandn %xmm7,%xmm3; \ + movdqa %xmm3,tmp_at(9); \ + pand tmp_at(5),%xmm7; \ + movdqa tmp_at(6),%xmm3; \ + movdqa %xmm0,%xmm2; \ + pxor %xmm1,%xmm2; \ + pandn tmp_at(4),%xmm3; \ + pandn %xmm2,%xmm4; \ + movdqa tmp_at(2),%xmm2; \ + pxor %xmm4,%xmm7; \ + pxor tmp_at(8),%xmm4; \ + pxor %xmm3,%xmm5; \ + por %xmm3,%xmm4; \ + pxor tmp_at(1),%xmm4; \ + pxor %xmm0,%xmm3; \ + pandn %xmm3,%xmm2; \ + pxor tmp_at(5),%xmm0; \ + movdqa tmp_at(7),%xmm3; \ + por tmp_at(2),%xmm3; \ + pxor pnot,%xmm7; \ + pxor out1,%xmm3; \ + pxor %xmm7,%xmm2; \ + pxor tmp_at(5),%xmm4; \ + pxor out3,%xmm2; \ + pxor %xmm4,%xmm7; \ + pxor %xmm7,%xmm3; \ + movdqa %xmm3,out1; \ + por %xmm6,%xmm5; \ + por tmp_at(8),%xmm7; \ + por %xmm5,%xmm0; \ + pxor out2,%xmm7; \ + pxor %xmm4,%xmm0; \ + pxor %xmm0,%xmm7; \ + por tmp_at(4),%xmm1; \ + movdqa tmp_at(2),%xmm3; \ + pand tmp_at(9),%xmm4; \ + pandn %xmm1,%xmm0; \ + pxor %xmm0,%xmm4; \ + por tmp_at(9),%xmm3; \ + por tmp_at(2),%xmm4; \ + movdqa %xmm2,out3; \ + pxor %xmm3,%xmm7; \ + pxor %xmm5,%xmm4; \ + pxor out4,%xmm4; \ + movdqa %xmm7,out2; \ + movdqa %xmm4,out4 + +#define S2(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm2,tmp_at(2); \ + movdqa %xmm1,tmp_at(1); \ + movdqa %xmm5,%xmm2; \ + movdqa %xmm4,tmp_at(4); \ + pandn %xmm0,%xmm2; \ + movdqa %xmm3,tmp_at(3); \ + pandn %xmm4,%xmm2; \ + movdqa %xmm0,%xmm6; \ + movdqa %xmm2,%xmm7; \ + pxor pnot,%xmm0; \ + por %xmm1,%xmm7; \ + pxor %xmm4,%xmm1; \ + movdqa %xmm7,tmp_at(5); \ + pand %xmm1,%xmm6; \ + movdqa %xmm5,%xmm7; \ + pxor %xmm4,%xmm6; \ + pandn %xmm1,%xmm7; \ + movdqa %xmm3,%xmm4; \ + pxor %xmm7,%xmm2; \ + pandn %xmm6,%xmm7; \ + pxor %xmm5,%xmm1; \ + movdqa %xmm7,tmp_at(7); \ + movdqa %xmm5,%xmm7; \ + pand tmp_at(2),%xmm5; \ + pand tmp_at(5),%xmm2; \ + movdqa %xmm5,tmp_at(8); \ + pandn %xmm2,%xmm5; \ + pand tmp_at(2),%xmm2; \ + movdqa tmp_at(8),%xmm7; \ + pandn tmp_at(3),%xmm5; \ + pandn %xmm1,%xmm7; \ + pxor %xmm2,%xmm0; \ + movdqa %xmm7,%xmm3; \ + pxor %xmm0,%xmm3; \ + pxor out2,%xmm5; \ + pandn tmp_at(1),%xmm7; \ + pxor %xmm6,%xmm7; \ + pxor %xmm3,%xmm5; \ + movdqa %xmm7,%xmm6; \ + movdqa %xmm5,out2; \ + movdqa tmp_at(7),%xmm5; \ + pandn tmp_at(5),%xmm4; \ + pandn %xmm0,%xmm6; \ + pxor tmp_at(5),%xmm3; \ + movdqa %xmm1,%xmm0; \ + pxor %xmm4,%xmm6; \ + pxor tmp_at(2),%xmm0; \ + pxor %xmm0,%xmm6; \ + movdqa %xmm0,%xmm4; \ + pxor out1,%xmm6; \ + pandn tmp_at(1),%xmm0; \ + pxor tmp_at(4),%xmm2; \ + pxor %xmm3,%xmm0; \ + movdqa %xmm6,out1; \ + por %xmm1,%xmm3; \ + por tmp_at(8),%xmm0; \ + pxor %xmm4,%xmm0; \ + movdqa %xmm0,%xmm4; \ + pandn tmp_at(2),%xmm0; \ + movdqa tmp_at(3),%xmm6; \ + pxor tmp_at(7),%xmm0; \ + por %xmm7,%xmm0; \ + por %xmm6,%xmm5; \ + pxor %xmm0,%xmm2; \ + pandn %xmm2,%xmm7; \ + por %xmm2,%xmm6; \ + pxor out4,%xmm7; \ + pxor %xmm4,%xmm6; \ + pxor out3,%xmm6; \ + pxor %xmm5,%xmm7; \ + pxor %xmm3,%xmm7; \ + movdqa %xmm6,out3; \ + movdqa %xmm7,out4 + +#define S3(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm0,tmp_at(1); \ + movdqa %xmm1,tmp_at(2); \ + movdqa %xmm0,%xmm7; \ + pandn %xmm0,%xmm1; \ + movdqa %xmm2,tmp_at(3); \ + movdqa %xmm5,%xmm0; \ + pxor %xmm2,%xmm0; \ + movdqa %xmm4,tmp_at(4); \ + movdqa %xmm5,%xmm2; \ + por %xmm0,%xmm1; \ + pxor %xmm3,%xmm2; \ + movdqa %xmm0,%xmm4; \ + movdqa %xmm5,%xmm6; \ + pandn %xmm2,%xmm7; \ + pxor tmp_at(2),%xmm4; \ + movdqa %xmm7,tmp_at(5); \ + pxor %xmm1,%xmm7; \ + pandn %xmm4,%xmm6; \ + movdqa %xmm7,tmp_at(6); \ + pxor %xmm6,%xmm1; \ + pand %xmm0,%xmm2; \ + movdqa %xmm1,%xmm6; \ + movdqa %xmm3,%xmm0; \ + pandn %xmm7,%xmm6; \ + pand %xmm5,%xmm7; \ + pand %xmm3,%xmm5; \ + por %xmm3,%xmm7; \ + pand tmp_at(1),%xmm7; \ + movdqa tmp_at(4),%xmm3; \ + pandn tmp_at(6),%xmm3; \ + pxor %xmm4,%xmm7; \ + pxor tmp_at(1),%xmm0; \ + movdqa %xmm7,tmp_at(7); \ + pxor %xmm3,%xmm7; \ + movdqa tmp_at(2),%xmm3; \ + pxor out4,%xmm7; \ + pxor %xmm0,%xmm1; \ + movdqa %xmm7,out4; \ + movdqa tmp_at(3),%xmm7; \ + por tmp_at(3),%xmm1; \ + pandn %xmm1,%xmm2; \ + por tmp_at(5),%xmm0; \ + movdqa %xmm0,%xmm1; \ + pandn %xmm5,%xmm3; \ + pandn tmp_at(7),%xmm1; \ + por %xmm4,%xmm5; \ + pxor %xmm3,%xmm1; \ + por tmp_at(2),%xmm7; \ + movdqa tmp_at(3),%xmm3; \ + pandn %xmm1,%xmm3; \ + pxor %xmm4,%xmm0; \ + pandn %xmm5,%xmm3; \ + movdqa tmp_at(4),%xmm5; \ + pxor tmp_at(1),%xmm3; \ + pand %xmm2,%xmm5; \ + pxor pnot,%xmm0; \ + pxor %xmm5,%xmm3; \ + movdqa %xmm7,%xmm5; \ + pxor out2,%xmm3; \ + pandn tmp_at(4),%xmm6; \ + pandn tmp_at(6),%xmm7; \ + pxor %xmm0,%xmm6; \ + movdqa %xmm3,out2; \ + pxor tmp_at(1),%xmm2; \ + por tmp_at(4),%xmm1; \ + por %xmm2,%xmm0; \ + pxor tmp_at(6),%xmm5; \ + pxor %xmm1,%xmm0; \ + pxor out1,%xmm6; \ + pxor out3,%xmm5; \ + pxor tmp_at(7),%xmm0; \ + pxor %xmm7,%xmm6; \ + pxor %xmm5,%xmm0; \ + movdqa %xmm6,out1; \ + movdqa %xmm0,out3 + +#define S4(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm1,%xmm7; \ + pxor %xmm2,%xmm0; \ + por %xmm3,%xmm1; \ + pxor %xmm4,%xmm2; \ + movdqa %xmm5,tmp_at(2); \ + pxor %xmm4,%xmm1; \ + movdqa %xmm7,%xmm6; \ + movdqa %xmm7,%xmm5; \ + pandn %xmm2,%xmm7; \ + pandn %xmm2,%xmm1; \ + por %xmm7,%xmm4; \ + pxor %xmm3,%xmm7; \ + movdqa %xmm7,%xmm6; \ + por %xmm0,%xmm7; \ + pxor %xmm5,%xmm3; \ + movdqa %xmm1,tmp_at(3); \ + pandn %xmm7,%xmm1; \ + movdqa %xmm1,%xmm7; \ + pxor %xmm5,%xmm1; \ + pand %xmm1,%xmm6; \ + movdqa %xmm6,%xmm5; \ + pxor %xmm1,%xmm0; \ + pandn %xmm2,%xmm6; \ + pandn %xmm0,%xmm6; \ + pxor %xmm0,%xmm4; \ + movdqa %xmm3,%xmm0; \ + pandn %xmm4,%xmm3; \ + movdqa tmp_at(2),%xmm2; \ + pxor %xmm7,%xmm3; \ + pxor tmp_at(3),%xmm6; \ + movdqa %xmm6,%xmm7; \ + pandn %xmm2,%xmm6; \ + pxor out1,%xmm6; \ + pandn %xmm7,%xmm2; \ + pxor out2,%xmm2; \ + pxor %xmm3,%xmm6; \ + pxor pnot,%xmm3; \ + pxor %xmm3,%xmm2; \ + pxor %xmm7,%xmm3; \ + movdqa %xmm6,out1; \ + pandn %xmm3,%xmm0; \ + por %xmm5,%xmm0; \ + movdqa %xmm2,out2; \ + movdqa tmp_at(2),%xmm3; \ + por %xmm1,%xmm3; \ + pand tmp_at(2),%xmm1; \ + pxor %xmm4,%xmm0; \ + pxor %xmm0,%xmm3; \ + pxor out3,%xmm3; \ + pxor %xmm1,%xmm0; \ + movdqa %xmm3,out3; \ + pxor out4,%xmm0; \ + movdqa %xmm0,out4 + +#define S5(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm2,tmp_at(3); \ + movdqa %xmm0,tmp_at(1); \ + por %xmm0,%xmm2; \ + movdqa %xmm5,%xmm6; \ + movdqa %xmm2,tmp_at(4); \ + pandn %xmm2,%xmm5; \ + movdqa %xmm2,%xmm7; \ + movdqa %xmm5,%xmm2; \ + pxor %xmm0,%xmm5; \ + movdqa %xmm3,%xmm7; \ + movdqa %xmm5,tmp_at(5); \ + pxor tmp_at(3),%xmm5; \ + movdqa %xmm1,tmp_at(2); \ + por %xmm5,%xmm0; \ + por %xmm3,%xmm5; \ + pandn %xmm2,%xmm3; \ + pxor tmp_at(3),%xmm3; \ + movdqa %xmm3,tmp_at(6); \ + movdqa %xmm0,%xmm1; \ + pand %xmm4,%xmm3; \ + pxor %xmm0,%xmm3; \ + pand %xmm7,%xmm0; \ + pxor %xmm7,%xmm3; \ + movdqa %xmm3,tmp_at(3); \ + pxor %xmm3,%xmm6; \ + movdqa %xmm6,%xmm2; \ + por tmp_at(5),%xmm6; \ + movdqa %xmm6,%xmm3; \ + pand %xmm4,%xmm6; \ + movdqa %xmm6,tmp_at(7); \ + pxor tmp_at(5),%xmm6; \ + pxor %xmm6,%xmm0; \ + movdqa tmp_at(1),%xmm6; \ + movdqa %xmm0,tmp_at(8); \ + pandn %xmm3,%xmm6; \ + movdqa tmp_at(2),%xmm0; \ + movdqa %xmm6,%xmm3; \ + pxor tmp_at(6),%xmm6; \ + pxor %xmm5,%xmm4; \ + pandn %xmm4,%xmm6; \ + pxor pnot,%xmm6; \ + pandn %xmm6,%xmm0; \ + pxor tmp_at(3),%xmm0; \ + movdqa tmp_at(7),%xmm6; \ + pandn tmp_at(6),%xmm6; \ + pxor out3,%xmm0; \ + pxor %xmm4,%xmm3; \ + movdqa %xmm0,out3; \ + por tmp_at(8),%xmm3; \ + movdqa tmp_at(6),%xmm0; \ + pandn %xmm3,%xmm6; \ + pand tmp_at(6),%xmm1; \ + pand %xmm6,%xmm2; \ + movdqa %xmm6,%xmm3; \ + pandn %xmm5,%xmm6; \ + pxor %xmm4,%xmm2; \ + por %xmm2,%xmm1; \ + pxor tmp_at(4),%xmm3; \ + pxor tmp_at(7),%xmm1; \ + pand %xmm2,%xmm7; \ + pand tmp_at(2),%xmm1; \ + pxor tmp_at(1),%xmm7; \ + pxor tmp_at(8),%xmm1; \ + pxor %xmm7,%xmm3; \ + por tmp_at(2),%xmm6; \ + pxor out4,%xmm1; \ + movdqa %xmm1,out4; \ + pxor %xmm5,%xmm0; \ + pxor tmp_at(5),%xmm2; \ + pxor %xmm3,%xmm6; \ + pandn %xmm0,%xmm3; \ + pand tmp_at(2),%xmm5; \ + pxor %xmm2,%xmm3; \ + pxor out2,%xmm5; \ + pxor %xmm5,%xmm3; \ + pxor out1,%xmm6; \ + movdqa %xmm3,out2; \ + movdqa %xmm6,out1 + +#define S6(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm4,tmp_at(2); \ + pxor %xmm1,%xmm4; \ + movdqa %xmm5,tmp_at(3); \ + por %xmm1,%xmm5; \ + movdqa %xmm2,%xmm7; \ + pand %xmm0,%xmm5; \ + pxor %xmm0,%xmm2; \ + movdqa %xmm0,tmp_at(1); \ + pxor %xmm5,%xmm4; \ + movdqa %xmm4,tmp_at(4); \ + pxor tmp_at(3),%xmm4; \ + movdqa %xmm4,%xmm6; \ + pandn tmp_at(2),%xmm4; \ + pand %xmm0,%xmm6; \ + movdqa %xmm6,tmp_at(5); \ + pxor %xmm1,%xmm6; \ + movdqa %xmm6,tmp_at(6); \ + por %xmm2,%xmm6; \ + movdqa %xmm6,tmp_at(7); \ + pxor tmp_at(4),%xmm6; \ + movdqa %xmm6,%xmm0; \ + pand %xmm7,%xmm6; \ + movdqa %xmm6,tmp_at(8); \ + movdqa tmp_at(3),%xmm6; \ + por %xmm1,%xmm2; \ + pandn tmp_at(8),%xmm6; \ + movdqa %xmm6,tmp_at(9); \ + movdqa tmp_at(6),%xmm6; \ + por %xmm4,%xmm6; \ + movdqa %xmm6,tmp_at(6); \ + pxor tmp_at(9),%xmm6; \ + movdqa %xmm6,tmp_at(10); \ + pand %xmm3,%xmm6; \ + pxor out4,%xmm6; \ + pxor %xmm0,%xmm6; \ + por tmp_at(1),%xmm0; \ + movdqa %xmm6,out4; \ + movdqa tmp_at(7),%xmm6; \ + pxor %xmm1,%xmm6; \ + movdqa %xmm3,%xmm1; \ + movdqa %xmm6,tmp_at(7); \ + pandn tmp_at(3),%xmm6; \ + pxor %xmm7,%xmm6; \ + movdqa tmp_at(8),%xmm7; \ + movdqa %xmm6,tmp_at(12); \ + pandn tmp_at(2),%xmm7; \ + pand tmp_at(6),%xmm0; \ + por %xmm6,%xmm7; \ + pxor %xmm6,%xmm0; \ + movdqa tmp_at(9),%xmm6; \ + por %xmm3,%xmm4; \ + pandn %xmm0,%xmm6; \ + por %xmm7,%xmm5; \ + pxor %xmm4,%xmm6; \ + pxor tmp_at(4),%xmm0; \ + pxor out3,%xmm6; \ + pxor %xmm2,%xmm5; \ + movdqa %xmm6,out3; \ + movdqa tmp_at(5),%xmm6; \ + pandn tmp_at(2),%xmm0; \ + pxor pnot,%xmm2; \ + pxor tmp_at(7),%xmm2; \ + pxor tmp_at(3),%xmm6; \ + pxor out2,%xmm5; \ + movdqa tmp_at(12),%xmm4; \ + pxor %xmm2,%xmm0; \ + pxor tmp_at(1),%xmm4; \ + pxor tmp_at(10),%xmm5; \ + pand %xmm6,%xmm4; \ + pandn %xmm0,%xmm3; \ + pxor out1,%xmm4; \ + pandn %xmm7,%xmm1; \ + pxor tmp_at(8),%xmm4; \ + pxor %xmm2,%xmm1; \ + pxor %xmm3,%xmm5; \ + movdqa %xmm5,out2; \ + pxor %xmm1,%xmm4; \ + movdqa %xmm4,out1 + +#define S7(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm0,tmp_at(1); \ + movdqa %xmm4,tmp_at(3); \ + movdqa %xmm4,%xmm0; \ + pxor %xmm3,%xmm4; \ + movdqa %xmm5,tmp_at(4); \ + movdqa %xmm4,%xmm7; \ + movdqa %xmm3,tmp_at(2); \ + pxor %xmm2,%xmm4; \ + movdqa %xmm4,tmp_at(5); \ + pand %xmm5,%xmm4; \ + movdqa %xmm7,%xmm5; \ + pxor tmp_at(4),%xmm5; \ + pand %xmm3,%xmm7; \ + movdqa %xmm7,tmp_at(6); \ + movdqa %xmm7,%xmm6; \ + pxor %xmm1,%xmm7; \ + pand tmp_at(4),%xmm6; \ + pxor %xmm2,%xmm6; \ + movdqa %xmm7,tmp_at(7); \ + movdqa tmp_at(1),%xmm3; \ + movdqa %xmm6,%xmm0; \ + por %xmm7,%xmm6; \ + pand %xmm4,%xmm7; \ + pxor %xmm5,%xmm6; \ + pandn %xmm3,%xmm7; \ + pxor %xmm4,%xmm0; \ + pxor out4,%xmm7; \ + pxor %xmm5,%xmm4; \ + pxor %xmm6,%xmm7; \ + movdqa %xmm7,out4; \ + pandn tmp_at(2),%xmm4; \ + por tmp_at(6),%xmm6; \ + movdqa tmp_at(5),%xmm7; \ + pandn tmp_at(3),%xmm7; \ + pandn tmp_at(7),%xmm4; \ + movdqa %xmm7,tmp_at(9); \ + por tmp_at(7),%xmm7; \ + pandn tmp_at(5),%xmm5; \ + pxor %xmm0,%xmm7; \ + pxor tmp_at(3),%xmm0; \ + pxor %xmm4,%xmm0; \ + movdqa tmp_at(1),%xmm4; \ + pand %xmm0,%xmm2; \ + por %xmm2,%xmm6; \ + pxor %xmm5,%xmm6; \ + pandn %xmm6,%xmm3; \ + movdqa %xmm6,%xmm5; \ + pxor %xmm7,%xmm3; \ + pxor %xmm6,%xmm7; \ + por %xmm0,%xmm6; \ + pxor out1,%xmm3; \ + pand tmp_at(4),%xmm6; \ + pxor pnot,%xmm5; \ + pand %xmm6,%xmm1; \ + pxor out3,%xmm0; \ + pxor %xmm7,%xmm1; \ + movdqa %xmm3,out1; \ + movdqa %xmm4,%xmm3; \ + pxor tmp_at(3),%xmm7; \ + por %xmm1,%xmm2; \ + pxor %xmm6,%xmm2; \ + por %xmm2,%xmm7; \ + pand %xmm7,%xmm4; \ + pxor %xmm6,%xmm7; \ + por tmp_at(9),%xmm7; \ + pxor %xmm5,%xmm7; \ + pxor out2,%xmm1; \ + pandn %xmm7,%xmm3; \ + pxor %xmm4,%xmm0; \ + movdqa %xmm0,out3; \ + pxor %xmm3,%xmm1; \ + movdqa %xmm1,out2 + +#define S8(out1, out2, out3, out4, extra) \ + extra; \ + movdqa %xmm2,%xmm7; \ + movdqa %xmm1,tmp_at(1); \ + pandn %xmm2,%xmm1; \ + movdqa %xmm2,tmp_at(2); \ + pandn %xmm4,%xmm2; \ + movdqa %xmm5,tmp_at(5); \ + pxor %xmm3,%xmm2; \ + movdqa %xmm4,tmp_at(4); \ + movdqa %xmm1,%xmm5; \ + movdqa %xmm3,tmp_at(3); \ + movdqa %xmm2,%xmm4; \ + movdqa %xmm2,%xmm3; \ + pandn tmp_at(1),%xmm4; \ + pand %xmm0,%xmm2; \ + pandn tmp_at(1),%xmm7; \ + pandn %xmm2,%xmm1; \ + pxor tmp_at(4),%xmm7; \ + movdqa %xmm4,%xmm6; \ + por %xmm0,%xmm4; \ + movdqa %xmm7,tmp_at(6); \ + pand %xmm4,%xmm7; \ + pxor pnot,%xmm3; \ + por %xmm7,%xmm2; \ + pxor %xmm7,%xmm3; \ + pandn tmp_at(2),%xmm4; \ + movdqa tmp_at(5),%xmm7; \ + pxor %xmm4,%xmm3; \ + por %xmm1,%xmm7; \ + pxor %xmm3,%xmm5; \ + pxor %xmm5,%xmm7; \ + pxor %xmm0,%xmm5; \ + pxor out2,%xmm7; \ + movdqa %xmm7,out2; \ + pxor tmp_at(1),%xmm3; \ + movdqa %xmm5,%xmm4; \ + pand tmp_at(4),%xmm5; \ + pxor %xmm3,%xmm5; \ + por tmp_at(3),%xmm3; \ + pxor %xmm5,%xmm6; \ + pxor tmp_at(6),%xmm3; \ + pxor %xmm2,%xmm5; \ + pxor %xmm6,%xmm3; \ + por tmp_at(1),%xmm5; \ + pxor %xmm3,%xmm0; \ + pxor %xmm4,%xmm5; \ + por tmp_at(3),%xmm4; \ + pxor tmp_at(4),%xmm5; \ + pand tmp_at(5),%xmm2; \ + pandn %xmm5,%xmm4; \ + pand tmp_at(5),%xmm0; \ + pxor %xmm6,%xmm0; \ + por %xmm1,%xmm4; \ + pxor out4,%xmm0; \ + pxor %xmm4,%xmm3; \ + pxor out3,%xmm2; \ + por tmp_at(5),%xmm3; \ + pxor out1,%xmm3; \ + pxor %xmm5,%xmm2; \ + pxor %xmm6,%xmm3; \ + movdqa %xmm0,out4; \ + movdqa %xmm2,out3; \ + movdqa %xmm3,out1 + +#define a1 %xmm0 +#define a2 %xmm1 +#define a3 %xmm2 +#define a4 %xmm3 +#define a5 %xmm4 +#define a6 %xmm5 + +#define zero %xmm0 + +#define DES_bs_clear_block_8(i) \ + movdqa zero,B(i); \ + movdqa zero,B(i + 1); \ + movdqa zero,B(i + 2); \ + movdqa zero,B(i + 3); \ + movdqa zero,B(i + 4); \ + movdqa zero,B(i + 5); \ + movdqa zero,B(i + 6); \ + movdqa zero,B(i + 7) + +#define DES_bs_clear_block \ + DES_bs_clear_block_8(0); \ + DES_bs_clear_block_8(8); \ + DES_bs_clear_block_8(16); \ + DES_bs_clear_block_8(24); \ + DES_bs_clear_block_8(32); \ + DES_bs_clear_block_8(40); \ + DES_bs_clear_block_8(48); \ + DES_bs_clear_block_8(56) + +#define k_ptr %edx +#define K(i) nvec(i)(k_ptr) +#define k(i) nptr(i)(k_ptr) + +#define a6_xor_ptr %esi +#define a6_p pxor (a6_xor_ptr),a6 +#define a6_v(i) pxor K(i),a6 + +#define tmp1 %ecx +#define tmp2 a6_xor_ptr + +#define xor_E(i) \ + movl E(i),tmp1; \ + movdqa K(i),a1; \ + movl E(i + 1),tmp2; \ + movdqa K(i + 1),a2; \ + pxor (tmp1),a1; \ + pxor (tmp2),a2; \ + movl E(i + 2),tmp1; \ + movdqa K(i + 2),a3; \ + movl E(i + 3),tmp2; \ + movdqa K(i + 3),a4; \ + pxor (tmp1),a3; \ + pxor (tmp2),a4; \ + movl E(i + 4),tmp1; \ + movdqa K(i + 4),a5; \ + movl E(i + 5),a6_xor_ptr; \ + movdqa K(i + 5),a6; \ + pxor (tmp1),a5 + +#define xor_B(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6) \ + movdqa B(b1),a1; \ + movdqa B(b2),a2; \ + pxor K(k1),a1; \ + movdqa B(b3),a3; \ + pxor K(k2),a2; \ + movdqa B(b4),a4; \ + pxor K(k3),a3; \ + movdqa B(b5),a5; \ + pxor K(k4),a4; \ + movdqa B(b6),a6; \ + pxor K(k5),a5 + +#define xor_B_KS_p(b1, k1, b2, k2, b3, k3, b4, k4, b5, k5, b6, k6) \ + movl k(k1),tmp1; \ + movl k(k2),tmp2; \ + movdqa B(b1),a1; \ + movdqa B(b2),a2; \ + pxor (tmp1),a1; \ + movl k(k3),tmp1; \ + pxor (tmp2),a2; \ + movl k(k4),tmp2; \ + movdqa B(b3),a3; \ + movdqa B(b4),a4; \ + pxor (tmp1),a3; \ + movl k(k5),tmp1; \ + pxor (tmp2),a4; \ + movdqa B(b5),a5; \ + movl k(k6),a6_xor_ptr; \ + movdqa B(b6),a6; \ + pxor (tmp1),a5 + +#define mask01 tmp_at(15) + +#define v_ptr %eax +#define V(i) nvec(i)(v_ptr) + +#if 1 +#define SHLB1(reg) paddb reg,reg +#else +#define SHLB1(reg) psllq $1,reg +#endif + +#define FINALIZE_NEXT_KEY_BITS_0_6 \ + movdqa mask01,%xmm7; \ +\ + movdqa V(0),%xmm0; \ + movdqa V(1),%xmm1; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + SHLB1(%xmm1); \ + psllq $2,%xmm2; \ + psllq $3,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $4,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psllq $5,%xmm5; \ + psllq $6,%xmm6; \ + psllq $7,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(0); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $1,%xmm0; \ + SHLB1(%xmm2); \ + psllq $2,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $3,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psllq $4,%xmm5; \ + psllq $5,%xmm6; \ + psllq $6,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(1); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $2,%xmm0; \ + psrlq $1,%xmm1; \ + SHLB1(%xmm3); \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psllq $2,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psllq $3,%xmm5; \ + psllq $4,%xmm6; \ + psllq $5,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(2); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $3,%xmm0; \ + psrlq $2,%xmm1; \ + psrlq $1,%xmm2; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + SHLB1(%xmm4); \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psllq $2,%xmm5; \ + psllq $3,%xmm6; \ + psllq $4,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(3); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $4,%xmm0; \ + psrlq $3,%xmm1; \ + psrlq $2,%xmm2; \ + psrlq $1,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + SHLB1(%xmm5); \ + psllq $2,%xmm6; \ + psllq $3,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(4); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $5,%xmm0; \ + psrlq $4,%xmm1; \ + psrlq $3,%xmm2; \ + psrlq $2,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psrlq $1,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + SHLB1(%xmm6); \ + psllq $2,%xmm0; \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + movdqa V(1),%xmm1; \ + por %xmm3,%xmm0; \ + SHLB1(%xmm7); \ + movdqa %xmm0,K(5); \ +\ + movdqa V(0),%xmm0; \ + movdqa V(2),%xmm2; \ + movdqa V(3),%xmm3; \ + pand %xmm7,%xmm0; \ + pand %xmm7,%xmm1; \ + pand %xmm7,%xmm2; \ + pand %xmm7,%xmm3; \ + psrlq $6,%xmm0; \ + psrlq $5,%xmm1; \ + psrlq $4,%xmm2; \ + psrlq $3,%xmm3; \ + por %xmm0,%xmm1; \ + por %xmm2,%xmm3; \ + movdqa V(4),%xmm4; \ + movdqa V(5),%xmm5; \ + por %xmm1,%xmm3; \ + pand %xmm7,%xmm4; \ + pand %xmm7,%xmm5; \ + movdqa V(6),%xmm6; \ + movdqa V(7),%xmm0; \ + psrlq $2,%xmm4; \ + pand %xmm7,%xmm6; \ + pand %xmm7,%xmm0; \ + psrlq $1,%xmm5; \ + SHLB1(%xmm0); \ + por %xmm4,%xmm5; \ + por %xmm6,%xmm3; \ + por %xmm5,%xmm0; \ + por %xmm3,%xmm0; \ + movdqa %xmm0,K(6) + +.text + +DO_ALIGN(6) +.globl DES_bs_init_asm +DES_bs_init_asm: + pcmpeqd %xmm0,%xmm0 + movdqa %xmm0,pnot + paddb %xmm0,%xmm0 + pxor pnot,%xmm0 + movdqa %xmm0,mask01 + ret + +#define rounds_and_swapped %ebp +#define iterations %eax + +DO_ALIGN(6) +.globl DES_bs_crypt +DES_bs_crypt: + cmpl $0,DES_bs_all_keys_changed + jz DES_bs_crypt_body + call DES_bs_finalize_keys +DES_bs_crypt_body: + movl 4(%esp),iterations + pxor zero,zero + pushl %ebp + pushl %esi + movl $DES_bs_all_KS_v,k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped +DES_bs_crypt_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62), a6_p) + xor_E(6) + S2(B(44), B(59), B(33), B(49), a6_p) + xor_E(12) + S3(B(55), B(47), B(61), B(37), a6_p) + xor_E(18) + S4(B(57), B(51), B(41), B(32), a6_p) + xor_E(24) + S5(B(39), B(45), B(56), B(34), a6_p) + xor_E(30) + S6(B(35), B(60), B(42), B(50), a6_p) + xor_E(36) + S7(B(63), B(43), B(53), B(38), a6_p) + xor_E(42) + S8(B(36), B(58), B(46), B(52), a6_p) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_next +DES_bs_crypt_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30), a6_p) + xor_E(54) + S2(B(12), B(27), B(1), B(17), a6_p) + xor_E(60) + S3(B(23), B(15), B(29), B(5), a6_p) + xor_E(66) + S4(B(25), B(19), B(9), B(0), a6_p) + xor_E(72) + S5(B(7), B(13), B(24), B(2), a6_p) + xor_E(78) + S6(B(3), B(28), B(10), B(18), a6_p) + xor_E(84) + S7(B(31), B(11), B(21), B(6), a6_p) + xor_E(90) + addl $nvec(96),k_ptr + S8(B(4), B(26), B(14), B(20), a6_p) + decl rounds_and_swapped + jnz DES_bs_crypt_start + subl $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_swap + popl %esi + popl %ebp + ret +DES_bs_crypt_next: + subl $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_start + popl %esi + popl %ebp + ret + +DO_ALIGN(6) +.globl DES_bs_crypt_25 +DES_bs_crypt_25: + cmpl $0,DES_bs_all_keys_changed + jnz DES_bs_finalize_keys_25 +DES_bs_crypt_25_body: + pxor zero,zero + pushl %ebp + pushl %esi + movl $DES_bs_all_KS_v,k_ptr + DES_bs_clear_block + movl $8,rounds_and_swapped + movl $25,iterations +DES_bs_crypt_25_start: + xor_E(0) + S1(B(40), B(48), B(54), B(62), a6_p) + xor_E(6) + S2(B(44), B(59), B(33), B(49), a6_p) + xor_B(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12) + S3(B(55), B(47), B(61), B(37), a6_v(17)) + xor_B(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16) + S4(B(57), B(51), B(41), B(32), a6_v(23)) + xor_E(24) + S5(B(39), B(45), B(56), B(34), a6_p) + xor_E(30) + S6(B(35), B(60), B(42), B(50), a6_p) + xor_B(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28) + S7(B(63), B(43), B(53), B(38), a6_v(41)) + xor_B(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0) + S8(B(36), B(58), B(46), B(52), a6_v(47)) + cmpl $0x100,rounds_and_swapped + je DES_bs_crypt_25_next +DES_bs_crypt_25_swap: + xor_E(48) + S1(B(8), B(16), B(22), B(30), a6_p) + xor_E(54) + S2(B(12), B(27), B(1), B(17), a6_p) + xor_B(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44) + S3(B(23), B(15), B(29), B(5), a6_v(65)) + xor_B(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48) + S4(B(25), B(19), B(9), B(0), a6_v(71)) + xor_E(72) + S5(B(7), B(13), B(24), B(2), a6_p) + xor_E(78) + S6(B(3), B(28), B(10), B(18), a6_p) + xor_B(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60) + S7(B(31), B(11), B(21), B(6), a6_v(89)) + xor_B(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32) + S8(B(4), B(26), B(14), B(20), a6_v(95)) + addl $nvec(96),k_ptr + decl rounds_and_swapped + jnz DES_bs_crypt_25_start + subl $nvec(0x300+48),k_ptr + movl $0x108,rounds_and_swapped + decl iterations + jnz DES_bs_crypt_25_swap + popl %esi + popl %ebp + ret +DES_bs_crypt_25_next: + subl $nvec(0x300-48),k_ptr + movl $8,rounds_and_swapped + decl iterations + jmp DES_bs_crypt_25_start + +DES_bs_finalize_keys_25: + pushl $DES_bs_crypt_25_body +DES_bs_finalize_keys: + movl $DES_bs_all_xkeys,v_ptr + movl $DES_bs_all_K,k_ptr + movl $0,DES_bs_all_keys_changed +DES_bs_finalize_keys_main_loop: + FINALIZE_NEXT_KEY_BITS_0_6 + addl $nvec(7),k_ptr + addl $nvec(8),v_ptr + cmpl $DES_bs_all_K+nvec(56),k_ptr + jb DES_bs_finalize_keys_main_loop + pushl %esi + movl $DES_bs_all_KSp,k_ptr + movl $DES_bs_all_KS_v,v_ptr +DES_bs_finalize_keys_expand_loop: + movl k(0),tmp1 + movl k(1),tmp2 + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movl k(2),tmp1 + movl k(3),tmp2 + movdqa %xmm0,V(0) + movdqa %xmm1,V(1) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movl k(4),tmp1 + movl k(5),tmp2 + movdqa %xmm0,V(2) + movdqa %xmm1,V(3) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + movl k(6),tmp1 + movl k(7),tmp2 + movdqa %xmm0,V(4) + movdqa %xmm1,V(5) + movdqa (tmp1),%xmm0 + movdqa (tmp2),%xmm1 + addl $nptr(8),k_ptr + movdqa %xmm0,V(6) + movdqa %xmm1,V(7) + addl $nvec(8),v_ptr + cmpl $DES_bs_all_KSp+nptr(0x300),k_ptr + jb DES_bs_finalize_keys_expand_loop + popl %esi + ret + +#define ones %xmm1 + +#define rounds %eax + +DO_ALIGN(6) +.globl DES_bs_crypt_LM +DES_bs_crypt_LM: + movl $DES_bs_all_xkeys,v_ptr + movl $DES_bs_all_K,k_ptr +DES_bs_finalize_keys_LM_loop: + FINALIZE_NEXT_KEY_BITS_0_6 +# bit 7 + SHLB1(%xmm7) + movdqa V(0),%xmm0 + movdqa V(1),%xmm1 + movdqa V(2),%xmm2 + movdqa V(3),%xmm3 + pand %xmm7,%xmm0 + pand %xmm7,%xmm1 + pand %xmm7,%xmm2 + pand %xmm7,%xmm3 + psrlq $7,%xmm0 + psrlq $6,%xmm1 + psrlq $5,%xmm2 + psrlq $4,%xmm3 + por %xmm0,%xmm1 + por %xmm2,%xmm3 + movdqa V(4),%xmm4 + movdqa V(5),%xmm5 + por %xmm1,%xmm3 + pand %xmm7,%xmm4 + pand %xmm7,%xmm5 + movdqa V(6),%xmm6 + movdqa V(7),%xmm0 + psrlq $3,%xmm4 + pand %xmm7,%xmm6 + pand %xmm7,%xmm0 + psrlq $2,%xmm5 + psrlq $1,%xmm6 + por %xmm4,%xmm5 + por %xmm6,%xmm3 + por %xmm5,%xmm0 + addl $nvec(8),v_ptr + por %xmm3,%xmm0 + movdqa %xmm0,K(7) + addl $nvec(8),k_ptr + cmpl $DES_bs_all_K+nvec(56),k_ptr + jb DES_bs_finalize_keys_LM_loop + + pxor zero,zero + pushl %esi + pcmpeqd ones,ones + movl $DES_bs_all_KS_p,k_ptr + movdqa zero,B(0) + movdqa zero,B(1) + movdqa zero,B(2) + movdqa zero,B(3) + movdqa zero,B(4) + movdqa zero,B(5) + movdqa zero,B(6) + movdqa zero,B(7) + movdqa ones,B(8) + movdqa ones,B(9) + movdqa ones,B(10) + movdqa zero,B(11) + movdqa ones,B(12) + movdqa zero,B(13) + movdqa zero,B(14) + movdqa zero,B(15) + movdqa zero,B(16) + movdqa zero,B(17) + movdqa zero,B(18) + movdqa zero,B(19) + movdqa zero,B(20) + movdqa zero,B(21) + movdqa zero,B(22) + movdqa ones,B(23) + movdqa zero,B(24) + movdqa zero,B(25) + movdqa ones,B(26) + movdqa zero,B(27) + movdqa zero,B(28) + movdqa ones,B(29) + movdqa ones,B(30) + movdqa ones,B(31) + movdqa zero,B(32) + movdqa zero,B(33) + movdqa zero,B(34) + movdqa ones,B(35) + movdqa zero,B(36) + movdqa ones,B(37) + movdqa ones,B(38) + movdqa ones,B(39) + movdqa zero,B(40) + movdqa zero,B(41) + movdqa zero,B(42) + movdqa zero,B(43) + movdqa zero,B(44) + movdqa ones,B(45) + movdqa zero,B(46) + movdqa zero,B(47) + movdqa ones,B(48) + movdqa ones,B(49) + movdqa zero,B(50) + movdqa zero,B(51) + movdqa zero,B(52) + movdqa zero,B(53) + movdqa ones,B(54) + movdqa zero,B(55) + movdqa ones,B(56) + movdqa zero,B(57) + movdqa ones,B(58) + movdqa zero,B(59) + movdqa ones,B(60) + movdqa ones,B(61) + movdqa ones,B(62) + movdqa ones,B(63) + movl $8,rounds +DES_bs_crypt_LM_loop: + xor_B_KS_p(31, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5) + S1(B(40), B(48), B(54), B(62), a6_p) + xor_B_KS_p(3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11) + S2(B(44), B(59), B(33), B(49), a6_p) + xor_B_KS_p(7, 12, 8, 13, 9, 14, 10, 15, 11, 16, 12, 17) + S3(B(55), B(47), B(61), B(37), a6_p) + xor_B_KS_p(11, 18, 12, 19, 13, 20, 14, 21, 15, 22, 16, 23) + S4(B(57), B(51), B(41), B(32), a6_p) + xor_B_KS_p(15, 24, 16, 25, 17, 26, 18, 27, 19, 28, 20, 29) + S5(B(39), B(45), B(56), B(34), a6_p) + xor_B_KS_p(19, 30, 20, 31, 21, 32, 22, 33, 23, 34, 24, 35) + S6(B(35), B(60), B(42), B(50), a6_p) + xor_B_KS_p(23, 36, 24, 37, 25, 38, 26, 39, 27, 40, 28, 41) + S7(B(63), B(43), B(53), B(38), a6_p) + xor_B_KS_p(27, 42, 28, 43, 29, 44, 30, 45, 31, 46, 0, 47) + S8(B(36), B(58), B(46), B(52), a6_p) + xor_B_KS_p(63, 48, 32, 49, 33, 50, 34, 51, 35, 52, 36, 53) + S1(B(8), B(16), B(22), B(30), a6_p) + xor_B_KS_p(35, 54, 36, 55, 37, 56, 38, 57, 39, 58, 40, 59) + S2(B(12), B(27), B(1), B(17), a6_p) + xor_B_KS_p(39, 60, 40, 61, 41, 62, 42, 63, 43, 64, 44, 65) + S3(B(23), B(15), B(29), B(5), a6_p) + xor_B_KS_p(43, 66, 44, 67, 45, 68, 46, 69, 47, 70, 48, 71) + S4(B(25), B(19), B(9), B(0), a6_p) + xor_B_KS_p(47, 72, 48, 73, 49, 74, 50, 75, 51, 76, 52, 77) + S5(B(7), B(13), B(24), B(2), a6_p) + xor_B_KS_p(51, 78, 52, 79, 53, 80, 54, 81, 55, 82, 56, 83) + S6(B(3), B(28), B(10), B(18), a6_p) + xor_B_KS_p(55, 84, 56, 85, 57, 86, 58, 87, 59, 88, 60, 89) + S7(B(31), B(11), B(21), B(6), a6_p) + xor_B_KS_p(59, 90, 60, 91, 61, 92, 62, 93, 63, 94, 32, 95) + addl $nptr(96),k_ptr + S8(B(4), B(26), B(14), B(20), a6_p) + decl rounds + jnz DES_bs_crypt_LM_loop + movl 8(%esp),%eax + popl %esi + movl (%eax),%eax + ret + +#endif + +#if defined(__ELF__) && defined(__linux__) +.section .note.GNU-stack,"",@progbits +#endif diff --git a/src/x86-sse.h b/src/x86-sse.h new file mode 100644 index 0000000..1e4fa03 --- /dev/null +++ b/src/x86-sse.h @@ -0,0 +1,139 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2002,2005,2006,2008,2010,2011,2013 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * Architecture specific parameters for x86 with SSE2. + */ + +#ifndef _JOHN_ARCH_H +#define _JOHN_ARCH_H + +#define ARCH_WORD long +#define ARCH_SIZE 4 +#define ARCH_BITS 32 +#define ARCH_BITS_LOG 5 +#define ARCH_BITS_STR "32" +#define ARCH_LITTLE_ENDIAN 1 +#define ARCH_INT_GT_32 0 +#define ARCH_ALLOWS_UNALIGNED 1 +#define ARCH_INDEX(x) ((unsigned int)(unsigned char)(x)) + +#define CPU_DETECT 1 +#define CPU_REQ 1 +#define CPU_NAME "SSE2" +#ifndef CPU_FALLBACK +#define CPU_FALLBACK 0 +#endif +#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY) +#define CPU_FALLBACK_BINARY "john-non-sse" +#define CPU_FALLBACK_BINARY_DEFAULT +#endif + +#ifdef __XOP__ +#define JOHN_XOP +#endif +#if defined(__AVX__) || defined(JOHN_XOP) +#define JOHN_AVX +#endif + +#define DES_ASM 1 +#define DES_128K 0 +#define DES_X2 1 +#define DES_MASK 1 +#define DES_SCALE 0 +#define DES_EXTB 0 +#define DES_COPY 1 +#define DES_STD_ALGORITHM_NAME "DES 48/64 4K MMX" +#define DES_BS 1 +#if defined(JOHN_AVX) && (defined(__GNUC__) || defined(_OPENMP)) +/* + * Require gcc for AVX/XOP because DES_bs_all is aligned in a gcc-specific way, + * except in OpenMP-enabled builds, where it's aligned by different means. + */ +#define CPU_REQ_AVX +#undef CPU_NAME +#define CPU_NAME "AVX" +#ifdef CPU_FALLBACK_BINARY_DEFAULT +#undef CPU_FALLBACK_BINARY +#define CPU_FALLBACK_BINARY "john-non-avx" +#endif +#define DES_BS_ASM 0 +#if 1 +#define DES_BS_VECTOR 8 +#if defined(JOHN_XOP) && defined(__GNUC__) +/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */ +#define CPU_REQ_XOP +#undef CPU_NAME +#define CPU_NAME "XOP" +#ifdef CPU_FALLBACK_BINARY_DEFAULT +#undef CPU_FALLBACK_BINARY +#define CPU_FALLBACK_BINARY "john-non-xop" +#endif +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 256/256 XOP" +#else +#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX" +#endif +#else +#define DES_BS_VECTOR 4 +#ifdef JOHN_XOP +#undef DES_BS +#define DES_BS 3 +#define DES_BS_ALGORITHM_NAME "DES 128/128 XOP" +#else +#define DES_BS_ALGORITHM_NAME "DES 128/128 AVX" +#endif +#endif +#elif defined(__SSE2__) && defined(_OPENMP) +#define DES_BS_ASM 0 +#if 1 +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2" +#elif 0 +#define DES_BS_VECTOR 6 +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2 + 64/64 MMX" +#elif 0 +#define DES_BS_VECTOR 5 +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2 + 32/32" +#else +#define DES_BS_VECTOR 7 +#define DES_BS_VECTOR_SIZE 8 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2 + 64/64 MMX + 32/32" +#endif +#else +#define DES_BS_ASM 1 +#define DES_BS_VECTOR 4 +#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2" +#endif +#define DES_BS_EXPAND 1 + +#ifdef _OPENMP +#define MD5_ASM 0 +#else +#define MD5_ASM 1 +#endif +#define MD5_X2 0 +#define MD5_IMM 1 + +#if defined(_OPENMP) || \ + (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))) +#define BF_ASM 0 +#define BF_X2 1 +#else +#define BF_ASM 1 +#define BF_X2 0 +#endif +#define BF_SCALE 1 + +#endif diff --git a/src/x86.S b/src/x86.S new file mode 100644 index 0000000..7cf7b6d --- /dev/null +++ b/src/x86.S @@ -0,0 +1,1429 @@ +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2003,2006,2011 by Solar Designer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + */ + +/* + * x86 assembly routines. + */ + +#include "arch.h" + +#ifdef UNDERSCORES +#define DES_IV _DES_IV +#define DES_count _DES_count +#define DES_KS_current _DES_KS_current +#define DES_KS_copy _DES_KS_copy +#define DES_KS_table _DES_KS_table +#define DES_SPE_L _DES_SPE_L +#define DES_SPE_H _DES_SPE_H +#define DES_SPE_F _DES_SPE_F +#define DES_std_crypt _DES_std_crypt +#define DES_xor_key1 _DES_xor_key1 +#define DES_xor_key2 _DES_xor_key2 +#define MD5_body _MD5_body +#define BF_body _BF_body +#define BF_current _BF_current +#define CPU_detect _CPU_detect +#endif + +/* + * Some broken systems don't offer section alignments larger than 4 bytes, + * while for the MMX code we need at least an 8 byte alignment. ALIGN_FIX + * is here to work around this issue when we happen to get bad addresses. + */ +#ifndef ALIGN_FIX +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align (log) +#elif defined(DUMBAS) +#define DO_ALIGN(log) .align 1 << log +#else +#define DO_ALIGN(log) .align (1 << (log)) +#endif +#else +#ifdef ALIGN_LOG +#define DO_ALIGN(log) .align (log); .space 4 +#else +#define DO_ALIGN(log) .align (1 << (log)); .space 4 +#endif +#endif + +/* + * DES stuff. + * + * Included are versions for: + * 1. MMX (Pentium MMX and newer Intel x86 CPUs, some clones); + * 2. Intel Pentium without MMX; + * 3. The rest (good for Pentium Pro, 486, clones). + * + * MMX has to be enabled at compile time (via DES_X2 in arch.h), while #2 + * or #3 is chosen based on CPUID info at runtime. + * + * Note: MMX code for the bitslice DES implementation is in x86-mmx.S, so + * you probably want to look in there instead. + */ + +.text + +#if DES_X2 + +/* + * DES MMX routines. + */ + +#define R %mm0 +#define L %mm1 +#define tmp1 %mm2 +#define tmp2 %mm3 +#define K1 %mm4 +#define K2 %mm5 +#define K3 %mm6 +#define K4 %mm7 + +#define DES_copy(ofs1, ofs2) \ + movq ofs1(%edx),%mm0; \ + movq ofs2(%edx),%mm1; \ + movq %mm0,DES_KS_copy+ofs1; \ + movq %mm1,DES_KS_copy+ofs2 + +#define DES_2_ROUNDS_START(K) \ + pxor R,tmp1; \ + movd tmp1,%eax; \ + movb %al,%bl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + psrlq $32,tmp1; \ + pxor DES_SPE_F(%ebx,%ebx),L; \ + pxor DES_SPE_F+0x200(%edx,%edx),L; \ + movb %al,%bl; \ + movb %ah,%dl; \ + movd tmp1,%eax; \ + pxor DES_SPE_F+0x400(%ebx,%ebx),L; \ + pxor DES_SPE_F+0x600(%edx,%edx),L; \ + movb %al,%bl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + pxor DES_SPE_F+0x800(%ebx,%ebx),L; \ + pxor DES_SPE_F+0xA00(%edx,%edx),L; \ + movb %al,%bl; \ + movb %ah,%dl; \ + movq K,tmp1; \ + pxor DES_SPE_F+0xC00(%ebx,%ebx),L; \ + pxor DES_SPE_F+0xE00(%edx,%edx),L; \ + pxor L,tmp1; \ + movd tmp1,%eax; \ + movb %al,%bl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + psrlq $32,tmp1; \ + pxor DES_SPE_F(%ebx,%ebx),R; \ + pxor DES_SPE_F+0x200(%edx,%edx),R; \ + movb %al,%bl; \ + movb %ah,%dl; \ + movd tmp1,%eax; \ + pxor DES_SPE_F+0x400(%ebx,%ebx),R; \ + pxor DES_SPE_F+0x600(%edx,%edx),R; \ + movb %al,%bl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + pxor DES_SPE_F+0x800(%ebx,%ebx),R; \ + pxor DES_SPE_F+0xA00(%edx,%edx),R; \ + movb %al,%bl; \ + movb %ah,%dl + +#define DES_2_ROUNDS(K1, K2) \ + DES_2_ROUNDS_START(K1); \ + movq K2,tmp1; \ + pxor DES_SPE_F+0xC00(%ebx,%ebx),R; \ + pxor DES_SPE_F+0xE00(%edx,%edx),R + +DO_ALIGN(12) +.globl DES_std_crypt +DES_std_crypt: + movl 4(%esp),%edx + pushl %ebx + movl DES_count,%ecx + xorl %ebx,%ebx + movq (%edx),K1 + movq 32(%edx),K2 + movq K1,tmp1 + movq 8(%edx),K3 + movq 16(%edx),K4 + DES_copy(24, 40) + DES_copy(48, 56) + DES_copy(64, 96) + DES_copy(72, 80) + DES_copy(88, 104) + DES_copy(112, 120) + movq DES_IV,R + xorl %edx,%edx + movq DES_IV+8,L +DES_loop: + DES_2_ROUNDS(K3, K4) + DES_2_ROUNDS(DES_KS_copy+24, K2) + DES_2_ROUNDS(DES_KS_copy+40, DES_KS_copy+48) + DES_2_ROUNDS(DES_KS_copy+56, DES_KS_copy+64) + DES_2_ROUNDS(DES_KS_copy+72, DES_KS_copy+80) + DES_2_ROUNDS(DES_KS_copy+88, DES_KS_copy+96) + DES_2_ROUNDS(DES_KS_copy+104, DES_KS_copy+112) + DES_2_ROUNDS_START(DES_KS_copy+120) + movq K1,tmp1 + pxor DES_SPE_F+0xC00(%ebx,%ebx),R + movq L,tmp2 + pxor DES_SPE_F+0xE00(%edx,%edx),R + decl %ecx + movq R,L + movq tmp2,R + jnz DES_loop + movl 12(%esp),%edx + popl %ebx + movq R,(%edx) + movq L,8(%edx) +#ifdef EMMS + emms +#endif + ret + +#define DES_xor1(ofs1, ofs2) \ + movq DES_KS_current+ofs1,%mm0; \ + movq DES_KS_current+ofs2,%mm1; \ + pxor ofs1(%edx),%mm0; \ + pxor ofs2(%edx),%mm1; \ + movq %mm0,DES_KS_current+ofs1; \ + movq %mm1,DES_KS_current+ofs2 + +DO_ALIGN(4) +.globl DES_xor_key1 +DES_xor_key1: + movl 4(%esp),%edx + DES_xor1(0, 32) + DES_xor1(8, 16) + DES_xor1(24, 40) + DES_xor1(48, 56) + DES_xor1(64, 96) + DES_xor1(72, 80) + DES_xor1(88, 104) + DES_xor1(112, 120) +#ifdef EMMS + emms +#endif + ret + +#define DES_xor2(ofs1, ofs2) \ + movq DES_KS_current+ofs1,%mm0; \ + movq DES_KS_current+ofs2,%mm1; \ + pxor ofs1(%edx),%mm0; \ + pxor ofs2(%edx),%mm1; \ + pxor ofs1(%ecx),%mm0; \ + pxor ofs2(%ecx),%mm1; \ + movq %mm0,DES_KS_current+ofs1; \ + movq %mm1,DES_KS_current+ofs2 + +DO_ALIGN(4) +.globl DES_xor_key2 +DES_xor_key2: + movl 4(%esp),%edx + movl 8(%esp),%ecx + DES_xor2(0, 32) + DES_xor2(8, 16) + DES_xor2(24, 40) + DES_xor2(48, 56) + DES_xor2(64, 96) + DES_xor2(72, 80) + DES_xor2(88, 104) + DES_xor2(112, 120) +#ifdef EMMS + emms +#endif + ret + +#else + +/* + * DES non-MMX routines. + */ + +#define Rl %ecx +#define Rh %ebp +#define Ll %esi +#define Lh %edi + +#define DES_copy(ofs) \ + movl ofs(%edx),%esi; \ + movl ofs+4(%edx),%edi; \ + movl %esi,DES_KS_copy+ofs; \ + movl %edi,DES_KS_copy+ofs+4 + +#define DES_CRYPT_START \ + movl 4(%esp),%edx; \ + pushl %ebp; \ + pushl %esi; \ + pushl %edi; \ + pushl %ebx; \ + movl (%edx),%eax; \ + movl 4(%edx),%edi; \ + movl %eax,DES_KS_copy; \ + movl %edi,DES_KS_copy+4; \ + DES_copy(32); \ + DES_copy(8); \ + DES_copy(16); \ + DES_copy(24); \ + DES_copy(40); \ + DES_copy(48); \ + DES_copy(56); \ + DES_copy(64); \ + DES_copy(96); \ + DES_copy(72); \ + DES_copy(80); \ + DES_copy(88); \ + DES_copy(104); \ + DES_copy(112); \ + DES_copy(120); \ + movl DES_IV,Rl; \ + movl DES_IV+4,Rh; \ + movl DES_IV+8,Ll; \ + movl DES_IV+12,Lh; \ + movl DES_count,%edx; \ + xorl %ebx,%ebx; \ + movl %edx,DES_count_tmp; \ + xorl %edx,%edx + +#define DES_CRYPT_END \ + movl 24(%esp),%edx; \ + popl %ebx; \ + movl Rl,(%edx); \ + movl Rh,4(%edx); \ + movl Ll,8(%edx); \ + movl Lh,12(%edx); \ + popl %edi; \ + popl %esi; \ + popl %ebp; \ + ret + +/* + * Intel Pentium optimized version, extra operations are used to avoid + * imperfect pairing. + */ + +#define DES_2_ROUNDS_START_P1(K) \ + xorl Rl,%eax; \ + movb %al,%bl; \ + movb %ah,%dl; \ + movl Rl,DES_SavedL; \ + shrl $16,%eax; \ + movl DES_SPE_L(%ebx),Rl; \ + xorl Rl,Ll; \ + movl DES_SPE_H(%ebx),Rl; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x100(%edx),Rl; \ + xorl Rl,Ll; \ + movl DES_SPE_H+0x100(%edx),Rl; \ + movb %al,%bl; \ + xorl Rl,Lh; \ + movb %ah,%dl; \ + movl K+4,%eax; \ + movl DES_SPE_L+0x200(%ebx),Rl; \ + xorl Rh,%eax; \ + xorl Rl,Ll; \ + movl DES_SPE_H+0x200(%ebx),Rl; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x300(%edx),Rl; \ + xorl Rl,Ll; \ + movb %al,%bl; \ + movl DES_SPE_H+0x300(%edx),Rl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x400(%ebx),Rl; \ + xorl Rl,Ll; \ + movl DES_SPE_H+0x400(%ebx),Rl; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x500(%edx),Rl; \ + xorl Rl,Ll; \ + movb %al,%bl; \ + movl DES_SPE_H+0x500(%edx),Rl; \ + movb %ah,%dl; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x600(%ebx),Rl; \ + xorl Rl,Ll; \ + movl DES_SPE_H+0x600(%ebx),Rl; \ + xorl Rl,Lh; \ + movl DES_SPE_L+0x700(%edx),Rl; \ + xorl Rl,Ll; \ + movl K+8,%eax; \ + movl DES_SPE_H+0x700(%edx),Rl; \ + xorl Ll,%eax; \ + xorl Rl,Lh; \ + movb %al,%bl; \ + movl DES_SavedL,Rl; \ + movb %ah,%dl; \ + movl Ll,DES_SavedL; \ + shrl $16,%eax; \ + movl DES_SPE_L(%ebx),Ll; \ + xorl Ll,Rl; \ + movl DES_SPE_H(%ebx),Ll; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x100(%edx),Ll; \ + xorl Ll,Rl; \ + movl DES_SPE_H+0x100(%edx),Ll; \ + movb %al,%bl; \ + xorl Ll,Rh; \ + movb %ah,%dl; \ + movl K+12,%eax; \ + movl DES_SPE_L+0x200(%ebx),Ll; \ + xorl Lh,%eax; \ + xorl Ll,Rl; \ + movl DES_SPE_H+0x200(%ebx),Ll; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x300(%edx),Ll; \ + xorl Ll,Rl; \ + movb %al,%bl; \ + movl DES_SPE_H+0x300(%edx),Ll; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x400(%ebx),Ll; \ + xorl Ll,Rl; \ + movl DES_SPE_H+0x400(%ebx),Ll; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x500(%edx),Ll; \ + xorl Ll,Rl; \ + movb %al,%bl; \ + movl DES_SPE_H+0x500(%edx),Ll; \ + movb %ah,%dl; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x600(%ebx),Ll; \ + xorl Ll,Rl; \ + movl DES_SPE_H+0x600(%ebx),Ll; \ + xorl Ll,Rh; \ + movl DES_SPE_L+0x700(%edx),Ll + +#define DES_2_ROUNDS_P1(K) \ + DES_2_ROUNDS_START_P1(K); \ + xorl Ll,Rl; \ + movl DES_SPE_H+0x700(%edx),Ll; \ + xorl Ll,Rh; \ + movl K+16,%eax; \ + movl DES_SavedL,Ll + +DO_ALIGN(12) +DES_std_crypt_P1: + DES_CRYPT_START +DES_loop_P1: + DES_2_ROUNDS_P1(DES_KS_copy) + DES_2_ROUNDS_P1(DES_KS_copy+16) + DES_2_ROUNDS_P1(DES_KS_copy+32) + DES_2_ROUNDS_P1(DES_KS_copy+48) + DES_2_ROUNDS_P1(DES_KS_copy+64) + DES_2_ROUNDS_P1(DES_KS_copy+80) + DES_2_ROUNDS_P1(DES_KS_copy+96) + DES_2_ROUNDS_START_P1(DES_KS_copy+112) + xorl Rl,Ll + movl DES_SPE_H+0x700(%edx),%eax + xorl Rh,%eax + movl Lh,Rh + movl %eax,Lh + movl DES_count_tmp,%eax + movl DES_SavedL,Rl + decl %eax + movl %eax,DES_count_tmp + movl DES_KS_copy,%eax + jnz DES_loop_P1 + DES_CRYPT_END + +/* + * Generic x86 version. + */ + +#define DES_2_ROUNDS_START_ANY(K) \ + xorl Rl,%eax; \ + movb %al,%bl; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + xorl DES_SPE_L(%ebx),Ll; \ + xorl DES_SPE_H(%ebx),Lh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x100(%edx),Ll; \ + xorl DES_SPE_H+0x100(%edx),Lh; \ + movb %ah,%dl; \ + movl K+4,%eax; \ + xorl DES_SPE_L+0x200(%ebx),Ll; \ + xorl Rh,%eax; \ + xorl DES_SPE_H+0x200(%ebx),Lh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x300(%edx),Ll; \ + xorl DES_SPE_H+0x300(%edx),Lh; \ + movb %ah,%dl; \ + xorl DES_SPE_L+0x400(%ebx),Ll; \ + shrl $16,%eax; \ + xorl DES_SPE_H+0x400(%ebx),Lh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x500(%edx),Ll; \ + xorl DES_SPE_H+0x500(%edx),Lh; \ + movb %ah,%dl; \ + xorl DES_SPE_L+0x600(%ebx),Ll; \ + xorl DES_SPE_H+0x600(%ebx),Lh; \ + xorl DES_SPE_L+0x700(%edx),Ll; \ + movl K+8,%eax; \ + xorl Ll,%eax; \ + movb %al,%bl; \ + xorl DES_SPE_H+0x700(%edx),Lh; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + xorl DES_SPE_L(%ebx),Rl; \ + xorl DES_SPE_H(%ebx),Rh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x100(%edx),Rl; \ + xorl DES_SPE_H+0x100(%edx),Rh; \ + movb %ah,%dl; \ + movl K+12,%eax; \ + xorl DES_SPE_L+0x200(%ebx),Rl; \ + xorl Lh,%eax; \ + xorl DES_SPE_H+0x200(%ebx),Rh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x300(%edx),Rl; \ + xorl DES_SPE_H+0x300(%edx),Rh; \ + movb %ah,%dl; \ + shrl $16,%eax; \ + xorl DES_SPE_L+0x400(%ebx),Rl; \ + xorl DES_SPE_H+0x400(%ebx),Rh; \ + movb %al,%bl; \ + xorl DES_SPE_L+0x500(%edx),Rl; \ + xorl DES_SPE_H+0x500(%edx),Rh; \ + movb %ah,%dl + +#define DES_2_ROUNDS_ANY(K) \ + DES_2_ROUNDS_START_ANY(K); \ + xorl DES_SPE_L+0x600(%ebx),Rl; \ + xorl DES_SPE_H+0x600(%ebx),Rh; \ + movl K+16,%eax; \ + xorl DES_SPE_L+0x700(%edx),Rl; \ + xorl DES_SPE_H+0x700(%edx),Rh + +DO_ALIGN(12) +DES_std_crypt_generic: + DES_CRYPT_START +DES_loop_generic: + DES_2_ROUNDS_ANY(DES_KS_copy) + DES_2_ROUNDS_ANY(DES_KS_copy+16) + DES_2_ROUNDS_ANY(DES_KS_copy+32) + DES_2_ROUNDS_ANY(DES_KS_copy+48) + DES_2_ROUNDS_ANY(DES_KS_copy+64) + DES_2_ROUNDS_ANY(DES_KS_copy+80) + DES_2_ROUNDS_ANY(DES_KS_copy+96) + DES_2_ROUNDS_START_ANY(DES_KS_copy+112) + movl Ll,%eax + xorl DES_SPE_L+0x600(%ebx),Rl + xorl DES_SPE_H+0x600(%ebx),Rh + movl DES_SPE_L+0x700(%edx),Ll + xorl Rl,Ll + movl %eax,Rl + movl Lh,%eax + movl DES_SPE_H+0x700(%edx),Lh + xorl Rh,Lh + decl DES_count_tmp + movl %eax,Rh + movl DES_KS_copy,%eax + jnz DES_loop_generic + DES_CRYPT_END + +#define DES_xor1(ofs) \ + movl DES_KS_current+ofs,%esi; \ + movl DES_KS_current+ofs+4,%edi; \ + movl ofs(%edx),%eax; \ + movl ofs+4(%edx),%ecx; \ + xorl %esi,%eax; \ + xorl %edi,%ecx; \ + movl %eax,DES_KS_current+ofs; \ + movl %ecx,DES_KS_current+ofs+4 + +DO_ALIGN(4) +.globl DES_xor_key1 +DES_xor_key1: + movl 4(%esp),%edx + pushl %esi + pushl %edi + DES_xor1(0) + DES_xor1(32) + DES_xor1(8) + DES_xor1(16) + DES_xor1(24) + DES_xor1(40) + DES_xor1(48) + DES_xor1(56) + DES_xor1(64) + DES_xor1(96) + DES_xor1(72) + DES_xor1(80) + DES_xor1(88) + DES_xor1(104) + DES_xor1(112) + DES_xor1(120) + popl %edi + popl %esi + ret + +#define DES_xor2(ofs) \ + movl ofs(%edx),%eax; \ + movl ofs+4(%edx),%ecx; \ + movl ofs(%ebx),%esi; \ + movl ofs+4(%ebx),%edi; \ + xorl %esi,%eax; \ + xorl %edi,%ecx; \ + movl DES_KS_current+ofs,%esi; \ + movl DES_KS_current+ofs+4,%edi; \ + xorl %esi,%eax; \ + xorl %edi,%ecx; \ + movl %eax,DES_KS_current+ofs; \ + movl %ecx,DES_KS_current+ofs+4 + +DO_ALIGN(4) +.globl DES_xor_key2 +DES_xor_key2: + pushl %ebx + movl 8(%esp),%edx + movl 12(%esp),%ebx + pushl %esi + pushl %edi + DES_xor2(0) + DES_xor2(32) + DES_xor2(8) + DES_xor2(16) + DES_xor2(24) + DES_xor2(40) + DES_xor2(48) + DES_xor2(56) + DES_xor2(64) + DES_xor2(96) + DES_xor2(72) + DES_xor2(80) + DES_xor2(88) + DES_xor2(104) + DES_xor2(112) + DES_xor2(120) + popl %edi + popl %esi + popl %ebx + ret + +#endif + +.data + +/* + * Weird alignments to make sure KS address's bits 5-11 never match current + * instruction pointer's bits 5-11. + */ +#ifdef DUMBAS +DO_ALIGN(12) +.zero 0x1000 - 32 - 128 +#elif defined(__DJGPP__) +.text +DO_ALIGN(12) +.space (0x1000 - 32 - 128 - 0xE0) +#else +DO_ALIGN(12) +.space (0x1000 - 32 - 128) +#endif + +#if !DES_X2 +/* + * The function pointer, set by CPU_detect(). + */ +.globl DES_std_crypt +DES_std_crypt: +.long DES_std_crypt_generic + +DES_SavedL: +.long 0 +#endif + +/* + * These are in .data, not .bss, to get them in a cache line that has to be + * already loaded at DES_std_crypt() startup. + */ +.globl DES_IV +DES_IV: +#ifdef DUMBAS +.zero 16 +#else +.space 16 +#endif + +.globl DES_count +DES_count: +.long 0 + +DES_count_tmp: +.long 0 + +DO_ALIGN(5) +.globl DES_KS_copy +DES_KS_copy: +#ifdef DUMBAS +.zero 128 +#else +.space 128 +#endif + +#ifdef __DJGPP__ +.space 32 +#endif + +#ifndef BSD +.bss +DO_ALIGN(5) +#endif + +#if DES_X2 + +.globl DES_SPE_F +DES_SPE_F: +#ifdef DUMBAS +.zero 0x1000 +#else +.space 0x1000 +#endif + +#else + +.globl DES_SPE_L +DES_SPE_L: +#ifdef DUMBAS +.zero 0x800 +#else +.space 0x800 +#endif + +/* + * Cache bank shift. This should be at least as large as the word size, but + * smaller than the cache line size. (At least on Intel Pentium, two loads + * can't dual issue if accessing the same cache bank.) + */ +.long 0 + +.globl DES_SPE_H +DES_SPE_H: +#ifdef DUMBAS +.zero 0x800 +#else +.space 0x800 +#endif + +#endif + +DO_ALIGN(5) + +.globl DES_KS_current +DES_KS_current: +#ifdef DUMBAS +.zero 128 +#else +.space 128 +#endif + +.globl DES_KS_table +DES_KS_table: +#ifdef DUMBAS +.zero 0x20000 +#else +.space (8 * 128 * 16 * 8) +#endif + +/* + * MD5 stuff, optimized for Intel Pentium only right now. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define Ca 0x67452301 +#define Cb 0xefcdab89 +#define Cc 0x98badcfe +#define Cd 0x10325476 + +#define a %esi +#define b %edi +#define c %edx +#define d %ebx +#undef tmp1 +#undef tmp2 +#define tmp1 %eax +#define tmp2 %ecx +#ifdef DUMBAS +#define x(i) i+i+i+i(%ebp) +#else +#define x(i) 4*i(%ebp) +#endif + +.text + +#define FF(a, b, c, d, x, s, ac) \ + andl b,tmp1; \ + addl x,a; \ + xorl d,tmp1; \ + addl $ac,a; \ + addl tmp1,a; \ + movl b,tmp1; \ + roll $s,a; \ + xorl c,tmp1; \ + addl b,a + +#define GG(a, b, c, d, x, s, ac) \ + movl x,tmp2; \ + xorl b,tmp1; \ + addl tmp2,a; \ + andl d,tmp1; \ + addl $ac,a; \ + xorl c,tmp1; \ + addl tmp1,a; \ + roll $s,a; \ + movl b,tmp1; \ + addl b,a + +#define HH(a, b, c, d, x, s, ac) \ + movl c,tmp1; \ + addl tmp2,a; \ + xorl d,tmp1; \ + addl $ac,a; \ + xorl b,tmp1; \ + movl x,tmp2; \ + addl tmp1,a; \ + roll $s,a; \ + addl b,a + +#define II(a, b, c, d, x, s, ac) \ + xorl d,tmp2; \ + addl x,a; \ + orl b,tmp2; \ + addl $ac,a; \ + xorl c,tmp2; \ + addl tmp2,a; \ + movl $-1,tmp2; \ + roll $s,a; \ + addl b,a + +DO_ALIGN(5) +.globl MD5_body +MD5_body: + pushl %ebp + movl 8(%esp),%ebp + pushl %ebx + pushl %esi + pushl %edi +/* Round 1 */ + movl x(0),a + movl x(1),d + addl $0xd76aa477,a + roll $S11,a + addl $0xf8fa0bcc,d + addl $Cb,a + movl x(2),c + movl a,tmp1 + movl a,tmp2 + andl $0x77777777,tmp1 + xorl $Cb,tmp2 + xorl $Cc,tmp1 + addl $0xbcdb4dd9,c + addl tmp1,d + roll $S12,d + addl a,d + andl d,tmp2 + xorl $Cb,tmp2 + addl tmp2,c + movl d,tmp1 + roll $S13,c + xorl a,tmp1 + addl d,c + andl c,tmp1 + movl x(3),b + xorl a,tmp1 + addl $0xb18b7a77,b + addl tmp1,b + movl c,tmp1 + roll $S14,b + xorl d,tmp1 + addl c,b + FF (a, b, c, d, x( 4), S11, 0xf57c0faf) /* 5 */ + FF (d, a, b, c, x( 5), S12, 0x4787c62a) /* 6 */ + FF (c, d, a, b, x( 6), S13, 0xa8304613) /* 7 */ + FF (b, c, d, a, x( 7), S14, 0xfd469501) /* 8 */ + FF (a, b, c, d, x( 8), S11, 0x698098d8) /* 9 */ + FF (d, a, b, c, x( 9), S12, 0x8b44f7af) /* 10 */ + FF (c, d, a, b, x(10), S13, 0xffff5bb1) /* 11 */ + FF (b, c, d, a, x(11), S14, 0x895cd7be) /* 12 */ + FF (a, b, c, d, x(12), S11, 0x6b901122) /* 13 */ + FF (d, a, b, c, x(13), S12, 0xfd987193) /* 14 */ + FF (c, d, a, b, x(14), S13, 0xa679438e) /* 15 */ + andl c,tmp1 + addl $0x49b40821,b + xorl a,tmp1 + addl tmp1,b + roll $S14,b + movl c,tmp1 + addl c,b +/* Round 2 */ + GG (a, b, c, d, x( 1), S21, 0xf61e2562) /* 17 */ + GG (d, a, b, c, x( 6), S22, 0xc040b340) /* 18 */ + GG (c, d, a, b, x(11), S23, 0x265e5a51) /* 19 */ + GG (b, c, d, a, x( 0), S24, 0xe9b6c7aa) /* 20 */ + GG (a, b, c, d, x( 5), S21, 0xd62f105d) /* 21 */ + GG (d, a, b, c, x(10), S22, 0x2441453) /* 22 */ + xorl d,tmp1 + andl b,tmp1 + addl $0xd8a1e681,c + xorl a,tmp1 + addl tmp1,c + roll $S23,c + movl d,tmp1 + addl d,c + GG (b, c, d, a, x( 4), S24, 0xe7d3fbc8) /* 24 */ + GG (a, b, c, d, x( 9), S21, 0x21e1cde6) /* 25 */ + GG (d, a, b, c, x(14), S22, 0xc33707d6) /* 26 */ + GG (c, d, a, b, x( 3), S23, 0xf4d50d87) /* 27 */ + GG (b, c, d, a, x( 8), S24, 0x455a14ed) /* 28 */ + GG (a, b, c, d, x(13), S21, 0xa9e3e905) /* 29 */ + GG (d, a, b, c, x( 2), S22, 0xfcefa3f8) /* 30 */ + GG (c, d, a, b, x( 7), S23, 0x676f02d9) /* 31 */ + movl x(12),tmp2 + xorl c,tmp1 + addl tmp2,b + andl a,tmp1 + addl $0x8d2a4c8a,b + xorl d,tmp1 + movl x(5),tmp2 + addl tmp1,b + roll $S24,b + addl c,b +/* Round 3 */ + HH (a, b, c, d, x( 8), S31, 0xfffa3942) /* 33 */ + HH (d, a, b, c, x(11), S32, 0x8771f681) /* 34 */ + HH (c, d, a, b, x(14), S33, 0x6d9d6122) /* 35 */ + HH (b, c, d, a, x( 1), S34, 0xfde5380c) /* 36 */ + HH (a, b, c, d, x( 4), S31, 0xa4beea44) /* 37 */ + HH (d, a, b, c, x( 7), S32, 0x4bdecfa9) /* 38 */ + HH (c, d, a, b, x(10), S33, 0xf6bb4b60) /* 39 */ + HH (b, c, d, a, x(13), S34, 0xbebfbc70) /* 40 */ + HH (a, b, c, d, x( 0), S31, 0x289b7ec6) /* 41 */ + HH (d, a, b, c, x( 3), S32, 0xeaa127fa) /* 42 */ + HH (c, d, a, b, x( 6), S33, 0xd4ef3085) /* 43 */ + HH (b, c, d, a, x( 9), S34, 0x4881d05) /* 44 */ + HH (a, b, c, d, x(12), S31, 0xd9d4d039) /* 45 */ + HH (d, a, b, c, x( 2), S32, 0xe6db99e5) /* 46 */ + movl a,tmp1 + xorl b,tmp1 + addl $0x1fa27cf8,c + xorl d,tmp1 + addl tmp1,c + roll $S33,c + addl d,c + HH (b, c, d, a, $-1, S34, 0xc4ac5665) /* 48 */ +/* Round 4 */ + II (a, b, c, d, x( 0), S41, 0xf4292244) /* 49 */ + II (d, a, b, c, x( 7), S42, 0x432aff97) /* 50 */ + II (c, d, a, b, x(14), S43, 0xab9423a7) /* 51 */ + II (b, c, d, a, x( 5), S44, 0xfc93a039) /* 52 */ + II (a, b, c, d, x(12), S41, 0x655b59c3) /* 53 */ + II (d, a, b, c, x( 3), S42, 0x8f0ccc92) /* 54 */ + II (c, d, a, b, x(10), S43, 0xffeff47d) /* 55 */ + II (b, c, d, a, x( 1), S44, 0x85845dd1) /* 56 */ + II (a, b, c, d, x( 8), S41, 0x6fa87e4f) /* 57 */ + xorl c,tmp2 + orl a,tmp2 + addl $0xfe2ce6e0,d + xorl b,tmp2 + addl tmp2,d + movl $-1,tmp2 + roll $S42,d + addl a,d + II (c, d, a, b, x( 6), S43, 0xa3014314) /* 59 */ + II (b, c, d, a, x(13), S44, 0x4e0811a1) /* 60 */ + II (a, b, c, d, x( 4), S41, 0xf7537e82) /* 61 */ + II (d, a, b, c, x(11), S42, 0xbd3af235) /* 62 */ + II (c, d, a, b, x( 2), S43, 0x2ad7d2bb) /* 63 */ + xorl a,tmp2 + addl x(9),b + orl c,tmp2 + addl $0xeb86d391,b + xorl d,tmp2 + addl tmp2,b + movl 24(%esp),tmp1 + roll $S44,b +/* Update the state and return */ + addl $Ca,a + addl $Cd,d + movl a,(tmp1) + leal Cb(b,c),b + addl $Cc,c + movl b,4(tmp1) + movl c,8(tmp1) + movl d,12(tmp1) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret + +#if BF_ASM +/* + * Blowfish stuff. + */ + +#ifdef DUMBAS +#define P(N) BF_current+0x1000+N+N+N+N +#else +#define P(N) BF_current+0x1000+4*N +#endif + +/* + * Intel Pentium optimized version, extra operations are used to avoid + * imperfect pairing. Also used on the Pentium 4. + */ + +#undef L +#undef R +#undef tmp1 +#undef tmp2 +#define L %esi +#define R %edi +#define tmp1 %eax +#define tmp1_lo %al +#define tmp2 %ecx +#define tmp2_hi %ch +#define tmp3 %edx +#define tmp3_lo %dl +#define tmp4 %ebx +#define tmp4_hi %bh +#define tmp5 %ebp + +.text + +#define BF_ROUND_P1(L, R, N) \ + xorl L,tmp2; \ + xorl tmp1,tmp1; \ + movl tmp2,L; \ + shrl $16,tmp2; \ + movl L,tmp4; \ + movb tmp2_hi,tmp1_lo; \ + andl $0xFF,tmp2; \ + movb tmp4_hi,tmp3_lo; \ + andl $0xFF,tmp4; \ + movl BF_current(,tmp1,4),tmp1; \ + movl BF_current+0x400(,tmp2,4),tmp5; \ + addl tmp5,tmp1; \ + movl BF_current+0x800(,tmp3,4),tmp5; \ + xorl tmp5,tmp1; \ + movl BF_current+0xC00(,tmp4,4),tmp5; \ + addl tmp1,tmp5; \ + movl P(N)+4,tmp2; \ + xorl tmp5,R + +#define BF_ENCRYPT_START_P1 \ + BF_ROUND_P1(L, R, 0); \ + BF_ROUND_P1(R, L, 1); \ + BF_ROUND_P1(L, R, 2); \ + BF_ROUND_P1(R, L, 3); \ + BF_ROUND_P1(L, R, 4); \ + BF_ROUND_P1(R, L, 5); \ + BF_ROUND_P1(L, R, 6); \ + BF_ROUND_P1(R, L, 7); \ + BF_ROUND_P1(L, R, 8); \ + BF_ROUND_P1(R, L, 9); \ + BF_ROUND_P1(L, R, 10); \ + BF_ROUND_P1(R, L, 11); \ + BF_ROUND_P1(L, R, 12); \ + BF_ROUND_P1(R, L, 13); \ + BF_ROUND_P1(L, R, 14); \ + BF_ROUND_P1(R, L, 15); \ + movl BF_ptr,tmp5; \ + xorl L,tmp2; \ + movl P(17),L + +#define BF_ENCRYPT_END_P1 \ + xorl R,L; \ + movl tmp2,R + +DO_ALIGN(12) +.globl BF_body_P1 +BF_body_P1: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + xorl L,L + xorl R,R + movl P(0),tmp2 + xorl tmp3,tmp3 + movl $P(0),BF_ptr +BF_loop_P_P1: + BF_ENCRYPT_START_P1 + addl $8,tmp5 + BF_ENCRYPT_END_P1 + movl tmp5,BF_ptr + cmpl $P(18),tmp5 + movl L,-8(tmp5) + movl R,-4(tmp5) + movl P(0),tmp2 + jb BF_loop_P_P1 +#ifndef DONT_AVOID_PENTIUMPRO_FAMILY_PARTIAL_REGISTER_STALLS + xorl tmp3,tmp3 +#endif + movl $BF_current,BF_ptr +BF_loop_S_P1: + BF_ENCRYPT_START_P1 + BF_ENCRYPT_END_P1 + movl P(0),tmp2 + movl L,(tmp5) + movl R,4(tmp5) + BF_ENCRYPT_START_P1 + BF_ENCRYPT_END_P1 + movl P(0),tmp2 + movl L,8(tmp5) + movl R,12(tmp5) + BF_ENCRYPT_START_P1 + BF_ENCRYPT_END_P1 + movl P(0),tmp2 + movl L,16(tmp5) + movl R,20(tmp5) + BF_ENCRYPT_START_P1 + addl $32,tmp5 + BF_ENCRYPT_END_P1 + movl tmp5,BF_ptr + cmpl $BF_current+0x1000,tmp5 + movl P(0),tmp2 + movl L,-8(tmp5) + movl R,-4(tmp5) + jb BF_loop_S_P1 + popl %edi + popl %esi + popl %ebx + popl %ebp + ret + +/* + * Generic x86 version. + */ + +#undef L +#undef R +#undef tmp1 +#undef tmp1_lo +#undef tmp2 +#undef tmp2_hi +#undef tmp3 +#undef tmp3_lo +#undef tmp4 +#undef tmp4_hi +#undef tmp5 +#define L %edx +#define L_lo %dl +#define L_hi %dh +#define R %ebx +#define R_lo %bl +#define R_hi %bh +#define tmp1 %eax +#define tmp2 %ecx +#define tmp2_hi %ch +#define tmp3 %esi +#define tmp4 %edi +#define ptr %ebp + +#define BF_ROUND_START(L, L_lo, L_hi) \ + shldl $16,L,tmp2; \ + movzbl L_hi,tmp3; \ + movzbl tmp2_hi,tmp1; \ + andl $0xFF,tmp2; \ + movzbl L_lo,tmp4; \ + movl BF_current(,tmp1,4),tmp1; \ + addl BF_current+0x400(,tmp2,4),tmp1 + +#define BF_ROUND_END(R, N) \ + xorl BF_current+0x800(,tmp3,4),tmp1; \ + addl BF_current+0xC00(,tmp4,4),tmp1; \ + xorl P(N)+4,R; \ + xorl tmp1,R + +#define BF_ROUND(L, L_lo, L_hi, R, N) \ + BF_ROUND_START(L, L_lo, L_hi); \ + BF_ROUND_END(R, N) + +#define BF_ENCRYPT_START \ + xorl P(0),L; \ + BF_ROUND(L, L_lo, L_hi, R, 0); \ + BF_ROUND(R, R_lo, R_hi, L, 1); \ + BF_ROUND(L, L_lo, L_hi, R, 2); \ + BF_ROUND(R, R_lo, R_hi, L, 3); \ + BF_ROUND(L, L_lo, L_hi, R, 4); \ + BF_ROUND(R, R_lo, R_hi, L, 5); \ + BF_ROUND(L, L_lo, L_hi, R, 6); \ + BF_ROUND(R, R_lo, R_hi, L, 7); \ + BF_ROUND(L, L_lo, L_hi, R, 8); \ + BF_ROUND(R, R_lo, R_hi, L, 9); \ + BF_ROUND(L, L_lo, L_hi, R, 10); \ + BF_ROUND(R, R_lo, R_hi, L, 11); \ + BF_ROUND(L, L_lo, L_hi, R, 12); \ + BF_ROUND(R, R_lo, R_hi, L, 13); \ + BF_ROUND(L, L_lo, L_hi, R, 14); \ + BF_ROUND_START(R, R_lo, R_hi); \ + movl R,tmp2; \ + movl P(16),R; \ + xorl BF_current+0x800(,tmp3,4),tmp1; \ + xorl L,R; \ + addl BF_current+0xC00(,tmp4,4),tmp1; \ + movl P(17),L; \ + xorl tmp1,R; \ + +#define BF_ENCRYPT_END \ + xorl tmp2,L + +DO_ALIGN(12) +.globl BF_body_generic +BF_body_generic: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + xorl L,L + xorl R,R + movl $P(0),ptr +BF_loop_P_generic: + BF_ENCRYPT_START + addl $8,ptr + BF_ENCRYPT_END + cmpl $P(18),ptr + movl L,-8(ptr) + movl R,-4(ptr) + jb BF_loop_P_generic + movl $BF_current,ptr +BF_loop_S_generic: + BF_ENCRYPT_START + BF_ENCRYPT_END + movl L,(ptr) + movl R,4(ptr) + BF_ENCRYPT_START + BF_ENCRYPT_END + movl L,8(ptr) + movl R,12(ptr) + BF_ENCRYPT_START + BF_ENCRYPT_END + movl L,16(ptr) + movl R,20(ptr) + BF_ENCRYPT_START + addl $32,ptr + BF_ENCRYPT_END + cmpl $BF_current+0x1000,ptr + movl L,-8(ptr) + movl R,-4(ptr) + jb BF_loop_S_generic + popl %edi + popl %esi + popl %ebx + popl %ebp + ret + +#ifdef BSD +.data +#else +.bss +#endif + +#ifdef DUMBAS +DO_ALIGN(12) +.zero 0x1000 - 96 +#elif defined(__DJGPP__) +.text +DO_ALIGN(12) +.space (0x1000 - 96 - 0x100) +#else +DO_ALIGN(12) +.space (0x1000 - 96) +#endif + +.globl BF_current +BF_current: +#ifdef DUMBAS +.zero 0x1000 + 72 +#else +.space (0x1000 + 72) +#endif + +BF_ptr: +.long 0 + +/* + * The function pointer, set by CPU_detect(). + */ +.globl BF_body +BF_body: +.long 0 + +#ifdef __DJGPP__ +.space 32 +#endif + +/* Blowfish stuff ends here */ +#endif + +/* + * CPU detection. + */ + +#define EF_ID $0x00200000 +#define CF_MMX $0x00800000 +#define CF_SSE2 $0x04000000 +#define CF_XSAVE_OSXSAVE_AVX $0x1C000000 +#define CF_XOP $0x00000800 +/* "GenuineIntel" */ +#define CV_INTEL $0x6C65746E +/* "AuthenticAMD" */ +#define CV_AMD $0x444D4163 +/* "CentaurHauls" */ +#define CV_CENTAUR $0x736C7561 + +.text + +#if !DES_X2 +#define cpuid \ + .byte 0x0F; \ + .byte 0xA2 +#endif + +.globl CPU_detect +CPU_detect: + pushl %ebx +#if BF_ASM + movl $BF_body_generic,BF_body +#endif + pushfl + pushfl + xorl EF_ID,(%esp) + popfl + pushfl + popl %eax + xorl (%esp),%eax + popfl + andl EF_ID,%eax + jz CPU_detect_ret /* 386/486 */ + xorl %eax,%eax + cpuid + testl %eax,%eax + jz CPU_detect_ret /* Newer 486s */ + pushl %ecx + movl $1,%eax + cpuid +#if defined(CPU_REQ_AVX) || defined(CPU_REQ_XOP) + andl CF_XSAVE_OSXSAVE_AVX,%ecx + cmpl CF_XSAVE_OSXSAVE_AVX,%ecx + jne CPU_detect_pop_ecx_fail + xorl %ecx,%ecx + pushl %eax + pushl %edx + xgetbv + andb $0x6,%al + cmpb $0x6,%al + popl %edx + popl %eax + je CPU_detect_AVX +CPU_detect_pop_ecx_fail: + popl %ecx + xorl %eax,%eax + jmp CPU_detect_ret +CPU_detect_AVX: +#endif +#ifdef CPU_REQ_XOP + pushl %eax + pushl %edx + movl $0x80000000,%eax + cpuid + movl $0x80000001,%edx + cmpl %edx,%eax + jl CPU_detect_no_XOP + xchgl %edx,%eax + cpuid + testl CF_XOP,%ecx + jnz CPU_detect_XOP +CPU_detect_no_XOP: + popl %edx + popl %eax + jmp CPU_detect_pop_ecx_fail +CPU_detect_XOP: + popl %edx + popl %eax +#endif + popl %ecx +#if DES_BS_VECTOR >= 4 + xchgl %edx,%eax + andl CF_SSE2,%eax + jz CPU_detect_ret /* No SSE2 */ + xchgl %edx,%eax +#elif DES_X2 + xchgl %edx,%eax + andl CF_MMX,%eax + jz CPU_detect_ret /* No MMX */ + xchgl %edx,%eax +#endif + andl $0xF0FF0,%eax /* Extended model, family, and model */ + orb $1,%al /* Detected a suitable CPU */ + cmpl CV_AMD,%ecx + je CPU_detect_AMD /* Is an AMD processor */ + cmpl CV_CENTAUR,%ecx + je CPU_detect_P1 /* Is a Centaur Technology processor */ + cmpl CV_INTEL,%ecx + jne CPU_detect_ret /* Not an Intel processor */ + cmpb $5,%ah + je CPU_detect_P1 /* Intel Pentium */ + cmpb $15,%ah + je CPU_detect_P1 /* Intel Pentium 4 */ + cmpl $0x106a1,%eax /* Family 6, model 26 */ + je CPU_detect_i7 /* Core i7 or Xeon W5580/W5590 */ + jmp CPU_detect_ret +CPU_detect_AMD: + cmpb $6,%ah + je CPU_detect_P1 /* AMD Athlon */ + cmpb $15,%ah + jne CPU_detect_ret /* Neither AMD Athlon nor AMD64 */ +CPU_detect_P1: +/* + * Enable Intel Pentium optimizations when running on one of: + * + * Intel Pentium + * Intel Pentium 4 + * AMD Athlon + * AMD64 processors + * Centaur Technology processors (IDT Winchip to VIA C3 and beyond) + * + */ +#if !DES_X2 + movl $DES_std_crypt_P1,DES_std_crypt +#endif +CPU_detect_i7: +#if BF_ASM + movl $BF_body_P1,BF_body +#endif +CPU_detect_ret: + movzbl %al,%eax + popl %ebx + ret + +#if defined(__ELF__) && defined(__linux__) +.section .note.GNU-stack,"",@progbits +#endif