Browse Source

Plan 9 from Bell Labs 2004-02-23

David du Colombier 19 years ago
parent
commit
cefc6ddea0
36 changed files with 3908 additions and 409 deletions
  1. 37 22
      dist/replica/plan9.db
  2. 37 0
      dist/replica/plan9.log
  3. 1 2
      sys/src/cmd/ip/snoopy/ninep.c
  4. 5 1
      sys/src/cmd/unix/drawterm/auth.c
  5. 1 1
      sys/src/cmd/unix/drawterm/auth.h
  6. 5 349
      sys/src/cmd/unix/drawterm/crypt.c
  7. 4 1
      sys/src/cmd/unix/drawterm/devcon.c
  8. 1455 0
      sys/src/cmd/unix/drawterm/devssl.c
  9. 8 1
      sys/src/cmd/unix/drawterm/devtab.c
  10. 1 1
      sys/src/cmd/unix/drawterm/doprint.c
  11. 52 14
      sys/src/cmd/unix/drawterm/drawterm.c
  12. 1 1
      sys/src/cmd/unix/drawterm/latin1.c
  13. 1 0
      sys/src/cmd/unix/drawterm/lib9.h
  14. 480 0
      sys/src/cmd/unix/drawterm/libsec/des.c
  15. 58 0
      sys/src/cmd/unix/drawterm/libsec/desCBC.c
  16. 47 0
      sys/src/cmd/unix/drawterm/libsec/desECB.c
  17. 31 0
      sys/src/cmd/unix/drawterm/libsec/desmodes.c
  18. 339 0
      sys/src/cmd/unix/drawterm/libsec/libsec.h
  19. 271 0
      sys/src/cmd/unix/drawterm/libsec/md4.c
  20. 148 0
      sys/src/cmd/unix/drawterm/libsec/md5.c
  21. 267 0
      sys/src/cmd/unix/drawterm/libsec/md5block.c
  22. 104 0
      sys/src/cmd/unix/drawterm/libsec/rc4.c
  23. 127 0
      sys/src/cmd/unix/drawterm/libsec/sha1.c
  24. 187 0
      sys/src/cmd/unix/drawterm/libsec/sha1block.c
  25. 126 0
      sys/src/cmd/unix/drawterm/libsec/u64.c
  26. 17 1
      sys/src/cmd/unix/drawterm/mkfile
  27. 2 0
      sys/src/cmd/unix/drawterm/mkfile-FreeBSD
  28. 2 0
      sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power
  29. 2 0
      sys/src/cmd/unix/drawterm/mkfile-Irix
  30. 3 1
      sys/src/cmd/unix/drawterm/mkfile-Linux
  31. 2 0
      sys/src/cmd/unix/drawterm/mkfile-OSF1
  32. 2 0
      sys/src/cmd/unix/drawterm/mkfile-Solaris
  33. 2 0
      sys/src/cmd/unix/drawterm/mkfile-Windows
  34. 43 0
      sys/src/cmd/unix/drawterm/pushssl.c
  35. 29 14
      sys/src/cmd/unix/drawterm/qio.c
  36. 11 0
      sys/src/cmd/unix/drawterm/sys.h

+ 37 - 22
dist/replica/plan9.db

@@ -386,7 +386,7 @@
 386/bin/snap - 775 sys sys 1068558112 289953
 386/bin/snapfs - 775 sys sys 1068717504 361553
 386/bin/sniffer - 775 sys sys 1038443185 99028
-386/bin/snoopy - 775 sys sys 1068385806 153816
+386/bin/snoopy - 775 sys sys 1077508785 153943
 386/bin/sort - 775 sys sys 1064598313 81046
 386/bin/spin - 775 sys sys 1071245348 654328
 386/bin/split - 775 sys sys 1064598314 74007
@@ -542,7 +542,7 @@
 386/lib/libmach.a - 664 sys sys 1073851272 746962
 386/lib/libmemdraw.a - 664 sys sys 1073851273 291288
 386/lib/libmemlayer.a - 664 sys sys 1073851273 47636
-386/lib/libmp.a - 664 sys sys 1077422340 78536
+386/lib/libmp.a - 664 sys sys 1077508785 77700
 386/lib/libndb.a - 664 sys sys 1073851273 54474
 386/lib/libplumb.a - 664 sys sys 1073851274 18876
 386/lib/libregexp.a - 664 sys sys 1073851274 37502
@@ -9514,7 +9514,7 @@ sys/src/cmd/ip/snoopy/ip.c - 664 sys sys 1055699194 4291
 sys/src/cmd/ip/snoopy/ip6.c - 664 sys sys 1067722979 5362
 sys/src/cmd/ip/snoopy/main.c - 664 sys sys 1063306798 14371
 sys/src/cmd/ip/snoopy/mkfile - 664 sys sys 1045505384 775
-sys/src/cmd/ip/snoopy/ninep.c - 664 sys sys 1032059933 704
+sys/src/cmd/ip/snoopy/ninep.c - 664 sys sys 1077484166 695
 sys/src/cmd/ip/snoopy/ospf.c - 664 sys sys 1032059934 7516
 sys/src/cmd/ip/snoopy/ppp.c - 664 sys sys 1045505315 10502
 sys/src/cmd/ip/snoopy/ppp_ccp.c - 664 sys sys 1015090061 50
@@ -10566,8 +10566,8 @@ sys/src/cmd/unix/drawterm/argv0.c - 664 sys sys 954098599 32
 sys/src/cmd/unix/drawterm/asm-Solaris-386.s - 664 sys sys 954098600 885
 sys/src/cmd/unix/drawterm/asm-Solaris-sparc.s - 664 sys sys 954098600 312
 sys/src/cmd/unix/drawterm/atexit.c - 664 sys sys 954098601 818
-sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 954098601 2093
-sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 954098602 2984
+sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 1077480264 2218
+sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 1077480264 2992
 sys/src/cmd/unix/drawterm/authaux.c - 664 sys sys 954098602 11934
 sys/src/cmd/unix/drawterm/authdial.c - 664 sys sys 954098603 145
 sys/src/cmd/unix/drawterm/authlocal.h - 664 sys sys 954098603 162
@@ -10588,9 +10588,9 @@ sys/src/cmd/unix/drawterm/convM2T.c - 664 sys sys 954098607 557
 sys/src/cmd/unix/drawterm/convM2TR.c - 664 sys sys 954098608 269
 sys/src/cmd/unix/drawterm/convS2M.c - 664 sys sys 954098608 2984
 sys/src/cmd/unix/drawterm/convTR2M.c - 664 sys sys 954098609 529
-sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 954098609 17813
+sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 1077480266 963
 sys/src/cmd/unix/drawterm/dev.c - 664 sys sys 954098610 5006
-sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 985124883 7006
+sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 1077480267 7105
 sys/src/cmd/unix/drawterm/devdraw.c - 664 sys sys 958504757 39499
 sys/src/cmd/unix/drawterm/devip-unix.c - 664 sys sys 1046970237 15063
 sys/src/cmd/unix/drawterm/devip-win.c - 664 sys sys 1015701212 15055
@@ -10599,12 +10599,13 @@ sys/src/cmd/unix/drawterm/devmouse.c - 664 sys sys 954098613 3982
 sys/src/cmd/unix/drawterm/devntfs.c - 664 sys sys 954098614 10545
 sys/src/cmd/unix/drawterm/devpipe.c - 664 sys sys 954098614 4958
 sys/src/cmd/unix/drawterm/devroot.c - 664 sys sys 954098615 1534
-sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 954098616 1940
+sys/src/cmd/unix/drawterm/devssl.c - 664 sys sys 1077480268 25283
+sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 1077480268 2113
 sys/src/cmd/unix/drawterm/devunixfs.c - 664 sys sys 954098616 9548
 sys/src/cmd/unix/drawterm/dial.c - 664 sys sys 954098617 3640
 sys/src/cmd/unix/drawterm/dirfstat.c - 664 sys sys 954098617 179
-sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 954098618 11749
-sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1040672905 11492
+sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 1077480269 11757
+sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1077480270 12639
 sys/src/cmd/unix/drawterm/error.c - 664 sys sys 954098619 2515
 sys/src/cmd/unix/drawterm/error.h - 664 sys sys 954098619 3075
 sys/src/cmd/unix/drawterm/exportfs.c - 664 sys sys 964798439 13405
@@ -10617,8 +10618,8 @@ sys/src/cmd/unix/drawterm/ip.h - 664 sys sys 954098625 560
 sys/src/cmd/unix/drawterm/irix.c - 664 sys sys 954098626 7552
 sys/src/cmd/unix/drawterm/kbd.c - 664 sys sys 954098627 8210
 sys/src/cmd/unix/drawterm/keyboard.h - 664 sys sys 954098628 270
-sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 954098628 7799
-sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 954098629 7906
+sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1077480272 7808
+sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 1077480272 7930
 sys/src/cmd/unix/drawterm/libdraw - 20000000775 sys sys 954098713 0
 sys/src/cmd/unix/drawterm/libdraw/alloc.c - 664 sys sys 954098710 111
 sys/src/cmd/unix/drawterm/libdraw/arith.c - 664 sys sys 954098710 2043
@@ -10673,21 +10674,34 @@ sys/src/cmd/unix/drawterm/libmemlayer/lsetrefresh.c - 664 sys sys 954098728 732
 sys/src/cmd/unix/drawterm/libmemlayer/ltofront.c - 664 sys sys 954098728 1179
 sys/src/cmd/unix/drawterm/libmemlayer/ltorear.c - 664 sys sys 954098729 1089
 sys/src/cmd/unix/drawterm/libmemlayer/memlayer.h - 664 sys sys 954098729 1691
+sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
+sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1077480282 17511
+sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1077480282 1078
+sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1077480282 860
+sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1077480283 662
+sys/src/cmd/unix/drawterm/libsec/libsec.h - 664 sys sys 1077480283 8912
+sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1077480283 4275
+sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1077480283 3313
+sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1077480283 5030
+sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1077480284 1430
+sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1077480284 2294
+sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1077480284 4678
+sys/src/cmd/unix/drawterm/libsec/u64.c - 664 sys sys 1077480285 3270
 sys/src/cmd/unix/drawterm/linux.c - 664 sys sys 963353235 9886
 sys/src/cmd/unix/drawterm/lock-irix.s - 664 sys sys 954098631 290
 sys/src/cmd/unix/drawterm/lock-osf1.s - 664 sys sys 954098631 887
 sys/src/cmd/unix/drawterm/lock.c - 664 sys sys 954098632 627
 sys/src/cmd/unix/drawterm/mallocz.c - 664 sys sys 954098632 104
-sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1019839869 2354
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 964470495 483
-sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1019839869 477
-sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 964470495 470
-sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1020313486 452
-sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 964470496 481
-sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 964470497 522
+sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1077480273 2572
+sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 1077480274 555
+sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1077480274 549
+sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 1077480275 542
+sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1077480275 534
+sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 1077480276 553
+sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 1077480276 594
 sys/src/cmd/unix/drawterm/mkfile-Solaris-386 - 664 sys sys 954098636 25
 sys/src/cmd/unix/drawterm/mkfile-Solaris-sparc - 664 sys sys 954098637 27
-sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 964470497 1283
+sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 1077480277 1353
 sys/src/cmd/unix/drawterm/nan.c - 664 sys sys 954098638 718
 sys/src/cmd/unix/drawterm/ndrawterm.mdp - 664 sys sys 954098639 33792
 sys/src/cmd/unix/drawterm/netmkaddr.c - 664 sys sys 954098639 784
@@ -10700,7 +10714,8 @@ sys/src/cmd/unix/drawterm/posix.c - 664 sys sys 964470494 8065
 sys/src/cmd/unix/drawterm/pow10.c - 664 sys sys 954098643 1121
 sys/src/cmd/unix/drawterm/print.c - 664 sys sys 954098644 1069
 sys/src/cmd/unix/drawterm/proc.c - 664 sys sys 954098645 3355
-sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 954098645 14464
+sys/src/cmd/unix/drawterm/pushssl.c - 664 sys sys 1077480278 897
+sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 1077480279 14729
 sys/src/cmd/unix/drawterm/readn.c - 664 sys sys 954098646 219
 sys/src/cmd/unix/drawterm/ref.c - 664 sys sys 954098646 216
 sys/src/cmd/unix/drawterm/rune.c - 664 sys sys 954098647 2085
@@ -10709,7 +10724,7 @@ sys/src/cmd/unix/drawterm/screen-win.c - 664 sys sys 954098648 11441
 sys/src/cmd/unix/drawterm/screen-x11.c - 664 sys sys 964470495 21726
 sys/src/cmd/unix/drawterm/screen.h - 664 sys sys 954098649 1083
 sys/src/cmd/unix/drawterm/solaris.c - 664 sys sys 954098649 7927
-sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 954098650 13475
+sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 1077480280 13888
 sys/src/cmd/unix/drawterm/syscall.c - 664 sys sys 954098651 12813
 sys/src/cmd/unix/drawterm/tabs.c - 664 sys sys 954098651 56506
 sys/src/cmd/unix/drawterm/tabs.h - 664 sys sys 954098652 681

+ 37 - 0
dist/replica/plan9.log

@@ -13951,3 +13951,40 @@
 1077422406 0 c 386/bin/acme - 775 sys sys 1077422339 424461
 1077422406 1 c 386/bin/disk/dump9660 - 775 sys sys 1077422340 152343
 1077422406 2 c 386/lib/libmp.a - 664 sys sys 1077422340 78536
