home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume22
/
crack
/
part03
< prev
next >
Wrap
Text File
|
1991-08-23
|
48KB
|
1,464 lines
Newsgroups: comp.sources.misc
From: Alec David Muffett <aem@aber.ac.uk>
Subject: v22i051: crack - The Password Cracker, version 3.2a, Part03/04
Message-ID: <1991Aug23.150438.1061@sparky.IMD.Sterling.COM>
X-Md4-Signature: bfc74b025bd6d09f1fd67571cb6bc8cb
Date: Fri, 23 Aug 1991 15:04:38 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Alec David Muffett <aem@aber.ac.uk>
Posting-number: Volume 22, Issue 51
Archive-name: crack/part03
Environment: UNIX
#! /bin/sh
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 4)."
# Contents: Docs/README.ms Sources/crack-fcrypt.c
# Wrapped by aem@aberda on Fri Aug 23 13:20:42 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Docs/README.ms' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Docs/README.ms'\"
else
echo shar: Extracting \"'Docs/README.ms'\" \(20032 characters\)
sed "s/^X//" >'Docs/README.ms' <<'END_OF_FILE'
X.de C
X.ie n .B "\\$1" \\$2
X.el .CW "\\$1" \\$2
X..
X.TL
X"Crack Version 3.2"
X.br
XA Sensible Password Checker for
X.UX
X.AU
XAlec D.E. Muffett
X.AI
XComputer Unit, University College of Wales
XAberystwyth, Wales, SY23 3DB
X.I aem@aber.ac.uk
X+44 970 622492
X.AB
X.B Crack \**
X.FS
X.C Crack
Xis available for anonymous FTP from
X.I "wuarchive.wustl.edu"
X(128.252.135.4) in
X.I ~/packages
X.FE
Xis a freely available program designed to find standard
X.UX
Xeight-character DES encrypted passwords by standard guessing techniques
Xoutlined below. It is written to be flexible, configurable and fast,
Xand to be able to make use of several networked hosts via the Berkeley
X.C rsh
Xprogram (or similar), where possible.
X.AE
X.NH 1
XIntent of this program
X.LP
XMy intentions, whilst writing this program, were
X.IP 1)
XTo provide the average system manager with a simple, flexible and fast
Xtool to find passwords which would be easily compromised by a dictionary
Xsearch.
X.IP 2)
XTo weaken the complacency which has developed amongst many (in)?experienced
X.UX
Xsystems managers about password security. Just because the
X.C crypt()
Xfunction cannot be reversed does not mean that your passwords are
Xsecure. If this program helps to raise the overall quotient of paranoia
Xjust one little bit, then it will have served its purpose and is all to
Xthe good.
X.LP
XI am quite certain that some childish morons out there will abuse the
Xwork that I have put into creating this program. It's up to them how
Xthey use it, but if it's used for some illegal purpose it's not my
Xintention, nor my fault. I hope they get caught.
X.LP
XCrack was not designed to do anything
X.I nasty ,
Xother than to attack passwords in sensible order. This is why I feel I
Xcan post it to the net without fear of recrimination.
XThis version of Crack is supplied with a (hopefully) portable version of
X.C fcrypt() ,
Xfor speed reasons. Fcrypt() is not yet widely available, but several
Xversions have now been posted to USENET, and with the growing ability to
Xaccess anonymous FTP databases like
X.B Archie ,
XI believe that people who really want access to such programs as
Xfcrypt() will be able to get them easily. People who need them but
Xdon't have the time to look, on the other hand, will not get them. This
Xis not a good thing if you are a systems manager, because it gives the
Xcrackers an advantage. My philosophy is:
X.I "give it to everyone, then at least the people who need it can get it" .
X.NH 1
XFcrypt() Statistics
X.LP
XThe version of fcrypt() that comes with Crack is some 3.4 times faster
Xthan the version that was originally supplied to me, and should
Xoutperform most others which are publicly available. I haven't tried
Xmany speed-demon style tricks, but rather I have gone for portability,
Xelegance and simplicity, where applicable
X.C 8-).
XOn a DECStation 5000/200, fcrypt() iterates ~550 times per second, and
Xoverall, I measure this to be 13 times faster than standard crypt().
XThere are faster versions available, but at least I feel free to
Xredistrubute this version without stepping on anyones toes.
X.LP
XA final note about my motives: If you think that I am a moron for
Xwriting and then distributing this program, and you think that the
Xprogram is in itself dangerous, I suggest that you carefully consider
Xthe fact that any moron could have written this program. Flames to
X.C /dev/null ,
Xplease.
X.NH 1
XImplementation
X.LP
XI have tried to make Crack as portable as possible without compromising
Xspeed. Needless to say, it is imperfect in the this respect, but I have
Xtried. If you have problems getting Crack up, please let me know what
Xthese problems were, and what system you were trying to put Crack up on.
XI believe that Crack will work on
X.B Xenix
Xand various versions of
X.B "System V" ,
Xbut it may require a little effort if your
X.UX
Xis not fairly modern.
X.LP
XThere have been some nasty stories sent back to me about problems
Xencountered due to the Crack script being written in c-shell. Because
Xof this, I enclose a program
X.C Crack.sh
Xwhich is a functionally equivalent script in Bourne shell, using
X.C nohup
Xto kick the cracker off into the background. If your version of c-shell
Xis non standard (ie: not BSDish) or you are worried, you may use
X.C Crack.sh
Xin
X.C Crack 's
Xplace. Note, though, that if you want to use the network options, you
Xwill also have to edit
X.C Scripts/RCrack
Xto change the program-name that is called on remote machines to
X.C Crack.sh .
XFor more on this, see below.
X.LP
XTo use the
X.C "Crack -network"
Xoption, you must have
X.C rsh ,
Xor a similar program.
X.C rsh
Xis a BSD-ism which has become fairly common on non-BSD systems. If you
Xdon't have it or something similar, let me know what you do have which
Xmight, with a little ingenuity, do the job, and I shall see what I can
Xdo. Again, have a look in
X.C Scripts/RCrack
Xif you want to play around.
X.QP
X.B Note:
X.B Xenix
Xusers and some others have a
X.C rcmd
Xprogram instead of
X.C rsh .
XI'm not sure of the correct syntax for this program, but it should not
Xbe hard to get it to work. There is a note about it in
X.C Scripts/RCrack
X.QP
XOn such System V based systems, users may also be missing the BSD
Xfunction
X.C gethostname() .
XIf this is so, but you
X.B do
Xhave the
X.C uname()
Xsystem call, define the macro
X.C CRACK_UNAME
Xin
X.C Sources/conf.h
Xinstead. This ought to fix the problem, but it
X.I may
Xneed a little user intervention first (it depends where your header file for
X.C uname()
Xis).
X.I "Caveat Emptor!"
X.NH 1
XMethod of Password Cracking
X.LP
XCrack does not take the serial approach to password guessing that other
Xprograms like the
X.B COPS
Xpassword cracker does. Rather, Crack makes two passes over the users'
Xpassword entries.
X.LP
XThe first pass bases its guesses on the contents of the
X.I gecos
Xfield (containing the users' real name), and the username itself. The
Xfirst pass is fast and usually very fruitful, and completes quite
Xquickly. You would be surprised at the number of spods out there who
Xstill think that their middle name, backwards and capitalised, is a good
Xpassword.
X.LP
XThe second pass is made by encrypting several pre-processed dictionaries
Xon the fly, and comparing the results with users passwords. Crack
Xoptimises the number of calls to the encryption function by sorting the
Xuser passwords by their
X.I "encryption salt"
Xbefore loading, so that the dictionaries only have to be encrypted once
Xfor each different salt. This generally saves about 30% of the calls
Xyou would have to make to
X.C crypt() .
X.LP
XThe preprocessed dictionaries are created my merging the source
Xdictionaries found in the directory
X.C DictSrc
Xand then truncating, sorting and uniq'ing the output from the
Xpreprocessor. The default dictionaries named are
X.C /usr/dict/words
Xwhich provides the bulk of the input data, and
X.C DictSrc/bad_pws.dat
Xwhich is meant to provide all of those non-dictionary passwords, such as
X.I 12345678
Xor
X.I qwerty .\**
X.FS
XExtra dictionaries (those used in Dan Klein's paper, below) can be
Xobtained via anonymous FTP from
X.I uunet.uu.net
X(192.48.96.2) as
X.I ~/pub/dictionaries.tar.Z
X.FE
X.LP
XIf you wish to add a dictionary of your own, just copy it into the
X.C DictSrc
Xdirectory and then delete the contents of the
X.C Dicts
Xdirectory. Your new dictionary will be merged in on the next run. Do
Xnot worry about replication of data, as the preprocessor driver script
Xsorts and uniq's the data before putting it into the
X.C Dicts
Xdirectory.
X.LP
XThe formats of the output dictionaries are:
X.IP a)
XUnique words that have been forced lowercase, forwards. These are the
Xmost common passwords you will find, thus they are tried first.
X.IP b)
XDictionary words which have been artificially pluralised, because not
Xmany dictionaries contain plurals.
X.IP c)
XDictionary words which were supplied in mixed-case (eg:
X.I Capitalised ).
X.IP d)
XDictionary words forced lowercase and backwards.
X.IP e)
XDictionary words, forced lowercase, with a leading or trailing 0 or 1
X(this may be extended by hacking Sources/crack-pp.c).
X.IP f)
XDictionary words, forced uppercase, forwards.
X.IP g)
XDictionary words, forced uppercase, backwards.
X.IP h)
XDictionary words which were supplied in mixed-case, backwards (eg:
X.I desilatipaC ).
X.sp 1v
X.LP
XThis choice of attack is entirely empirical, my own, and made up on the
Xspot. It has also been horrendously successful, and because Crack uses
Xeach of these dictionaries in turn, it tends to get passwords faster
Xthan a program like the
X.B COPS
Xpassword cracker which tries words every-which-way for each user.\**
X.FS
XFor more information, see "Foiling the Cracker: A Survey of, and
XImprovements to, Password Security" by Daniel Klein, available from
Xmajor FTP sites.
X.FE
X.QP
XOptimisation Note: Crack has an
X.B compile-time
Xoption, called
X.C CRACK_SHORT_PASSWDS ,
Xwhich, if
X.B not
Xdefined, makes the dictionary preprocessor
X.I "throw away"
Xwords which are less than 5 characters long. The reasoning for this is
Xthat many sites, with a semi-sensible
X.C passwd
Xprogram, will not have passwords shorter than 5 characters long.
X.QP
XIt is up to you whether you bother testing these short passwords, but I
Xwould recommend that you do so at least once, to be safe. (Setting the
Xoption also leads to having smaller pre-processed dictionaries. The
Xoption, however, is defined by default)
X.NH 1
XInstallation
X.LP
XCrack is one of those most unusual of beasties, a self-installing
Xprogram. Once the necessary configuration options have been set, the
Xexecutables are created via 'make' by running the main shellscript.
X.LP
XSome people have complained about this apparent weirdness, but it has
Xgrown up with Crack ever since the earliest network version, when I
Xcould not be bothered to log into several different machines with
Xseveral different architectures, just in order to build the binaries.
X.LP
XCrack needs to know where it has been installed. Please edit the
X.C CRACK_HOME
Xvariable in the Crack shellscript to the correct value. This variable
Xshould be set to an absolute path name (relative to
X.I ~user
Xis OK) through which the directory containing Crack may be accessed on
X.B all
Xthe machines that Crack will be run on.
X.LP
XThe other bit of installation you will have to do is decide whether
Xyou will want to use the
X.C \&-network
Xoption. If you do, edit the file
X.C Sources/conf.h
Xand define the
X.C CRACK_NETWORK
Xsymbol. This forces Crack to create all of its output files with an
Xembedded hostname (obtained by the
X.C gethostname()
Xroutine) so that you can keep track of output from all over the network.
XIf you have no
X.C gethostname()
Xbut have a
X.C uname()
Xsystem call, you can use that instead, by defining
X.C CRACK_UNAME
Xin
X.C Sources/conf.h .
X.LP
XYou will then have to generate a
X.C Scripts/network.conf
Xfile. This contains a list of hostnames to
X.C rsh
Xto, what their binary type is (useful when running a network Crack on
Xseveral different architectures), a guesstimate of their relative power
X(take your slowest machine as unary, and measure all others relative to
Xit), and a list of per-host default flags. There is an example of such
Xa file provided in the Scripts directory - take a look at it.
X.LP
XI also recommend that you play around with the
X.C #define s
Xin the file
X.C Sources/conf.h .
XEach switch has a small note explaining its meaning. Where I've been in
Xdoubt about the portability of certain library functions, usually I've
Xre-written it, so it shouldn't be much of a problem. Let me know of
Xyour problems.
X.C 8-).
X.NH 1
XCrack Usage
X.LP
X.DS B
X.fi
X.C Crack
X[\c
X.I options ]
X[\c
X.I bindir ]
X.C /etc/passwd
X[...other passwd files]
X.sp 1v
X.C "Crack -network"
X[\c
X.I options ]
X.C /etc/passwd
X[...other passwd files]
X.DE
X.LP
XWhere
X.B bindir
Xis the optional name of the directory where you want the binaries
Xinstalled. This is useful where you want to be able to run versions of
XCrack on several different architectures. If
X.B bindir
Xdoes not exist, a warning will be issued, and the directory, created.
X.QP
XNote:
X.B bindir
Xdefaults to the name
X.C generic
Xif not supplied.
X.QP
X.B "Yellow Pages (NIS) Users:"
XI have had some queries about how to get Crack running from a YP
Xpassword file. There are several methods, but by far the simplest is to
Xgenerate a passwd format file by running:-
X.DS B
X.C "ypcat passwd > passwd.yp"
X.DE
Xand then running Crack on this file.
X.NH 1
XOptions
X.IP "\fB-network\fP"
XThrows Crack into network mode, in which it reads the
X.C Scripts/network.conf
Xfile, splits its input into chunks which are sized according to the
Xpower of the target machine, and calls
X.C rsh
Xto run Crack on that machine. Options for Crack running on the target
Xmachine may be supplied on the command line (eg: verbose or recover
Xmode), or in the network.conf file if they pertain to specific hosts
X(eg:
X.C nice()
Xvalues).
X.IP "\fB-v\fP"
XSets verbose mode, whereby Crack will print every guess it is trying on
Xa per-user basis. This is a very quick way of flooding your filestore.
XIf you undefine the
X.C CRACK_VERBOSE
Xsymbol in
X.C Sources/conf.h ,
Xverbose mode will be permanently disabled.
X.IP "\fB-nvalue\fP"
XSets the process to be
X.C nice() ed
Xto
X.I value ,
Xso that the switch
X.C \&-n19
Xsets the Crack process to run at the lowest priority.
X.IP "\fB-rpointfile\fP"
XThis is only for use when running in
X.I recover
Xmode. When a running Crack starts pass 2, it periodically saves its
Xstate in a file named
X.C "point.<pid>"
Xor
X.C "point.<hostname>.<pid>"
Xdepending on your naming convention (see "Installation", above). This
Xfile can be used to recover where you were should a host crash. Simply
Xinvoke Crack in
X.B exactly
Xthe same manner as the last time, with the addition of the
X.C -rpoint.file.name
Xswitch. Crack will startup and read the file, and jump to slightly
Xbefore where it left off. If you are cracking a very large password
Xfile, this can save oodles of time after a crash.
X.QP
XIf you are running a
X.I network
XCrack, then the jobs will again be spawned onto all the machines of the
Xoriginal Crack. The program will then check that the host it is running
Xon is the same as is mentioned in the pointfile. If it is not, it will
Xsilently die. Thus, assuming that you supply the same input data and do
Xnot change your
X.C network.conf
Xfile, Crack should pick up
X.B exactly
Xwhere it left off. This is a bit inelegant, but it's better than
Xnothing at the moment.
X.NH
XMultiprocessing and parallelism
X.LP
XThe method of error recovery outlined above causes headaches for users
Xwho want to do multiprocessing on parallel architectures. Crack is in
Xno way parallel, and because of the way it's structured, readind stdin
Xfrom shellscript frontends, it is a pain to divide the work amongst
Xseveral processes via
X.C fork() ing.
X.LP
XThe hack solution to get several copies of Crack running on one machine
Xwith
X.I n
Xprocessors at the moment is to run with the
X.C CRACK_NETWORK
Xoption enabled, and insert
X.I n
Xcopies of the entry for your parallel machine into the
X.C Scripts/network.conf
Xfile. If you use the
X.C \&-r
Xoption in these circumstances however, you will get
X.I n
Xcopies of the recovered process running, only one of them will have the
Xcorrect input data. I'm working on this. My current solution is to
Xsave the current username in the checkpoint file, and test it on
Xstartup, but doing this
X.I may
Xbreak your recovery if you supply different input data (so that the data
Xis sorted even slightly differently). Hohum. If you want to use this
X.I "verify username"
Xfacility, use
X.C \&-R
Xin place of
X.C \&-r .
X.LP
XAs for not using the
X.C network.conf
Xfile to provide multiprocessing, I'm working on it.
X.NH 1
XNotes on fast crypt() implementations
X.LP
XThe stdlib version of the
X.C crypt()
Xsubroutine is incredibly slow. It is a
X.I massive
Xbottleneck to the execution of Crack and on typical platforms that you
Xget at universities, it is rare to find a machine which will achieve
Xmore than 50 standard
X.C crypt() s
Xper second. On low-end diskless workstations, you may expect 2 or 3 per
Xsecond. It was this slowness of the
X.C crypt()
Xalgorithm which originally supplied much of the security
X.UX
Xneeded.\**
X.FS
XSee: "Password Security, A Case History" by Bob Morris & Ken Thomson, in
Xthe
X.UX
XProgrammer Docs.
X.FE
X.LP
XHowever, there are now
X.C many
Ximplementations of faster versions of
X.C crypt()
Xto be found on the network. The one supplied with Crack v3.2 and
Xupwards is called
X.C fcrypt() .
X.LP
X.C fcrypt()
Xwas originally written in May 1986 by Robert Baldwin at MIT, and is a
Xgood version of the
X.C crypt()
Xsubroutine. I received a copy from Icarus Sparry at Bath University,
Xwho had made a couple of portability enhancements to the code.
X.LP
XI rewrote most of the tables and the KeySchedule generating algorithm in
Xthe original
X.I fdes-init.c
Xto knock 40% off the execution overhead of
X.C fcrypt()
Xin the form that it was shipped to me. I inlined a bunch of stuff, put
Xit into a single file, got some advice from Matt Bishop and Bob Baldwin
X[both of whom I am greatly indebted to] about what to do to the
X.C xform()
Xroutine and to the fcrypt function itself, and tidied up some algorithms.
XI've also added more lookup tables and reduced several formula for
Xfaster use.
X.C fcrypt()
Xis now barely recognisable as being based on its former incarnation.
X.LP
XOn a DecStation 5000/200, it is also ~13 times faster than the standard
Xcrypt (your mileage may vary with other architectures and compilers).
XThis speed puts
X.C fcrypt()
Xinto the "moderately fast" league of crypt implementations. By using
X.C fcrypt()
Xwith Crack, I extracted 135 passwords from my standard 1087 user
Xpassword file in a little over 1 hour using 3 networked machines. This
Xis from a moderately good password file.
X.LP
XWhy am I saying this sort of thing ? Am I scaremongering ? In a word, yes.
X.LP
XIf a fast version of
X.C crypt()
Xis wired into a program like Crack it can break a poorly passworded site
Xopen in minutes. There are such programs available, eg: the "Killer
XCracker" written by the anonymous "Doctor Dissector", with anonymous
Xmotives. It comes with a modified version of Baldwin's fcrypt, as a
XMS-DOS executable with a GNU copyleft licence.
X.LP
XThe point that needs to be hammered home is that unless something is
Xdone, and done soon, about the general quality of passwords on
X.UX
Xsystems, then in the near future our doors will be wide open to people
Xwho have programs like Crack and questionable motives.
X.NH 1
XSolutions and Conclusions
X.LP
XWhat can be done about this form of attack ?
X.LP
XYou must get a drop-in replacement for the
X.C passwd
Xand
X.C yppasswd
Xcommands; one which will stop people from choosing bad passwords in the
Xfirst place. There are several programs to do this; Matt Bishop's
X.C "passwd+"
Xand Clyde Hoover's
X.C "npasswd"
Xprogram are good examples which are freely available. Consult an
X.B Archie
Xdatabase for more details on where you can get them from.
X.LP
XA little common-sense is all that is required to vet passwords: I
Xenclose a module in the Sources directory
X.I goodpass.c
Xwhich I use in a modified version of the
X.C yppasswd
Xin order to provide some security. It is quite heavily customised for
Xuse in the UK, but it should be easily portable. The routine is invoked:
X.sp 1v
X.DS B
X.C "char *retval = GoodPass(char *input);"
X.DE
X.LP
Xwhere
X.C input
Xis the password under test, and
X.C retval
Xwill be set either to NULL (if the password is OK) or to a diagnostic
Xstring which says what is wrong with the password. It is far less
Xcomplex than a system such as
X.I passwd+ ,
Xbut still effective enough to make a password file withstand
X.C Crack .
XIt would be nice if an organisation (such as
X.B CERT ?)
Xcould be persuaded to supply skeletons of
X.I sensible
Xpasswd commands for the public good, as well as an archive of security
Xrelated utilities\**
Xon top of the excellent
X.C COPS .
X.FS
X.C COPS
Xis available for anonymous FTP from
X.I "cert.sei.cmu.edu"
X(128.237.253.5) in
X.I ~/cops
X.FE
XHowever, for
X.UX
Xsecurity to improve on a global scale, we will also require pressure on
Xthe vendors, so that programs are written correctly from the beginning.
END_OF_FILE
if test 20032 -ne `wc -c <'Docs/README.ms'`; then
echo shar: \"'Docs/README.ms'\" unpacked with wrong size!
fi
# end of 'Docs/README.ms'
fi
if test -f 'Sources/crack-fcrypt.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Sources/crack-fcrypt.c'\"
else
echo shar: Extracting \"'Sources/crack-fcrypt.c'\" \(24641 characters\)
sed "s/^X//" >'Sources/crack-fcrypt.c' <<'END_OF_FILE'
X/*
X * This program is copyright (c) Alec Muffett 1991 except for certain
X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
X * Sparry and Alec Muffett. The author(s) disclaims all responsibility or
X * liability with respect to it's usage or its effect upon hardware or
X * computer systems. This software is in the public domain and is freely
X * redistributable PROVIDED that this notice remains intact.
X */
X
X/*
X * Misc defs for the fast password transform optimisations.
X */
X
X#include "crack.h" /* contains switches - AEM */
X
X/*
X * Rename the types for greater convenience ? - This is from original code.
X */
X#define reg register
X#define uns unsigned
X#define unsb uns char
X#define unsl uns long
X
X/*
X * Types for the different ways to represent DES bit patterns. Bits are
X * always right justified within fields. Bits which have lower indices in
X * the NBS spec are stored in the vax bits with less significance (e.g., Bit
X * 1 of NBS spec is stored in the bit with weight 2 ** 0 to the Vax.
X */
X
X#define obpb1 unsb /* One bit per byte. */
X#define sbpb6 unsb /* Six bits per byte, 6 held. */
X#define sbpb6R unsb /* Six bits per byte Reversed order, 6 held. */
X#define sbpb24 unsl /* Six bits per byte, 24 held. */
X#define ebpb24 unsl /* Eight bits per bit, 24 held. */
X#define fbpb4 unsb /* Four bits per byte, 4 held. */
X#define fbpb4R unsb /* Four bits per byte Reversed order, 4 held. */
X
X/*
X * The operation (6 * x) is often better optimised as this (for really
X * braindead compilers) - AEM
X */
X
X#ifdef BRAINDEAD6
X#define SIX_TIMES(exprn) (((exprn) << 2) + ((exprn) << 1))
X#else
X#define SIX_TIMES(exprn) (6 * (exprn))
X#endif /* BRAINDEAD6 */
X
X/*
X * Data segment gathered into one place - AEM
X */
X
X/* Try to keep this stuff long aligned - AEM */
Xstatic char iobuf[16];
Xstatic obpb1 L[32], R[32];
Xstatic obpb1 crypt_block[72]; /* 72 is next multiple of 8 bytes after 66 */
Xstatic sbpb24 KS[32];
Xstatic sbpb24 S0H[64], S1H[64], S2H[64], S3H[64];
Xstatic sbpb24 S4H[64], S5H[64], S6H[64], S7H[64];
Xstatic sbpb24 S0L[64], S1L[64], S2L[64], S3L[64];
Xstatic sbpb24 S4L[64], S5L[64], S6L[64], S7L[64];
Xstatic sbpb24 out96[4];
X
X/*
X * These used to be rather slow and frequently used functions - AEM
X */
X
X#define TF_TO_SIXBIT(tf) \
X (sbpb24)((tf & 077L) | \
X ((tf & 07700L) << 2) | \
X ((tf & 0770000L) << 4) | \
X ((tf & 077000000L) << 6))
X
X#define SIXBIT_TO_TF(sb) \
X (ebpb24)((sb & 0x3fL) | \
X ((sb & 0x3f00L) >> 2) | \
X ((sb & 0x3f0000L) >> 4) | \
X ((sb & 0x3f000000L) >> 6))
X/*
X * Start of the real thing
X */
X
Xvoid
XtoBA64 (quarters /* , crypt_block */ )
X reg sbpb24 *quarters;
X{
X static unsb UnDoE[] =
X {
X 1, 2, 3, 4, 7, 8, 9, 10,
X 13, 14, 15, 16, 19, 20, 21, 22,
X 25, 26, 27, 28, 31, 32, 33, 34,
X 37, 38, 39, 40, 43, 44, 45, 46
X };
X static unsb FP[] =
X {
X 39, 7, 47, 15, 55, 23, 63, 31,
X 38, 6, 46, 14, 54, 22, 62, 30,
X 37, 5, 45, 13, 53, 21, 61, 29,
X 36, 4, 44, 12, 52, 20, 60, 28,
X 35, 3, 43, 11, 51, 19, 59, 27,
X 34, 2, 42, 10, 50, 18, 58, 26,
X 33, 1, 41, 9, 49, 17, 57, 25,
X 32, 0, 40, 8, 48, 16, 56, 24,
X };
X
X reg i;
X static obpb1 tmpE[48];
X reg unsb *onebits48;
X reg sbpb24 quarter;
X
X onebits48 = tmpE;
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X /*
X * Testing one bit and setting another may be faster than shifting and
X * setting - it's certainly not slower - AEM
X */
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X /* the next loop used to be the call: undoe (tmpE, L); - AEM */
X
X for (i = 0; i < 32; i++)
X {
X L[i] = tmpE[UnDoE[i]];
X }
X
X onebits48 = tmpE;
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X quarter = SIXBIT_TO_TF (*quarters);
X quarters++;
X
X *onebits48++ = (quarter & 0x000001L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000002L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000004L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000008L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000010L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000020L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000040L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000080L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000100L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000200L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000400L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x000800L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x001000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x002000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x004000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x008000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x010000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x020000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x040000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x080000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x100000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x200000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x400000L) ? 0x01 : 0;
X *onebits48++ = (quarter & 0x800000L) ? 0x01 : 0;
X
X /* the next loop used to be the call: undoe (tmpE, R); - AEM */
X
X for (i = 0; i < 32; i++)
X {
X R[i] = tmpE[UnDoE[i]];
X }
X
X /* the next loop used to be the call: Fperm (crypt_block); - AEM */
X
X for (i = 0; i < 64; i++)
X {
X crypt_block[i] = L[FP[i]];
X }
X}
X
Xvoid
Xfsetkey ()
X{
X /*
X * This used to be utterly horrendous. It still is, but it's much, much,
X * smaller... AEM.
X */
X static unsb KeyToKS[] =
X {
X 9, 50, 33, 59, 48, 16, 32, 56, 1, 8, 18, 41, 2, 34, 25, 24,
X 43, 57, 58, 0, 35, 26, 17, 40, 21, 27, 38, 53, 36, 3, 46, 29,
X 4, 52, 22, 28, 60, 20, 37, 62, 14, 19, 44, 13, 12, 61, 54, 30,
X 1, 42, 25, 51, 40, 8, 24, 48, 58, 0, 10, 33, 59, 26, 17, 16,
X 35, 49, 50, 57, 56, 18, 9, 32, 13, 19, 30, 45, 28, 62, 38, 21,
X 27, 44, 14, 20, 52, 12, 29, 54, 6, 11, 36, 5, 4, 53, 46, 22,
X 50, 26, 9, 35, 24, 57, 8, 32, 42, 49, 59, 17, 43, 10, 1, 0,
X 48, 33, 34, 41, 40, 2, 58, 16, 60, 3, 14, 29, 12, 46, 22, 5,
X 11, 28, 61, 4, 36, 27, 13, 38, 53, 62, 20, 52, 19, 37, 30, 6,
X 34, 10, 58, 48, 8, 41, 57, 16, 26, 33, 43, 1, 56, 59, 50, 49,
X 32, 17, 18, 25, 24, 51, 42, 0, 44, 54, 61, 13, 27, 30, 6, 52,
X 62, 12, 45, 19, 20, 11, 60, 22, 37, 46, 4, 36, 3, 21, 14, 53,
X 18, 59, 42, 32, 57, 25, 41, 0, 10, 17, 56, 50, 40, 43, 34, 33,
X 16, 1, 2, 9, 8, 35, 26, 49, 28, 38, 45, 60, 11, 14, 53, 36,
X 46, 27, 29, 3, 4, 62, 44, 6, 21, 30, 19, 20, 54, 5, 61, 37,
X 2, 43, 26, 16, 41, 9, 25, 49, 59, 1, 40, 34, 24, 56, 18, 17,
X 0, 50, 51, 58, 57, 48, 10, 33, 12, 22, 29, 44, 62, 61, 37, 20,
X 30, 11, 13, 54, 19, 46, 28, 53, 5, 14, 3, 4, 38, 52, 45, 21,
X 51, 56, 10, 0, 25, 58, 9, 33, 43, 50, 24, 18, 8, 40, 2, 1,
X 49, 34, 35, 42, 41, 32, 59, 17, 27, 6, 13, 28, 46, 45, 21, 4,
X 14, 62, 60, 38, 3, 30, 12, 37, 52, 61, 54, 19, 22, 36, 29, 5,
X 35, 40, 59, 49, 9, 42, 58, 17, 56, 34, 8, 2, 57, 24, 51, 50,
X 33, 18, 48, 26, 25, 16, 43, 1, 11, 53, 60, 12, 30, 29, 5, 19,
X 61, 46, 44, 22, 54, 14, 27, 21, 36, 45, 38, 3, 6, 20, 13, 52,
X 56, 32, 51, 41, 1, 34, 50, 9, 48, 26, 0, 59, 49, 16, 43, 42,
X 25, 10, 40, 18, 17, 8, 35, 58, 3, 45, 52, 4, 22, 21, 60, 11,
X 53, 38, 36, 14, 46, 6, 19, 13, 28, 37, 30, 62, 61, 12, 5, 44,
X 40, 16, 35, 25, 50, 18, 34, 58, 32, 10, 49, 43, 33, 0, 56, 26,
X 9, 59, 24, 2, 1, 57, 48, 42, 54, 29, 36, 19, 6, 5, 44, 62,
X 37, 22, 20, 61, 30, 53, 3, 60, 12, 21, 14, 46, 45, 27, 52, 28,
X 24, 0, 48, 9, 34, 2, 18, 42, 16, 59, 33, 56, 17, 49, 40, 10,
X 58, 43, 8, 51, 50, 41, 32, 26, 38, 13, 20, 3, 53, 52, 28, 46,
X 21, 6, 4, 45, 14, 37, 54, 44, 27, 5, 61, 30, 29, 11, 36, 12,
X 8, 49, 32, 58, 18, 51, 2, 26, 0, 43, 17, 40, 1, 33, 24, 59,
X 42, 56, 57, 35, 34, 25, 16, 10, 22, 60, 4, 54, 37, 36, 12, 30,
X 5, 53, 19, 29, 61, 21, 38, 28, 11, 52, 45, 14, 13, 62, 20, 27,
X 57, 33, 16, 42, 2, 35, 51, 10, 49, 56, 1, 24, 50, 17, 8, 43,
X 26, 40, 41, 48, 18, 9, 0, 59, 6, 44, 19, 38, 21, 20, 27, 14,
X 52, 37, 3, 13, 45, 5, 22, 12, 62, 36, 29, 61, 60, 46, 4, 11,
X 41, 17, 0, 26, 51, 48, 35, 59, 33, 40, 50, 8, 34, 1, 57, 56,
X 10, 24, 25, 32, 2, 58, 49, 43, 53, 28, 3, 22, 5, 4, 11, 61,
X 36, 21, 54, 60, 29, 52, 6, 27, 46, 20, 13, 45, 44, 30, 19, 62,
X 25, 1, 49, 10, 35, 32, 48, 43, 17, 24, 34, 57, 18, 50, 41, 40,
X 59, 8, 9, 16, 51, 42, 33, 56, 37, 12, 54, 6, 52, 19, 62, 45,
X 20, 5, 38, 44, 13, 36, 53, 11, 30, 4, 60, 29, 28, 14, 3, 46,
X 17, 58, 41, 2, 56, 24, 40, 35, 9, 16, 26, 49, 10, 42, 33, 32,
X 51, 0, 1, 8, 43, 34, 25, 48, 29, 4, 46, 61, 44, 11, 54, 37,
X 12, 60, 30, 36, 5, 28, 45, 3, 22, 27, 52, 21, 20, 6, 62, 38
X };
X
X reg int i, j, r;
X reg unsb *k;
X
X k = KeyToKS;
X
X for (i = 0; i < 32; i++) /* loops cache better ? - AEM */
X {
X r = 0;
X for (j = 0; j < 24; j++)
X {
X r |= crypt_block[*(k++)] << j;
X }
X KS[i] = TF_TO_SIXBIT (r);
X }
X}
X
Xvoid
Xxform (quarters, saltvalue)
X sbpb24 *quarters;
X sbpb24 saltvalue;
X{
X union
X {
X sbpb24 b[2];
X sbpb6 c[8];
X } sdata;
X
X#ifdef sun /* Icarus Sparry, Bath */
X#define STEP --
X#define START &sdata.c[7]
X#define Dl sdata.b[1]
X#define Dh sdata.b[0]
X#else
X#define STEP ++
X#define START &sdata.c[0]
X#define Dl sdata.b[0]
X#define Dh sdata.b[1]
X#endif
X sbpb24 Rl, Rh;
X sbpb24 Ll, Lh;
X
X reg int loop;
X reg sbpb24 k;
X reg sbpb6 *dp;
X reg sbpb24 *kp;
X reg sbpb24 *kend;
X
X Ll = Lh = Rl = Rh = 0;
X
X kend = &KS[32];
X
X /*
X * Thanks to Matt Bishop for this idea... AEM.
X */
X
X#ifndef FDES_4BYTE
X#define SIZEFIX 0
X#define INDIRECT(a,b) (a)[b]
X#else
X#define SIZEFIX 2 /* "n" where 2^n == sizeof(sbpb24) */
X#define INDIRECT(a,b) (*((sbpb24 *)(((unsigned char *) a) + (b))))
X#endif
X
X for (loop = 25; loop-- > 0; /* nothing */ )
X {
X for (kp = KS; kp < kend; /* nothing */ )
X {
X k = (Rl ^ Rh) & saltvalue;
X Dl = (k ^ Rl ^ *kp++) << SIZEFIX;
X Dh = (k ^ Rh ^ *kp++) << SIZEFIX;
X
X /*
X * Oddly enough, direct addressing of dp slows things down, as
X * well as knackering portability - AEM
X */
X dp = START;
X Lh ^= INDIRECT (S0H, *dp STEP);
X Lh ^= INDIRECT (S1H, *dp STEP);
X Lh ^= INDIRECT (S2H, *dp STEP);
X Lh ^= INDIRECT (S3H, *dp STEP);
X Lh ^= INDIRECT (S4H, *dp STEP);
X Lh ^= INDIRECT (S5H, *dp STEP);
X Lh ^= INDIRECT (S6H, *dp STEP);
X Lh ^= INDIRECT (S7H, *dp STEP);
X
X dp = START;
X Ll ^= INDIRECT (S0L, *dp STEP);
X Ll ^= INDIRECT (S1L, *dp STEP);
X Ll ^= INDIRECT (S2L, *dp STEP);
X Ll ^= INDIRECT (S3L, *dp STEP);
X Ll ^= INDIRECT (S4L, *dp STEP);
X Ll ^= INDIRECT (S5L, *dp STEP);
X Ll ^= INDIRECT (S6L, *dp STEP);
X Ll ^= INDIRECT (S7L, *dp STEP);
X
X k = (Ll ^ Lh) & saltvalue;
X Dl = (k ^ Ll ^ *kp++) << SIZEFIX;
X Dh = (k ^ Lh ^ *kp++) << SIZEFIX;
X
X dp = START;
X Rh ^= INDIRECT (S0H, *dp STEP);
X Rh ^= INDIRECT (S1H, *dp STEP);
X Rh ^= INDIRECT (S2H, *dp STEP);
X Rh ^= INDIRECT (S3H, *dp STEP);
X Rh ^= INDIRECT (S4H, *dp STEP);
X Rh ^= INDIRECT (S5H, *dp STEP);
X Rh ^= INDIRECT (S6H, *dp STEP);
X Rh ^= INDIRECT (S7H, *dp STEP);
X
X dp = START;
X Rl ^= INDIRECT (S0L, *dp STEP);
X Rl ^= INDIRECT (S1L, *dp STEP);
X Rl ^= INDIRECT (S2L, *dp STEP);
X Rl ^= INDIRECT (S3L, *dp STEP);
X Rl ^= INDIRECT (S4L, *dp STEP);
X Rl ^= INDIRECT (S5L, *dp STEP);
X Rl ^= INDIRECT (S6L, *dp STEP);
X Rl ^= INDIRECT (S7L, *dp STEP);
X }
X
X Ll ^= Rl;
X Lh ^= Rh;
X Rl ^= Ll;
X Rh ^= Lh;
X Ll ^= Rl;
X Lh ^= Rh;
X }
X
X {
X reg sbpb24 *qp;
X qp = quarters;
X *qp++ = Ll;
X *qp++ = Lh;
X *qp++ = Rl;
X *qp++ = Rh;
X }
X return;
X}
X
Xchar *
Xfcrypt (pw, salt)
X char *pw;
X char *salt;
X{
X /* Table lookups for salts reduce fcrypt() overhead dramatically */
X static sbpb24 salt0[] =
X {
X 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
X 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
X 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1,
X 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 5, 6, 7, 8, 9, 10,
X 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
X 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4,
X 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
X 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4,
X 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
X 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
X 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
X 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4
X };
X static sbpb24 salt1[] =
X {
X 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600,
X 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112,
X 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624,
X 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136,
X 3200, 3264, 3328, 3392, 3456, 3520, 3584, 3648,
X 3712, 3776, 3840, 3904, 3968, 4032, 0, 64,
X 128, 192, 256, 320, 384, 448, 512, 576,
X 640, 704, 320, 384, 448, 512, 576, 640,
X 704, 768, 832, 896, 960, 1024, 1088, 1152,
X 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664,
X 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176,
X 2240, 2304, 2368, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256,
X 320, 384, 448, 512, 576, 640, 704, 768,
X 832, 896, 960, 1024, 1088, 1152, 1216, 1280,
X 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
X 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256,
X 320, 384, 448, 512, 576, 640, 704, 768,
X 832, 896, 960, 1024, 1088, 1152, 1216, 1280,
X 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
X 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304,
X 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816,
X 2880, 2944, 3008, 3072, 3136, 3200, 3264, 3328,
X 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840,
X 3904, 3968, 4032, 0, 64, 128, 192, 256
X };
X
X /* final perutation desalting */
X static obpb1 final[] =
X {
X 46, 47, 48, 49, 50, 51, 52, 53,
X 54, 55, 56, 57, 65, 66, 67, 68,
X 69, 70, 71, 72, 73, 74, 75, 76,
X 77, 78, 79, 80, 81, 82, 83, 84,
X 85, 86, 87, 88, 89, 90, 97, 98,
X 99, 100, 101, 102, 103, 104, 105, 106,
X 107, 108, 109, 110, 111, 112, 113, 114,
X 115, 116, 117, 118, 119, 120, 121, 122,
X 123, 124, 125, 126, 127, 128, 129, 130,
X 131, 132, 133, 134, 135, 136, 137, 138,
X 139, 140, 141, 142, 143, 144, 145, 146,
X 147, 148, 149, 150, 151, 152, 153, 154,
X 155, 156, 157, 158, 159, 160, 161, 162,
X 163, 164, 165, 166, 167, 168, 169, 170,
X 171, 172, 173, 174, 175, 176, 177, 178,
X 179, 180, 181, 182, 183, 184, 185, 186,
X 187, 188, 189, 190, 191, 192, 193, 194,
X 195, 196, 197, 198, 199, 200, 201, 202,
X 203, 204, 205, 206, 207, 208, 209, 210,
X 211, 212, 213, 214, 215, 216, 217, 218,
X 219, 220, 221, 222, 223, 224, 225, 226,
X 227, 228, 229, 230, 231, 232, 233, 234,
X 235, 236, 237, 238, 239, 240, 241, 242,
X 243, 244, 245, 246, 247, 248, 249, 250,
X 251, 252, 253, 254, 255,
X /* Truncate overflow bits at 256 */
X 0, 1, 2, 3, 4, 5, 6, 7,
X 8, 9, 10, 11, 12, 13, 14, 15,
X 16, 17, 18, 19, 20, 21, 22, 23,
X 24, 25, 26, 27, 28, 29, 30, 31,
X 32, 33, 34, 35, 36, 37, 38, 39,
X 40, 41, 42, 43, 44, 45, 46, 47,
X 48, 49, 50, 51, 52, 53, 54, 55,
X 56, 57, 58
X };
X
X reg int i, j, k;
X reg long int *lip;
X sbpb24 saltvalue;
X
X#if defined(BUILTIN_CLEAR)
X lip = (long int *) crypt_block;
X for (i = (sizeof (crypt_block) / sizeof (long int)); i > 0; i--)
X {
X *(lip++) = 0L;
X }
X#elif defined(BZERO)
X bzero (crypt_block, 66);
X#else
X for (i = 0; i < 66; i++)
X {
X crypt_block[i] = '\0';
X }
X#endif
X
X for (i = 0; (k = *pw) && i < 64; pw++)
X {
X crypt_block[i++] = (k >> 6) & 01;
X crypt_block[i++] = (k >> 5) & 01;
X crypt_block[i++] = (k >> 4) & 01;
X crypt_block[i++] = (k >> 3) & 01;
X crypt_block[i++] = (k >> 2) & 01;
X crypt_block[i++] = (k >> 1) & 01;
X crypt_block[i++] = (k >> 0) & 01;
X i++; /* have to skip one here (parity bit) */
X }
X
X fsetkey ( /* crypt_block */ );
X
X
X#if defined(BUILTIN_CLEAR)
X lip = (long int *) crypt_block;
X for (i = (sizeof (crypt_block) / sizeof (long int)); i > 0; i--)
X {
X *(lip++) = 0L;
X }
X#elif defined(BZERO)
X bzero (crypt_block, 66);
X#else
X for (i = 0; i < 66; i++)
X {
X crypt_block[i] = '\0';
X }
X#endif
X
X iobuf[0] = salt[0];
X iobuf[1] = salt[1];
X
X saltvalue = salt0[iobuf[0]] | salt1[iobuf[1]];
X saltvalue = TF_TO_SIXBIT (saltvalue);
X
X xform (out96, saltvalue);
X
X toBA64 (out96 /* , crypt_block */ );
X
X for (i = 0; i < 11; i++)
X {
X k = 0;
X
X for (j = 0; j < 6; j++)
X {
X k = (k << 1) | crypt_block[SIX_TIMES (i) + j];
X }
X iobuf[i + 2] = final[k];
X }
X
X iobuf[i + 2] = 0;
X
X if (iobuf[1] == 0)
X {
X iobuf[1] = iobuf[0];
X }
X return (iobuf);
X}
X/********* INITIALISATION ROUTINES *********/
X
Xfbpb4
XlookupS (tableno, t6bits)
X unsl tableno;
X sbpb6R t6bits;
X{
X static fbpb4R S[8][64] =
X {
X 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
X 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
X 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
X 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
X
X 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
X 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
X 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
X 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
X
X 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
X 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
X 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
X 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
X
X 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
X 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
X 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
X 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
X
X 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
X 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
X 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
X 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
X
X 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
X 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
X 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
X 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
X
X 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
X 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
X 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
X 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
X
X 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
X 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
X 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
X 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
X };
X sbpb6 fixed6bits;
X fbpb4R r;
X fbpb4 fixedr;
X
X fixed6bits = (((t6bits >> 0) & 01) << 5) +
X (((t6bits >> 1) & 01) << 3) +
X (((t6bits >> 2) & 01) << 2) +
X (((t6bits >> 3) & 01) << 1) +
X (((t6bits >> 4) & 01) << 0) +
X (((t6bits >> 5) & 01) << 4);
X
X r = S[tableno][fixed6bits];
X
X fixedr = (((r >> 3) & 01) << 0) +
X (((r >> 2) & 01) << 1) +
X (((r >> 1) & 01) << 2) +
X (((r >> 0) & 01) << 3);
X
X return (fixedr);
X}
X
Xvoid
Xinit (tableno, lowptr, highptr)
X unsl tableno;
X sbpb24 *lowptr, *highptr;
X{
X
X static unsb P[] =
X {
X 15, 6, 19, 20,
X 28, 11, 27, 16,
X 0, 14, 22, 25,
X 4, 17, 30, 9,
X 1, 7, 23, 13,
X 31, 26, 2, 8,
X 18, 12, 29, 5,
X 21, 10, 3, 24,
X };
X
X static unsb E[] =
X {
X 31, 0, 1, 2, 3, 4,
X 3, 4, 5, 6, 7, 8,
X 7, 8, 9, 10, 11, 12,
X 11, 12, 13, 14, 15, 16,
X 15, 16, 17, 18, 19, 20,
X 19, 20, 21, 22, 23, 24,
X 23, 24, 25, 26, 27, 28,
X 27, 28, 29, 30, 31, 0,
X };
X
X static obpb1 tmp32[32];
X static obpb1 tmpP32[32];
X static obpb1 tmpE[32];
X
X int j, k, i;
X int tablenoX4;
X reg sbpb24 spare24;
X
X tablenoX4 = tableno * 4;
X
X for (j = 0; j < 64; j++)
X {
X k = lookupS (tableno, j);
X
X for (i = 0; i < 32; i++)
X {
X tmp32[i] = 0;
X }
X for (i = 0; i < 4; i++)
X {
X tmp32[tablenoX4 + i] = (k >> i) & 01;
X }
X for (i = 0; i < 32; i++)
X {
X tmpP32[i] = tmp32[P[i]];
X }
X for (i = 0; i < 48; i++)
X {
X tmpE[i] = tmpP32[E[i]];
X }
X
X lowptr[j] = 0;
X highptr[j] = 0;
X
X for (i = 0; i < 24; i++)
X {
X lowptr[j] |= tmpE[i] << i;
X }
X for (k = 0, i = 24; i < 48; i++, k++)
X {
X highptr[j] |= tmpE[i] << k;
X }
X
X spare24 = lowptr[j]; /* to allow for macro expansion */
X lowptr[j] = TF_TO_SIXBIT (spare24);
X spare24 = highptr[j]; /* to allow for macro expansion */
X highptr[j] = TF_TO_SIXBIT (spare24);
X }
X}
Xinit_des ()
X{
X init (0, S0L, S0H);
X init (1, S1L, S1H);
X init (2, S2L, S2H);
X init (3, S3L, S3H);
X init (4, S4L, S4H);
X init (5, S5L, S5H);
X init (6, S6L, S6H);
X init (7, S7L, S7H);
X}
END_OF_FILE
if test 24641 -ne `wc -c <'Sources/crack-fcrypt.c'`; then
echo shar: \"'Sources/crack-fcrypt.c'\" unpacked with wrong size!
fi
# end of 'Sources/crack-fcrypt.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 4 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
exit 0 # Just in case...