Newsgroups: comp.sources.misc From: Alec David Muffett 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 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 '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." Xor X.C "point.." 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...