home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume10 / des < prev    next >
Text File  |  1993-07-19  |  43KB  |  1,792 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i031: DES encryption routines and a login front-end
  5. Message-ID: <523@uunet.UU.NET>
  6. Date: 2 Jul 87 03:04:55 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1781
  9. Approved: rs@uunet.uu.net
  10.  
  11. Mod.Sources: Volume 10, Number 31
  12. Submitted by: Bdale Garbee <winfree!bdale>
  13. Archive-name: des
  14.  
  15. [  Those of you who have a copy of the Volume 6 posting should consider
  16.    this a replacement for it.  Those of you concerned about the legality
  17.    of posting this, don't be --r$  ]
  18.  
  19. Rich - Here is an updated copy of the DES routines shar file.  Phil found
  20. and fixed a bug in the main.c module that caused the DES program to
  21. occasionally mutilate keys resulting in un-decodable files.  He also has
  22. now included uuencode and uudecode routines, which are helpful for creating
  23. filters into and out of mail systems... since many mailers don't deal with
  24. 8-bit data.
  25.  
  26. Regards,
  27.  
  28. Bdale Garbee, N3EUA        phone: 303/593-9828 h, 303/590-2868 w
  29. uucp: {bellcore,crash,hp-lsd,hpcsma,ncc,pitt,usafa,vixie}!winfree!bdale
  30. fido: sysop of 128/19        packet: n3eua @ k0hoa, Colorado Springs
  31.  
  32. - - - - - - - - - -
  33. #!/bin/sh
  34. # to extract, remove the header and type "sh filename"
  35. if `test ! -s ./Makefile`
  36. then
  37. echo "writing ./Makefile"
  38. cat > ./Makefile << '\SHAR\EOF\'
  39. CFLAGS=-O -DLITTLE_ENDIAN
  40. all: descalc descycle descert certify radlogin benchmark des uuencode uudecode
  41.  
  42. des: main.o des.o getpass.o misc.o
  43.     cc -o des main.o des.o getpass.o misc.o
  44.  
  45. benchmark: benchmark.o des.o
  46.     cc -o benchmark benchmark.o des.o
  47.  
  48. radlogin: radlogin.o des.o
  49.     cc -o radlogin radlogin.o des.o
  50.  
  51. descert: descert.o des.o
  52.     cc -o descert descert.o des.o
  53.  
  54. descalc: descalc.o des.o
  55.     cc -o descalc descalc.o des.o
  56.  
  57. descycle: descycle.o des.o
  58.     cc -o descycle descycle.o des.o
  59.  
  60. certify: descert testdata
  61.     descert < testdata
  62.     touch certify
  63.  
  64. radlogin.o: radlogin.c
  65.     cc -c -O -DUTMP_FILE=\"/etc/utmp\" radlogin.c
  66.  
  67. uuencode: uuencode.o
  68.     cc -o uuencode uuencode.o
  69.  
  70. uudecode: uudecode.o
  71.     cc -o uudecode uudecode.o
  72.  
  73. clean:
  74.     rm -f descalc descycle descert certify radlogin benchmark des *.o
  75.     rm -f uuencode uudecode
  76. \SHAR\EOF\
  77. else
  78.   echo "will not over write ./Makefile"
  79. fi
  80. if `test ! -s ./README`
  81. then
  82. echo "writing ./README"
  83. cat > ./README << '\SHAR\EOF\'
  84. Late breaking news:
  85.     Versions of uuencode and uudecode now included, which are helpful
  86.     for using this package to send/receive encrypted mail.
  87.  
  88. Phil asked me to clean this up slightly and package it for distribution.
  89. I've got it running on my Symmetric 4.2bsd system, Phil reports it runs fine
  90. on a variety of systems at Bellcore.  Note that getopt is required but not
  91. provided, as there is already a getopt package in the mod.sources archives.
  92.  
  93. Bdale Garbee, N3EUA  870401    
  94. winfree!bdale aka bdale%winfree.uucp@flash.bellcore.com
  95.  
  96. - - - - -
  97.  
  98. This package contains a DES subroutine library based on the original public
  99. domain code by James Gillogly, but made faster and more flexible. Commands
  100. using this library have been added for testing and for encrypting and
  101. decrypting files (compatible with the DES command under Sun UNIX), among
  102. other things.
  103.  
  104. Run make. That will compile everything and run test data (from the NBS
  105. certification suite) through it.  It runs as-is under UNIX. It will run
  106. under MS-DOS with a few minor changes: make sure you define LITTLE_ENDIAN
  107. when compiling des.c, and change the name of the console in getpass.c.  If
  108. you have the byte order flag set wrong, you will get ENCRYPT FAIL messages
  109. when the descert test is run.
  110.  
  111. radlogin.c is an experimental program for secure UNIX login via insecure
  112. channels (like amateur packet radio). Make it and set it up as the login
  113. shell for a special, password-free login (e.g., "radio"). When it starts the
  114. user will be asked his REAL login name, which is then looked up in
  115. /etc/rkeys. (This file must be read protected since it contains DES keys).
  116. The time of day is then printed in hex as a challenge. The user must encrypt
  117. it using DES and his key and type the answer back.  The user may use the
  118. program "descalc" to perform his local calculation. All this is very clumsy;
  119. it works, but after all it's only experimental.
  120.  
  121. Phil Karn, KA9Q
  122. bellcore!karn aka karn@flash.bellcore.com
  123.  
  124. - - - - -
  125. Subject: Re:  rkeys file
  126.  
  127. rkeys:
  128. karn 0123456789abcdef
  129. uid  des_key_in_hex
  130.  
  131. - - - - -
  132. \SHAR\EOF\
  133. else
  134.   echo "will not over write ./README"
  135. fi
  136. if `test ! -s ./benchmark.c`
  137. then
  138. echo "writing ./benchmark.c"
  139. cat > ./benchmark.c << '\SHAR\EOF\'
  140. /* Just run DES in a loop consuming CPU time; good for benchmarking
  141.  * Phil Karn
  142.  */
  143. #include <stdio.h>
  144. main()
  145. {
  146.     char key[8],work[8];
  147.     long iter,count;
  148.  
  149.     desinit(0);
  150.     printf("Enter key: ");
  151.     get8(key);
  152.     printf("Setting key: "); put8(key); printf("\n");
  153.     setkey(key);
  154.     printf("Enter starting value: ");
  155.     get8(work);
  156.     printf("Starting value: "); put8(work); printf("\n");
  157.     printf("Number of iterations: ");
  158.     scanf("%ld",&count);
  159.  
  160.     for(iter = 0;iter < count; iter++)
  161.         endes(work);
  162. }
  163. get8(cp)
  164. char *cp;
  165. {
  166.     int i,t;
  167.  
  168.     for(i=0;i<8;i++){
  169.         scanf("%2x",&t);
  170.         *cp++ = t;
  171.     }
  172. }
  173. put8(cp)
  174. char *cp;
  175. {
  176.     int i;
  177.  
  178.     for(i=0;i<8;i++){
  179.         printf("%2x ",*cp++ & 0xff);
  180.     }
  181. }
  182. \SHAR\EOF\
  183. else
  184.   echo "will not over write ./benchmark.c"
  185. fi
  186. if `test ! -s ./des.1`
  187. then
  188. echo "writing ./des.1"
  189. cat > ./des.1 << '\SHAR\EOF\'
  190. .TH DES 1  "24 March 1987"
  191. .SH NAME
  192. des - DES file encryption
  193. .SH SYNOPSIS
  194. .PP
  195. .B des -e|-d [-h] [-k key] [-b]
  196. .SH DESCRIPTION
  197. .B des
  198. is a filter that encrypts or decrypts standard input to standard output
  199. with the Data Encryption Standard (DES).
  200. Either -e (encrypt) or -d (decrypt) must be specified. If the key is not
  201. given on the command line with the -k option the command will prompt for it
  202. twice, suppressing echo and comparing the two responses to guard against
  203. mistyping.
  204. .P
  205. The -h flag controls how the key string is to be interpreted.
  206. Without the -h flag, the key is an ASCII string.
  207. Since DES ignores the low
  208. order bit of each key byte, the
  209. high order bit is set for odd parity, thus retaining the information contained
  210. in the low order bit.
  211. If the -h flag is set, the key string is interpreted as
  212. 16 hex/ASCII characters; the low order bit of each byte is again ignored as per
  213. the DES algorithm.
  214. This allows the use of any arbitrary 56-bit key, including bytes representing
  215. control characters that could not be typed if the -h option were not used.
  216. .PP
  217. By default, DES Cipher Block Chaining (CBC) mode is used, with an initial
  218. vector (IV) of all zeros; if the -b option is specified, Electronic Code
  219. Book (ECB) mode is used instead.
  220. .PP
  221. Except for the -h option, this command is compatible with the
  222. .B des
  223. command on the Sun Microsystems workstation.
  224. .SH "SEE ALSO"
  225. Sun Microsystems DES(1) manual page, which describes in detail how
  226. the length of the file is encoded in the last block of ciphertext.
  227. .SH AUTHOR
  228. Phil Karn, KA9Q
  229. \SHAR\EOF\
  230. else
  231.   echo "will not over write ./des.1"
  232. fi
  233. if `test ! -s ./des.3`
  234. then
  235. echo "writing ./des.3"
  236. cat > ./des.3 << '\SHAR\EOF\'
  237. .TH DES 3  "24 March 1987"
  238. .SH NAME
  239. desinit, setkey, endes, dedes, desdone - DES encryption
  240. .SH SYNOPSIS
  241. .PP
  242. .B desinit(mode)
  243. .B int mode;
  244. .PP
  245. .B setkey(key)
  246. .B char *key;
  247. .PP
  248. .B endes(block)
  249. .B char *block;
  250. .PP
  251. .B dedes(block)
  252. .B char *block;
  253. .PP
  254. .B desdone()
  255. .SH DESCRIPTION
  256. These routines implement both standard and modified forms of the NBS Data
  257. Encryption Standard (DES). The user must first call
  258. .B desinit
  259. with one of three operating modes:
  260. .PP
  261. 0 - Standard, vanilla DES.
  262. .PP
  263. 1 - DES with the initial and final permutations removed.
  264. As these permutations do not strengthen the algorithm,
  265. they are widely regarded as having no purpose other than to slow
  266. down software implementations.
  267. Removing them speeds it up but of course the algorithm is no longer standard
  268. and it will not be compatible with hardware DES chips.
  269. .PP
  270. 2 - DES with the initial and final permutations removed, and with independent
  271. 48-bit subkeys for each of the 16 rounds. Needless to say this is even
  272. less standard than mode 1, but if properly used (randomize ALL key bytes --
  273. no padding!) it should strengthen the algorithm.
  274. .PP
  275. After calling
  276. .B desinit
  277. the user next calls
  278. .B setkey.
  279. In modes 0 and 1, 8 key bytes are expected, with the low order bit of
  280. each key byte ignored (parity is not checked). This gives a 56-bit key.
  281. In mode 2, 128 key bytes are expected; the high order 2 bits of each byte are
  282. ignored, giving a 768 bit key.
  283. In this mode, the first 8 bytes will be used in the first round, the
  284. second 8 bytes in the second round, and so on.
  285. .PP
  286. Once the key is set, the user may perform in-place encryption and decryption
  287. of 8-byte blocks of data with calls to
  288. .B endes
  289. and
  290. .B dedes.
  291. .PP
  292. To free up memory dynamically allocated by
  293. .B desinit
  294. the user may call
  295. .B desdone.
  296. If further encryption or decryption is to be done,
  297. .B desinit
  298. and
  299. .B setkey
  300. must be called again.
  301. .SH AUTHOR
  302. Phil Karn, KA9Q, building heavily on the earlier public domain code
  303. by Jim Gillogly.
  304.  
  305.  
  306. \SHAR\EOF\
  307. else
  308.   echo "will not over write ./des.3"
  309. fi
  310. if `test ! -s ./des.c`
  311. then
  312. echo "writing ./des.c"
  313. cat > ./des.c << '\SHAR\EOF\'
  314. /* Sofware DES functions
  315.  * written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted from
  316.  * the 1977 public-domain program by Jim Gillogly
  317.  */
  318. #define    NULL    0
  319.  
  320. #ifdef    LITTLE_ENDIAN
  321. unsigned long byteswap();
  322. #endif
  323.  
  324. /* Tables defined in the Data Encryption Standard documents */
  325.  
  326. /* initial permutation IP */
  327. static char ip[] = {
  328.     58, 50, 42, 34, 26, 18, 10,  2,
  329.     60, 52, 44, 36, 28, 20, 12,  4,
  330.     62, 54, 46, 38, 30, 22, 14,  6,
  331.     64, 56, 48, 40, 32, 24, 16,  8,
  332.     57, 49, 41, 33, 25, 17,  9,  1,
  333.     59, 51, 43, 35, 27, 19, 11,  3,
  334.     61, 53, 45, 37, 29, 21, 13,  5,
  335.     63, 55, 47, 39, 31, 23, 15,  7
  336. };
  337.  
  338. /* final permutation IP^-1 */
  339. static char fp[] = {
  340.     40,  8, 48, 16, 56, 24, 64, 32,
  341.     39,  7, 47, 15, 55, 23, 63, 31,
  342.     38,  6, 46, 14, 54, 22, 62, 30,
  343.     37,  5, 45, 13, 53, 21, 61, 29,
  344.     36,  4, 44, 12, 52, 20, 60, 28,
  345.     35,  3, 43, 11, 51, 19, 59, 27,
  346.     34,  2, 42, 10, 50, 18, 58, 26,
  347.     33,  1, 41,  9, 49, 17, 57, 25
  348. };
  349.  
  350. /* expansion operation matrix
  351.  * This is for reference only; it is unused in the code
  352.  * as the f() function performs it implicitly for speed
  353.  */
  354. #ifdef notdef
  355. static char ei[] = {
  356.     32,  1,  2,  3,  4,  5,
  357.      4,  5,  6,  7,  8,  9,
  358.      8,  9, 10, 11, 12, 13,
  359.     12, 13, 14, 15, 16, 17,
  360.     16, 17, 18, 19, 20, 21,
  361.     20, 21, 22, 23, 24, 25,
  362.     24, 25, 26, 27, 28, 29,
  363.     28, 29, 30, 31, 32,  1 
  364. };
  365. #endif
  366.  
  367. /* permuted choice table (key) */
  368. static char pc1[] = {
  369.     57, 49, 41, 33, 25, 17,  9,
  370.      1, 58, 50, 42, 34, 26, 18,
  371.     10,  2, 59, 51, 43, 35, 27,
  372.     19, 11,  3, 60, 52, 44, 36,
  373.  
  374.     63, 55, 47, 39, 31, 23, 15,
  375.      7, 62, 54, 46, 38, 30, 22,
  376.     14,  6, 61, 53, 45, 37, 29,
  377.     21, 13,  5, 28, 20, 12,  4
  378. };
  379.  
  380. /* number left rotations of pc1 */
  381. static char totrot[] = {
  382.     1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
  383. };
  384.  
  385. /* permuted choice key (table) */
  386. static char pc2[] = {
  387.     14, 17, 11, 24,  1,  5,
  388.      3, 28, 15,  6, 21, 10,
  389.     23, 19, 12,  4, 26,  8,
  390.     16,  7, 27, 20, 13,  2,
  391.     41, 52, 31, 37, 47, 55,
  392.     30, 40, 51, 45, 33, 48,
  393.     44, 49, 39, 56, 34, 53,
  394.     46, 42, 50, 36, 29, 32
  395. };
  396.  
  397. /* The (in)famous S-boxes */
  398. static char si[8][64] = {
  399.     /* S1 */
  400.     14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
  401.      0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
  402.      4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
  403.     15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
  404.  
  405.     /* S2 */
  406.     15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
  407.      3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
  408.      0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
  409.     13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
  410.  
  411.     /* S3 */
  412.     10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
  413.     13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
  414.     13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
  415.      1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
  416.  
  417.     /* S4 */
  418.      7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
  419.     13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
  420.     10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
  421.      3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
  422.  
  423.     /* S5 */
  424.      2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
  425.     14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
  426.      4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
  427.     11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
  428.  
  429.     /* S6 */
  430.     12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
  431.     10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
  432.      9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
  433.      4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
  434.  
  435.     /* S7 */
  436.      4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
  437.     13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
  438.      1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
  439.      6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
  440.  
  441.     /* S8 */
  442.     13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
  443.      1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
  444.      7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
  445.      2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
  446. };
  447.  
  448. /* 32-bit permutation function P used on the output of the S-boxes */
  449. static char p32i[] = {    
  450.     16,  7, 20, 21,
  451.     29, 12, 28, 17,
  452.      1, 15, 23, 26,
  453.      5, 18, 31, 10,
  454.      2,  8, 24, 14,
  455.     32, 27,  3,  9,
  456.     19, 13, 30,  6,
  457.     22, 11,  4, 25
  458. };
  459. /* End of DES-defined tables */
  460.  
  461. /* Lookup tables initialized once only at startup by desinit() */
  462. static long (*sp)[64];        /* Combined S and P boxes */
  463.  
  464. static char (*iperm)[16][8];    /* Initial and final permutations */
  465. static char (*fperm)[16][8];
  466.  
  467. /* 8 6-bit subkeys for each of 16 rounds, initialized by setkey() */
  468. static unsigned char (*kn)[8];
  469.  
  470. /* bit 0 is left-most in byte */
  471. static int bytebit[] = {
  472.     0200,0100,040,020,010,04,02,01
  473. };
  474.  
  475. static int nibblebit[] = {
  476.      010,04,02,01
  477. };
  478. static int desmode;
  479.  
  480. /* Allocate space and initialize DES lookup arrays
  481.  * mode == 0: standard Data Encryption Algorithm
  482.  * mode == 1: DEA without initial and final permutations for speed
  483.  * mode == 2: DEA without permutations and with 128-byte key (completely
  484.  *            independent subkeys for each round)
  485.  */
  486. desinit(mode)
  487. int mode;
  488. {
  489.     char *malloc();
  490.  
  491.     if(sp != NULL){
  492.         /* Already initialized */
  493.         return 0;
  494.     }
  495.     desmode = mode;
  496.     
  497.     if((sp = (long (*)[64])malloc(sizeof(long) * 8 * 64)) == NULL){
  498.         return -1;
  499.     }
  500.     spinit();
  501.     kn = (unsigned char (*)[8])malloc(sizeof(char) * 8 * 16);
  502.     if(kn == NULL){
  503.         free((char *)sp);
  504.         return -1;
  505.     }
  506.     if(mode == 1 || mode == 2)    /* No permutations */
  507.         return 0;
  508.  
  509.     iperm = (char (*)[16][8])malloc(sizeof(char) * 16 * 16 * 8);
  510.     if(iperm == NULL){
  511.         free((char *)sp);
  512.         free((char *)kn);
  513.         return -1;
  514.     }
  515.     perminit(iperm,ip);
  516.  
  517.     fperm = (char (*)[16][8])malloc(sizeof(char) * 16 * 16 * 8);
  518.     if(fperm == NULL){
  519.         free((char *)sp);
  520.         free((char *)kn);
  521.         free((char *)iperm);
  522.         return -1;
  523.     }
  524.     perminit(fperm,fp);
  525.     
  526.     return 0;
  527. }
  528. /* Free up storage used by DES */
  529. desdone()
  530. {
  531.     if(sp == NULL)
  532.         return;    /* Already done */
  533.  
  534.     free((char *)sp);
  535.     free((char *)kn);
  536.     if(iperm != NULL)
  537.         free((char *)iperm);
  538.     if(fperm != NULL)
  539.         free((char *)fperm);
  540.  
  541.     sp = NULL;
  542.     iperm = NULL;
  543.     fperm = NULL;
  544.     kn = NULL;
  545. }
  546. /* Set key (initialize key schedule array) */
  547. setkey(key)
  548. char *key;            /* 64 bits (will use only 56) */
  549. {
  550.     char pc1m[56];        /* place to modify pc1 into */
  551.     char pcr[56];        /* place to rotate pc1 into */
  552.     register int i,j,l;
  553.     int m;
  554.  
  555.     /* In mode 2, the 128 bytes of subkey are set directly from the
  556.      * user's key, allowing him to use completely independent
  557.      * subkeys for each round. Note that the user MUST specify a
  558.      * full 128 bytes.
  559.      *
  560.      * I would like to think that this technique gives the NSA a real
  561.      * headache, but I'm not THAT naive.
  562.      */
  563.     if(desmode == 2){
  564.         for(i=0;i<16;i++)
  565.             for(j=0;j<8;j++)
  566.                 kn[i][j] = *key++;
  567.         return;
  568.     }
  569.     /* Clear key schedule */
  570.     for (i=0; i<16; i++)
  571.         for (j=0; j<8; j++)
  572.             kn[i][j]=0;
  573.  
  574.     for (j=0; j<56; j++) {        /* convert pc1 to bits of key */
  575.         l=pc1[j]-1;        /* integer bit location     */
  576.         m = l & 07;        /* find bit         */
  577.         pc1m[j]=(key[l>>3] &    /* find which key byte l is in */
  578.             bytebit[m])    /* and which bit of that byte */
  579.             ? 1 : 0;    /* and store 1-bit result */
  580.     }
  581.     for (i=0; i<16; i++) {        /* key chunk for each iteration */
  582.         for (j=0; j<56; j++)    /* rotate pc1 the right amount */
  583.             pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
  584.             /* rotate left and right halves independently */
  585.         for (j=0; j<48; j++){    /* select bits individually */
  586.             /* check bit that goes to kn[j] */
  587.             if (pcr[pc2[j]-1]){
  588.                 /* mask it in if it's there */
  589.                 l= j % 6;
  590.                 kn[i][j/6] |= bytebit[l] >> 2;
  591.             }
  592.         }
  593.     }
  594. }
  595. /* In-place encryption of 64-bit block */
  596. endes(block)
  597. char *block;
  598. {
  599.     register int i;
  600.     unsigned long work[2];         /* Working data storage */
  601.     long tmp;
  602.  
  603.     permute(block,iperm,(char *)work);    /* Initial Permutation */
  604. #ifdef LITTLE_ENDIAN
  605.     work[0] = byteswap(work[0]);
  606.     work[1] = byteswap(work[1]);
  607. #endif
  608.  
  609.     /* Do the 16 rounds */
  610.     for (i=0; i<16; i++)
  611.         round(i,work);
  612.  
  613.     /* Left/right half swap */
  614.     tmp = work[0];
  615.     work[0] = work[1];    
  616.     work[1] = tmp;
  617.  
  618. #ifdef LITTLE_ENDIAN
  619.     work[0] = byteswap(work[0]);
  620.     work[1] = byteswap(work[1]);
  621. #endif
  622.     permute((char *)work,fperm,block);    /* Inverse initial permutation */
  623. }
  624. /* In-place decryption of 64-bit block */
  625. dedes(block)
  626. char *block;
  627. {
  628.     register int i;
  629.     unsigned long work[2];    /* Working data storage */
  630.     long tmp;
  631.  
  632.     permute(block,iperm,(char *)work);    /* Initial permutation */
  633.  
  634. #ifdef LITTLE_ENDIAN
  635.     work[0] = byteswap(work[0]);
  636.     work[1] = byteswap(work[1]);
  637. #endif
  638.  
  639.     /* Left/right half swap */
  640.     tmp = work[0];
  641.     work[0] = work[1];    
  642.     work[1] = tmp;
  643.  
  644.     /* Do the 16 rounds in reverse order */
  645.     for (i=15; i >= 0; i--)
  646.         round(i,work);
  647.  
  648. #ifdef LITTLE_ENDIAN
  649.     work[0] = byteswap(work[0]);
  650.     work[1] = byteswap(work[1]);
  651. #endif
  652.  
  653.     permute((char *)work,fperm,block);    /* Inverse initial permutation */
  654. }
  655.  
  656. /* Permute inblock with perm */
  657. static
  658. permute(inblock,perm,outblock)
  659. char *inblock, *outblock;        /* result into outblock,64 bits */
  660. char perm[16][16][8];            /* 2K bytes defining perm. */
  661. {
  662.     register int i,j;
  663.     register char *ib, *ob;        /* ptr to input or output block */
  664.     register char *p, *q;
  665.  
  666.     if(perm == NULL){
  667.         /* No permutation, just copy */
  668.         for(i=8; i!=0; i--)
  669.             *outblock++ = *inblock++;
  670.         return;
  671.     }
  672.     /* Clear output block     */
  673.     for (i=8, ob = outblock; i != 0; i--)
  674.         *ob++ = 0;
  675.  
  676.     ib = inblock;
  677.     for (j = 0; j < 16; j += 2, ib++) { /* for each input nibble */
  678.         ob = outblock;
  679.         p = perm[j][(*ib >> 4) & 017];
  680.         q = perm[j + 1][*ib & 017];
  681.         for (i = 8; i != 0; i--){   /* and each output byte */
  682.             *ob++ |= *p++ | *q++;    /* OR the masks together*/
  683.         }
  684.     }
  685. }
  686.  
  687. /* Do one DES cipher round */
  688. static
  689. round(num,block)
  690. int num;                /* i.e. the num-th one     */
  691. unsigned long *block;
  692. {
  693.     long f();
  694.  
  695.     /* The rounds are numbered from 0 to 15. On even rounds
  696.      * the right half is fed to f() and the result exclusive-ORs
  697.      * the left half; on odd rounds the reverse is done.
  698.      */
  699.     if(num & 1){
  700.         block[1] ^= f(block[0],kn[num]);
  701.     } else {
  702.         block[0] ^= f(block[1],kn[num]);
  703.     }
  704. }
  705. /* The nonlinear function f(r,k), the heart of DES */
  706. static
  707. long
  708. f(r,subkey)
  709. unsigned long r;        /* 32 bits */
  710. unsigned char subkey[8];    /* 48-bit key for this round */
  711. {
  712.     register unsigned long rval,rt;
  713. #ifdef    TRACE
  714.     unsigned char *cp;
  715.     int i;
  716.  
  717.     printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ",
  718.         r,
  719.         subkey[0], subkey[1], subkey[2],
  720.         subkey[3], subkey[4], subkey[5],
  721.         subkey[6], subkey[7]);
  722. #endif
  723.     /* Run E(R) ^ K through the combined S & P boxes
  724.      * This code takes advantage of a convenient regularity in
  725.      * E, namely that each group of 6 bits in E(R) feeding
  726.      * a single S-box is a contiguous segment of R.
  727.      */
  728.     rt = (r >> 1) | ((r & 1) ? 0x80000000 : 0);
  729.     rval = 0;
  730.     rval |= sp[0][((rt >> 26) ^ *subkey++) & 0x3f];
  731.     rval |= sp[1][((rt >> 22) ^ *subkey++) & 0x3f];
  732.     rval |= sp[2][((rt >> 18) ^ *subkey++) & 0x3f];
  733.     rval |= sp[3][((rt >> 14) ^ *subkey++) & 0x3f];
  734.     rval |= sp[4][((rt >> 10) ^ *subkey++) & 0x3f];
  735.     rval |= sp[5][((rt >> 6) ^ *subkey++) & 0x3f];
  736.     rval |= sp[6][((rt >> 2) ^ *subkey++) & 0x3f];
  737.     rt = (r << 1) | ((r & 0x80000000) ? 1 : 0);
  738.     rval |= sp[7][(rt ^ *subkey) & 0x3f];
  739. #ifdef    TRACE
  740.     printf(" %08lx\n",rval);
  741. #endif
  742.     return rval;
  743. }
  744. /* initialize a perm array */
  745. static
  746. perminit(perm,p)
  747. char perm[16][16][8];            /* 64-bit, either init or final */
  748. char p[64];
  749. {
  750.     register int l, j, k;
  751.     int i,m;
  752.  
  753.     /* Clear the permutation array */
  754.     for (i=0; i<16; i++)
  755.         for (j=0; j<16; j++)
  756.             for (k=0; k<8; k++)
  757.                 perm[i][j][k]=0;
  758.  
  759.     for (i=0; i<16; i++)        /* each input nibble position */
  760.         for (j = 0; j < 16; j++)/* each possible input nibble */
  761.         for (k = 0; k < 64; k++)/* each output bit position */
  762.         {   l = p[k] - 1;    /* where does this bit come from*/
  763.             if ((l >> 2) != i)  /* does it come from input posn?*/
  764.             continue;    /* if not, bit k is 0     */
  765.             if (!(j & nibblebit[l & 3]))
  766.             continue;    /* any such bit in input? */
  767.             m = k & 07;    /* which bit is this in the byte*/
  768.             perm[i][j][k>>3] |= bytebit[m];
  769.         }
  770. }
  771.  
  772. /* Initialize the lookup table for the combined S and P boxes */
  773. static int
  774. spinit()
  775. {
  776.     char pbox[32];
  777.     int p,i,s,j,rowcol;
  778.     long val;
  779.  
  780.     /* Compute pbox, the inverse of p32i.
  781.      * This is easier to work with
  782.      */
  783.     for(p=0;p<32;p++){
  784.         for(i=0;i<32;i++){
  785.             if(p32i[i]-1 == p){
  786.                 pbox[p] = i;
  787.                 break;
  788.             }
  789.         }
  790.     }
  791.     for(s = 0; s < 8; s++){            /* For each S-box */
  792.         for(i=0; i<64; i++){        /* For each possible input */
  793.             val = 0;
  794.             /* The row number is formed from the first and last
  795.              * bits; the column number is from the middle 4
  796.              */
  797.             rowcol = (i & 32) | ((i & 1) ? 16 : 0) | ((i >> 1) & 0xf);
  798.             for(j=0;j<4;j++){    /* For each output bit */
  799.                 if(si[s][rowcol] & (8 >> j)){
  800.                  val |= 1L << (31 - pbox[4*s + j]);
  801.                 }
  802.             }
  803.             sp[s][i] = val;
  804.  
  805. #ifdef    DEBUG
  806.             printf("sp[%d][%2d] = %08lx\n",s,i,sp[s][i]);
  807. #endif
  808.         }
  809.     }
  810. }
  811. #ifdef    LITTLE_ENDIAN
  812. /* Byte swap a long */
  813. static
  814. unsigned long
  815. byteswap(x)
  816. unsigned long x;
  817. {
  818.     register char *cp,tmp;
  819.  
  820.     cp = (char *)&x;
  821.     tmp = cp[3];
  822.     cp[3] = cp[0];
  823.     cp[0] = tmp;
  824.  
  825.     tmp = cp[2];
  826.     cp[2] = cp[1];
  827.     cp[1] = tmp;
  828.  
  829.     return x;
  830. }
  831. #endif
  832. \SHAR\EOF\
  833. else
  834.   echo "will not over write ./des.c"
  835. fi
  836. if `test ! -s ./descalc.c`
  837. then
  838. echo "writing ./descalc.c"
  839. cat > ./descalc.c << '\SHAR\EOF\'
  840. /* DES "desk calculator"
  841.  * Phil Karn
  842.  * January 1987
  843.  */
  844. #include <stdio.h>
  845. #include <ctype.h>
  846. main()
  847. {
  848.     char key[8],work[8];
  849.     char line[80];
  850.     int keyset = 0;
  851.  
  852.     if(desinit(0) == -1){
  853.         printf("DES initialization failed\n");
  854.         exit(1);
  855.     }
  856.     printf("Enter in hexadecimal:\nk <key>\np <plaintext>\nc <ciphertext>\n");
  857.     printf("s - standard DES mode\n");
  858.     printf("f - fast mode (no IP)\n"); 
  859.     for(;;){
  860.         gets(line);
  861.         if(feof(stdin))
  862.             break;
  863.         if(isupper(line[0]))
  864.             line[0] = tolower(line[0]);
  865.         switch(line[0]){
  866.         case 's':
  867.             desdone();
  868.             desinit(0);
  869.             if(keyset)
  870.                 setkey(key);
  871.             break;
  872.         case 'f':
  873.             desdone();
  874.             desinit(1);
  875.             if(keyset)
  876.                 setkey(key);
  877.             break;
  878.         case 'k':    /* Set key */
  879.             get8(&line[1],key);
  880.             setkey(key);
  881.             keyset = 1;
  882.             break;
  883.         case 'c':    /* Decrypt ciphertext */
  884.             if(!keyset){
  885.                 printf("Enter key\n");
  886.                 break;
  887.             }
  888.             get8(&line[1],work);
  889.             dedes(work);
  890.             printf("Plaintext: ");
  891.             put8(work);
  892.             printf("\n");
  893.             break;
  894.         case 'p':    /* Encrypt plaintext */
  895.             if(!keyset){
  896.                 printf("Enter key\n");
  897.                 break;
  898.             }
  899.             get8(&line[1],work);
  900.             endes(work);
  901.             printf("Ciphertext: ");
  902.             put8(work);
  903.             printf("\n");
  904.             break;
  905.         default:
  906.             printf("eh?\n");
  907.             break;
  908.         }
  909.     }
  910. }
  911. get8(buf,cp)
  912. char *buf;
  913. register char *cp;
  914. {
  915.     int ikey[8],i;
  916.  
  917.     sscanf(buf,"%2x%2x%2x%2x%2x%2x%2x%2x",&ikey[0],&ikey[1],&ikey[2],
  918.         &ikey[3],&ikey[4],&ikey[5],&ikey[6],&ikey[7]);
  919.     for(i=0;i<8;i++)
  920.         *cp++ = ikey[i];
  921. }
  922. put8(cp)
  923. register char *cp;
  924. {
  925.     int i;
  926.  
  927.     for(i=0;i<8;i++){
  928.         printf("%02x ",*cp++ & 0xff);
  929.     }
  930. }
  931. \SHAR\EOF\
  932. else
  933.   echo "will not over write ./descalc.c"
  934. fi
  935. if `test ! -s ./descert.c`
  936. then
  937. echo "writing ./descert.c"
  938. cat > ./descert.c << '\SHAR\EOF\'
  939. #include <stdio.h>
  940. main()
  941. {
  942.     char key[8],plain[8],cipher[8],answer[8];
  943.     int i;
  944.     int test;
  945.     int fail;
  946.  
  947.     desinit(0);
  948.  
  949.     for(test=0;!feof(stdin);test++){
  950.  
  951.         get8(key);
  952.         printf(" K: "); put8(key);
  953.         setkey(key);
  954.  
  955.         get8(plain);
  956.         printf(" P: "); put8(plain);
  957.  
  958.         get8(answer);
  959.         printf(" C: "); put8(answer);
  960.  
  961.         for(i=0;i<8;i++)
  962.             cipher[i] = plain[i];
  963.         endes(cipher);
  964.  
  965.         for(i=0;i<8;i++)
  966.             if(cipher[i] != answer[i])
  967.                 break;
  968.         fail = 0;
  969.         if(i != 8){
  970.             printf(" Encrypt FAIL");
  971.             fail++;
  972.         }
  973.         dedes(cipher);
  974.         for(i=0;i<8;i++)
  975.             if(cipher[i] != plain[i])
  976.                 break;
  977.         if(i != 8){
  978.             printf(" Decrypt FAIL");
  979.             fail++;
  980.         }
  981.         if(fail == 0)
  982.             printf(" OK");
  983.         printf("\n");
  984.     }
  985. }
  986. get8(cp)
  987. char *cp;
  988. {
  989.     int i,t;
  990.  
  991.     for(i=0;i<8;i++){
  992.         scanf("%2x",&t);
  993.         if(feof(stdin))
  994.             exit(0);
  995.         *cp++ = t;
  996.     }
  997. }
  998. put8(cp)
  999. char *cp;
  1000. {
  1001.     int i;
  1002.  
  1003.     for(i=0;i<8;i++){
  1004.         printf("%02x",*cp++ & 0xff);
  1005.     }
  1006. }
  1007. \SHAR\EOF\
  1008. else
  1009.   echo "will not over write ./descert.c"
  1010. fi
  1011. if `test ! -s ./descycle.c`
  1012. then
  1013. echo "writing ./descycle.c"
  1014. cat > ./descycle.c << '\SHAR\EOF\'
  1015. /* Investigate cycles in DES output feedback mode (experimental)
  1016.  * Phil Karn
  1017.  */
  1018. #include <stdio.h>
  1019. main()
  1020. {
  1021.     char key[8],start[8],work[8];
  1022.     long update;
  1023.     register int i;
  1024.     long iter;
  1025.  
  1026.     desinit(0);
  1027.     printf("Enter key: ");
  1028.     get8(key);
  1029.     printf("Setting key: "); put8(key); printf("\n");
  1030.     setkey(key);
  1031.     printf("Enter starting value: ");
  1032.     get8(start);
  1033.     printf("Starting value: "); put8(start); printf("\n");
  1034.     printf("Update interval: ");
  1035.     scanf("%ld",&update);
  1036.  
  1037.     for(i=0;i<8;i++)
  1038.         work[i] = start[i];
  1039.  
  1040.     for(iter = 0;; iter++){
  1041.  
  1042.         endes(work);
  1043.         if((iter % update) == 0){
  1044.             printf("%ld ",iter);
  1045.             put8(work); printf("\n");
  1046.         }
  1047.         for(i=0;i<8;i++){
  1048.             if(work[i] != start[i])
  1049.                 break;
  1050.         }
  1051.         if(i == 8){
  1052.             printf("CYCLE FOUND after %ld iterations\n",iter);
  1053.             exit(0);
  1054.         }
  1055.     }
  1056. }
  1057. get8(cp)
  1058. char *cp;
  1059. {
  1060.     int i,t;
  1061.  
  1062.     for(i=0;i<8;i++){
  1063.         scanf("%2x",&t);
  1064.         *cp++ = t;
  1065.     }
  1066. }
  1067. put8(cp)
  1068. char *cp;
  1069. {
  1070.     int i;
  1071.  
  1072.     for(i=0;i<8;i++){
  1073.         printf("%2x ",*cp++ & 0xff);
  1074.     }
  1075. }
  1076. \SHAR\EOF\
  1077. else
  1078.   echo "will not over write ./descycle.c"
  1079. fi
  1080. if `test ! -s ./getopt.c`
  1081. then
  1082. echo "writing ./getopt.c"
  1083. cat > ./getopt.c << '\SHAR\EOF\'
  1084. /* got this off net.sources */
  1085. #include <stdio.h>
  1086.  
  1087. /*
  1088.  * get option letter from argument vector
  1089.  */
  1090. int    opterr = 1,        /* useless, never set or used */
  1091.     optind = 1,        /* index into parent argv vector */
  1092.     optopt;            /* character checked for validity */
  1093. char    *optarg;        /* argument associated with option */
  1094.  
  1095. #define BADCH    (int)'?'
  1096. #define EMSG    ""
  1097. #define tell(s)    fputs(*nargv,stderr);fputs(s,stderr); \
  1098.         fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
  1099.  
  1100. getopt(nargc,nargv,ostr)
  1101. int    nargc;
  1102. char    **nargv,
  1103.     *ostr;
  1104. {
  1105.     static char    *place = EMSG;    /* option letter processing */
  1106.     register char    *oli;        /* option letter list index */
  1107.     char    *index();
  1108.  
  1109.     if(!*place) {            /* update scanning pointer */
  1110.         if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
  1111.         if (*place == '-') {    /* found "--" */
  1112.             ++optind;
  1113.             return(EOF);
  1114.         }
  1115.     }                /* option letter okay? */
  1116.     if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
  1117.         if(!*place) ++optind;
  1118.         tell(": illegal option -- ");
  1119.     }
  1120.     if (*++oli != ':') {        /* don't need argument */
  1121.         optarg = NULL;
  1122.         if (!*place) ++optind;
  1123.     }
  1124.     else {                /* need an argument */
  1125.         if (*place) optarg = place;    /* no white space */
  1126.         else if (nargc <= ++optind) {    /* no arg */
  1127.             place = EMSG;
  1128.             tell(": option requires an argument -- ");
  1129.         }
  1130.          else optarg = nargv[optind];    /* white space */
  1131.         place = EMSG;
  1132.         ++optind;
  1133.     }
  1134.     return(optopt);            /* dump back option letter */
  1135. }
  1136. \SHAR\EOF\
  1137. else
  1138.   echo "will not over write ./getopt.c"
  1139. fi
  1140. if `test ! -s ./getpass.c`
  1141. then
  1142. echo "writing ./getpass.c"
  1143. cat > ./getpass.c << '\SHAR\EOF\'
  1144. #include <stdio.h>
  1145. #include <signal.h>
  1146. #include <sgtty.h>
  1147.  
  1148. #define    TTY    "/dev/tty"    /* Change to "con" for MS-DOS */
  1149.  
  1150. /* Issue prompt and read reply with echo turned off */
  1151. char *
  1152. getpass(prompt)
  1153. char *prompt;
  1154. {
  1155.     struct sgttyb ttyb,ttysav;
  1156.     register char *cp;
  1157.     int c;
  1158.     FILE *tty;
  1159.     static char pbuf[128];
  1160.     int (*signal())(),(*sig)();
  1161.  
  1162.     if ((tty = fdopen(open(TTY, 2), "r")) == NULL)
  1163.         tty = stdin;
  1164.     else
  1165.         setbuf(tty, (char *)NULL);
  1166.     sig = signal(SIGINT, SIG_IGN);
  1167.     ioctl(fileno(tty), TIOCGETP, &ttyb);
  1168.     ioctl(fileno(tty), TIOCGETP, &ttysav);
  1169.     ttyb.sg_flags |= RAW;
  1170.     ttyb.sg_flags &= ~ECHO;
  1171.     ioctl(fileno(tty), TIOCSETP, &ttyb);
  1172.     fprintf(stderr, "%s", prompt);
  1173.     fflush(stderr);
  1174.     cp = pbuf;
  1175.     for (;;) {
  1176.         c = getc(tty);
  1177.         if(c == '\r' || c == '\n' || c == EOF)
  1178.             break;
  1179.         if (cp < &pbuf[127])
  1180.             *cp++ = c;
  1181.     }
  1182.     *cp = '\0';
  1183.     fprintf(stderr,"\r\n");
  1184.     fflush(stderr);
  1185.     ioctl(fileno(tty), TIOCSETP, &ttysav);
  1186.     signal(SIGINT, sig);
  1187.     if (tty != stdin)
  1188.         fclose(tty);
  1189.     return(pbuf);
  1190. }
  1191. \SHAR\EOF\
  1192. else
  1193.   echo "will not over write ./getpass.c"
  1194. fi
  1195. if `test ! -s ./main.c`
  1196. then
  1197. echo "writing ./main.c"
  1198. cat > ./main.c << '\SHAR\EOF\'
  1199. /* Encrypt/decrypt command compatible with Sun's "des" command */
  1200. #include <stdio.h>
  1201.  
  1202. char iv[8];    /* Initial vector for CBC mode */
  1203. int block;
  1204.  
  1205. main(argc,argv)
  1206. int argc;
  1207. char *argv[];
  1208. {
  1209.     int c,cnt,encrypt,decrypt,hexflag;
  1210.     register int i;
  1211.     char key[8],tkey1[20],tkey2[20],*akey,*getpass();
  1212.     extern char *optarg;
  1213.  
  1214.     hexflag = block = encrypt = decrypt = 0;
  1215.     akey = NULL;
  1216.     while((c = getopt(argc,argv,"hedk:b")) != EOF){
  1217.         switch(c){
  1218.         case 'h':
  1219.             hexflag++;
  1220.             break;
  1221.         case 'e':
  1222.             encrypt++;
  1223.             break;
  1224.         case 'd':
  1225.             decrypt++;
  1226.             break;
  1227.         case 'k':
  1228.             akey = optarg;
  1229.             break;
  1230.         case 'b':
  1231.             block++;
  1232.             break;
  1233.         }
  1234.     }
  1235.     if(encrypt == 0 && decrypt == 0){
  1236.         fprintf(stderr,"Usage: des -e|-d [-h] [-k key]\n");
  1237.         exit(2);
  1238.     }
  1239.     if(akey == NULL){
  1240.         /* No key on command line, prompt for it */
  1241.         memset(tkey1,0,sizeof(tkey1));
  1242.         memset(tkey2,0,sizeof(tkey2));
  1243.         for(;;){
  1244.             akey = getpass("Enter key: ");
  1245.             strncpy(tkey1,akey,sizeof(tkey1));
  1246.             akey = getpass("Enter key again: ");
  1247.             strncpy(tkey2,akey,sizeof(tkey2));
  1248.             if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){
  1249.                 fprintf(stderr,"Key mistyped, try again\n");
  1250.             } else
  1251.                 break;
  1252.         }
  1253.         akey = tkey1;
  1254.     }
  1255.     if(hexflag){
  1256.         for(i=0;i<16;i++){
  1257.             if(htoa(akey[i]) == -1){
  1258.                 fprintf(stderr,"Non-hex character in key\n");
  1259.                 exit(1);
  1260.             }
  1261.         }
  1262.         gethex(key,akey,8);
  1263.     } else {
  1264.         strncpy(key,akey,8);
  1265.         /* Set up key, determine parity bit */
  1266.         for(cnt = 0; cnt < 8; cnt++){
  1267.             c = 0;
  1268.             for(i=0;i<7;i++)
  1269.                 if(key[cnt] & (1 << i))
  1270.                     c++;
  1271.             if((c & 1) == 0)
  1272.                 key[cnt] |= 0x80;
  1273.             else
  1274.                 key[cnt] &= ~0x80;
  1275.         }
  1276.     }
  1277.     /* Blot out original key */
  1278.     i = strlen(akey);
  1279.     i = (i < 8) ? i : 8;
  1280.     memset(akey,0,i);
  1281.  
  1282.     desinit(0);
  1283.     setkey(key);
  1284.  
  1285.     /* Initialize IV to all zeros */
  1286.     memset(iv,0,8);
  1287.  
  1288.     if(encrypt){
  1289.         doencrypt();
  1290.     } else {
  1291.         dodecrypt();
  1292.     }
  1293. }
  1294. /* Encrypt standard input to standard output */
  1295. doencrypt()
  1296. {
  1297.     char work[8],*cp,*cp1;
  1298.     int cnt,i;
  1299.  
  1300.     for(;;){
  1301.         if((cnt = fread(work,1,8,stdin)) != 8){
  1302.             /* Put residual byte count in the last block.
  1303.              * Note that garbage is left in the other bytes,
  1304.              * if any; this is a feature, not a bug, since it'll
  1305.              * be stripped out at decrypt time.
  1306.              */
  1307.             work[7] = cnt;
  1308.         }
  1309.         if(!block){
  1310.             /* CBC mode; chain in last cipher word */
  1311.             cp = work;
  1312.             cp1 = iv;
  1313.             for(i=8; i!=0; i--)
  1314.                 *cp++ ^= *cp1++;
  1315.         }
  1316.         endes(work);    /* Encrypt block */
  1317.         if(!block){    /* Save outgoing ciphertext for chain */
  1318.             memcpy(iv,work,8);
  1319.         }
  1320.         fwrite(work,1,8,stdout);
  1321.         if(cnt != 8)
  1322.             break;
  1323.     }
  1324. }
  1325. dodecrypt()
  1326. {
  1327.     char work[8],nwork[8],ivtmp[8],*cp,*cp1;
  1328.     int cnt,i;
  1329.  
  1330.  
  1331.     cnt = fread(work,1,8,stdin);    /* Prime the pump */
  1332.     for(;;){
  1333.         if(!block){    /* Save incoming ciphertext for chain */
  1334.             memcpy(ivtmp,work,8);
  1335.         }
  1336.         dedes(work);
  1337.         if(!block){    /* Unchain block, save ciphertext for next */
  1338.             cp = work;
  1339.             cp1 = iv;
  1340.             for(i=8; i!=0; i--){
  1341.                 *cp++ ^= *cp1++;
  1342.             }
  1343.             memcpy(iv,ivtmp,8);
  1344.         }
  1345.         /* Save buffer pending next read */
  1346.         memcpy(nwork,work,8);
  1347.         /* Try to read next block */
  1348.         cnt = fread(work,1,8,stdin);
  1349.         if(cnt != 8){    /* Can "only" be 0 if not 8 */
  1350.             /* Prev block was last one, write appropriate number
  1351.              * of bytes
  1352.              */
  1353.             cnt = nwork[7];
  1354.             if(cnt < 0 || cnt > 7){
  1355.                 fprintf(stderr,"Corrupted file or wrong key\n");
  1356.             } else if(cnt != 0)
  1357.                 fwrite(nwork,1,cnt,stdout);
  1358.             exit(0);
  1359.         } else {
  1360.             /* Now okay to write previous buffer */
  1361.             fwrite(nwork,1,8,stdout);
  1362.         }
  1363.  
  1364.     }
  1365. }
  1366. /* Convert hex/ascii nybble to binary */
  1367. int
  1368. htoa(c)
  1369. char c;
  1370. {
  1371.     if(c >= '0' && c <= '9')
  1372.         return c - '0';
  1373.     if(c >= 'a' && c <= 'f')
  1374.         return 10 + c - 'a';
  1375.     if(c >= 'A' && c <= 'F')
  1376.         return 10 + c - 'A';
  1377.     return -1;
  1378. }
  1379. /* Convert bytes from hex/ascii to binary */
  1380. gethex(result,cp,cnt)
  1381. register char *result;
  1382. register char *cp;
  1383. register int cnt;
  1384. {
  1385.     while(cnt-- != 0){
  1386.         *result = htoa(*cp++) << 4;
  1387.         *result++ |= htoa(*cp++);
  1388.     }
  1389. }
  1390. #ifdef    DEBUG
  1391. put8(cp)
  1392. register char *cp;
  1393. {
  1394.     int i;
  1395.  
  1396.     for(i=0;i<8;i++){
  1397.         fprintf(stderr,"%02x ",*cp++ & 0xff);
  1398.     }
  1399. }
  1400. #endif
  1401.  
  1402. \SHAR\EOF\
  1403. else
  1404.   echo "will not over write ./main.c"
  1405. fi
  1406. if `test ! -s ./misc.c`
  1407. then
  1408. echo "writing ./misc.c"
  1409. cat > ./misc.c << '\SHAR\EOF\'
  1410. /* Set block of memory to constant */
  1411. memset(blk,val,size)
  1412. register char *blk;
  1413. register char val;
  1414. register unsigned size;
  1415. {
  1416.     while(size-- != 0)
  1417.         *blk++ = val;
  1418. }
  1419.  
  1420. /* Copy block of memory */
  1421. memcpy(dest,src,size)
  1422. register char *dest,*src;
  1423. register unsigned size;
  1424. {
  1425.     while(size-- != 0)
  1426.         *dest++ = *src++;
  1427. }
  1428.  
  1429. /* Compare two blocks of memory */
  1430. memcmp(a,b,size)
  1431. register char *a,*b;
  1432. register unsigned size;
  1433. {
  1434.     while(size-- != 0)
  1435.         if(*a++ != *b++)
  1436.             return 1;
  1437.     return 0;
  1438. }
  1439.  
  1440. \SHAR\EOF\
  1441. else
  1442.   echo "will not over write ./misc.c"
  1443. fi
  1444. if `test ! -s ./radlogin.c`
  1445. then
  1446. echo "writing ./radlogin.c"
  1447. cat > ./radlogin.c << '\SHAR\EOF\'
  1448. /*
  1449.  * Secure packet radio login command. The system first prompts for the
  1450.  * user's name. It then generates and sends a unique "challenge" (a 64-bit
  1451.  * hexadecimal integer) based on the time of day. The user encrypts
  1452.  * this value using the Data Encryption Standard and his private key and
  1453.  * type it back to the system. The system also encrypts the challenge
  1454.  * with the user's key and compares the two. If they match, he's in.
  1455.  *
  1456.  * 18 December 1986 Phil Karn, KA9Q
  1457.  *
  1458.  * mods:
  1459.  *   870318 Bdale, N3EUA     Add code to run user's .login commands.
  1460.  *   870317 Bdale, N3EUA     Hacked to remove putenv() by calling execle()
  1461.  *                           instead of execl().
  1462.  */
  1463. #include <stdio.h>
  1464. #include <strings.h>
  1465. #include <pwd.h>
  1466. #include <utmp.h>
  1467. #define    KEYFILE    "/etc/rkeys"    /* This file must be read-protected */
  1468. main(argc,argv)
  1469. int argc;
  1470. char *argv[];
  1471. {
  1472.     struct passwd *pp,*getpwnam();
  1473.     unsigned long t;
  1474.     FILE *fp;
  1475.     char name[64];
  1476.     char key[8];
  1477.     char work[8];
  1478.     char answer[8];
  1479.     char fbuf[64];
  1480.     char ibuf[64];
  1481.     char home[64];
  1482.     char login[64];
  1483.     char shell[64];
  1484.     char user[64];
  1485.     char *keyp;
  1486.     char *cp,*tty,*ttyname();
  1487.     int i,ikey[8];
  1488.     struct utmp utmp;
  1489.     char *ep[5];               /* we'll build an environment here */
  1490.  
  1491.     if((fp = fopen(KEYFILE,"r")) == NULL){
  1492.         printf("Can't open key file\n");
  1493.         exit(1);
  1494.     }
  1495.     /* Get user's name and look it up in the database */
  1496.     printf("Enter login name: ");
  1497.     fgets(ibuf,sizeof(ibuf),stdin);
  1498.     if((cp = index(ibuf,'\n')) != NULL)
  1499.         *cp = '\0';
  1500.     strncpy(name,ibuf,sizeof(name));
  1501.     for(;;){
  1502.         fgets(fbuf,sizeof(fbuf),fp);
  1503.         if(feof(fp)){
  1504.             printf("No key for login name\n");
  1505.             exit(2);
  1506.         }
  1507.         if((cp = index(fbuf,'\n')) != NULL)
  1508.             *cp = '\0';
  1509.         if(strncmp(name,fbuf,strlen(name)) == 0)
  1510.             break;
  1511.     }
  1512.     fclose(fp);
  1513.     /* Find the user's DES key */
  1514.     if((keyp = index(fbuf,' ')) == NULL){
  1515.         printf("Missing key field\n");
  1516.         exit(3);
  1517.     }
  1518.     keyp++;
  1519.     /* Initialize DES with the user's key */
  1520.     sscanf(keyp,"%2x%2x%2x%2x%2x%2x%2x%2x",
  1521.      &ikey[0], &ikey[1], &ikey[2], &ikey[3], &ikey[4], &ikey[5],
  1522.      &ikey[6], &ikey[7]);
  1523.  
  1524.     for(i=0;i<8;i++)
  1525.         key[i] = ikey[i];
  1526.  
  1527.     desinit(0);
  1528.     setkey(key);
  1529.  
  1530.     /* Generate and send the challenge */
  1531.     time(&t);
  1532.     printf("Challenge: %016x\n",t);
  1533.  
  1534.     /* Encrypt it locally... */
  1535.     for(i=0;i<4;i++)
  1536.         work[i] = 0;
  1537.     work[4] = t >> 24;
  1538.     work[5] = t >> 16;
  1539.     work[6] = t >> 8;
  1540.     work[7] = t;
  1541.     endes(work);
  1542.     
  1543.     /* ...and see if the user can do the same */
  1544.     printf("Response:  ");
  1545.     for(i=0;i<8;i++){
  1546.         scanf("%2x",&t);
  1547.         answer[i] = t;
  1548.     }
  1549.     printf("\n");     /* I like it better with a blank line here - bdale */
  1550.     /* Compare the ciphertexts. If they match, he's in */
  1551.     for(i=0; i < 8; i++){
  1552.         if(work[i] != answer[i]){
  1553.             printf("Wrong response\n");
  1554.             exit(4);
  1555.         }
  1556.     }
  1557.     if((pp = getpwnam(name)) == NULL){
  1558.         printf("login name \"%s\" not in /etc/passwd\n",name);
  1559.         exit(4);
  1560.     }
  1561.     if((fp = fopen(UTMP_FILE,"r+")) == NULL){
  1562.         printf("can't open utmp\n");
  1563.         exit(4);
  1564.     }
  1565.     tty = ttyname(0);
  1566.     if((cp = rindex(tty,'/')) != NULL)
  1567.         tty = cp + 1;
  1568.     while(fread((char *)&utmp,sizeof(struct utmp),1,fp),!feof(fp)){
  1569.         if(strncmp(utmp.ut_line,tty,8) == 0){
  1570.             strncpy(utmp.ut_name,name,8);
  1571.             fseek(fp,(long)-sizeof(struct utmp),1);
  1572.             fwrite((char *)&utmp,sizeof(struct utmp),1,fp);
  1573.             break;
  1574.         }
  1575.     }
  1576.     fclose(fp);
  1577.     chdir(pp->pw_dir);
  1578.     setregid(pp->pw_gid,pp->pw_gid);
  1579.     setreuid(pp->pw_uid,pp->pw_uid);
  1580.     if(pp->pw_shell == NULL || *pp->pw_shell == '\0')
  1581.         pp->pw_shell = "/bin/ksh";
  1582.     sprintf(home,"HOME=%s",pp->pw_dir);
  1583.     sprintf(shell,"SHELL=%s",pp->pw_shell);
  1584.     sprintf(user,"USER=%s",name);
  1585.     sprintf(login,"%s/.login",pp->pw_dir);
  1586.     ep[0] = home;
  1587.     ep[1] = shell;
  1588.     ep[2] = user;
  1589.     ep[3] = (char *) NULL;
  1590.     execle(pp->pw_shell,"-",0,ep);
  1591.     printf("Exec failed\n");
  1592. }
  1593. \SHAR\EOF\
  1594. else
  1595.   echo "will not over write ./radlogin.c"
  1596. fi
  1597. if `test ! -s ./rkeys.format`
  1598. then
  1599. echo "writing ./rkeys.format"
  1600. cat > ./rkeys.format << '\SHAR\EOF\'
  1601. >From bellcore!karn@flash.bellcore.com Sat Mar 14 23:48:50 1987
  1602. Received: by flash.bellcore.com (4.12/4.7)
  1603.     id AA13633; Sat, 14 Mar 87 00:05:44 est
  1604. Date: Sat, 14 Mar 87 00:05:44 est
  1605. From: karn@flash.bellcore.com (Phil R. Karn)
  1606. Message-Id: <8703140505.AA13633@flash.bellcore.com>
  1607. To: bdale@winfree.UUCP
  1608. Subject: Re:  rkeys file
  1609. Status: R
  1610.  
  1611. rkeys:
  1612. karn 0123456789abcdef
  1613. uid  des_key_in_hex
  1614.  
  1615. Phil
  1616.  
  1617. \SHAR\EOF\
  1618. else
  1619.   echo "will not over write ./rkeys.format"
  1620. fi
  1621. if `test ! -s ./testdata`
  1622. then
  1623. echo "writing ./testdata"
  1624. cat > ./testdata << '\SHAR\EOF\'
  1625. 0000000000000000 0000000000000000 8CA64DE9C1B123A7
  1626. FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58
  1627. 3000000000000000 1000000000000001 958E6E627A05557B
  1628. 1111111111111111 1111111111111111 F40379AB9E0EC533
  1629. 0123456789ABCDEF 1111111111111111 17668DFC7292532D
  1630. 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD
  1631. 0000000000000000 0000000000000000 8CA64DE9C1B123A7
  1632. FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4
  1633. 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
  1634. 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
  1635. 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
  1636. 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
  1637. 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
  1638. 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
  1639. 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
  1640. 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
  1641. 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
  1642. 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
  1643. 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
  1644. 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
  1645. 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
  1646. 025816164629B007 480D39006EE762F2 A1F9915541020B56
  1647. 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
  1648. 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
  1649. 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
  1650. 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
  1651. 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
  1652. 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100
  1653. 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606
  1654. E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7
  1655. 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451
  1656. FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE
  1657. 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D
  1658. FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2
  1659. \SHAR\EOF\
  1660. else
  1661.   echo "will not over write ./testdata"
  1662. fi
  1663. if `test ! -s ./uudecode.c`
  1664. then
  1665. echo "writing ./uudecode.c"
  1666. cat > ./uudecode.c << '\SHAR\EOF\'
  1667. /* uudecode.c - convert ascii-encoded files back to their original form
  1668.  * Usage: uudecode [infile]
  1669.  *
  1670.  * This command differs from the regular UNIX one in that the embedded
  1671.  * file name "/dev/stdout" is recognized, allowing it to be used in a pipeline
  1672.  *
  1673.  * Written and placed in the public domain by Phil Karn, KA9Q 31 March 1987
  1674.  */
  1675. #include <stdio.h>
  1676. #define    LINELEN    80
  1677. main(argc,argv)
  1678. int argc;
  1679. char *argv[];
  1680. {
  1681.     char linebuf[LINELEN],*index(),*fgets();
  1682.     register char *cp;
  1683.     int linelen,i;
  1684.     FILE *in,*out;
  1685.     
  1686.     if(argc > 1){
  1687.         if((in = fopen(argv[1],"r")) == NULL){
  1688.             fprintf(stderr,"Can't read %s\n",argv[1]);
  1689.             exit(1);
  1690.         }
  1691.     } else
  1692.         in = stdin;
  1693.  
  1694.     /* Find begin line */
  1695.     while(fgets(linebuf,LINELEN,in) != NULL){
  1696.         if((cp = index(linebuf,'\n')) != NULL)
  1697.             *cp = '\0';
  1698.         if(strncmp(linebuf,"begin",5) == 0)
  1699.             break;
  1700.     }
  1701.     if(feof(in)){
  1702.         fprintf(stderr,"No begin found\n");
  1703.         exit(1);
  1704.     }
  1705.     /* Find beginning of file name */
  1706.     cp = &linebuf[6];
  1707.     if((cp = index(cp,' ')) != NULL)
  1708.         cp++;
  1709.     /* Set up output stream */
  1710.     if(cp == NULL || strcmp(cp,"/dev/stdout") == 0){
  1711.         out = stdout;
  1712.     } else if((out = fopen(cp,"w")) == NULL){
  1713.             fprintf(stderr,"Can't open %s\n",cp);
  1714.             exit(1);
  1715.     }
  1716.     /* Now crunch the input file */
  1717.     while(fgets(linebuf,LINELEN,in) != NULL){
  1718.         linelen = linebuf[0] - ' ';
  1719.         if(linelen == 0 || strncmp(linebuf,"end",3) == 0)
  1720.             break;
  1721.         for(cp = &linebuf[1];linelen > 0;cp += 4){
  1722.             for(i=0;i<4;i++)
  1723.                 cp[i] -= ' ';
  1724.             putc((cp[0] << 2) | ((cp[1] >> 4) & 0x3),out);
  1725.             if(--linelen > 0)
  1726.                 putc((cp[1] << 4) | ((cp[2] >> 2) & 0xf),out);
  1727.             if(--linelen > 0)
  1728.                 putc((cp[2] << 6) | cp[3],out);
  1729.             linelen--;
  1730.         }
  1731.     }
  1732.     fclose(out);
  1733. }
  1734.  
  1735. \SHAR\EOF\
  1736. else
  1737.   echo "will not over write ./uudecode.c"
  1738. fi
  1739. if `test ! -s ./uuencode.c`
  1740. then
  1741. echo "writing ./uuencode.c"
  1742. cat > ./uuencode.c << '\SHAR\EOF\'
  1743. /* uuencode.c - convert files to ascii-encoded form
  1744.  * Usage: uuencode [filename] < infile
  1745.  *
  1746.  * If [filename] isn't specified, "/dev/stdout" is the default.  This allows
  1747.  * use of my uudecode as a pipeline filter.
  1748.  *
  1749.  * Written and placed in the public domain by Phil Karn, KA9Q
  1750.  * 31 March 1987
  1751.  */
  1752. #include <stdio.h>
  1753. #define    LINELEN    45
  1754. main(argc,argv)
  1755. int argc;
  1756. char *argv[];
  1757. {
  1758.     char linebuf[LINELEN];
  1759.     register char *cp;
  1760.     int linelen;
  1761.  
  1762.     if(argc > 1)
  1763.         printf("begin 0666 %s\n",argv[1]);
  1764.     else
  1765.         printf("begin 0666 /dev/stdout\n");
  1766.     for(;;){
  1767.         linelen = fread(linebuf,1,LINELEN,stdin);
  1768.         if(linelen <= 0)
  1769.             break;
  1770.         putchar(' ' + linelen);    /* Record length */
  1771.         for(cp = linebuf; cp < &linebuf[linelen]; cp += 3){
  1772.                 putchar(' ' + ((cp[0] >> 2) & 0x3f));
  1773.             putchar(' ' + (((cp[0] << 4) & 0x30) | ((cp[1] >> 4) & 0xf)));
  1774.             putchar(' ' + (((cp[1] << 2) & 0x3c) | ((cp[2] >> 6) & 0x3)));
  1775.             putchar(' ' + (cp[2] & 0x3f));
  1776.         }
  1777.         putchar('\n');
  1778.     }
  1779.     printf(" \n");    /* 0-length null record */
  1780.     printf("end\n");
  1781. }
  1782.  
  1783. \SHAR\EOF\
  1784. else
  1785.   echo "will not over write ./uuencode.c"
  1786. fi
  1787. echo "Finished archive 1 of 1"
  1788. exit
  1789.  
  1790.  
  1791.  
  1792.