+1077480354 0 c sys/src/cmd/unix/drawterm/auth.c - 664 sys sys 1077480264 2218
+1077480354 1 c sys/src/cmd/unix/drawterm/auth.h - 664 sys sys 1077480264 2992
+1077480354 2 c sys/src/cmd/unix/drawterm/crypt.c - 664 sys sys 1077480266 963
+1077480354 3 c sys/src/cmd/unix/drawterm/devcon.c - 664 sys sys 1077480267 7105
+1077480354 4 c sys/src/cmd/unix/drawterm/devtab.c - 664 sys sys 1077480268 2113
+1077480354 5 c sys/src/cmd/unix/drawterm/doprint.c - 664 sys sys 1077480269 11757
+1077480354 6 c sys/src/cmd/unix/drawterm/drawterm.c - 664 sys sys 1077480270 12639
+1077480354 7 c sys/src/cmd/unix/drawterm/latin1.c - 664 sys sys 1077480272 7808
+1077480354 8 c sys/src/cmd/unix/drawterm/lib9.h - 664 sys sys 1077480272 7930
+1077480354 9 c sys/src/cmd/unix/drawterm/mkfile - 664 sys sys 1077480273 2572
+1077480354 10 c sys/src/cmd/unix/drawterm/mkfile-FreeBSD - 664 sys sys 1077480274 555
+1077480354 11 c sys/src/cmd/unix/drawterm/mkfile-Irix - 664 sys sys 1077480275 542
+1077480354 12 c sys/src/cmd/unix/drawterm/mkfile-Linux - 664 sys sys 1077480275 534
+1077480354 13 c sys/src/cmd/unix/drawterm/mkfile-OSF1 - 664 sys sys 1077480276 553
+1077480354 14 c sys/src/cmd/unix/drawterm/mkfile-Solaris - 664 sys sys 1077480276 594
+1077480354 15 c sys/src/cmd/unix/drawterm/mkfile-Windows - 664 sys sys 1077480277 1353
+1077480354 16 a sys/src/cmd/unix/drawterm/devssl.c - 664 sys sys 1077480268 25283
+1077480354 17 a sys/src/cmd/unix/drawterm/libsec - 20000000775 sys sys 1077480285 0
+1077480354 18 a sys/src/cmd/unix/drawterm/libsec/des.c - 664 sys sys 1077480282 17511
+1077480354 19 a sys/src/cmd/unix/drawterm/libsec/desCBC.c - 664 sys sys 1077480282 1078
+1077480354 20 a sys/src/cmd/unix/drawterm/libsec/desECB.c - 664 sys sys 1077480282 860
+1077480354 21 a sys/src/cmd/unix/drawterm/libsec/desmodes.c - 664 sys sys 1077480283 662
+1077480354 22 a sys/src/cmd/unix/drawterm/libsec/libsec.h - 664 sys sys 1077480283 8912
+1077480354 23 a sys/src/cmd/unix/drawterm/libsec/md4.c - 664 sys sys 1077480283 4275
+1077480354 24 a sys/src/cmd/unix/drawterm/libsec/md5.c - 664 sys sys 1077480283 3313
+1077480354 25 a sys/src/cmd/unix/drawterm/libsec/md5block.c - 664 sys sys 1077480283 5030
+1077480354 26 a sys/src/cmd/unix/drawterm/libsec/rc4.c - 664 sys sys 1077480284 1430
+1077480354 27 a sys/src/cmd/unix/drawterm/libsec/sha1.c - 664 sys sys 1077480284 2294
+1077480354 28 a sys/src/cmd/unix/drawterm/libsec/sha1block.c - 664 sys sys 1077480284 4678
+1077480354 29 a sys/src/cmd/unix/drawterm/libsec/u64.c - 664 sys sys 1077480285 3270
+1077480354 30 c sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power - 664 sys sys 1077480274 549
+1077480354 31 a sys/src/cmd/unix/drawterm/pushssl.c - 664 sys sys 1077480278 897
+1077480354 32 c sys/src/cmd/unix/drawterm/qio.c - 664 sys sys 1077480279 14729
+1077480354 33 c sys/src/cmd/unix/drawterm/sys.h - 664 sys sys 1077480280 13888
+1077485417 0 c sys/src/cmd/ip/snoopy/ninep.c - 664 sys sys 1077484166 695
+1077508821 0 c 386/bin/snoopy - 775 sys sys 1077508785 153943
+1077508821 1 c 386/lib/libmp.a - 664 sys sys 1077508785 77700

+ 1 - 2
sys/src/cmd/ip/snoopy/ninep.c

@@ -26,8 +26,7 @@ p_seprint(Msg *m)
 	memset(&f, 0, sizeof(f));
 	f.type = 0;
 	f.data = 0;	/* protection for %F */
-	convM2S(m->ps, m->pe-m->ps, &f);
-	if(f.type){
+	if(convM2S(m->ps, m->pe-m->ps, &f)){
 		p = m->p;
 		m->p = seprint(m->p, m->e, "%F", &f);
 		while(p < m->p){

+ 5 - 1
sys/src/cmd/unix/drawterm/auth.c

@@ -8,7 +8,7 @@ static char *srmsg = "server refused authentication";
 static char *sgmsg = "server gave up";
 
 int
-auth(int fd)
+auth(int fd, uchar *secret)
 {
 	int n, afd;
 	int rv;
@@ -99,5 +99,9 @@ auth(int fd)
 			werrstr("server lies");
 		return -1;
 	}
+	if (secret){
+		decrypt(secret, tbuf, TICKETLEN);
+		des56to64((uchar*)(tbuf+TICKETLEN-DESKEYLEN), secret);
+	}
 	return 0;
 }

+ 1 - 1
sys/src/cmd/unix/drawterm/auth.h

@@ -107,7 +107,7 @@ extern	int	passtokey(void*, char*);
 extern	int	authenticate(int, int);
 extern	int	newns(char*, char*);
 extern	int	authdial(void);
-extern	int	auth(int);
+extern	int	auth(int, uchar*);
 extern	int	srvauth(int, char*);
 extern	int	getchal(Chalstate*, char*);
 extern	int	chalreply(Chalstate*, char*);

+ 5 - 349
sys/src/cmd/unix/drawterm/crypt.c

@@ -6,12 +6,7 @@
  */
 #include "lib9.h"
 #include "auth.h"
-
-static	long	ip_low(char [8]);
-static	long	ip_high(char [8]);
-static	void	fp(long, long, char[8]);
-static	void	key_setup(char[DESKEYLEN], char[128]);
-static	void	block_cipher(char[128], char[8], int);
+#include "libsec/libsec.h"
 
 /*
  * destructively encrypt the buffer, which
@@ -20,7 +15,8 @@ static	void	block_cipher(char[128], char[8], int);
 int
 encrypt(void *key, void *vbuf, int n)
 {
-	char ekey[128], *buf;
+	ulong ekey[32];
+	uchar *buf;
 	int i, r;
 
 	if(n < 8)
@@ -46,7 +42,8 @@ encrypt(void *key, void *vbuf, int n)
 int
 decrypt(void *key, void *vbuf, int n)
 {
-	char ekey[128], *buf;
+	ulong ekey[32];
+	uchar *buf;
 	int i, r;
 
 	if(n < 8)
@@ -65,344 +62,3 @@ decrypt(void *key, void *vbuf, int n)
 	}
 	return 1;
 }
-
-/*
- *	Tables for Combined S and P Boxes
- */
-
-static long  s0p[] = {
-0x00410100,0x00010000,0x40400000,0x40410100,0x00400000,0x40010100,0x40010000,0x40400000,
-0x40010100,0x00410100,0x00410000,0x40000100,0x40400100,0x00400000,0x00000000,0x40010000,
-0x00010000,0x40000000,0x00400100,0x00010100,0x40410100,0x00410000,0x40000100,0x00400100,
-0x40000000,0x00000100,0x00010100,0x40410000,0x00000100,0x40400100,0x40410000,0x00000000,
-0x00000000,0x40410100,0x00400100,0x40010000,0x00410100,0x00010000,0x40000100,0x00400100,
-0x40410000,0x00000100,0x00010100,0x40400000,0x40010100,0x40000000,0x40400000,0x00410000,
-0x40410100,0x00010100,0x00410000,0x40400100,0x00400000,0x40000100,0x40010000,0x00000000,
-0x00010000,0x00400000,0x40400100,0x00410100,0x40000000,0x40410000,0x00000100,0x40010100,
-};
-
-static long  s1p[] = {
-0x08021002,0x00000000,0x00021000,0x08020000,0x08000002,0x00001002,0x08001000,0x00021000,
-0x00001000,0x08020002,0x00000002,0x08001000,0x00020002,0x08021000,0x08020000,0x00000002,
-0x00020000,0x08001002,0x08020002,0x00001000,0x00021002,0x08000000,0x00000000,0x00020002,
-0x08001002,0x00021002,0x08021000,0x08000002,0x08000000,0x00020000,0x00001002,0x08021002,
-0x00020002,0x08021000,0x08001000,0x00021002,0x08021002,0x00020002,0x08000002,0x00000000,
-0x08000000,0x00001002,0x00020000,0x08020002,0x00001000,0x08000000,0x00021002,0x08001002,
-0x08021000,0x00001000,0x00000000,0x08000002,0x00000002,0x08021002,0x00021000,0x08020000,
-0x08020002,0x00020000,0x00001002,0x08001000,0x08001002,0x00000002,0x08020000,0x00021000,
-};
-
-static long  s2p[] = {
-0x20800000,0x00808020,0x00000020,0x20800020,0x20008000,0x00800000,0x20800020,0x00008020,
-0x00800020,0x00008000,0x00808000,0x20000000,0x20808020,0x20000020,0x20000000,0x20808000,
-0x00000000,0x20008000,0x00808020,0x00000020,0x20000020,0x20808020,0x00008000,0x20800000,
-0x20808000,0x00800020,0x20008020,0x00808000,0x00008020,0x00000000,0x00800000,0x20008020,
-0x00808020,0x00000020,0x20000000,0x00008000,0x20000020,0x20008000,0x00808000,0x20800020,
-0x00000000,0x00808020,0x00008020,0x20808000,0x20008000,0x00800000,0x20808020,0x20000000,
-0x20008020,0x20800000,0x00800000,0x20808020,0x00008000,0x00800020,0x20800020,0x00008020,
-0x00800020,0x00000000,0x20808000,0x20000020,0x20800000,0x20008020,0x00000020,0x00808000,
-};
-
-static long  s3p[] = {
-0x00080201,0x02000200,0x00000001,0x02080201,0x00000000,0x02080000,0x02000201,0x00080001,
-0x02080200,0x02000001,0x02000000,0x00000201,0x02000001,0x00080201,0x00080000,0x02000000,
-0x02080001,0x00080200,0x00000200,0x00000001,0x00080200,0x02000201,0x02080000,0x00000200,
-0x00000201,0x00000000,0x00080001,0x02080200,0x02000200,0x02080001,0x02080201,0x00080000,
-0x02080001,0x00000201,0x00080000,0x02000001,0x00080200,0x02000200,0x00000001,0x02080000,
-0x02000201,0x00000000,0x00000200,0x00080001,0x00000000,0x02080001,0x02080200,0x00000200,
-0x02000000,0x02080201,0x00080201,0x00080000,0x02080201,0x00000001,0x02000200,0x00080201,
-0x00080001,0x00080200,0x02080000,0x02000201,0x00000201,0x02000000,0x02000001,0x02080200,
-};
-
-static long  s4p[] = {
-0x01000000,0x00002000,0x00000080,0x01002084,0x01002004,0x01000080,0x00002084,0x01002000,
-0x00002000,0x00000004,0x01000004,0x00002080,0x01000084,0x01002004,0x01002080,0x00000000,
-0x00002080,0x01000000,0x00002004,0x00000084,0x01000080,0x00002084,0x00000000,0x01000004,
-0x00000004,0x01000084,0x01002084,0x00002004,0x01002000,0x00000080,0x00000084,0x01002080,
-0x01002080,0x01000084,0x00002004,0x01002000,0x00002000,0x00000004,0x01000004,0x01000080,
-0x01000000,0x00002080,0x01002084,0x00000000,0x00002084,0x01000000,0x00000080,0x00002004,
-0x01000084,0x00000080,0x00000000,0x01002084,0x01002004,0x01002080,0x00000084,0x00002000,
-0x00002080,0x01002004,0x01000080,0x00000084,0x00000004,0x00002084,0x01002000,0x01000004,
-};
-
-static long  s5p[] = {
-0x10000008,0x00040008,0x00000000,0x10040400,0x00040008,0x00000400,0x10000408,0x00040000,
-0x00000408,0x10040408,0x00040400,0x10000000,0x10000400,0x10000008,0x10040000,0x00040408,
-0x00040000,0x10000408,0x10040008,0x00000000,0x00000400,0x00000008,0x10040400,0x10040008,
-0x10040408,0x10040000,0x10000000,0x00000408,0x00000008,0x00040400,0x00040408,0x10000400,
-0x00000408,0x10000000,0x10000400,0x00040408,0x10040400,0x00040008,0x00000000,0x10000400,
-0x10000000,0x00000400,0x10040008,0x00040000,0x00040008,0x10040408,0x00040400,0x00000008,
-0x10040408,0x00040400,0x00040000,0x10000408,0x10000008,0x10040000,0x00040408,0x00000000,
-0x00000400,0x10000008,0x10000408,0x10040400,0x10040000,0x00000408,0x00000008,0x10040008,
-};
-
-static long  s6p[] = {
-0x00000800,0x00000040,0x00200040,0x80200000,0x80200840,0x80000800,0x00000840,0x00000000,
-0x00200000,0x80200040,0x80000040,0x00200800,0x80000000,0x00200840,0x00200800,0x80000040,
-0x80200040,0x00000800,0x80000800,0x80200840,0x00000000,0x00200040,0x80200000,0x00000840,
-0x80200800,0x80000840,0x00200840,0x80000000,0x80000840,0x80200800,0x00000040,0x00200000,
-0x80000840,0x00200800,0x80200800,0x80000040,0x00000800,0x00000040,0x00200000,0x80200800,
-0x80200040,0x80000840,0x00000840,0x00000000,0x00000040,0x80200000,0x80000000,0x00200040,
-0x00000000,0x80200040,0x00200040,0x00000840,0x80000040,0x00000800,0x80200840,0x00200000,
-0x00200840,0x80000000,0x80000800,0x80200840,0x80200000,0x00200840,0x00200800,0x80000800,
-};
-
-static long  s7p[] = {
-0x04100010,0x04104000,0x00004010,0x00000000,0x04004000,0x00100010,0x04100000,0x04104010,
-0x00000010,0x04000000,0x00104000,0x00004010,0x00104010,0x04004010,0x04000010,0x04100000,
-0x00004000,0x00104010,0x00100010,0x04004000,0x04104010,0x04000010,0x00000000,0x00104000,
-0x04000000,0x00100000,0x04004010,0x04100010,0x00100000,0x00004000,0x04104000,0x00000010,
-0x00100000,0x00004000,0x04000010,0x04104010,0x00004010,0x04000000,0x00000000,0x00104000,
-0x04100010,0x04004010,0x04004000,0x00100010,0x04104000,0x00000010,0x00100010,0x04004000,
-0x04104010,0x00100000,0x04100000,0x04000010,0x00104000,0x00004010,0x04004010,0x04100000,
-0x00000010,0x04104000,0x00104010,0x00000000,0x04000000,0x04100010,0x00004000,0x00104010,
-};
-
-/*
- *	DES electronic codebook encryption of one block
- */
-static void
-block_cipher(char expanded_key[128], char text[8], int decrypting)
-{
-	char *key;
-	long crypto, temp, right, left;
-	int i, key_offset;
-
-	key = expanded_key;
-	left = ip_low(text);
-	right = ip_high(text);
-	if (decrypting) {
-		key_offset = 16;
-		key = key + 128 - 8;
-	} else
-		key_offset = 0;
-	for (i = 0; i < 16; i++) {
-		temp = (right << 1) | ((right >> 31) & 1);
-		crypto  = s0p[(temp         & 0x3f) ^ *key++];
-		crypto |= s1p[((temp >>  4) & 0x3f) ^ *key++];
-		crypto |= s2p[((temp >>  8) & 0x3f) ^ *key++];
-		crypto |= s3p[((temp >> 12) & 0x3f) ^ *key++];
-		crypto |= s4p[((temp >> 16) & 0x3f) ^ *key++];
-		crypto |= s5p[((temp >> 20) & 0x3f) ^ *key++];
-		crypto |= s6p[((temp >> 24) & 0x3f) ^ *key++];
-		temp = ((right & 1) << 5) | ((right >> 27) & 0x1f);
-		crypto |= s7p[temp ^ *key++];
-		temp = left;
-		left = right;
-		right = temp ^ crypto;
-		key -= key_offset;
-	}
-	/*
-	 *	standard final permutation (IPI)
-	 *	left and right are reversed here
-	 */
-	fp(right, left, text);
-}
-
-/*
- *	Initial Permutation
- */
-static long iptab[] = {
-	0x00000000, 0x00008000, 0x00000000, 0x00008000,
-	0x00000080, 0x00008080, 0x00000080, 0x00008080
-};
-
-static long
-ip_low(char block[8])
-{
-	int i;
-	long l;
-
-	l = 0;
-	for(i = 0; i < 8; i++){
-		l |= iptab[(block[i] >> 4) & 7] >> i;
-		l |= iptab[block[i] & 7] << (16 - i);
-	}
-	return l;
-}
-
-static long
-ip_high(char block[8])
-{
-	int i;
-	long l;
-
-	l = 0;
-	for(i = 0; i < 8; i++){
-		l |= iptab[(block[i] >> 5) & 7] >> i;
-		l |= iptab[(block[i] >> 1) & 7] << (16 - i);
-	}
-	return l;
-}
-
-/*
- *	Final Permutation
- */
-static unsigned long	fptab[] = {
-0x00000000,0x80000000,0x00800000,0x80800000,0x00008000,0x80008000,0x00808000,0x80808000,
-0x00000080,0x80000080,0x00800080,0x80800080,0x00008080,0x80008080,0x00808080,0x80808080,
-};
-
-static void
-fp(long left, long right, char text[8])
-{
-	unsigned long ta[2], t, v[2];
-	int i, j, sh;
-
-	ta[0] = right;
-	ta[1] = left;
-	v[0] = v[1] = 0;
-	for(i = 0; i < 2; i++){
-		t = ta[i];
-		sh = i;
-		for(j = 0; j < 4; j++){
-			v[1] |= fptab[t & 0xf] >> sh;
-			t >>= 4;
-			v[0] |= fptab[t & 0xf] >> sh;
-			t >>= 4;
-			sh += 2;
-		}
-	}
-	for(i = 0; i < 2; i++)
-		for(j = 0; j < 4; j++){
-			*text++ = v[i];
-			v[i] >>= 8;
-		}
-}
-
-/*
- *	Key set-up
- */
-static uchar keyexpand[][15][2] = {
-	{   3,  2,   9,  8,  18,  8,  27, 32,  33,  2,  42, 16,  48,  8,  65, 16, 
-	   74,  2,  80,  2,  89,  4,  99, 16, 104,  4, 122, 32,   0,  0, },
-	{   1,  4,   8,  1,  18,  4,  25, 32,  34, 32,  41,  8,  50,  8,  59, 32, 
-	   64, 16,  75,  4,  90,  1,  97, 16, 106,  2, 112,  2, 123,  1, },
-	{   2,  1,  19,  8,  35,  1,  40,  1,  50,  4,  57, 32,  75,  2,  80, 32, 
-	   89,  1,  96, 16, 107,  4, 120,  8,   0,  0,   0,  0,   0,  0, },
-	{   4, 32,  20,  2,  31,  4,  37, 32,  47,  1,  54,  1,  63,  2,  68,  1, 
-	   78,  4,  84,  8, 101, 16, 108,  4, 119, 16, 126,  8,   0,  0, },
-	{   5,  4,  15,  4,  21, 32,  31,  1,  38,  1,  47,  2,  53,  2,  68,  8, 
-	   85, 16,  92,  4, 103, 16, 108, 32, 118, 32, 124,  2,   0,  0, },
-	{  15,  2,  21,  2,  39,  8,  46, 16,  55, 32,  61,  1,  71, 16,  76, 32, 
-	   86, 32,  93,  4, 102,  2, 108, 16, 117,  8, 126,  1,   0,  0, },
-	{  14, 16,  23, 32,  29,  1,  38,  8,  52,  2,  63,  4,  70,  2,  76, 16, 
-	   85,  8, 100,  1, 110,  4, 116,  8, 127,  8,   0,  0,   0,  0, },
-	{   1,  8,   8, 32,  17,  1,  24, 16,  35,  4,  50,  1,  57, 16,  67,  8, 
-	   83,  1,  88,  1,  98,  4, 105, 32, 114, 32, 123,  2,   0,  0, },
-	{   0,  1,  11, 16,  16,  4,  35,  2,  40, 32,  49,  1,  56, 16,  65,  2, 
-	   74, 16,  80,  8,  99,  8, 115,  1, 121,  4,   0,  0,   0,  0, },
-	{   9, 16,  18,  2,  24,  2,  33,  4,  43, 16,  48,  4,  66, 32,  73,  8, 
-	   82,  8,  91, 32,  97,  2, 106, 16, 112,  8, 122,  1,   0,  0, },
-	{  14, 32,  21,  4,  30,  2,  36, 16,  45,  8,  60,  1,  69,  2,  87,  8, 
-	   94, 16, 103, 32, 109,  1, 118,  8, 124, 32,   0,  0,   0,  0, },
-	{   7,  4,  14,  2,  20, 16,  29,  8,  44,  1,  54,  4,  60,  8,  71,  8, 
-	   78, 16,  87, 32,  93,  1, 102,  8, 116,  2, 125,  4,   0,  0, },
-	{   7,  2,  12,  1,  22,  4,  28,  8,  45, 16,  52,  4,  63, 16,  70,  8, 
-	   84,  2,  95,  4, 101, 32, 111,  1, 118,  1,   0,  0,   0,  0, },
-	{   6, 16,  13, 16,  20,  4,  31, 16,  36, 32,  46, 32,  53,  4,  62,  2, 
-	   69, 32,  79,  1,  86,  1,  95,  2, 101,  2, 119,  8,   0,  0, },
-	{   0, 32,  10,  8,  19, 32,  25,  2,  34, 16,  40,  8,  59,  8,  66,  2, 
-	   72,  2,  81,  4,  91, 16,  96,  4, 115,  2, 121,  8,   0,  0, },
-	{   3, 16,  10,  4,  17, 32,  26, 32,  33,  8,  42,  8,  51, 32,  57,  2, 
-	   67,  4,  82,  1,  89, 16,  98,  2, 104,  2, 113,  4, 120,  1, },
-	{   1, 16,  11,  8,  27,  1,  32,  1,  42,  4,  49, 32,  58, 32,  67,  2, 
-	   72, 32,  81,  1,  88, 16,  99,  4, 114,  1,   0,  0,   0,  0, },
-	{   6, 32,  12,  2,  23,  4,  29, 32,  39,  1,  46,  1,  55,  2,  61,  2, 
-	   70,  4,  76,  8,  93, 16, 100,  4, 111, 16, 116, 32,   0,  0, },
-	{   6,  2,  13, 32,  23,  1,  30,  1,  39,  2,  45,  2,  63,  8,  77, 16, 
-	   84,  4,  95, 16, 100, 32, 110, 32, 117,  4, 127,  4,   0,  0, },
-	{   4,  1,  13,  2,  31,  8,  38, 16,  47, 32,  53,  1,  62,  8,  68, 32, 
-	   78, 32,  85,  4,  94,  2, 100, 16, 109,  8, 127,  2,   0,  0, },
-	{   5, 16,  15, 32,  21,  1,  30,  8,  44,  2,  55,  4,  61, 32,  68, 16, 
-	   77,  8,  92,  1, 102,  4, 108,  8, 126, 16,   0,  0,   0,  0, },
-	{   2,  8,   9,  1,  16, 16,  27,  4,  42,  1,  49, 16,  58,  2,  75,  1, 
-	   80,  1,  90,  4,  97, 32, 106, 32, 113,  8, 120, 32,   0,  0, },
-	{   2,  4,   8,  4,  27,  2,  32, 32,  41,  1,  48, 16,  59,  4,  66, 16, 
-	   72,  8,  91,  8, 107,  1, 112,  1, 123, 16,   0,  0,   0,  0, },
-	{   3,  8,  10,  2,  16,  2,  25,  4,  35, 16,  40,  4,  59,  2,  65,  8, 
-	   74,  8,  83, 32,  89,  2,  98, 16, 104,  8, 121, 16,   0,  0, },
-	{   4,  2,  13,  4,  22,  2,  28, 16,  37,  8,  52,  1,  62,  4,  79,  8, 
-	   86, 16,  95, 32, 101,  1, 110,  8, 126, 32,   0,  0,   0,  0, },
-	{   5, 32,  12, 16,  21,  8,  36,  1,  46,  4,  52,  8,  70, 16,  79, 32, 
-	   85,  1,  94,  8, 108,  2, 119,  4, 126,  2,   0,  0,   0,  0, },
-	{   5,  2,  14,  4,  20,  8,  37, 16,  44,  4,  55, 16,  60, 32,  76,  2, 
-	   87,  4,  93, 32, 103,  1, 110,  1, 119,  2, 124,  1,   0,  0, },
-	{   7, 32,  12,  4,  23, 16,  28, 32,  38, 32,  45,  4,  54,  2,  60, 16, 
-	   71,  1,  78,  1,  87,  2,  93,  2, 111,  8, 118, 16, 125, 16, },
-	{   1,  1,  11, 32,  17,  2,  26, 16,  32,  8,  51,  8,  64,  2,  73,  4, 
-	   83, 16,  88,  4, 107,  2, 112, 32, 122,  8,   0,  0,   0,  0, },
-	{   0,  4,   9, 32,  18, 32,  25,  8,  34,  8,  43, 32,  49,  2,  58, 16, 
-	   74,  1,  81, 16,  90,  2,  96,  2, 105,  4, 115, 16, 122,  4, },
-	{   2,  2,  19,  1,  24,  1,  34,  4,  41, 32,  50, 32,  57,  8,  64, 32, 
-	   73,  1,  80, 16,  91,  4, 106,  1, 113, 16, 123,  8,   0,  0, },
-	{   3,  4,  10, 16,  16,  8,  35,  8,  51,  1,  56,  1,  67, 16,  72,  4, 
-	   91,  2,  96, 32, 105,  1, 112, 16, 121,  2,   0,  0,   0,  0, },
-	{   4, 16,  15,  1,  22,  1,  31,  2,  37,  2,  55,  8,  62, 16,  69, 16, 
-	   76,  4,  87, 16,  92, 32, 102, 32, 109,  4, 118,  2, 125, 32, },
-	{   6,  4,  23,  8,  30, 16,  39, 32,  45,  1,  54,  8,  70, 32,  77,  4, 
-	   86,  2,  92, 16, 101,  8, 116,  1, 125,  2,   0,  0,   0,  0, },
-	{   4,  4,  13,  1,  22,  8,  36,  2,  47,  4,  53, 32,  63,  1,  69,  8, 
-	   84,  1,  94,  4, 100,  8, 117, 16, 127, 32,   0,  0,   0,  0, },
-	{   3, 32,   8, 16,  19,  4,  34,  1,  41, 16,  50,  2,  56,  2,  67,  1, 
-	   72,  1,  82,  4,  89, 32,  98, 32, 105,  8, 114,  8, 121,  1, },
-	{   1, 32,  19,  2,  24, 32,  33,  1,  40, 16,  51,  4,  64,  8,  83,  8, 
-	   99,  1, 104,  1, 114,  4, 120,  4,   0,  0,   0,  0,   0,  0, },
-	{   8,  2,  17,  4,  27, 16,  32,  4,  51,  2,  56, 32,  66,  8,  75, 32, 
-	   81,  2,  90, 16,  96,  8, 115,  8, 122,  2,   0,  0,   0,  0, },
-	{   2, 16,  18,  1,  25, 16,  34,  2,  40,  2,  49,  4,  59, 16,  66,  4, 
-	   73, 32,  82, 32,  89,  8,  98,  8, 107, 32, 113,  2, 123,  4, },
-	{   7,  1,  13,  8,  28,  1,  38,  4,  44,  8,  61, 16,  71, 32,  77,  1, 
-	   86,  8, 100,  2, 111,  4, 117, 32, 124, 16,   0,  0,   0,  0, },
-	{  12,  8,  29, 16,  36,  4,  47, 16,  52, 32,  62, 32,  68,  2,  79,  4, 
-	   85, 32,  95,  1, 102,  1, 111,  2, 117,  2, 126,  4,   0,  0, },
-	{   5,  1,  15, 16,  20, 32,  30, 32,  37,  4,  46,  2,  52, 16,  61,  8, 
-	   70,  1,  79,  2,  85,  2, 103,  8, 110, 16, 119, 32, 124,  4, },
-	{   0, 16,   9,  2,  18, 16,  24,  8,  43,  8,  59,  1,  65,  4,  75, 16, 
-	   80,  4,  99,  2, 104, 32, 113,  1, 123, 32,   0,  0,   0,  0, },
-	{  10, 32,  17,  8,  26,  8,  35, 32,  41,  2,  50, 16,  56,  8,  66,  1, 
-	   73, 16,  82,  2,  88,  2,  97,  4, 107, 16, 112,  4, 121, 32, },
-	{   0,  2,  11,  1,  16,  1,  26,  4,  33, 32,  42, 32,  49,  8,  58,  8, 
-	   65,  1,  72, 16,  83,  4,  98,  1, 105, 16, 114,  2,   0,  0, },
-	{   8,  8,  27,  8,  43,  1,  48,  1,  58,  4,  64,  4,  83,  2,  88, 32, 
-	   97,  1, 104, 16, 115,  4, 122, 16,   0,  0,   0,  0,   0,  0, },
-	{   5,  8,  14,  1,  23,  2,  29,  2,  47,  8,  54, 16,  63, 32,  68,  4, 
-	   79, 16,  84, 32,  94, 32, 101,  4, 110,  2, 116, 16, 127,  1, },
-	{   4,  8,  15,  8,  22, 16,  31, 32,  37,  1,  46,  8,  60,  2,  69,  4, 
-	   78,  2,  84, 16,  93,  8, 108,  1, 118,  4,   0,  0,   0,  0, },
-	{   7, 16,  14,  8,  28,  2,  39,  4,  45, 32,  55,  1,  62,  1,  76,  1, 
-	   86,  4,  92,  8, 109, 16, 116,  4, 125,  1,   0,  0,   0,  0, },
-	{   1,  2,  11,  4,  26,  1,  33, 16,  42,  2,  48,  2,  57,  4,  64,  1, 
-	   74,  4,  81, 32,  90, 32,  97,  8, 106,  8, 115, 32, 120, 16, },
-	{   2, 32,  11,  2,  16, 32,  25,  1,  32, 16,  43,  4,  58,  1,  75,  8, 
-	   91,  1,  96,  1, 106,  4, 113, 32,   0,  0,   0,  0,   0,  0, },
-	{   3,  1,   9,  4,  19, 16,  24,  4,  43,  2,  48, 32,  57,  1,  67, 32, 
-	   73,  2,  82, 16,  88,  8, 107,  8, 120,  2,   0,  0,   0,  0, },
-	{   0,  8,  10,  1,  17, 16,  26,  2,  32,  2,  41,  4,  51, 16,  56,  4, 
-	   65, 32,  74, 32,  81,  8,  90,  8,  99, 32, 105,  2, 114, 16, },
-	{   6,  1,  20,  1,  30,  4,  36,  8,  53, 16,  60,  4,  69,  1,  78,  8, 
-	   92,  2, 103,  4, 109, 32, 119,  1, 125,  8,   0,  0,   0,  0, },
-	{   7,  8,  21, 16,  28,  4,  39, 16,  44, 32,  54, 32,  61,  4,  71,  4, 
-	   77, 32,  87,  1,  94,  1, 103,  2, 109,  2, 124,  8,   0,  0, },
-	{   6,  8,  12, 32,  22, 32,  29,  4,  38,  2,  44, 16,  53,  8,  71,  2, 
-	   77,  2,  95,  8, 102, 16, 111, 32, 117,  1, 127, 16,   0,  0, }
-};
-
-static void
-key_setup(char key[DESKEYLEN], char *ek)
-{
-	int i, j, k, mask;
-	uchar (*x)[2];
-
-	memset(ek, 0, 128);
-	x = keyexpand[0];
-	for(i = 0; i < 7; i++){
-		k = key[i];
-		for(mask = 0x80; mask; mask >>= 1){
-			if(k & mask)
-				for(j = 0; j < 15; j++)
-					ek[x[j][0]] |= x[j][1];
-			x += 15;
-		}
-	}
-}

+ 4 - 1
sys/src/cmd/unix/drawterm/devcon.c

@@ -333,8 +333,11 @@ conwrite(Chan *c, void *va, long count, ulong offset)
 int
 nrand(int n)
 {
-	static ulong randn;
+	static ulong randn = 0;
 
+	/* ticks() always starts at 0, so we need another seed */
+	if (randn == 0)
+		randn = time(0);
 	randn = randn*1103515245 + 12345 + ticks();
 	return (randn>>16) % n;
 }

+ 1455 - 0
sys/src/cmd/unix/drawterm/devssl.c

@@ -0,0 +1,1455 @@
+/*
+ *  devssl - secure sockets layer
+ */
+#include        "lib9.h"
+#include        "sys.h"
+#include        "error.h"
+#include		"libsec/libsec.h"
+
+#define NOSPOOKS 1
+
+typedef struct OneWay OneWay;
+struct OneWay
+{
+	Qlock	q;
+	Qlock	ctlq;
+
+	void	*state;		/* encryption state */
+	int	slen;		/* hash data length */
+	uchar	*secret;	/* secret */
+	ulong	mid;		/* message id */
+};
+
+enum
+{
+	/* connection states */
+	Sincomplete=	0,
+	Sclear=		1,
+	Sencrypting=	2,
+	Sdigesting=	4,
+	Sdigenc=	Sencrypting|Sdigesting,
+
+	/* encryption algorithms */
+	Noencryption=	0,
+	DESCBC=		1,
+	DESECB=		2,
+	RC4=		3
+};
+
+typedef struct Dstate Dstate;
+struct Dstate
+{
+	Chan	*c;		/* io channel */
+	uchar	state;		/* state of connection */
+	int	ref;		/* serialized by dslock for atomic destroy */
+
+	uchar	encryptalg;	/* encryption algorithm */
+	ushort	blocklen;	/* blocking length */
+
+	ushort	diglen;		/* length of digest */
+	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);	/* hash func */
+
+	/* for SSL format */
+	int	max;		/* maximum unpadded data per msg */
+	int	maxpad;		/* maximum padded data per msg */
+
+	/* input side */
+	OneWay	in;
+	Block	*processed;
+	Block	*unprocessed;
+
+	/* output side */
+	OneWay	out;
+
+	/* protections */
+	char	*user;
+	int	perm;
+};
+
+enum
+{
+	Maxdmsg=	1<<16,
+	Maxdstate=	128,	/* must be a power of 2 */
+};
+
+Lock	dslock;
+int	dshiwat;
+char	*dsname[Maxdstate];
+Dstate	*dstate[Maxdstate];
+char	*encalgs;
+char	*hashalgs;
+
+enum{
+	Qtopdir		= 1,	/* top level directory */
+	Qprotodir,
+	Qclonus,
+	Qconvdir,		/* directory for a conversation */
+	Qdata,
+	Qctl,
+	Qsecretin,
+	Qsecretout,
+	Qencalgs,
+	Qhashalgs,
+};
+
+#define TYPE(x) 	((x).path & 0xf)
+#define CONV(x) 	(((x).path >> 5)&(Maxdstate-1))
+#define QID(c, y) 	(((c)<<5) | (y))
+
+static void	ensure(Dstate*, Block**, int);
+static void	consume(Block**, uchar*, int);
+static void	setsecret(OneWay*, uchar*, int);
+static Block*	encryptb(Dstate*, Block*, int);
+static Block*	decryptb(Dstate*, Block*);
+static Block*	digestb(Dstate*, Block*, int);
+static void	checkdigestb(Dstate*, Block*);
+static Chan*	buftochan(char*);
+static void	sslhangup(Dstate*);
+static Dstate*	dsclone(Chan *c);
+static void	dsnew(Chan *c, Dstate **);
+static long	sslput(Dstate *s, Block * volatile b);
+
+Block *pullupblock(Block*, int);
+
+char *sslnames[] = {
+/*0*/		0,
+/*Qtopdir*/	0,
+/*Qprotodir*/	0,
+/*Qclonus*/	"clone",
+/*Qconvdir*/	0,
+/*Qdata*/		"data",
+/*Qctl*/		"ctl",
+/*Qsecretin*/	"secretin",
+/*Qsecretout*/	"secretout",
+/*Qencalgs*/	"encalgs",
+/*Qhashalgs*/	"hashalgs",
+};
+
+static int
+sslgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
+{
+	Qid q;
+	Dstate *ds;
+	char name[16], *p, *nm;
+	int ft;
+
+	USED(nd);
+	USED(d);
+
+	q.vers = 0;
+
+	ft = TYPE(c->qid);
+	switch(ft) {
+	case Qtopdir:
+		if(s > 0)
+			return -1;
+		q.path = CHDIR|QID(0, Qprotodir);
+		devdir(c, q, "ssl", 0, eve, 0555, dp);
+		return 1;
+	case Qprotodir:
+		if(s < dshiwat) {
+			q.path = CHDIR|QID(s, Qconvdir);
+			ds = dstate[s];
+			if(ds != 0)
+				nm = ds->user;
+			else
+				nm = eve;
+			if(dsname[s] == nil){
+				sprint(name, "%d", s);
+				dsname[s] = strdup(name);
+			}
+			devdir(c, q, dsname[s], 0, nm, 0555, dp);
+			return 1;
+		}
+		if(s > dshiwat)
+			return -1;
+		q.path = QID(0, Qclonus);
+		devdir(c, q, "clone", 0, eve, 0555, dp);
+		return 1;
+	case Qconvdir:
+		ds = dstate[CONV(c->qid)];
+		if(ds != 0)
+			nm = ds->user;
+		else
+			nm = eve;
+		switch(s) {
+		default:
+			return -1;
+		case 0:
+			q.path = QID(CONV(c->qid), Qctl);
+			p = "ctl";
+			break;
+		case 1:
+			q.path = QID(CONV(c->qid), Qdata);
+			p = "data";
+			break;
+		case 2:
+			q.path = QID(CONV(c->qid), Qsecretin);
+			p = "secretin";
+			break;
+		case 3:
+			q.path = QID(CONV(c->qid), Qsecretout);
+			p = "secretout";
+			break;
+		case 4:
+			q.path = QID(CONV(c->qid), Qencalgs);
+			p = "encalgs";
+			break;
+		case 5:
+			q.path = QID(CONV(c->qid), Qhashalgs);
+			p = "hashalgs";
+			break;
+		}
+		devdir(c, q, p, 0, nm, 0660, dp);
+		return 1;
+	case Qclonus:
+		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp);
+		return 1;
+	default:
+		ds = dstate[CONV(c->qid)];
+		if(ds != 0)
+			nm = ds->user;
+		else
+			nm = eve;
+		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp);
+		return 1;
+	}
+	return -1;
+}
+
+Chan*
+sslattach(void *spec)
+{
+	Chan *c;
+
+	c = devattach('D', spec);
+	c->qid.path = CHDIR|QID(0, Qtopdir);
+	c->qid.vers = 0;
+	return c;
+}
+
+int
+sslwalk(Chan *c, char *name)
+{
+	if(strcmp(name, "..") == 0){
+		switch(TYPE(c->qid)){
+		case Qtopdir:
+			return 1;
+		case Qprotodir:
+			c->qid.path = CHDIR|QID(0, Qtopdir);
+			c->qid.vers = 0;
+			return 1;
+		case Qconvdir:
+			c->qid.path = CHDIR|QID(0, Qprotodir);
+			c->qid.vers = 0;
+			return 1;
+		}
+	}
+	return devwalk(c, name, nil, 0, sslgen);
+}
+
+void
+sslstat(Chan *c, char *db)
+{
+	devstat(c, db, nil, 0, sslgen);
+}
+
+Chan*
+sslopen(Chan *c, int omode)
+{
+	Dstate *s, **pp;
+	int perm;
+	int ft;
+
+	perm = 0;
+	omode &= 3;
+	switch(omode) {
+	case OREAD:
+		perm = 4;
+		break;
+	case OWRITE:
+		perm = 2;
+		break;
+	case ORDWR:
+		perm = 6;
+		break;
+	}
+
+	ft = TYPE(c->qid);
+	switch(ft) {
+	default:
+		panic("sslopen");
+	case Qtopdir:
+	case Qprotodir:
+	case Qconvdir:
+		if(omode != OREAD)
+			error(Eperm);
+		break;
+	case Qclonus:
+		s = dsclone(c);
+		if(s == 0)
+			error(Enodev);
+		break;
+	case Qctl:
+	case Qdata:
+	case Qsecretin:
+	case Qsecretout:
+		if(waserror()) {
+			unlock(&dslock);
+			nexterror();
+		}
+		lock(&dslock);
+		pp = &dstate[CONV(c->qid)];
+		s = *pp;
+		if(s == 0)
+			dsnew(c, pp);
+		else {
+			if((perm & (s->perm>>6)) != perm
+			   && (strcmp(up->user, s->user) != 0
+			     || (perm & s->perm) != perm))
+				error(Eperm);
+
+			s->ref++;
+		}
+		unlock(&dslock);
+		poperror();
+		break;
+	case Qencalgs:
+	case Qhashalgs:
+		if(omode != OREAD)
+			error(Eperm);
+		break;
+	}
+	c->mode = openmode(omode);
+	c->flag |= COPEN;
+	c->offset = 0;
+	return c;
+}
+
+void
+sslwstat(Chan *c, char *s)
+{
+	error(Eperm);
+}
+
+void
+sslclose(Chan *c)
+{
+	Dstate *s;
+	int ft;
+
+	ft = TYPE(c->qid);
+	switch(ft) {
+	case Qctl:
+	case Qdata:
+	case Qsecretin:
+	case Qsecretout:
+		if((c->flag & COPEN) == 0)
+			break;
+
+		s = dstate[CONV(c->qid)];
+		if(s == 0)
+			break;
+
+		lock(&dslock);
+		if(--s->ref > 0) {
+			unlock(&dslock);
+			break;
+		}
+		dstate[CONV(c->qid)] = 0;
+		unlock(&dslock);
+
+		if(s->user != nil)
+			free(s->user);
+		sslhangup(s);
+		if(s->c)
+			cclose(s->c);
+		if(s->in.secret)
+			free(s->in.secret);
+		if(s->out.secret)
+			free(s->out.secret);
+		if(s->in.state)
+			free(s->in.state);
+		if(s->out.state)
+			free(s->out.state);
+		free(s);
+
+	}
+}
+
+/*
+ *  make sure we have at least 'n' bytes in list 'l'
+ */
+static void
+ensure(Dstate *s, Block **l, int n)
+{
+	int sofar, i;
+	Block *b, *bl;
+
+	sofar = 0;
+	for(b = *l; b; b = b->next){
+		sofar += BLEN(b);
+		if(sofar >= n)
+			return;
+		l = &b->next;
+	}
+
+	while(sofar < n){
+		bl = devtab[s->c->type].bread(s->c, Maxdmsg, 0);
+		if(bl == 0)
+			nexterror();
+		*l = bl;
+		i = 0;
+		for(b = bl; b; b = b->next){
+			i += BLEN(b);
+			l = &b->next;
+		}
+		if(i == 0)
+			error(Ehungup);
+		sofar += i;
+	}
+}
+
+/*
+ *  copy 'n' bytes from 'l' into 'p' and free
+ *  the bytes in 'l'
+ */
+static void
+consume(Block **l, uchar *p, int n)
+{
+	Block *b;
+	int i;
+
+	for(; *l && n > 0; n -= i){
+		b = *l;
+		i = BLEN(b);
+		if(i > n)
+			i = n;
+		memmove(p, b->rp, i);
+		b->rp += i;
+		p += i;
+		if(BLEN(b) < 0)
+			panic("consume");
+		if(BLEN(b))
+			break;
+		*l = b->next;
+		freeb(b);
+	}
+}
+
+/*
+ *  give back n bytes
+static void
+regurgitate(Dstate *s, uchar *p, int n)
+{
+	Block *b;
+
+	if(n <= 0)
+		return;
+	b = s->unprocessed;
+	if(s->unprocessed == nil || b->rp - b->base < n) {
+		b = allocb(n);
+		memmove(b->wp, p, n);
+		b->wp += n;
+		b->next = s->unprocessed;
+		s->unprocessed = b;
+	} else {
+		b->rp -= n;
+		memmove(b->rp, p, n);
+	}
+}
+ */
+
+/*
+ *  remove at most n bytes from the queue, if discard is set
+ *  dump the remainder
+ */
+static Block*
+qtake(Block **l, int n, int discard)
+{
+	Block *nb, *b, *first;
+	int i;
+
+	first = *l;
+	for(b = first; b; b = b->next){
+		i = BLEN(b);
+		if(i == n){
+			if(discard){
+				freeblist(b->next);
+				*l = 0;
+			} else
+				*l = b->next;
+			b->next = 0;
+			return first;
+		} else if(i > n){
+			i -= n;
+			if(discard){
+				freeblist(b->next);
+				b->wp -= i;
+				*l = 0;
+			} else {
+				nb = allocb(i);
+				memmove(nb->wp, b->rp+n, i);
+				nb->wp += i;
+				b->wp -= i;
+				nb->next = b->next;
+				*l = nb;
+			}
+			b->next = 0;
+			if(BLEN(b) < 0)
+				panic("qtake");
+			return first;
+		} else
+			n -= i;
+		if(BLEN(b) < 0)
+			panic("qtake");
+	}
+	*l = 0;
+	return first;
+}
+
+/*
+ *  We can't let Eintr's lose data since the program
+ *  doing the read may be able to handle it.  The only
+ *  places Eintr is possible is during the read's in consume.
+ *  Therefore, we make sure we can always put back the bytes
+ *  consumed before the last ensure.
+ */
+Block*
+sslbread(Chan *c, long n, ulong offset)
+{
+	Dstate * volatile s;
+	Block *b;
+	uchar consumed[3], *p;
+	int toconsume;
+	int len, pad;
+
+	s = dstate[CONV(c->qid)];
+	if(s == 0)
+		panic("sslbread");
+	if(s->state == Sincomplete)
+		error(Ebadusefd);
+
+	qlock(&s->in.q);
+	if(waserror()){
+		qunlock(&s->in.q);
+		nexterror();
+	}
+
+	if(s->processed == 0){
+		/*
+		 * Read in the whole message.  Until we've got it all,
+		 * it stays on s->unprocessed, so that if we get Eintr,
+		 * we'll pick up where we left off.
+		 */
+		ensure(s, &s->unprocessed, 3);
+		s->unprocessed = pullupblock(s->unprocessed, 2);
+		p = s->unprocessed->rp;
+		if(p[0] & 0x80){
+			len = ((p[0] & 0x7f)<<8) | p[1];
+			ensure(s, &s->unprocessed, len);
+			pad = 0;
+			toconsume = 2;
+		} else {
+			s->unprocessed = pullupblock(s->unprocessed, 3);
+			len = ((p[0] & 0x3f)<<8) | p[1];
+			pad = p[2];
+			if(pad > len){
+				print("pad %d buf len %d\n", pad, len);
+				error("bad pad in ssl message");
+			}
+			toconsume = 3;
+		}
+		ensure(s, &s->unprocessed, toconsume+len);
+
+		/* skip header */
+		consume(&s->unprocessed, consumed, toconsume);
+
+		/* grab the next message and decode/decrypt it */
+		b = qtake(&s->unprocessed, len, 0);
+
+		if(blocklen(b) != len)
+			print("devssl: sslbread got wrong count %d != %d", blocklen(b), len);
+
+		if(waserror()){
+			qunlock(&s->in.ctlq);
+			if(b != nil)
+				freeb(b);
+			nexterror();
+		}
+		qlock(&s->in.ctlq);
+		switch(s->state){
+		case Sencrypting:
+			if(b == nil)
+				error("ssl message too short (encrypting)");
+			b = decryptb(s, b);
+			break;
+		case Sdigesting:
+			b = pullupblock(b, s->diglen);
+			if(b == nil)
+				error("ssl message too short (digesting)");
+			checkdigestb(s, b);
+			b->rp += s->diglen;
+			break;
+		case Sdigenc:
+			b = decryptb(s, b);
+			b = pullupblock(b, s->diglen);
+			if(b == nil)
+				error("ssl message too short (dig+enc)");
+			checkdigestb(s, b);
+			b->rp += s->diglen;
+			len -= s->diglen;
+			break;
+		}
+
+		/* remove pad */
+		if(pad)
+			s->processed = qtake(&b, len - pad, 1);
+		else
+			s->processed = b;
+		b = nil;
+		s->in.mid++;
+		qunlock(&s->in.ctlq);
+		poperror();
+	}
+
+	/* return at most what was asked for */
+	b = qtake(&s->processed, n, 0);
+
+	qunlock(&s->in.q);
+	poperror();
+
+	return b;
+}
+
+long
+sslread(Chan *c, void *a, long n, ulong off)
+{
+	Block * volatile b;
+	Block *nb;
+	uchar *va;
+	int i;
+	char buf[128];
+	ulong offset = off;
+	int ft;
+
+	if(c->qid.path & CHDIR)
+		return devdirread(c, a, n, 0, 0, sslgen);
+
+	ft = TYPE(c->qid);
+	switch(ft) {
+	default:
+		error(Ebadusefd);
+	case Qctl:
+		ft = CONV(c->qid);
+		sprint(buf, "%d", ft);
+		return readstr(offset, a, n, buf);
+	case Qdata:
+		b = sslbread(c, n, offset);
+		break;
+	case Qencalgs:
+		return readstr(offset, a, n, encalgs);
+		break;
+	case Qhashalgs:
+		return readstr(offset, a, n, hashalgs);
+		break;
+	}
+
+	if(waserror()){
+		freeblist(b);
+		nexterror();
+	}
+
+	n = 0;
+	va = a;
+	for(nb = b; nb; nb = nb->next){
+		i = BLEN(nb);
+		memmove(va+n, nb->rp, i);
+		n += i;
+	}
+
+	freeblist(b);
+	poperror();
+
+	return n;
+}
+
+/*
+ *  this algorithm doesn't have to be great since we're just
+ *  trying to obscure the block fill
+ */
+static void
+randfill(uchar *buf, int len)
+{
+	while(len-- > 0)
+		*buf++ = nrand(256);
+}
+
+long
+sslbwrite(Chan *c, Block *b, ulong offset)
+{
+	Dstate * volatile s;
+	long rv;
+
+	s = dstate[CONV(c->qid)];
+	if(s == nil)
+		panic("sslbwrite");
+
+	if(s->state == Sincomplete){
+		freeb(b);
+		error(Ebadusefd);
+	}
+
+	/* lock so split writes won't interleave */
+	if(waserror()){
+		qunlock(&s->out.q);
+		nexterror();
+	}
+	qlock(&s->out.q);
+
+	rv = sslput(s, b);
+
+	poperror();
+	qunlock(&s->out.q);
+
+	return rv;
+}
+
+/*
+ *  use SSL record format, add in count, digest and/or encrypt.
+ *  the write is interruptable.  if it is interrupted, we'll
+ *  get out of sync with the far side.  not much we can do about
+ *  it since we don't know if any bytes have been written.
+ */
+static long
+sslput(Dstate *s, Block * volatile b)
+{
+	Block *nb;
+	int h, n, m, pad, rv;
+	uchar *p;
+	int offset;
+
+	if(waserror()){
+		if(b != nil)
+			free(b);
+		nexterror();
+	}
+
+	rv = 0;
+	while(b != nil){
+		m = n = BLEN(b);
+		h = s->diglen + 2;
+
+		/* trim to maximum block size */
+		pad = 0;
+		if(m > s->max){
+			m = s->max;
+		} else if(s->blocklen != 1){
+			pad = (m + s->diglen)%s->blocklen;
+			if(pad){
+				if(m > s->maxpad){
+					pad = 0;
+					m = s->maxpad;
+				} else {
+					pad = s->blocklen - pad;
+					h++;
+				}
+			}
+		}
+
+		rv += m;
+		if(m != n){
+			nb = allocb(m + h + pad);
+			memmove(nb->wp + h, b->rp, m);
+			nb->wp += m + h;
+			b->rp += m;
+		} else {
+			/* add header space */
+			nb = padblock(b, h);
+			b = 0;
+		}
+		m += s->diglen;
+
+		/* SSL style count */
+		if(pad){
+			nb = padblock(nb, -pad);
+			randfill(nb->wp, pad);
+			nb->wp += pad;
+			m += pad;
+
+			p = nb->rp;
+			p[0] = (m>>8);
+			p[1] = m;
+			p[2] = pad;
+			offset = 3;
+		} else {
+			p = nb->rp;
+			p[0] = (m>>8) | 0x80;
+			p[1] = m;
+			offset = 2;
+		}
+
+		switch(s->state){
+		case Sencrypting:
+			nb = encryptb(s, nb, offset);
+			break;
+		case Sdigesting:
+			nb = digestb(s, nb, offset);
+			break;
+		case Sdigenc:
+			nb = digestb(s, nb, offset);
+			nb = encryptb(s, nb, offset);
+			break;
+		}
+
+		s->out.mid++;
+
+		m = BLEN(nb);
+		devtab[s->c->type].bwrite(s->c, nb, s->c->offset);
+		s->c->offset += m;
+	}
+
+	poperror();
+	return rv;
+}
+
+static void
+setsecret(OneWay *w, uchar *secret, int n)
+{
+	if(w->secret)
+		free(w->secret);
+
+	w->secret = mallocz(n);
+	memmove(w->secret, secret, n);
+	w->slen = n;
+}
+
+static void
+initDESkey(OneWay *w)
+{
+	if(w->state){
+		free(w->state);
+		w->state = 0;
+	}
+
+	w->state = mallocz(sizeof(DESstate));
+	if(w->slen >= 16)
+		setupDESstate(w->state, w->secret, w->secret+8);
+	else if(w->slen >= 8)
+		setupDESstate(w->state, w->secret, 0);
+	else
+		error("secret too short");
+}
+
+/*
+ *  40 bit DES is the same as 56 bit DES.  However,
+ *  16 bits of the key are masked to zero.
+ */
+static void
+initDESkey_40(OneWay *w)
+{
+	uchar key[8];
+
+	if(w->state){
+		free(w->state);
+		w->state = 0;
+	}
+
+	if(w->slen >= 8){
+		memmove(key, w->secret, 8);
+		key[0] &= 0x0f;
+		key[2] &= 0x0f;
+		key[4] &= 0x0f;
+		key[6] &= 0x0f;
+	}
+
+	w->state = malloc(sizeof(DESstate));
+	if(w->slen >= 16)
+		setupDESstate(w->state, key, w->secret+8);
+	else if(w->slen >= 8)
+		setupDESstate(w->state, key, 0);
+	else
+		error("secret too short");
+}
+
+static void
+initRC4key(OneWay *w)
+{
+	if(w->state){
+		free(w->state);
+		w->state = 0;
+	}
+
+	w->state = mallocz(sizeof(RC4state));
+	setupRC4state(w->state, w->secret, w->slen);
+}
+
+/*
+ *  40 bit RC4 is the same as n-bit RC4.  However,
+ *  we ignore all but the first 40 bits of the key.
+ */
+static void
+initRC4key_40(OneWay *w)
+{
+	if(w->state){
+		free(w->state);
+		w->state = 0;
+	}
+
+	if(w->slen > 5)
+		w->slen = 5;
+
+	w->state = malloc(sizeof(RC4state));
+	setupRC4state(w->state, w->secret, w->slen);
+}
+
+/*
+ *  128 bit RC4 is the same as n-bit RC4.  However,
+ *  we ignore all but the first 128 bits of the key.
+ */
+static void
+initRC4key_128(OneWay *w)
+{
+	if(w->state){
+		free(w->state);
+		w->state = 0;
+	}
+
+	if(w->slen > 16)
+		w->slen = 16;
+
+	w->state = malloc(sizeof(RC4state));
+	setupRC4state(w->state, w->secret, w->slen);
+}
+
+
+typedef struct Hashalg Hashalg;
+struct Hashalg
+{
+	char	*name;
+	int	diglen;
+	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);
+};
+
+Hashalg hashtab[] =
+{
+	{ "md4", MD4dlen, md4, },
+	{ "md5", MD5dlen, md5, },
+	{ "sha1", SHA1dlen, sha1, },
+	{ "sha", SHA1dlen, sha1, },
+	{ 0 }
+};
+
+static int
+parsehashalg(char *p, Dstate *s)
+{
+	Hashalg *ha;
+
+	for(ha = hashtab; ha->name; ha++){
+		if(strcmp(p, ha->name) == 0){
+			s->hf = ha->hf;
+			s->diglen = ha->diglen;
+			s->state &= ~Sclear;
+			s->state |= Sdigesting;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+typedef struct Encalg Encalg;
+struct Encalg
+{
+	char	*name;
+	int	blocklen;
+	int	alg;
+	void	(*keyinit)(OneWay*);
+};
+
+#ifdef NOSPOOKS
+Encalg encrypttab[] =
+{
+	{ "descbc", 8, DESCBC, initDESkey, },           /* DEPRECATED -- use des_56_cbc */
+	{ "desecb", 8, DESECB, initDESkey, },           /* DEPRECATED -- use des_56_ecb */
+	{ "des_56_cbc", 8, DESCBC, initDESkey, },
+	{ "des_56_ecb", 8, DESECB, initDESkey, },
+	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
+	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
+	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
+	{ "rc4_256", 1, RC4, initRC4key, },
+	{ "rc4_128", 1, RC4, initRC4key_128, },
+	{ "rc4_40", 1, RC4, initRC4key_40, },
+	{ 0 }
+};
+#else
+Encalg encrypttab[] =
+{
+	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
+	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
+	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
+	{ "rc4_40", 1, RC4, initRC4key_40, },
+	{ 0 }
+};
+#endif NOSPOOKS
+
+static int
+parseencryptalg(char *p, Dstate *s)
+{
+	Encalg *ea;
+
+	for(ea = encrypttab; ea->name; ea++){
+		if(strcmp(p, ea->name) == 0){
+			s->encryptalg = ea->alg;
+			s->blocklen = ea->blocklen;
+			(*ea->keyinit)(&s->in);
+			(*ea->keyinit)(&s->out);
+			s->state &= ~Sclear;
+			s->state |= Sencrypting;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+long
+sslwrite(Chan *c, void *a, long n, ulong offset)
+{
+	Dstate * volatile s;
+	Block * volatile b;
+	int m, t;
+	char *p, *np, *e, buf[128];
+	uchar *x;
+
+	s = dstate[CONV(c->qid)];
+	if(s == 0)
+		panic("sslwrite");
+
+	t = TYPE(c->qid);
+	if(t == Qdata){
+		if(s->state == Sincomplete)
+			error(Ebadusefd);
+
+		/* lock should a write gets split over multiple records */
+		if(waserror()){
+			qunlock(&s->out.q);
+			nexterror();
+		}
+		qlock(&s->out.q);
+
+		p = a;
+		e = p + n;
+		do {
+			m = e - p;
+			if(m > s->max)
+				m = s->max;
+
+			b = allocb(m);
+			if(waserror()){
+				freeb(b);
+				nexterror();
+			}
+			memmove(b->wp, p, m);
+			poperror();
+			b->wp += m;
+
+			sslput(s, b);
+
+			p += m;
+		} while(p < e);
+
+		poperror();
+		qunlock(&s->out.q);
+		return n;
+	}
+
+	/* mutex with operations using what we're about to change */
+	if(waserror()){
+		qunlock(&s->in.ctlq);
+		qunlock(&s->out.q);
+		nexterror();
+	}
+	qlock(&s->in.ctlq);
+	qlock(&s->out.q);
+
+	switch(t){
+	default:
+		panic("sslwrite");
+	case Qsecretin:
+		setsecret(&s->in, a, n);
+		goto out;
+	case Qsecretout:
+		setsecret(&s->out, a, n);
+		goto out;
+	case Qctl:
+		break;
+	}
+
+	if(n >= sizeof(buf))
+		error("arg too long");
+	strncpy(buf, a, n);
+	buf[n] = 0;
+	p = strchr(buf, '\n');
+	if(p)
+		*p = 0;
+	p = strchr(buf, ' ');
+	if(p)
+		*p++ = 0;
+
+	if(strcmp(buf, "fd") == 0){
+		s->c = buftochan(p);
+
+		/* default is clear (msg delimiters only) */
+		s->state = Sclear;
+		s->blocklen = 1;
+		s->diglen = 0;
+		s->maxpad = s->max = (1<<15) - s->diglen - 1;
+		s->in.mid = 0;
+		s->out.mid = 0;
+	} else if(strcmp(buf, "alg") == 0 && p != 0){
+		s->blocklen = 1;
+		s->diglen = 0;
+
+		if(s->c == 0)
+			error("must set fd before algorithm");
+
+		s->state = Sclear;
+		s->maxpad = s->max = (1<<15) - s->diglen - 1;
+		if(strcmp(p, "clear") == 0){
+			goto out;
+		}
+
+		if(s->in.secret && s->out.secret == 0)
+			setsecret(&s->out, s->in.secret, s->in.slen);
+		if(s->out.secret && s->in.secret == 0)
+			setsecret(&s->in, s->out.secret, s->out.slen);
+		if(s->in.secret == 0 || s->out.secret == 0)
+			error("algorithm but no secret");
+
+		s->hf = 0;
+		s->encryptalg = Noencryption;
+		s->blocklen = 1;
+
+		for(;;){
+			np = strchr(p, ' ');
+			if(np)
+				*np++ = 0;
+
+			if(parsehashalg(p, s) < 0)
+			if(parseencryptalg(p, s) < 0)
+				error("bad algorithm");
+
+			if(np == 0)
+				break;
+			p = np;
+		}
+
+		if(s->hf == 0 && s->encryptalg == Noencryption)
+			error("bad algorithm");
+
+		if(s->blocklen != 1){
+			s->max = (1<<15) - s->diglen - 1;
+			s->max -= s->max % s->blocklen;
+			s->maxpad = (1<<14) - s->diglen - 1;
+			s->maxpad -= s->maxpad % s->blocklen;
+		} else
+			s->maxpad = s->max = (1<<15) - s->diglen - 1;
+	} else if(strcmp(buf, "secretin") == 0 && p != 0) {
+		m = (strlen(p)*3)/2;
+		x = mallocz(m);
+		t = dec64(x, m, p, strlen(p));
+		setsecret(&s->in, x, t);
+		free(x);
+	} else if(strcmp(buf, "secretout") == 0 && p != 0) {
+		m = (strlen(p)*3)/2 + 1;
+		x = mallocz(m);
+		t = dec64(x, m, p, strlen(p));
+		setsecret(&s->out, x, t);
+		free(x);
+	} else
+		error(Ebadarg);
+
+out:
+	qunlock(&s->in.ctlq);
+	qunlock(&s->out.q);
+	poperror();
+	return n;
+}
+
+void
+sslinit(void)
+{
+	struct Encalg *e;
+	struct Hashalg *h;
+	int n;
+	char *cp;
+
+	n = 1;
+	for(e = encrypttab; e->name != nil; e++)
+		n += strlen(e->name) + 1;
+	cp = encalgs = mallocz(n);
+	for(e = encrypttab;;){
+		strcpy(cp, e->name);
+		cp += strlen(e->name);
+		e++;
+		if(e->name == nil)
+			break;
+		*cp++ = ' ';
+	}
+	*cp = 0;
+
+	n = 1;
+	for(h = hashtab; h->name != nil; h++)
+		n += strlen(h->name) + 1;
+	cp = hashalgs = mallocz(n);
+	for(h = hashtab;;){
+		strcpy(cp, h->name);
+		cp += strlen(h->name);
+		h++;
+		if(h->name == nil)
+			break;
+		*cp++ = ' ';
+	}
+	*cp = 0;
+}
+
+static Block*
+encryptb(Dstate *s, Block *b, int offset)
+{
+	uchar *p, *ep, *p2, *ip, *eip;
+	DESstate *ds;
+
+	switch(s->encryptalg){
+	case DESECB:
+		ds = s->out.state;
+		ep = b->rp + BLEN(b);
+		for(p = b->rp + offset; p < ep; p += 8)
+			block_cipher(ds->expanded, p, 0);
+		break;
+	case DESCBC:
+		ds = s->out.state;
+		ep = b->rp + BLEN(b);
+		for(p = b->rp + offset; p < ep; p += 8){
+			p2 = p;
+			ip = ds->ivec;
+			for(eip = ip+8; ip < eip; )
+				*p2++ ^= *ip++;
+			block_cipher(ds->expanded, p, 0);
+			memmove(ds->ivec, p, 8);
+		}
+		break;
+	case RC4:
+		rc4(s->out.state, b->rp + offset, BLEN(b) - offset);
+		break;
+	}
+	return b;
+}
+
+static Block*
+decryptb(Dstate *s, Block *bin)
+{
+	Block *b, **l;
+	uchar *p, *ep, *tp, *ip, *eip;
+	DESstate *ds;
+	uchar tmp[8];
+	int i;
+
+	l = &bin;
+	for(b = bin; b; b = b->next){
+		/* make sure we have a multiple of s->blocklen */
+		if(s->blocklen > 1){
+			i = BLEN(b);
+			if(i % s->blocklen){
+				*l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen));
+				if(b == 0)
+					error("ssl encrypted message too short");
+			}
+		}
+		l = &b->next;
+
+		/* decrypt */
+		switch(s->encryptalg){
+		case DESECB:
+			ds = s->in.state;
+			ep = b->rp + BLEN(b);
+			for(p = b->rp; p < ep; p += 8)
+				block_cipher(ds->expanded, p, 1);
+			break;
+		case DESCBC:
+			ds = s->in.state;
+			ep = b->rp + BLEN(b);
+			for(p = b->rp; p < ep;){
+				memmove(tmp, p, 8);
+				block_cipher(ds->expanded, p, 1);
+				tp = tmp;
+				ip = ds->ivec;
+				for(eip = ip+8; ip < eip; ){
+					*p++ ^= *ip;
+					*ip++ = *tp++;
+				}
+			}
+			break;
+		case RC4:
+			rc4(s->in.state, b->rp, BLEN(b));
+			break;
+		}
+	}
+	return bin;
+}
+
+static Block*
+digestb(Dstate *s, Block *b, int offset)
+{
+	uchar *p;
+	DigestState ss;
+	uchar msgid[4];
+	ulong n, h;
+	OneWay *w;
+
+	w = &s->out;
+
+	memset(&ss, 0, sizeof(ss));
+	h = s->diglen + offset;
+	n = BLEN(b) - h;
+
+	/* hash secret + message */
+	(*s->hf)(w->secret, w->slen, 0, &ss);
+	(*s->hf)(b->rp + h, n, 0, &ss);
+
+	/* hash message id */
+	p = msgid;
+	n = w->mid;
+	*p++ = n>>24;
+	*p++ = n>>16;
+	*p++ = n>>8;
+	*p = n;
+	(*s->hf)(msgid, 4, b->rp + offset, &ss);
+
+	return b;
+}
+
+static void
+checkdigestb(Dstate *s, Block *bin)
+{
+	uchar *p;
+	DigestState ss;
+	uchar msgid[4];
+	int n, h;
+	OneWay *w;
+	uchar digest[128];
+	Block *b;
+
+	w = &s->in;
+
+	memset(&ss, 0, sizeof(ss));
+
+	/* hash secret */
+	(*s->hf)(w->secret, w->slen, 0, &ss);
+
+	/* hash message */
+	h = s->diglen;
+	for(b = bin; b; b = b->next){
+		n = BLEN(b) - h;
+		if(n < 0)
+			panic("checkdigestb");
+		(*s->hf)(b->rp + h, n, 0, &ss);
+		h = 0;
+	}
+
+	/* hash message id */
+	p = msgid;
+	n = w->mid;
+	*p++ = n>>24;
+	*p++ = n>>16;
+	*p++ = n>>8;
+	*p = n;
+	(*s->hf)(msgid, 4, digest, &ss);
+
+	if(memcmp(digest, bin->rp, s->diglen) != 0)
+		error("bad digest");
+}
+
+/* get channel associated with an fd */
+static Chan*
+buftochan(char *p)
+{
+	Chan *c;
+	int fd;
+
+	if(p == 0)
+		error(Ebadarg);
+	fd = strtoul(p, 0, 0);
+	if(fd < 0)
+		error(Ebadarg);
+	c = fdtochan(fd, -1, 0, 1);	/* error check and inc ref */
+	if(devtab[c->type].init == sslinit){
+		cclose(c);
+		error("cannot ssl encrypt devssl files");
+	}
+	return c;
+}
+
+/* hand up a digest connection */
+static void
+sslhangup(Dstate *s)
+{
+	Block *b;
+
+	qlock(&s->in.q);
+	for(b = s->processed; b; b = s->processed){
+		s->processed = b->next;
+		freeb(b);
+	}
+	if(s->unprocessed){
+		freeb(s->unprocessed);
+		s->unprocessed = 0;
+	}
+	s->state = Sincomplete;
+	qunlock(&s->in.q);
+}
+
+static Dstate*
+dsclone(Chan *ch)
+{
+	int i;
+	Dstate *ret;
+
+	if(waserror()) {
+		unlock(&dslock);
+		nexterror();
+	}
+	lock(&dslock);
+	ret = nil;
+	for(i=0; i<Maxdstate; i++){
+		if(dstate[i] == nil){
+			dsnew(ch, &dstate[i]);
+			ret = dstate[i];
+			break;
+		}
+	}
+	unlock(&dslock);
+	poperror();
+	return ret;
+}
+
+static void
+dsnew(Chan *ch, Dstate **pp)
+{
+	Dstate *s;
+	int t;
+
+	*pp = s = malloc(sizeof(*s));
+	if(!s)
+		error(Enomem);
+	if(pp - dstate >= dshiwat)
+		dshiwat++;
+	memset(s, 0, sizeof(*s));
+	s->state = Sincomplete;
+	s->ref = 1;
+	s->user = strdup(up->user);
+	s->perm = 0660;
+	t = TYPE(ch->qid);
+	if(t == Qclonus)
+		t = Qctl;
+	ch->qid.path = QID(pp - dstate, t);
+	ch->qid.vers = 0;
+}

+ 8 - 1
sys/src/cmd/unix/drawterm/devtab.c

@@ -4,7 +4,7 @@
 
 Ref     mountid;
 
-Rune    devchar[] = { '/', 'U', 'M', 'I', 'c', 'i', 'm', '|', 0 };
+Rune    devchar[] = { '/', 'U', 'M', 'I', 'c', 'i', 'm', '|', 'D', 0 };
 Dev     devtab[] =
 {
 	/* Root File System */
@@ -63,4 +63,11 @@ Dev     devtab[] =
 		piperead,	pipebread,	pipewrite,       pipebwrite,
 		piperemove,	pipewstat
 	},
+	/* SSL */
+	{
+		sslinit, 	sslattach,	devclone,		sslwalk,
+		sslstat,	sslopen,	devcreate,		sslclose,
+		sslread,	sslbread,	sslwrite,		sslbwrite,
+		devremove,	sslwstat
+	},
 };

+ 1 - 1
sys/src/cmd/unix/drawterm/doprint.c

@@ -527,7 +527,7 @@ cconv(va_list *arg, Fconv *fp)
 	char s[10];
 	Rune rune;
 
-	rune = va_arg(*arg, Rune);
+	rune = va_arg(*arg, unsigned int);
 	if(fp->chr == 'c')
 		rune &= 0xff;
 	s[runetochar(s, &rune)] = 0;

+ 52 - 14
sys/src/cmd/unix/drawterm/drawterm.c

@@ -1,8 +1,10 @@
 #include "lib9.h"
 #include "auth.h"
+#include "libsec/libsec.h"
 
 char	*cpuaddr = "plan9cpu";
 char	*authaddr = "plan9auth";
+char	*ealgs = "rc4_256 sha1";
 
 static char *pbmsg = "AS protocol botch";
 static char *ccmsg = "can't connect to AS";
@@ -15,7 +17,7 @@ static void	fdwritestr(int, char*, char*, int);
 static int	fdreadstr(int, char*, int);
 static void	noteproc(char *pid);
 static void	getpasswd(char *p, int len);
-static void	userpasswd(int islocal);
+static void	userpasswd(char *key, int islocal);
 static int	outin(char *prompt, char *def, int len);
 static char	*checkkey(char *name, char *key);
 static int	writefile(char *name, char *buf, int len);
@@ -63,6 +65,11 @@ main(int argc, char *argv[])
 	case 'd':
 		depth = atoi(ARGF());
 		break;
+	case 'e':
+		ealgs = ARGF();
+		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
+			ealgs = nil;
+		break;
 	case 'n':
 		setam("netkey");
 		break;
@@ -141,24 +148,24 @@ cpu(void)
 	int fd;
 	char na[256];
 
-	userpasswd(0);
+	userpasswd(na, 0);
 	
 	netmkaddr(na, cpuaddr, "tcp", "17005");
 	if((fd = dial(na, 0, 0, 0)) < 0) {
 		fatal("can't dial %s: %r", na);
 	}
-	if(auth(fd) < 0)
+	if(auth(fd, 0) < 0)
 		fatal("can't authenticate: %r");
 	return fd;
 }
 
 /* authentication mechanisms */
-static int	netkeyauth(int);
+static int	netkeyauth(int, uchar*);
 
 typedef struct AuthMethod AuthMethod;
 struct AuthMethod {
 	char	*name;			/* name of method */
-	int	(*cf)(int);		/* client side authentication */
+	int	(*cf)(int, uchar*);		/* client side authentication */
 } authmethod[] =
 {
 	{ "p9",		auth},
@@ -177,13 +184,24 @@ setam(char *name)
 	return -1;
 }
 
+static void
+mksecret(char *t, uchar *f)
+{
+	sprint(t, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
+		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
+}
+
 char *negstr = "negotiating authentication method";
 int
 nncpu(void)
 {
 	char na[128];
 	char err[ERRLEN];
-	int fd, n;
+	uchar key[16];
+	uchar digest[SHA1dlen];
+	char fromclientsecret[21];
+	char fromserversecret[21];
+	int fd, n, i;
 
 	netmkaddr(na, cpuaddr, "tcp", "17013");
 	if((fd = dial(na, 0, 0, 0)) < 0) {
@@ -191,10 +209,14 @@ nncpu(void)
 	}
 
 	if(am->cf == auth)
-		userpasswd(0);
+		userpasswd(key+4, 0);
 	
 	/* negotiate authentication mechanism */
-	fdwritestr(fd, am->name, negstr, 0);
+	if(ealgs != nil)
+		snprint(na, sizeof(na), "%s %s", am->name, ealgs);
+	else
+		snprint(na, sizeof(na), "%s", am->name);
+	fdwritestr(fd, na, negstr, 0);
 	n = fdreadstr(fd, err, ERRLEN);
 	if(n < 0)
 		fatal(negstr);
@@ -202,8 +224,24 @@ nncpu(void)
 		fatal("%s: %s", negstr, err);
 
 	/* authenticate */
-	if((*am->cf)(fd) < 0)
+	if((*am->cf)(fd, key+4) < 0)
 		fatal("cannot authenticate with %s", am->name);
+	if(ealgs == nil)
+		return fd;
+
+	/* ssl handshake */
+	for(i = 0; i < 4; i++)
+		key[i] = nrand(256);
+	if(write(fd, key, 4) != 4 || readn(fd, key+12, 4) != 4)
+		fatal("cannot exchange random numbers for ssl: %r");
+	/* scramble into two secrets */
+	sha1(key, sizeof(key), digest, nil);
+	mksecret(fromclientsecret, digest);
+	mksecret(fromserversecret, digest+10);
+	/* set up encryption */
+	fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
+	if(fd < 0)
+		fatal("cannot establish ssl connection: %r");
 	return fd;
 }
 
@@ -228,11 +266,12 @@ readln(char *buf, int n)
 }
 
 static int
-netkeyauth(int fd)
+netkeyauth(int fd, uchar *secret)
 {
 	char chall[NAMELEN];
 	char resp[NAMELEN];
 
+	USED(secret);
 	strcpy(chall, getuser());
 	print("user[%s]: ", chall);
 	if(readln(resp, sizeof(resp)) < 0)
@@ -257,7 +296,7 @@ netkeyauth(int fd)
 void
 usage(void)
 {
-	iprint("usage: %s [-o@] [-n] [-m] [-c cpusrv] [-a authsrv] [-r root]\n", argv0);
+	iprint("usage: %s [-o@] [-n] [-m] [-c cpusrv] [-a authsrv] [-e 'crypt hash'] [-r root]\n", argv0);
 	exits(0);
 }
 
@@ -299,7 +338,7 @@ noteproc(char *pid)
 	netmkaddr(na, cpuaddr, "tcp", "17006");
 	if((fd = dial(na, 0, 0, 0)) < 0)
 		fatal("can't dial");
-	if(auth(fd) < 0)
+	if(auth(fd, 0) < 0)
 		fatal("can't authenticate");
 
 	sprint(cmd, "%s", pid);
@@ -335,11 +374,10 @@ char *homsg = "can't set user name or key; please reboot";
  *  get/set user name and password.  verify password with auth server.
  */
 void
-userpasswd(int islocal)
+userpasswd(char *hostkey, int islocal)
 {
 	int fd;
 	char *msg;
-	char hostkey[DESKEYLEN];
 
 	if(*username == 0 || strcmp(username, "none") == 0){
 		strcpy(username, "none");

+ 1 - 1
sys/src/cmd/unix/drawterm/latin1.c

@@ -62,7 +62,7 @@ struct cvlist
 	"v\"", "Uu", { 0x1D9, 0x1DA, },
 	"v", "CcDdEeLlNnRrSsTtZzAaIiOoUuGgKkj", { 0x10C, 0x10D, 0x10E, 0x10F, 0x11A, 0x11B, 0x13D, 0x13E, 0x147, 0x148, 0x158, 0x159, 0x160, 0x161, 0x164, 0x165, 0x17D, 0x17E, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1F0, },
 	"u", "AEeGgIiOoUu-a", { 0x102, 0x114, 0x115, 0x11E, 0x11F, 0x12C, 0x12D, 0x14E, 0x14F, 0x16C, 0x16D, 0x289, 0x2191, },
-	":", "-=)", { 0xF7, 0x2254, 0x263A, },
+	":", "-=()", { 0xF7, 0x2254, 0x2639, 0x263A, },
 	"a", "ebn", { 0xE6, 0x2194, 0x2220, },
 	"/", "Oo", { 0xD8, 0xF8, },
 	"Dv", "Zz", { 0x1C4, 0x1C5, },

+ 1 - 0
sys/src/cmd/unix/drawterm/lib9.h

@@ -48,6 +48,7 @@ typedef unsigned short	Rune;
 #define uchar	p9_uchar
 #define ushort	p9_ushort
 #define uint	p9_uint
+#define u32int	p9_ulong
 
 /* #define long int rather than p9_long so that "unsigned long" is valid */
 #define long	int

+ 480 - 0
sys/src/cmd/unix/drawterm/libsec/des.c

@@ -0,0 +1,480 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+/*
+ * integrated sbox & p perm
+ */
+static u32int spbox[] = {
+
+0x00808200,0x00000000,0x00008000,0x00808202,0x00808002,0x00008202,0x00000002,0x00008000,
+0x00000200,0x00808200,0x00808202,0x00000200,0x00800202,0x00808002,0x00800000,0x00000002,
+0x00000202,0x00800200,0x00800200,0x00008200,0x00008200,0x00808000,0x00808000,0x00800202,
+0x00008002,0x00800002,0x00800002,0x00008002,0x00000000,0x00000202,0x00008202,0x00800000,
+0x00008000,0x00808202,0x00000002,0x00808000,0x00808200,0x00800000,0x00800000,0x00000200,
+0x00808002,0x00008000,0x00008200,0x00800002,0x00000200,0x00000002,0x00800202,0x00008202,
+0x00808202,0x00008002,0x00808000,0x00800202,0x00800002,0x00000202,0x00008202,0x00808200,
+0x00000202,0x00800200,0x00800200,0x00000000,0x00008002,0x00008200,0x00000000,0x00808002,
+
+0x40084010,0x40004000,0x00004000,0x00084010,0x00080000,0x00000010,0x40080010,0x40004010,
+0x40000010,0x40084010,0x40084000,0x40000000,0x40004000,0x00080000,0x00000010,0x40080010,
+0x00084000,0x00080010,0x40004010,0x00000000,0x40000000,0x00004000,0x00084010,0x40080000,
+0x00080010,0x40000010,0x00000000,0x00084000,0x00004010,0x40084000,0x40080000,0x00004010,
+0x00000000,0x00084010,0x40080010,0x00080000,0x40004010,0x40080000,0x40084000,0x00004000,
+0x40080000,0x40004000,0x00000010,0x40084010,0x00084010,0x00000010,0x00004000,0x40000000,
+0x00004010,0x40084000,0x00080000,0x40000010,0x00080010,0x40004010,0x40000010,0x00080010,
+0x00084000,0x00000000,0x40004000,0x00004010,0x40000000,0x40080010,0x40084010,0x00084000,
+
+0x00000104,0x04010100,0x00000000,0x04010004,0x04000100,0x00000000,0x00010104,0x04000100,
+0x00010004,0x04000004,0x04000004,0x00010000,0x04010104,0x00010004,0x04010000,0x00000104,
+0x04000000,0x00000004,0x04010100,0x00000100,0x00010100,0x04010000,0x04010004,0x00010104,
+0x04000104,0x00010100,0x00010000,0x04000104,0x00000004,0x04010104,0x00000100,0x04000000,
+0x04010100,0x04000000,0x00010004,0x00000104,0x00010000,0x04010100,0x04000100,0x00000000,
+0x00000100,0x00010004,0x04010104,0x04000100,0x04000004,0x00000100,0x00000000,0x04010004,
+0x04000104,0x00010000,0x04000000,0x04010104,0x00000004,0x00010104,0x00010100,0x04000004,
+0x04010000,0x04000104,0x00000104,0x04010000,0x00010104,0x00000004,0x04010004,0x00010100,
+
+0x80401000,0x80001040,0x80001040,0x00000040,0x00401040,0x80400040,0x80400000,0x80001000,
+0x00000000,0x00401000,0x00401000,0x80401040,0x80000040,0x00000000,0x00400040,0x80400000,
+0x80000000,0x00001000,0x00400000,0x80401000,0x00000040,0x00400000,0x80001000,0x00001040,
+0x80400040,0x80000000,0x00001040,0x00400040,0x00001000,0x00401040,0x80401040,0x80000040,
+0x00400040,0x80400000,0x00401000,0x80401040,0x80000040,0x00000000,0x00000000,0x00401000,
+0x00001040,0x00400040,0x80400040,0x80000000,0x80401000,0x80001040,0x80001040,0x00000040,
+0x80401040,0x80000040,0x80000000,0x00001000,0x80400000,0x80001000,0x00401040,0x80400040,
+0x80001000,0x00001040,0x00400000,0x80401000,0x00000040,0x00400000,0x00001000,0x00401040,
+
+0x00000080,0x01040080,0x01040000,0x21000080,0x00040000,0x00000080,0x20000000,0x01040000,
+0x20040080,0x00040000,0x01000080,0x20040080,0x21000080,0x21040000,0x00040080,0x20000000,
+0x01000000,0x20040000,0x20040000,0x00000000,0x20000080,0x21040080,0x21040080,0x01000080,
+0x21040000,0x20000080,0x00000000,0x21000000,0x01040080,0x01000000,0x21000000,0x00040080,
+0x00040000,0x21000080,0x00000080,0x01000000,0x20000000,0x01040000,0x21000080,0x20040080,
+0x01000080,0x20000000,0x21040000,0x01040080,0x20040080,0x00000080,0x01000000,0x21040000,
+0x21040080,0x00040080,0x21000000,0x21040080,0x01040000,0x00000000,0x20040000,0x21000000,
+0x00040080,0x01000080,0x20000080,0x00040000,0x00000000,0x20040000,0x01040080,0x20000080,
+
+0x10000008,0x10200000,0x00002000,0x10202008,0x10200000,0x00000008,0x10202008,0x00200000,
+0x10002000,0x00202008,0x00200000,0x10000008,0x00200008,0x10002000,0x10000000,0x00002008,
+0x00000000,0x00200008,0x10002008,0x00002000,0x00202000,0x10002008,0x00000008,0x10200008,
+0x10200008,0x00000000,0x00202008,0x10202000,0x00002008,0x00202000,0x10202000,0x10000000,
+0x10002000,0x00000008,0x10200008,0x00202000,0x10202008,0x00200000,0x00002008,0x10000008,
+0x00200000,0x10002000,0x10000000,0x00002008,0x10000008,0x10202008,0x00202000,0x10200000,
+0x00202008,0x10202000,0x00000000,0x10200008,0x00000008,0x00002000,0x10200000,0x00202008,
+0x00002000,0x00200008,0x10002008,0x00000000,0x10202000,0x10000000,0x00200008,0x10002008,
+
+0x00100000,0x02100001,0x02000401,0x00000000,0x00000400,0x02000401,0x00100401,0x02100400,
+0x02100401,0x00100000,0x00000000,0x02000001,0x00000001,0x02000000,0x02100001,0x00000401,
+0x02000400,0x00100401,0x00100001,0x02000400,0x02000001,0x02100000,0x02100400,0x00100001,
+0x02100000,0x00000400,0x00000401,0x02100401,0x00100400,0x00000001,0x02000000,0x00100400,
+0x02000000,0x00100400,0x00100000,0x02000401,0x02000401,0x02100001,0x02100001,0x00000001,
+0x00100001,0x02000000,0x02000400,0x00100000,0x02100400,0x00000401,0x00100401,0x02100400,
+0x00000401,0x02000001,0x02100401,0x02100000,0x00100400,0x00000000,0x00000001,0x02100401,
+0x00000000,0x00100401,0x02100000,0x00000400,0x02000001,0x02000400,0x00000400,0x00100001,
+
+0x08000820,0x00000800,0x00020000,0x08020820,0x08000000,0x08000820,0x00000020,0x08000000,
+0x00020020,0x08020000,0x08020820,0x00020800,0x08020800,0x00020820,0x00000800,0x00000020,
+0x08020000,0x08000020,0x08000800,0x00000820,0x00020800,0x00020020,0x08020020,0x08020800,
+0x00000820,0x00000000,0x00000000,0x08020020,0x08000020,0x08000800,0x00020820,0x00020000,
+0x00020820,0x00020000,0x08020800,0x00000800,0x00000020,0x08020020,0x00000800,0x00020820,
+0x08000800,0x00000020,0x08000020,0x08020000,0x08020020,0x08000000,0x00020000,0x08000820,
+0x00000000,0x08020820,0x00020020,0x08000020,0x08020000,0x08000800,0x08000820,0x00000000,
+0x08020820,0x00020800,0x00020800,0x00000820,0x00000820,0x00020020,0x08000000,0x08020800,
+};
+
+/*
+ * for manual index calculation
+ * #define fetch(box, i, sh) (*((u32int*)((uchar*)spbox + (box << 8) + ((i >> (sh)) & 0xfc))))
+ */
+#define fetch(box, i, sh) ((spbox+(box << 6))[((i >> (sh + 2)) & 0x3f)])
+
+/*
+ * DES electronic codebook encryption of one block
+ */
+void
+block_cipher(ulong key[32], uchar text[8], int decrypting)
+{
+	u32int right, left, v0, v1;
+	int i, keystep;
+
+	/*
+	 * initial permutation
+	 */
+	v0 = text[0] | ((u32int)text[2]<<8) | ((u32int)text[4]<<16) | ((u32int)text[6]<<24);
+	left = text[1] | ((u32int)text[3]<<8) | ((u32int)text[5]<<16) | ((u32int)text[7]<<24);
+	right = (left & 0xaaaaaaaa) | ((v0 >> 1) & 0x55555555);
+	left = ((left << 1) & 0xaaaaaaaa) | (v0 & 0x55555555);
+	left = ((left << 6) & 0x33003300)
+		| (left & 0xcc33cc33)
+		| ((left >> 6) & 0x00cc00cc);
+	left = ((left << 12) & 0x0f0f0000)
+		| (left & 0xf0f00f0f)
+		| ((left >> 12) & 0x0000f0f0);
+	right = ((right << 6) & 0x33003300)
+		| (right & 0xcc33cc33)
+		| ((right >> 6) & 0x00cc00cc);
+	right = ((right << 12) & 0x0f0f0000)
+		| (right & 0xf0f00f0f)
+		| ((right >> 12) & 0x0000f0f0);
+
+	if (decrypting) {
+		keystep = -2;
+		key = key + 32 - 2;
+	} else
+		keystep = 2;
+	for (i = 0; i < 8; i++) {
+		v0 = key[0];
+		v0 ^= (right >> 1) | (right << 31);
+		left ^= fetch(0, v0, 24)
+			^ fetch(2, v0, 16)
+			^ fetch(4, v0, 8)
+			^ fetch(6, v0, 0);
+		v1 = key[1];
+		v1 ^= (right << 3) | (right >> 29);
+		left ^= fetch(1, v1, 24)
+			^ fetch(3, v1, 16)
+			^ fetch(5, v1, 8)
+			^ fetch(7, v1, 0);
+		key += keystep;
+		
+		v0 = key[0];
+		v0 ^= (left >> 1) | (left << 31);
+		right ^= fetch(0, v0, 24)
+			^ fetch(2, v0, 16)
+			^ fetch(4, v0, 8)
+			^ fetch(6, v0, 0);
+		v1 = key[1];
+		v1 ^= (left << 3) | (left >> 29);
+		right ^= fetch(1, v1, 24)
+			^ fetch(3, v1, 16)
+			^ fetch(5, v1, 8)
+			^ fetch(7, v1, 0);
+		key += keystep;
+	}
+
+	/*
+	 * final permutation, inverse initial permutation
+	 */
+	v0 = ((left << 1) & 0xaaaaaaaa) | (right & 0x55555555);
+	v1 = (left & 0xaaaaaaaa) | ((right >> 1) & 0x55555555);
+	v1 = ((v1 << 6) & 0x33003300)
+		| (v1 & 0xcc33cc33)
+		| ((v1 >> 6) & 0x00cc00cc);
+	v1 = ((v1 << 12) & 0x0f0f0000)
+		| (v1 & 0xf0f00f0f)
+		| ((v1 >> 12) & 0x0000f0f0);
+	v0 = ((v0 << 6) & 0x33003300)
+		| (v0 & 0xcc33cc33)
+		| ((v0 >> 6) & 0x00cc00cc);
+	v0 = ((v0 << 12) & 0x0f0f0000)
+		| (v0 & 0xf0f00f0f)
+		| ((v0 >> 12) & 0x0000f0f0);
+	text[0] = v0;
+	text[2] = v0 >> 8;
+	text[4] = v0 >> 16;
+	text[6] = v0 >> 24;
+	text[1] = v1;
+	text[3] = v1 >> 8;
+	text[5] = v1 >> 16;
+	text[7] = v1 >> 24;
+}
+
+/*
+ * triple DES electronic codebook encryption of one block
+ */
+void
+triple_block_cipher(ulong expanded_key[3][32], uchar text[8], int ende)
+{
+	ulong *key;
+	u32int right, left, v0, v1;
+	int i, j, keystep;
+
+	/*
+	 * initial permutation
+	 */
+	v0 = text[0] | ((u32int)text[2]<<8) | ((u32int)text[4]<<16) | ((u32int)text[6]<<24);
+	left = text[1] | ((u32int)text[3]<<8) | ((u32int)text[5]<<16) | ((u32int)text[7]<<24);
+	right = (left & 0xaaaaaaaa) | ((v0 >> 1) & 0x55555555);
+	left = ((left << 1) & 0xaaaaaaaa) | (v0 & 0x55555555);
+	left = ((left << 6) & 0x33003300)
+		| (left & 0xcc33cc33)
+		| ((left >> 6) & 0x00cc00cc);
+	left = ((left << 12) & 0x0f0f0000)
+		| (left & 0xf0f00f0f)
+		| ((left >> 12) & 0x0000f0f0);
+	right = ((right << 6) & 0x33003300)
+		| (right & 0xcc33cc33)
+		| ((right >> 6) & 0x00cc00cc);
+	right = ((right << 12) & 0x0f0f0000)
+		| (right & 0xf0f00f0f)
+		| ((right >> 12) & 0x0000f0f0);
+
+	for(j = 0; j < 3; j++){
+		if((ende & 1) == DES3D) {
+			key = &expanded_key[2-j][32-2];
+			keystep = -2;
+		} else {
+			key = &expanded_key[j][0];
+			keystep = 2;
+		}
+		ende >>= 1;
+		for (i = 0; i < 8; i++) {
+			v0 = key[0];
+			v0 ^= (right >> 1) | (right << 31);
+			left ^= fetch(0, v0, 24)
+				^ fetch(2, v0, 16)
+				^ fetch(4, v0, 8)
+				^ fetch(6, v0, 0);
+			v1 = key[1];
+			v1 ^= (right << 3) | (right >> 29);
+			left ^= fetch(1, v1, 24)
+				^ fetch(3, v1, 16)
+				^ fetch(5, v1, 8)
+				^ fetch(7, v1, 0);
+			key += keystep;
+			
+			v0 = key[0];
+			v0 ^= (left >> 1) | (left << 31);
+			right ^= fetch(0, v0, 24)
+				^ fetch(2, v0, 16)
+				^ fetch(4, v0, 8)
+				^ fetch(6, v0, 0);
+			v1 = key[1];
+			v1 ^= (left << 3) | (left >> 29);
+			right ^= fetch(1, v1, 24)
+				^ fetch(3, v1, 16)
+				^ fetch(5, v1, 8)
+				^ fetch(7, v1, 0);
+			key += keystep;
+		}
+
+		v0 = left;
+		left = right;
+		right = v0;
+	}
+
+	/*
+	 * final permutation, inverse initial permutation
+	 * left and right are swapped here
+	 */
+	v0 = ((right << 1) & 0xaaaaaaaa) | (left & 0x55555555);
+	v1 = (right & 0xaaaaaaaa) | ((left >> 1) & 0x55555555);
+	v1 = ((v1 << 6) & 0x33003300)
+		| (v1 & 0xcc33cc33)
+		| ((v1 >> 6) & 0x00cc00cc);
+	v1 = ((v1 << 12) & 0x0f0f0000)
+		| (v1 & 0xf0f00f0f)
+		| ((v1 >> 12) & 0x0000f0f0);
+	v0 = ((v0 << 6) & 0x33003300)
+		| (v0 & 0xcc33cc33)
+		| ((v0 >> 6) & 0x00cc00cc);
+	v0 = ((v0 << 12) & 0x0f0f0000)
+		| (v0 & 0xf0f00f0f)
+		| ((v0 >> 12) & 0x0000f0f0);
+	text[0] = v0;
+	text[2] = v0 >> 8;
+	text[4] = v0 >> 16;
+	text[6] = v0 >> 24;
+	text[1] = v1;
+	text[3] = v1 >> 8;
+	text[5] = v1 >> 16;
+	text[7] = v1 >> 24;
+}
+
+/*
+ * key compression permutation, 4 bits at a time
+ */
+static u32int comptab[] = {
+
+0x000000,0x010000,0x000008,0x010008,0x000080,0x010080,0x000088,0x010088,
+0x000000,0x010000,0x000008,0x010008,0x000080,0x010080,0x000088,0x010088,
+
+0x000000,0x100000,0x000800,0x100800,0x000000,0x100000,0x000800,0x100800,
+0x002000,0x102000,0x002800,0x102800,0x002000,0x102000,0x002800,0x102800,
+
+0x000000,0x000004,0x000400,0x000404,0x000000,0x000004,0x000400,0x000404,
+0x400000,0x400004,0x400400,0x400404,0x400000,0x400004,0x400400,0x400404,
+
+0x000000,0x000020,0x008000,0x008020,0x800000,0x800020,0x808000,0x808020,
+0x000002,0x000022,0x008002,0x008022,0x800002,0x800022,0x808002,0x808022,
+
+0x000000,0x000200,0x200000,0x200200,0x001000,0x001200,0x201000,0x201200,
+0x000000,0x000200,0x200000,0x200200,0x001000,0x001200,0x201000,0x201200,
+
+0x000000,0x000040,0x000010,0x000050,0x004000,0x004040,0x004010,0x004050,
+0x040000,0x040040,0x040010,0x040050,0x044000,0x044040,0x044010,0x044050,
+
+0x000000,0x000100,0x020000,0x020100,0x000001,0x000101,0x020001,0x020101,
+0x080000,0x080100,0x0a0000,0x0a0100,0x080001,0x080101,0x0a0001,0x0a0101,
+
+0x000000,0x000100,0x040000,0x040100,0x000000,0x000100,0x040000,0x040100,
+0x000040,0x000140,0x040040,0x040140,0x000040,0x000140,0x040040,0x040140,
+
+0x000000,0x400000,0x008000,0x408000,0x000008,0x400008,0x008008,0x408008,
+0x000400,0x400400,0x008400,0x408400,0x000408,0x400408,0x008408,0x408408,
+
+0x000000,0x001000,0x080000,0x081000,0x000020,0x001020,0x080020,0x081020,
+0x004000,0x005000,0x084000,0x085000,0x004020,0x005020,0x084020,0x085020,
+
+0x000000,0x000800,0x000000,0x000800,0x000010,0x000810,0x000010,0x000810,
+0x800000,0x800800,0x800000,0x800800,0x800010,0x800810,0x800010,0x800810,
+
+0x000000,0x010000,0x000200,0x010200,0x000000,0x010000,0x000200,0x010200,
+0x100000,0x110000,0x100200,0x110200,0x100000,0x110000,0x100200,0x110200,
+
+0x000000,0x000004,0x000000,0x000004,0x000080,0x000084,0x000080,0x000084,
+0x002000,0x002004,0x002000,0x002004,0x002080,0x002084,0x002080,0x002084,
+
+0x000000,0x000001,0x200000,0x200001,0x020000,0x020001,0x220000,0x220001,
+0x000002,0x000003,0x200002,0x200003,0x020002,0x020003,0x220002,0x220003,
+};
+
+static int keysh[] =
+{
+	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
+};
+
+static void
+keycompperm(u32int left, u32int right, ulong *ek)
+{
+	u32int v0, v1;
+	int i;
+
+	for(i = 0; i < 16; i++){
+		left = (left << keysh[i]) | (left >> (28 - keysh[i]));
+		left &= 0xfffffff0;
+		right = (right << keysh[i]) | (right >> (28 - keysh[i]));
+		right &= 0xfffffff0;
+		v0 = comptab[6 * (1 << 4) + ((left >> (32-4)) & 0xf)]
+			| comptab[5 * (1 << 4) + ((left >> (32-8)) & 0xf)]
+			| comptab[4 * (1 << 4) + ((left >> (32-12)) & 0xf)]
+			| comptab[3 * (1 << 4) + ((left >> (32-16)) & 0xf)]
+			| comptab[2 * (1 << 4) + ((left >> (32-20)) & 0xf)]
+			| comptab[1 * (1 << 4) + ((left >> (32-24)) & 0xf)]
+			| comptab[0 * (1 << 4) + ((left >> (32-28)) & 0xf)];
+		v1 = comptab[13 * (1 << 4) + ((right >> (32-4)) & 0xf)]
+			| comptab[12 * (1 << 4) + ((right >> (32-8)) & 0xf)]
+			| comptab[11 * (1 << 4) + ((right >> (32-12)) & 0xf)]
+			| comptab[10 * (1 << 4) + ((right >> (32-16)) & 0xf)]
+			| comptab[9 * (1 << 4) + ((right >> (32-20)) & 0xf)]
+			| comptab[8 * (1 << 4) + ((right >> (32-24)) & 0xf)]
+			| comptab[7 * (1 << 4) + ((right >> (32-28)) & 0xf)];
+		ek[0] = (((v0 >> (24-6)) & 0x3f) << 26)
+			| (((v0 >> (24-18)) & 0x3f) << 18)
+			| (((v1 >> (24-6)) & 0x3f) << 10)
+			| (((v1 >> (24-18)) & 0x3f) << 2);
+		ek[1] = (((v0 >> (24-12)) & 0x3f) << 26)
+			| (((v0 >> (24-24)) & 0x3f) << 18)
+			| (((v1 >> (24-12)) & 0x3f) << 10)
+			| (((v1 >> (24-24)) & 0x3f) << 2);
+		ek += 2;
+	}
+}
+
+void
+des_key_setup(uchar key[8], ulong *ek)
+{
+	u32int left, right, v0, v1;
+
+	v0 = key[0] | ((u32int)key[2] << 8) | ((u32int)key[4] << 16) | ((u32int)key[6] << 24);
+	v1 = key[1] | ((u32int)key[3] << 8) | ((u32int)key[5] << 16) | ((u32int)key[7] << 24);
+	left = ((v0 >> 1) & 0x40404040)
+		| ((v0 >> 2) & 0x10101010)
+		| ((v0 >> 3) & 0x04040404)
+		| ((v0 >> 4) & 0x01010101)
+		| ((v1 >> 0) & 0x80808080)
+		| ((v1 >> 1) & 0x20202020)
+		| ((v1 >> 2) & 0x08080808)
+		| ((v1 >> 3) & 0x02020202);
+	right = ((v0 >> 1) & 0x04040404)
+		| ((v0 << 2) & 0x10101010)
+		| ((v0 << 5) & 0x40404040)
+		| ((v1 << 0) & 0x08080808)
+		| ((v1 << 3) & 0x20202020)
+		| ((v1 << 6) & 0x80808080);
+	left = ((left << 6) & 0x33003300)
+		| (left & 0xcc33cc33)
+		| ((left >> 6) & 0x00cc00cc);
+	v0 = ((left << 12) & 0x0f0f0000)
+		| (left & 0xf0f00f0f)
+		| ((left >> 12) & 0x0000f0f0);
+	right = ((right << 6) & 0x33003300)
+		| (right & 0xcc33cc33)
+		| ((right >> 6) & 0x00cc00cc);
+	v1 = ((right << 12) & 0x0f0f0000)
+		| (right & 0xf0f00f0f)
+		| ((right >> 12) & 0x0000f0f0);
+	left = v0 & 0xfffffff0;
+	right = (v1 & 0xffffff00) | ((v0 << 4) & 0xf0);
+
+	keycompperm(left, right, ek);
+}
+
+static uchar parity[128] =
+{
+	0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e, 
+	0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f, 
+	0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f, 
+	0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e, 
+	0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f, 
+	0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e, 
+	0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e, 
+	0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f, 
+	0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f, 
+	0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e, 
+	0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae, 
+	0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf, 
+	0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce, 
+	0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf, 
+	0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef, 
+	0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe,
+};
+
+/*
+ *  convert a 7 byte key to an 8 byte one
+ */
+void
+des56to64(uchar *k56, uchar *k64)
+{
+	u32int hi, lo;
+
+	hi = ((u32int)k56[0]<<24)|((u32int)k56[1]<<16)|((u32int)k56[2]<<8)|k56[3];
+	lo = ((u32int)k56[4]<<24)|((u32int)k56[5]<<16)|((u32int)k56[6]<<8);
+
+	k64[0] = parity[(hi>>25)&0x7f];
+	k64[1] = parity[(hi>>18)&0x7f];
+	k64[2] = parity[(hi>>11)&0x7f];
+	k64[3] = parity[(hi>>4)&0x7f];
+	k64[4] = parity[((hi<<3)|(lo>>29))&0x7f];
+	k64[5] = parity[(lo>>22)&0x7f];
+	k64[6] = parity[(lo>>15)&0x7f];
+	k64[7] = parity[(lo>>8)&0x7f];
+}
+
+/*
+ *  convert an 8 byte key to a 7 byte one
+ */
+void
+des64to56(uchar *k64, uchar *k56)
+{
+	u32int hi, lo;
+
+	hi = (((u32int)k64[0]&0xfe)<<24)|(((u32int)k64[1]&0xfe)<<17)|(((u32int)k64[2]&0xfe)<<10)
+		|((k64[3]&0xfe)<<3)|(k64[4]>>4);
+	lo = (((u32int)k64[4]&0xfe)<<28)|(((u32int)k64[5]&0xfe)<<21)|(((u32int)k64[6]&0xfe)<<14)
+		|(((u32int)k64[7]&0xfe)<<7);
+
+	k56[0] = hi>>24;
+	k56[1] = hi>>16;
+	k56[2] = hi>>8;
+	k56[3] = hi>>0;
+	k56[4] = lo>>24;
+	k56[5] = lo>>16;
+	k56[6] = lo>>8;
+}
+
+void
+key_setup(uchar key[7], ulong *ek)
+{
+	uchar k64[8];
+
+	des56to64(key, k64);
+	des_key_setup(k64, ek);	
+}

+ 58 - 0
sys/src/cmd/unix/drawterm/libsec/desCBC.c

@@ -0,0 +1,58 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+// Because of the way that non multiple of 8
+// buffers are handled, the decryptor must
+// be fed buffers of the same size as the
+// encryptor
+
+
+// If the length is not a multiple of 8, I encrypt
+// the overflow to be compatible with lacy's cryptlib
+void
+desCBCencrypt(uchar *p, int len, DESstate *s)
+{
+	uchar *p2, *ip, *eip;
+
+	for(; len >= 8; len -= 8){
+		p2 = p;
+		ip = s->ivec;
+		for(eip = ip+8; ip < eip; )
+			*p2++ ^= *ip++;
+		block_cipher(s->expanded, p, 0);
+		memmove(s->ivec, p, 8);
+		p += 8;
+	}
+
+	if(len > 0){
+		ip = s->ivec;
+		block_cipher(s->expanded, ip, 0);
+		for(eip = ip+len; ip < eip; )
+			*p++ ^= *ip++;
+	}
+}
+
+void
+desCBCdecrypt(uchar *p, int len, DESstate *s)
+{
+	uchar *ip, *eip, *tp;
+	uchar tmp[8];
+
+	for(; len >= 8; len -= 8){
+		memmove(tmp, p, 8);
+		block_cipher(s->expanded, p, 1);
+		tp = tmp;
+		ip = s->ivec;
+		for(eip = ip+8; ip < eip; ){
+			*p++ ^= *ip;
+			*ip++ = *tp++;
+		}
+	}
+
+	if(len > 0){
+		ip = s->ivec;
+		block_cipher(s->expanded, ip, 0);
+		for(eip = ip+len; ip < eip; )
+			*p++ ^= *ip++;
+	}
+}

+ 47 - 0
sys/src/cmd/unix/drawterm/libsec/desECB.c

@@ -0,0 +1,47 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+// I wasn't sure what to do when the buffer was not
+// a multiple of 8.  I did what lacy's cryptolib did
+// to be compatible, but it looks dangerous to me
+// since its encrypting plain text with the key. -- presotto
+
+void
+desECBencrypt(uchar *p, int len, DESstate *s)
+{
+	int i;
+	uchar tmp[8];
+
+	for(; len >= 8; len -= 8){
+		block_cipher(s->expanded, p, 0);
+		p += 8;
+	}
+	
+	if(len > 0){
+		for (i=0; i<8; i++)
+			tmp[i] = i;
+		block_cipher(s->expanded, tmp, 0);
+		for (i = 0; i < len; i++)
+			p[i] ^= tmp[i];
+	}
+}
+
+void
+desECBdecrypt(uchar *p, int len, DESstate *s)
+{
+	int i;
+	uchar tmp[8];
+
+	for(; len >= 8; len -= 8){
+		block_cipher(s->expanded, p, 1);
+		p += 8;
+	}
+	
+	if(len > 0){
+		for (i=0; i<8; i++)
+			tmp[i] = i;
+		block_cipher(s->expanded, tmp, 0);
+		for (i = 0; i < len; i++)
+			p[i] ^= tmp[i];
+	}
+}

+ 31 - 0
sys/src/cmd/unix/drawterm/libsec/desmodes.c

@@ -0,0 +1,31 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"