Browse Source

Plan 9 from Bell Labs 2004-02-23

David du Colombier 20 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"
+
+/*
+ *  these routines use the 64bit format for
+ *  DES keys.
+ */
+
+void
+setupDESstate(DESstate *s, uchar key[8], uchar *ivec)
+{
+	memset(s, 0, sizeof(*s));
+	memmove(s->key, key, sizeof(s->key));
+	des_key_setup(key, s->expanded);
+	if(ivec)
+		memmove(s->ivec, ivec, 8);
+	s->setup = 0xdeadbeef;
+}
+
+void
+setupDES3state(DES3state *s, uchar key[3][8], uchar *ivec)
+{
+	memset(s, 0, sizeof(*s));
+	memmove(s->key, key, sizeof(s->key));
+	des_key_setup(key[0], s->expanded[0]);
+	des_key_setup(key[1], s->expanded[1]);
+	des_key_setup(key[2], s->expanded[2]);
+	if(ivec)
+		memmove(s->ivec, ivec, 8);
+	s->setup = 0xdeadbeef;
+}

+ 339 - 0
sys/src/cmd/unix/drawterm/libsec/libsec.h

@@ -0,0 +1,339 @@
+#ifndef _MPINT
+typedef struct mpint mpint;
+#endif
+
+/////////////////////////////////////////////////////////
+// AES definitions
+/////////////////////////////////////////////////////////
+
+enum
+{
+	AESbsize=	16,
+	AESmaxkey=	32,
+	AESmaxrounds=	14
+};
+
+typedef struct AESstate AESstate;
+struct AESstate
+{
+	ulong	setup;
+	int	rounds;
+	int	keybytes;
+	uchar	key[AESmaxkey];		/* unexpanded key */
+	u32int	ekey[4*(AESmaxrounds + 1)];	/* encryption key */
+	u32int	dkey[4*(AESmaxrounds + 1)];	/* decryption key */
+	uchar	ivec[AESbsize];	/* initialization vector */
+};
+
+void	setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
+void	aesCBCencrypt(uchar *p, int len, AESstate *s);
+void	aesCBCdecrypt(uchar *p, int len, AESstate *s);
+
+/////////////////////////////////////////////////////////
+// Blowfish Definitions
+/////////////////////////////////////////////////////////
+
+enum
+{
+	BFbsize	= 8,
+	BFrounds	= 16
+};
+
+// 16-round Blowfish
+typedef struct BFstate BFstate;
+struct BFstate
+{
+	ulong	setup;
+
+	uchar	key[56];
+	uchar	ivec[8];
+
+	u32int 	pbox[BFrounds+2];
+	u32int	sbox[1024];
+};
+
+void	setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec);
+void	bfCBCencrypt(uchar*, int, BFstate*);
+void	bfCBCdecrypt(uchar*, int, BFstate*);
+void	bfECBencrypt(uchar*, int, BFstate*);
+void	bfECBdecrypt(uchar*, int, BFstate*);
+
+/////////////////////////////////////////////////////////
+// DES definitions
+/////////////////////////////////////////////////////////
+
+enum
+{
+	DESbsize=	8
+};
+
+// single des
+typedef struct DESstate DESstate;
+struct DESstate
+{
+	ulong	setup;
+	uchar	key[8];		/* unexpanded key */
+	ulong	expanded[32];	/* expanded key */
+	uchar	ivec[8];	/* initialization vector */
+};
+
+void	setupDESstate(DESstate *s, uchar key[8], uchar *ivec);
+void	des_key_setup(uchar[8], ulong[32]);
+void	block_cipher(ulong*, uchar*, int);
+void	desCBCencrypt(uchar*, int, DESstate*);
+void	desCBCdecrypt(uchar*, int, DESstate*);
+void	desECBencrypt(uchar*, int, DESstate*);
+void	desECBdecrypt(uchar*, int, DESstate*);
+
+// for backward compatibility with 7 byte DES key format
+void	des56to64(uchar *k56, uchar *k64);
+void	des64to56(uchar *k64, uchar *k56);
+void	key_setup(uchar[7], ulong[32]);
+
+// triple des encrypt/decrypt orderings
+enum {
+	DES3E=		0,
+	DES3D=		1,
+	DES3EEE=	0,
+	DES3EDE=	2,
+	DES3DED=	5,
+	DES3DDD=	7
+};
+
+typedef struct DES3state DES3state;
+struct DES3state
+{
+	ulong	setup;
+	uchar	key[3][8];		/* unexpanded key */
+	ulong	expanded[3][32];	/* expanded key */
+	uchar	ivec[8];		/* initialization vector */
+};
+
+void	setupDES3state(DES3state *s, uchar key[3][8], uchar *ivec);
+void	triple_block_cipher(ulong keys[3][32], uchar*, int);
+void	des3CBCencrypt(uchar*, int, DES3state*);
+void	des3CBCdecrypt(uchar*, int, DES3state*);
+void	des3ECBencrypt(uchar*, int, DES3state*);
+void	des3ECBdecrypt(uchar*, int, DES3state*);
+
+/////////////////////////////////////////////////////////
+// digests
+/////////////////////////////////////////////////////////
+
+enum
+{
+	SHA1dlen=	20,	/* SHA digest length */
+	MD4dlen=	16,	/* MD4 digest length */
+	MD5dlen=	16	/* MD5 digest length */
+};
+
+typedef struct DigestState DigestState;
+struct DigestState
+{
+	uvlong len;
+	u32int state[5];
+	uchar buf[128];
+	int blen;
+	char malloced;
+	char seeded;
+};
+typedef struct DigestState SHAstate;	/* obsolete name */
+typedef struct DigestState SHA1state;
+typedef struct DigestState MD5state;
+typedef struct DigestState MD4state;
+
+DigestState* md4(uchar*, ulong, uchar*, DigestState*);
+DigestState* md5(uchar*, ulong, uchar*, DigestState*);
+DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
+char* sha1pickle(SHA1state*);
+SHA1state* sha1unpickle(char*);
+
+/////////////////////////////////////////////////////////
+// random number generation
+/////////////////////////////////////////////////////////
+void	genrandom(uchar *buf, int nbytes);
+void	prng(uchar *buf, int nbytes);
+ulong	fastrand(void);
+ulong	nfastrand(ulong);
+
+/////////////////////////////////////////////////////////
+// primes
+/////////////////////////////////////////////////////////
+void	genprime(mpint *p, int n, int accuracy); // generate an n bit probable prime
+void	gensafeprime(mpint *p, mpint *alpha, int n, int accuracy);	// prime and generator
+void	genstrongprime(mpint *p, int n, int accuracy);	// generate an n bit strong prime
+void	DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]);
+int	probably_prime(mpint *n, int nrep);	// miller-rabin test
+int	smallprimetest(mpint *p);		// returns -1 if not prime, 0 otherwise
+
+/////////////////////////////////////////////////////////
+// rc4
+/////////////////////////////////////////////////////////
+typedef struct RC4state RC4state;
+struct RC4state
+{
+	 uchar state[256];
+	 uchar x;
+	 uchar y;
+};
+
+void	setupRC4state(RC4state*, uchar*, int);
+void	rc4(RC4state*, uchar*, int);
+void	rc4skip(RC4state*, int);
+void	rc4back(RC4state*, int);
+
+/////////////////////////////////////////////////////////
+// rsa
+/////////////////////////////////////////////////////////
+typedef struct RSApub RSApub;
+typedef struct RSApriv RSApriv;
+
+// public/encryption key
+struct RSApub
+{
+	mpint	*n;	// modulus
+	mpint	*ek;	// exp (encryption key)
+};
+
+// private/decryption key
+struct RSApriv
+{
+	RSApub	pub;
+
+	mpint	*dk;	// exp (decryption key)
+
+	// precomputed values to help with chinese remainder theorem calc
+	mpint	*p;
+	mpint	*q;
+	mpint	*kp;	// dk mod p-1
+	mpint	*kq;	// dk mod q-1
+	mpint	*c2;	// (inv p) mod q
+};
+
+RSApriv*	rsagen(int nlen, int elen, int rounds);
+RSApriv*	rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q);
+mpint*		rsaencrypt(RSApub *k, mpint *in, mpint *out);
+mpint*		rsadecrypt(RSApriv *k, mpint *in, mpint *out);
+RSApub*		rsapuballoc(void);
+void		rsapubfree(RSApub*);
+RSApriv*	rsaprivalloc(void);
+void		rsaprivfree(RSApriv*);
+RSApub*		rsaprivtopub(RSApriv*);
+RSApub*		X509toRSApub(uchar*, int, char*, int);
+RSApriv*	asn1toRSApriv(uchar*, int);
+void		asn1dump(uchar *der, int len);
+uchar*		decodepem(char *s, char *type, int *len);
+uchar*		X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
+uchar*		X509req(RSApriv *priv, char *subj, int *certlen);
+char*		X509verify(uchar *cert, int ncert, RSApub *pk);
+void		X509dump(uchar *cert, int ncert);
+/////////////////////////////////////////////////////////
+// elgamal
+/////////////////////////////////////////////////////////
+typedef struct EGpub EGpub;
+typedef struct EGpriv EGpriv;
+typedef struct EGsig EGsig;
+
+// public/encryption key
+struct EGpub
+{
+	mpint	*p;	// modulus
+	mpint	*alpha;	// generator
+	mpint	*key;	// (encryption key) alpha**secret mod p
+};
+
+// private/decryption key
+struct EGpriv
+{
+	EGpub	pub;
+	mpint	*secret; // (decryption key)
+};
+
+// signature
+struct EGsig
+{
+	mpint	*r, *s;
+};
+
+EGpriv*		eggen(int nlen, int rounds);
+mpint*		egencrypt(EGpub *k, mpint *in, mpint *out);	// deprecated
+mpint*		egdecrypt(EGpriv *k, mpint *in, mpint *out);
+EGsig*		egsign(EGpriv *k, mpint *m);
+int		egverify(EGpub *k, EGsig *sig, mpint *m);
+EGpub*		egpuballoc(void);
+void		egpubfree(EGpub*);
+EGpriv*		egprivalloc(void);
+void		egprivfree(EGpriv*);
+EGsig*		egsigalloc(void);
+void		egsigfree(EGsig*);
+EGpub*		egprivtopub(EGpriv*);
+
+/////////////////////////////////////////////////////////
+// dsa
+/////////////////////////////////////////////////////////
+typedef struct DSApub DSApub;
+typedef struct DSApriv DSApriv;
+typedef struct DSAsig DSAsig;
+
+// public/encryption key
+struct DSApub
+{
+	mpint	*p;	// modulus
+	mpint	*q;	// group order, q divides p-1
+	mpint	*alpha;	// group generator
+	mpint	*key;	// (encryption key) alpha**secret mod p
+};
+
+// private/decryption key
+struct DSApriv
+{
+	DSApub	pub;
+	mpint	*secret; // (decryption key)
+};
+
+// signature
+struct DSAsig
+{
+	mpint	*r, *s;
+};
+
+DSApriv*	dsagen(DSApub *opub);	// opub not checked for consistency!
+DSAsig*		dsasign(DSApriv *k, mpint *m);
+int		dsaverify(DSApub *k, DSAsig *sig, mpint *m);
+DSApub*		dsapuballoc(void);
+void		dsapubfree(DSApub*);
+DSApriv*	dsaprivalloc(void);
+void		dsaprivfree(DSApriv*);
+DSAsig*		dsasigalloc(void);
+void		dsasigfree(DSAsig*);
+DSApub*		dsaprivtopub(DSApriv*);
+
+/////////////////////////////////////////////////////////
+// TLS
+/////////////////////////////////////////////////////////
+typedef struct Thumbprint{
+	struct Thumbprint *next;
+	uchar sha1[SHA1dlen];
+} Thumbprint;
+
+typedef struct TLSconn{
+	char dir[40];  // connection directory
+	uchar *cert;   // certificate (local on input, remote on output)
+	uchar *sessionID;
+	int certlen, sessionIDlen;
+	int (*trace)(char*fmt, ...);
+} TLSconn;
+
+// tlshand.c
+extern int tlsClient(int fd, TLSconn *c);
+extern int tlsServer(int fd, TLSconn *c);
+
+// thumb.c
+extern Thumbprint* initThumbprints(char *ok, char *crl);
+extern void freeThumbprints(Thumbprint *ok);
+extern int okThumbprint(uchar *sha1, Thumbprint *ok);
+
+// readcert.c
+extern uchar *readcert(char *filename, int *pcertlen);

+ 271 - 0
sys/src/cmd/unix/drawterm/libsec/md4.c

@@ -0,0 +1,271 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+/*
+ *  This MD4 is implemented from the description in Stinson's Cryptography,
+ *  theory and practice. -- presotto
+ */
+
+/*
+ *	Rotate ammounts used in the algorithm
+ */
+enum
+{
+	S11=	3,
+	S12=	7,
+	S13=	11,
+	S14=	19,
+
+	S21=	3,
+	S22=	5,
+	S23=	9,
+	S24=	13,
+
+	S31=	3,
+	S32=	9,
+	S33=	11,
+	S34=	15,
+};
+
+typedef struct MD4Table MD4Table;
+struct MD4Table
+{
+	uchar	x;	/* index into data block */
+	uchar	rot;	/* amount to rotate left by */
+};
+
+static MD4Table tab[] =
+{
+	/* round 1 */
+/*[0]*/	{ 0,	S11},	
+	{ 1,	S12},	
+	{ 2,	S13},	
+	{ 3,	S14},	
+	{ 4,	S11},	
+	{ 5,	S12},	
+	{ 6,	S13},	
+	{ 7,	S14},	
+	{ 8,	S11},	
+	{ 9,	S12},	
+	{ 10,	S13},	
+	{ 11,	S14},	
+	{ 12,	S11},	
+	{ 13,	S12},	
+	{ 14,	S13},	
+	{ 15,	S14},
+
+	/* round 2 */
+/*[16]*/{ 0,	S21},	
+	{ 4,	S22},	
+	{ 8,	S23},	
+	{ 12,	S24},	
+	{ 1,	S21},	
+	{ 5,	S22},	
+	{ 9,	S23},	
+	{ 13,	S24},	
+	{ 2,	S21},	
+	{ 6,	S22},	
+	{ 10,	S23},	
+	{ 14,	S24},	
+	{ 3,	S21},	
+	{ 7,	S22},	
+	{ 11,	S23},	
+	{ 15,	S24},
+
+	/* round 3 */
+/*[32]*/{ 0,	S31},	
+	{ 8,	S32},	
+	{ 4,	S33},	
+	{ 12,	S34},	
+	{ 2,	S31},	
+	{ 10,	S32},	
+	{ 6,	S33},	
+	{ 14,	S34},	
+	{ 1,	S31},	
+	{ 9,	S32},	
+	{ 5,	S33},	
+	{ 13,	S34},	
+	{ 3,	S31},	
+	{ 11,	S32},	
+	{ 7,	S33},	
+	{ 15,	S34},	
+};
+
+static void encode(uchar*, u32int*, ulong);
+static void decode(u32int*, uchar*, ulong);
+
+static void
+md4block(uchar *p, ulong len, MD4state *s)
+{
+	int i;
+	u32int a, b, c, d, tmp;
+	MD4Table *t;
+	uchar *end;
+	u32int x[16];
+
+	for(end = p+len; p < end; p += 64){
+		a = s->state[0];
+		b = s->state[1];
+		c = s->state[2];
+		d = s->state[3];
+
+		decode(x, p, 64);
+	
+		for(i = 0; i < 48; i++){
+			t = tab + i;
+			switch(i>>4){
+			case 0:
+				a += (b & c) | (~b & d);
+				break;
+			case 1:
+				a += ((b & c) | (b & d) | (c & d)) + 0x5A827999;
+				break;
+			case 2:
+				a += (b ^ c ^ d) + 0x6ED9EBA1;
+				break;
+			}
+			a += x[t->x];
+			a = (a << t->rot) | (a >> (32 - t->rot));
+	
+			/* rotate variables */
+			tmp = d;
+			d = c;
+			c = b;
+			b = a;
+			a = tmp;
+		}
+
+		s->state[0] += a;
+		s->state[1] += b;
+		s->state[2] += c;
+		s->state[3] += d;
+
+		s->len += 64;
+	}
+}
+
+MD4state*
+md4(uchar *p, ulong len, uchar *digest, MD4state *s)
+{
+	u32int x[16];
+	uchar buf[128];
+	int i;
+	uchar *e;
+
+	if(s == nil){
+		s = malloc(sizeof(*s));
+		if(s == nil)
+			return nil;
+		memset(s, 0, sizeof(*s));
+		s->malloced = 1;
+	}
+
+	if(s->seeded == 0){
+		/* seed the state, these constants would look nicer big-endian */
+		s->state[0] = 0x67452301;
+		s->state[1] = 0xefcdab89;
+		s->state[2] = 0x98badcfe;
+		s->state[3] = 0x10325476;
+		s->seeded = 1;
+	}
+
+	/* fill out the partial 64 byte block from previous calls */
+	if(s->blen){
+		i = 64 - s->blen;
+		if(len < i)
+			i = len;
+		memmove(s->buf + s->blen, p, i);
+		len -= i;
+		s->blen += i;
+		p += i;
+		if(s->blen == 64){
+			md4block(s->buf, s->blen, s);
+			s->blen = 0;
+		}
+	}
+
+	/* do 64 byte blocks */
+	i = len & ~0x3f;
+	if(i){
+		md4block(p, i, s);
+		len -= i;
+		p += i;
+	}
+
+	/* save the left overs if not last call */
+	if(digest == 0){
+		if(len){
+			memmove(s->buf, p, len);
+			s->blen += len;
+		}
+		return s;
+	}
+
+	/*
+	 *  this is the last time through, pad what's left with 0x80,
+	 *  0's, and the input count to create a multiple of 64 bytes
+	 */
+	if(s->blen){
+		p = s->buf;
+		len = s->blen;
+	} else {
+		memmove(buf, p, len);
+		p = buf;
+	}
+	s->len += len;
+	e = p + len;
+	if(len < 56)
+		i = 56 - len;
+	else
+		i = 120 - len;
+	memset(e, 0, i);
+	*e = 0x80;
+	len += i;
+
+	/* append the count */
+	x[0] = s->len<<3;
+	x[1] = s->len>>29;
+	encode(p+len, x, 8);
+
+	/* digest the last part */
+	md4block(p, len+8, s);
+
+	/* return result and free state */
+	encode(digest, s->state, MD4dlen);
+	if(s->malloced == 1)
+		free(s);
+	return nil;
+}
+
+/*
+ *	encodes input (u32int) into output (uchar). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+encode(uchar *output, u32int *input, ulong len)
+{
+	u32int x;
+	uchar *e;
+
+	for(e = output + len; output < e;) {
+		x = *input++;
+		*output++ = x;
+		*output++ = x >> 8;
+		*output++ = x >> 16;
+		*output++ = x >> 24;
+	}
+}
+
+/*
+ *	decodes input (uchar) into output (u32int). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+decode(u32int *output, uchar *input, ulong len)
+{
+	uchar *e;
+
+	for(e = input+len; input < e; input += 4)
+		*output++ = input[0] | (input[1] << 8) |
+			(input[2] << 16) | (input[3] << 24);
+}

+ 148 - 0
sys/src/cmd/unix/drawterm/libsec/md5.c

@@ -0,0 +1,148 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+/*
+ *  rfc1321 requires that I include this.  The code is new.  The constants
+ *  all come from the rfc (hence the copyright).  We trade a table for the
+ *  macros in rfc.  The total size is a lot less. -- presotto
+ *
+ *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ *	rights reserved.
+ *
+ *	License to copy and use this software is granted provided that it
+ *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ *	Algorithm" in all material mentioning or referencing this software
+ *	or this function.
+ *
+ *	License is also granted to make and use derivative works provided
+ *	that such works are identified as "derived from the RSA Data
+ *	Security, Inc. MD5 Message-Digest Algorithm" in all material
+ *	mentioning or referencing the derived work.
+ *
+ *	RSA Data Security, Inc. makes no representations concerning either
+ *	the merchantability of this software or the suitability of this
+ *	software forany particular purpose. It is provided "as is"
+ *	without express or implied warranty of any kind.
+ *	These notices must be retained in any copies of any part of this
+ *	documentation and/or software.
+ */
+
+static void encode(uchar*, u32int*, ulong);
+static void decode(u32int*, uchar*, ulong);
+
+extern void _md5block(uchar*, ulong, u32int*);
+
+MD5state*
+md5(uchar *p, ulong len, uchar *digest, MD5state *s)
+{
+	u32int x[16];
+	uchar buf[128];
+	int i;
+	uchar *e;
+
+	if(s == nil){
+		s = malloc(sizeof(*s));
+		if(s == nil)
+			return nil;
+		memset(s, 0, sizeof(*s));
+		s->malloced = 1;
+	}
+
+	if(s->seeded == 0){
+		/* seed the state, these constants would look nicer big-endian */
+		s->state[0] = 0x67452301;
+		s->state[1] = 0xefcdab89;
+		s->state[2] = 0x98badcfe;
+		s->state[3] = 0x10325476;
+		s->seeded = 1;
+	}
+
+	/* fill out the partial 64 byte block from previous calls */
+	if(s->blen){
+		i = 64 - s->blen;
+		if(len < i)
+			i = len;
+		memmove(s->buf + s->blen, p, i);
+		len -= i;
+		s->blen += i;
+		p += i;
+		if(s->blen == 64){
+			_md5block(s->buf, s->blen, s->state);
+			s->len += s->blen;
+			s->blen = 0;
+		}
+	}
+
+	/* do 64 byte blocks */
+	i = len & ~0x3f;
+	if(i){
+		_md5block(p, i, s->state);
+		s->len += i;
+		len -= i;
+		p += i;
+	}
+
+	/* save the left overs if not last call */
+	if(digest == 0){
+		if(len){
+			memmove(s->buf, p, len);
+			s->blen += len;
+		}
+		return s;
+	}
+
+	/*
+	 *  this is the last time through, pad what's left with 0x80,
+	 *  0's, and the input count to create a multiple of 64 bytes
+	 */
+	if(s->blen){
+		p = s->buf;
+		len = s->blen;
+	} else {
+		memmove(buf, p, len);
+		p = buf;
+	}
+	s->len += len;
+	e = p + len;
+	if(len < 56)
+		i = 56 - len;
+	else
+		i = 120 - len;
+	memset(e, 0, i);
+	*e = 0x80;
+	len += i;
+
+	/* append the count */
+	x[0] = s->len<<3;
+	x[1] = s->len>>29;
+	encode(p+len, x, 8);
+
+	/* digest the last part */
+	_md5block(p, len+8, s->state);
+	s->len += len;
+
+	/* return result and free state */
+	encode(digest, s->state, MD5dlen);
+	if(s->malloced == 1)
+		free(s);
+	return nil;
+}
+
+/*
+ *	encodes input (u32int) into output (uchar). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+encode(uchar *output, u32int *input, ulong len)
+{
+	u32int x;
+	uchar *e;
+
+	for(e = output + len; output < e;) {
+		x = *input++;
+		*output++ = x;
+		*output++ = x >> 8;
+		*output++ = x >> 16;
+		*output++ = x >> 24;
+	}
+}

+ 267 - 0
sys/src/cmd/unix/drawterm/libsec/md5block.c

@@ -0,0 +1,267 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+/*
+ *  rfc1321 requires that I include this.  The code is new.  The constants
+ *  all come from the rfc (hence the copyright).  We trade a table for the
+ *  macros in rfc.  The total size is a lot less. -- presotto
+ *
+ *	Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ *	rights reserved.
+ *
+ *	License to copy and use this software is granted provided that it
+ *	is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ *	Algorithm" in all material mentioning or referencing this software
+ *	or this function.
+ *
+ *	License is also granted to make and use derivative works provided
+ *	that such works are identified as "derived from the RSA Data
+ *	Security, Inc. MD5 Message-Digest Algorithm" in all material
+ *	mentioning or referencing the derived work.
+ *
+ *	RSA Data Security, Inc. makes no representations concerning either
+ *	the merchantability of this software or the suitability of this
+ *	software forany particular purpose. It is provided "as is"
+ *	without express or implied warranty of any kind.
+ *	These notices must be retained in any copies of any part of this
+ *	documentation and/or software.
+ */
+
+/*
+ *	Rotate ammounts used in the algorithm
+ */
+enum
+{
+	S11=	7,
+	S12=	12,
+	S13=	17,
+	S14=	22,
+
+	S21=	5,
+	S22=	9,
+	S23=	14,
+	S24=	20,
+
+	S31=	4,
+	S32=	11,
+	S33=	16,
+	S34=	23,
+
+	S41=	6,
+	S42=	10,
+	S43=	15,
+	S44=	21,
+};
+
+static u32int md5tab[] =
+{
+	/* round 1 */
+/*[0]*/	0xd76aa478,	
+	0xe8c7b756,	
+	0x242070db,	
+	0xc1bdceee,	
+	0xf57c0faf,	
+	0x4787c62a,	
+	0xa8304613,	
+	0xfd469501,	
+	0x698098d8,	
+	0x8b44f7af,	
+	0xffff5bb1,	
+	0x895cd7be,	
+	0x6b901122,	
+	0xfd987193,	
+	0xa679438e,	
+	0x49b40821,
+
+	/* round 2 */
+/*[16]*/0xf61e2562,	
+	0xc040b340,	
+	0x265e5a51,	
+	0xe9b6c7aa,	
+	0xd62f105d,	
+	 0x2441453,	
+	0xd8a1e681,	
+	0xe7d3fbc8,	
+	0x21e1cde6,	
+	0xc33707d6,	
+	0xf4d50d87,	
+	0x455a14ed,	
+	0xa9e3e905,	
+	0xfcefa3f8,	
+	0x676f02d9,	
+	0x8d2a4c8a,
+
+	/* round 3 */
+/*[32]*/0xfffa3942,	
+	0x8771f681,	
+	0x6d9d6122,	
+	0xfde5380c,	
+	0xa4beea44,	
+	0x4bdecfa9,	
+	0xf6bb4b60,	
+	0xbebfbc70,	
+	0x289b7ec6,	
+	0xeaa127fa,	
+	0xd4ef3085,	
+	 0x4881d05,	
+	0xd9d4d039,	
+	0xe6db99e5,	
+	0x1fa27cf8,	
+	0xc4ac5665,	
+
+	/* round 4 */
+/*[48]*/0xf4292244,	
+	0x432aff97,	
+	0xab9423a7,	
+	0xfc93a039,	
+	0x655b59c3,	
+	0x8f0ccc92,	
+	0xffeff47d,	
+	0x85845dd1,	
+	0x6fa87e4f,	
+	0xfe2ce6e0,	
+	0xa3014314,	
+	0x4e0811a1,	
+	0xf7537e82,	
+	0xbd3af235,	
+	0x2ad7d2bb,	
+	0xeb86d391,	
+};
+
+static void decode(u32int*, uchar*, ulong);
+extern void _md5block(uchar *p, ulong len, u32int *s);
+
+void
+_md5block(uchar *p, ulong len, u32int *s)
+{
+	u32int a, b, c, d, sh;
+	u32int *t;
+	uchar *end;
+	u32int x[16];
+
+	for(end = p+len; p < end; p += 64){
+		a = s[0];
+		b = s[1];
+		c = s[2];
+		d = s[3];
+
+		decode(x, p, 64);
+	
+		t = md5tab;
+		sh = 0;
+		for(; sh != 16; t += 4){
+			a += ((c ^ d) & b) ^ d;
+			a += x[sh] + t[0];
+			a = (a << S11) | (a >> (32 - S11));
+			a += b;
+
+			d += ((b ^ c) & a) ^ c;
+			d += x[sh + 1] + t[1];
+			d = (d << S12) | (d >> (32 - S12));
+			d += a;
+
+			c += ((a ^ b) & d) ^ b;
+			c += x[sh + 2] + t[2];
+			c = (c << S13) | (c >> (32 - S13));
+			c += d;
+
+			b += ((d ^ a) & c) ^ a;
+			b += x[sh + 3] + t[3];
+			b = (b << S14) | (b >> (32 - S14));
+			b += c;
+
+			sh += 4;
+		}
+		sh = 1;
+		for(; sh != 1+20*4; t += 4){
+			a += ((b ^ c) & d) ^ c;
+			a += x[sh & 0xf] + t[0];
+			a = (a << S21) | (a >> (32 - S21));
+			a += b;
+
+			d += ((a ^ b) & c) ^ b;
+			d += x[(sh + 5) & 0xf] + t[1];
+			d = (d << S22) | (d >> (32 - S22));
+			d += a;
+
+			c += ((d ^ a) & b) ^ a;
+			c += x[(sh + 10) & 0xf] + t[2];
+			c = (c << S23) | (c >> (32 - S23));
+			c += d;
+
+			b += ((c ^ d) & a) ^ d;
+			b += x[(sh + 15) & 0xf] + t[3];
+			b = (b << S24) | (b >> (32 - S24));
+			b += c;
+
+			sh += 20;
+		}
+		sh = 5;
+		for(; sh != 5+12*4; t += 4){
+			a += b ^ c ^ d;
+			a += x[sh & 0xf] + t[0];
+			a = (a << S31) | (a >> (32 - S31));
+			a += b;
+
+			d += a ^ b ^ c;
+			d += x[(sh + 3) & 0xf] + t[1];
+			d = (d << S32) | (d >> (32 - S32));
+			d += a;
+
+			c += d ^ a ^ b;
+			c += x[(sh + 6) & 0xf] + t[2];
+			c = (c << S33) | (c >> (32 - S33));
+			c += d;
+
+			b += c ^ d ^ a;
+			b += x[(sh + 9) & 0xf] + t[3];
+			b = (b << S34) | (b >> (32 - S34));
+			b += c;
+
+			sh += 12;
+		}
+		sh = 0;
+		for(; sh != 28*4; t += 4){
+			a += c ^ (b | ~d);
+			a += x[sh & 0xf] + t[0];
+			a = (a << S41) | (a >> (32 - S41));
+			a += b;
+
+			d += b ^ (a | ~c);
+			d += x[(sh + 7) & 0xf] + t[1];
+			d = (d << S42) | (d >> (32 - S42));
+			d += a;
+
+			c += a ^ (d | ~b);
+			c += x[(sh + 14) & 0xf] + t[2];
+			c = (c << S43) | (c >> (32 - S43));
+			c += d;
+
+			b += d ^ (c | ~a);
+			b += x[(sh + 21) & 0xf] + t[3];
+			b = (b << S44) | (b >> (32 - S44));
+			b += c;
+
+			sh += 28;
+		}
+
+		s[0] += a;
+		s[1] += b;
+		s[2] += c;
+		s[3] += d;
+	}
+}
+
+/*
+ *	decodes input (uchar) into output (u32int). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+decode(u32int *output, uchar *input, ulong len)
+{
+	uchar *e;
+
+	for(e = input+len; input < e; input += 4)
+		*output++ = input[0] | (input[1] << 8) |
+			(input[2] << 16) | (input[3] << 24);
+}

+ 104 - 0
sys/src/cmd/unix/drawterm/libsec/rc4.c

@@ -0,0 +1,104 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+void
+setupRC4state(RC4state *key, uchar *start, int n)
+{
+	int t;
+	int index2;
+	uchar *state;
+	uchar *p, *e, *sp, *se;
+
+	state = key->state;
+	se = &state[256];
+	for(sp = state; sp < se; sp++)
+		*sp = sp - state;
+
+	key->x = 0;
+	key->y = 0;
+	index2 = 0;
+	e = start + n;
+	p = start;
+	for(sp = state; sp < se; sp++)
+	{
+		t = *sp;
+		index2 = (*p + t + index2) & 255;
+		*sp = state[index2];
+		state[index2] = t;
+		if(++p >= e)
+			p = start;
+	}
+}
+
+void
+rc4(RC4state *key, uchar *p, int len)
+{
+	int tx, ty;
+	int x, y;
+	uchar *state;
+	uchar *e;
+
+	x = key->x;
+	y = key->y;
+	state = &key->state[0];
+	for(e = p + len; p < e; p++)
+	{
+		x = (x+1)&255;
+		tx = state[x];
+		y = (y+tx)&255;
+		ty = state[y];
+		state[x] = ty;
+		state[y] = tx;
+		*p ^= state[(tx+ty)&255];
+	}
+	key->x = x;
+	key->y = y;
+}
+
+void
+rc4skip(RC4state *key, int len)
+{
+	int tx, ty;
+	int x, y;
+	uchar *state;
+	int i;
+
+	x = key->x;
+	y = key->y;
+	state = &key->state[0];
+	for(i=0; i<len; i++)
+	{
+		x = (x+1)&255;
+		tx = state[x];
+		y = (y+tx)&255;
+		ty = state[y];
+		state[x] = ty;
+		state[y] = tx;
+	}
+	key->x = x;
+	key->y = y;
+}
+
+void
+rc4back(RC4state *key, int len)
+{
+	int tx, ty;
+	int x, y;
+	uchar *state;
+	int i;
+
+	x = key->x;
+	y = key->y;
+	state = &key->state[0];
+	for(i=0; i<len; i++)
+	{
+		ty = state[x];
+		tx = state[y];
+		state[y] = ty;
+		state[x] = tx;
+		y = (y-tx)&255;
+		x = (x-1)&255;
+	}
+	key->x = x;
+	key->y = y;
+}

+ 127 - 0
sys/src/cmd/unix/drawterm/libsec/sha1.c

@@ -0,0 +1,127 @@
+#include "../lib9.h"
+#include "../libsec/libsec.h"
+
+static void encode(uchar*, u32int*, ulong);
+
+extern void _sha1block(uchar*, ulong, u32int*);
+
+/*
+ *  we require len to be a multiple of 64 for all but
+ *  the last call.  There must be room in the input buffer
+ *  to pad.
+ */
+SHA1state*
+sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
+{
+	uchar buf[128];
+	u32int x[16];
+	int i;
+	uchar *e;
+
+	if(s == nil){
+		s = malloc(sizeof(*s));
+		if(s == nil)
+			return nil;
+		memset(s, 0, sizeof(*s));
+		s->malloced = 1;
+	}
+
+	if(s->seeded == 0){
+		/* seed the state, these constants would look nicer big-endian */
+		s->state[0] = 0x67452301;
+		s->state[1] = 0xefcdab89;
+		s->state[2] = 0x98badcfe;
+		s->state[3] = 0x10325476;
+		s->state[4] = 0xc3d2e1f0;
+		s->seeded = 1;
+	}
+
+	/* fill out the partial 64 byte block from previous calls */
+	if(s->blen){
+		i = 64 - s->blen;
+		if(len < i)
+			i = len;
+		memmove(s->buf + s->blen, p, i);
+		len -= i;
+		s->blen += i;
+		p += i;
+		if(s->blen == 64){
+			_sha1block(s->buf, s->blen, s->state);
+			s->len += s->blen;
+			s->blen = 0;
+		}
+	}
+
+	/* do 64 byte blocks */
+	i = len & ~0x3f;
+	if(i){
+		_sha1block(p, i, s->state);
+		s->len += i;
+		len -= i;
+		p += i;
+	}
+
+	/* save the left overs if not last call */
+	if(digest == 0){
+		if(len){
+			memmove(s->buf, p, len);
+			s->blen += len;
+		}
+		return s;
+	}
+
+	/*
+	 *  this is the last time through, pad what's left with 0x80,
+	 *  0's, and the input count to create a multiple of 64 bytes
+	 */
+	if(s->blen){
+		p = s->buf;
+		len = s->blen;
+	} else {
+		memmove(buf, p, len);
+		p = buf;
+	}
+	s->len += len;
+	e = p + len;
+	if(len < 56)
+		i = 56 - len;
+	else
+		i = 120 - len;
+	memset(e, 0, i);
+	*e = 0x80;
+	len += i;
+
+	/* append the count */
+	x[0] = s->len>>29;
+	x[1] = s->len<<3;
+	encode(p+len, x, 8);
+
+	/* digest the last part */
+	_sha1block(p, len+8, s->state);
+	s->len += len+8;
+
+	/* return result and free state */
+	encode(digest, s->state, SHA1dlen);
+	if(s->malloced == 1)
+		free(s);
+	return nil;
+}
+
+/*
+ *	encodes input (ulong) into output (uchar). Assumes len is
+ *	a multiple of 4.
+ */
+static void
+encode(uchar *output, u32int *input, ulong len)
+{
+	u32int x;
+	uchar *e;
+
+	for(e = output + len; output < e;) {
+		x = *input++;
+		*output++ = x >> 24;
+		*output++ = x >> 16;
+		*output++ = x >> 8;
+		*output++ = x;
+	}
+}

+ 187 - 0
sys/src/cmd/unix/drawterm/libsec/sha1block.c

@@ -0,0 +1,187 @@
+#include "../lib9.h"
+
+void
+_sha1block(uchar *p, ulong len, u32int *s)
+{
+	u32int a, b, c, d, e, x;
+	uchar *end;
+	u32int *wp, *wend;
+	u32int w[80];
+
+	/* at this point, we have a multiple of 64 bytes */
+	for(end = p+len; p < end;){
+		a = s[0];
+		b = s[1];
+		c = s[2];
+		d = s[3];
+		e = s[4];
+
+		wend = w + 15;
+		for(wp = w; wp < wend; wp += 5){
+			wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+			e += ((a<<5) | (a>>27)) + wp[0];
+			e += 0x5a827999 + (((c^d)&b)^d);
+			b = (b<<30)|(b>>2);
+
+			wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7];
+			d += ((e<<5) | (e>>27)) + wp[1];
+			d += 0x5a827999 + (((b^c)&a)^c);
+			a = (a<<30)|(a>>2);
+
+			wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11];
+			c += ((d<<5) | (d>>27)) + wp[2];
+			c += 0x5a827999 + (((a^b)&e)^b);
+			e = (e<<30)|(e>>2);
+
+			wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
+			b += ((c<<5) | (c>>27)) + wp[3];
+			b += 0x5a827999 + (((e^a)&d)^a);
+			d = (d<<30)|(d>>2);
+
+			wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19];
+			a += ((b<<5) | (b>>27)) + wp[4];
+			a += 0x5a827999 + (((d^e)&c)^e);
+			c = (c<<30)|(c>>2);
+			
+			p += 20;
+		}
+
+		wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+		e += ((a<<5) | (a>>27)) + wp[0];
+		e += 0x5a827999 + (((c^d)&b)^d);
+		b = (b<<30)|(b>>2);
+
+		x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15];
+		wp[1] = (x<<1) | (x>>31);
+		d += ((e<<5) | (e>>27)) + wp[1];
+		d += 0x5a827999 + (((b^c)&a)^c);
+		a = (a<<30)|(a>>2);
+
+		x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14];
+		wp[2] = (x<<1) | (x>>31);
+		c += ((d<<5) | (d>>27)) + wp[2];
+		c += 0x5a827999 + (((a^b)&e)^b);
+		e = (e<<30)|(e>>2);
+
+		x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13];
+		wp[3] = (x<<1) | (x>>31);
+		b += ((c<<5) | (c>>27)) + wp[3];
+		b += 0x5a827999 + (((e^a)&d)^a);
+		d = (d<<30)|(d>>2);
+
+		x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12];
+		wp[4] = (x<<1) | (x>>31);
+		a += ((b<<5) | (b>>27)) + wp[4];
+		a += 0x5a827999 + (((d^e)&c)^e);
+		c = (c<<30)|(c>>2);
+
+		wp += 5;
+		p += 4;
+
+		wend = w + 40;
+		for(; wp < wend; wp += 5){
+			x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16];
+			wp[0] = (x<<1) | (x>>31);
+			e += ((a<<5) | (a>>27)) + wp[0];
+			e += 0x6ed9eba1 + (b^c^d);
+			b = (b<<30)|(b>>2);
+
+			x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15];
+			wp[1] = (x<<1) | (x>>31);
+			d += ((e<<5) | (e>>27)) + wp[1];
+			d += 0x6ed9eba1 + (a^b^c);
+			a = (a<<30)|(a>>2);
+
+			x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14];
+			wp[2] = (x<<1) | (x>>31);
+			c += ((d<<5) | (d>>27)) + wp[2];
+			c += 0x6ed9eba1 + (e^a^b);
+			e = (e<<30)|(e>>2);
+
+			x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13];
+			wp[3] = (x<<1) | (x>>31);
+			b += ((c<<5) | (c>>27)) + wp[3];
+			b += 0x6ed9eba1 + (d^e^a);
+			d = (d<<30)|(d>>2);
+
+			x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12];
+			wp[4] = (x<<1) | (x>>31);
+			a += ((b<<5) | (b>>27)) + wp[4];
+			a += 0x6ed9eba1 + (c^d^e);
+			c = (c<<30)|(c>>2);
+		}
+
+		wend = w + 60;
+		for(; wp < wend; wp += 5){
+			x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16];
+			wp[0] = (x<<1) | (x>>31);
+			e += ((a<<5) | (a>>27)) + wp[0];
+			e += 0x8f1bbcdc + ((b&c)|((b|c)&d));
+			b = (b<<30)|(b>>2);
+
+			x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15];
+			wp[1] = (x<<1) | (x>>31);
+			d += ((e<<5) | (e>>27)) + wp[1];
+			d += 0x8f1bbcdc + ((a&b)|((a|b)&c));
+			a = (a<<30)|(a>>2);
+
+			x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14];
+			wp[2] = (x<<1) | (x>>31);
+			c += ((d<<5) | (d>>27)) + wp[2];
+			c += 0x8f1bbcdc + ((e&a)|((e|a)&b));
+			e = (e<<30)|(e>>2);
+
+			x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13];
+			wp[3] = (x<<1) | (x>>31);
+			b += ((c<<5) | (c>>27)) + wp[3];
+			b += 0x8f1bbcdc + ((d&e)|((d|e)&a));
+			d = (d<<30)|(d>>2);
+
+			x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12];
+			wp[4] = (x<<1) | (x>>31);
+			a += ((b<<5) | (b>>27)) + wp[4];
+			a += 0x8f1bbcdc + ((c&d)|((c|d)&e));
+			c = (c<<30)|(c>>2);
+		}
+
+		wend = w + 80;
+		for(; wp < wend; wp += 5){
+			x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16];
+			wp[0] = (x<<1) | (x>>31);
+			e += ((a<<5) | (a>>27)) + wp[0];
+			e += 0xca62c1d6 + (b^c^d);
+			b = (b<<30)|(b>>2);
+
+			x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15];
+			wp[1] = (x<<1) | (x>>31);
+			d += ((e<<5) | (e>>27)) + wp[1];
+			d += 0xca62c1d6 + (a^b^c);
+			a = (a<<30)|(a>>2);
+
+			x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14];
+			wp[2] = (x<<1) | (x>>31);
+			c += ((d<<5) | (d>>27)) + wp[2];
+			c += 0xca62c1d6 + (e^a^b);
+			e = (e<<30)|(e>>2);
+
+			x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13];
+			wp[3] = (x<<1) | (x>>31);
+			b += ((c<<5) | (c>>27)) + wp[3];
+			b += 0xca62c1d6 + (d^e^a);
+			d = (d<<30)|(d>>2);
+
+			x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12];
+			wp[4] = (x<<1) | (x>>31);
+			a += ((b<<5) | (b>>27)) + wp[4];
+			a += 0xca62c1d6 + (c^d^e);
+			c = (c<<30)|(c>>2);
+		}
+
+		/* save state */
+		s[0] += a;
+		s[1] += b;
+		s[2] += c;
+		s[3] += d;
+		s[4] += e;
+	}
+}

+ 126 - 0
sys/src/cmd/unix/drawterm/libsec/u64.c

@@ -0,0 +1,126 @@
+#include "../lib9.h"
+
+enum {
+	INVAL=	255
+};
+
+static uchar t64d[256] = {
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,   62,INVAL,INVAL,INVAL,   63,
+      52,   53,   54,   55,   56,   57,   58,   59,   60,   61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+      15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,
+      41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
+   INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
+};
+static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int
+dec64(uchar *out, int lim, char *in, int n)
+{
+	ulong b24;
+	uchar *start = out;
+	uchar *e = out + lim;
+	int i, c;
+
+	b24 = 0;
+	i = 0;
+	while(n-- > 0){
+ 
+		c = t64d[*(uchar*)in++];
+		if(c == INVAL)
+			continue;
+		switch(i){
+		case 0:
+			b24 = c<<18;
+			break;
+		case 1:
+			b24 |= c<<12;
+			break;
+		case 2:
+			b24 |= c<<6;
+			break;
+		case 3:
+			if(out + 3 > e)
+				goto exhausted;
+
+			b24 |= c;
+			*out++ = b24>>16;
+			*out++ = b24>>8;
+			*out++ = b24;
+			i = -1;
+			break;
+		}
+		i++;
+	}
+	switch(i){
+	case 2:
+		if(out + 1 > e)
+			goto exhausted;
+		*out++ = b24>>16;
+		break;
+	case 3:
+		if(out + 2 > e)
+			goto exhausted;
+		*out++ = b24>>16;
+		*out++ = b24>>8;
+		break;
+	}
+exhausted:
+	return out - start;
+}
+
+int
+enc64(char *out, int lim, uchar *in, int n)
+{
+	int i;
+	ulong b24;
+	char *start = out;
+	char *e = out + lim;
+
+	for(i = n/3; i > 0; i--){
+		b24 = (*in++)<<16;
+		b24 |= (*in++)<<8;
+		b24 |= *in++;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = t64e[(b24>>6)&0x3f];
+		*out++ = t64e[(b24)&0x3f];
+	}
+
+	switch(n%3){
+	case 2:
+		b24 = (*in++)<<16;
+		b24 |= (*in)<<8;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = t64e[(b24>>6)&0x3f];
+		*out++ = '=';
+		break;
+	case 1:
+		b24 = (*in)<<16;
+		if(out + 4 >= e)
+			goto exhausted;
+		*out++ = t64e[(b24>>18)];
+		*out++ = t64e[(b24>>12)&0x3f];
+		*out++ = '=';
+		*out++ = '=';
+		break;
+	}
+exhausted:
+	*out = 0;
+	return out - start;
+}

+ 17 - 1
sys/src/cmd/unix/drawterm/mkfile

@@ -36,6 +36,7 @@ DRAWTERM=\
 	devmouse.$O\
 	devpipe.$O\
 	devroot.$O\
+	devssl.$O\
 	drawterm.$O\
 	dial.$O\
 	dirfstat.$O\
@@ -56,6 +57,7 @@ DRAWTERM=\
 	pow10.$O\
 	print.$O\
 	proc.$O\
+	pushssl.$O\
 	qio.$O\
 	readn.$O\
 	ref.$O\
@@ -122,13 +124,26 @@ LIBDRAW=\
 	d-icossin.$O\
 	d-icossin2.$O\
 
+LIBSEC=\
+	s-des.$O\
+	s-desCBC.$O\
+	s-desECB.$O\
+	s-desmodes.$O\
+	s-md4.$O\
+	s-md5.$O\
+	s-md5block.$O\
+	s-rc4.$O\
+	s-sha1.$O\
+	s-sha1block.$O\
+	s-u64.$O\
+
 XFILES=\
 	md-alloc-x11.$O\
 	md-cload-x11.$O\
 	md-draw-x11.$O\
 	md-load-x11.$O\
 
-OFILES=$DRAWTERM $LIBMEMLAYER $LIBMEMDRAW $LIBDRAW
+OFILES=$DRAWTERM $LIBMEMLAYER $LIBMEMDRAW $LIBDRAW $LIBSEC
 
 all:V: $TARG
 
@@ -141,6 +156,7 @@ $TARG: $OFILES
 $LIBMEMDRAW: $DSRC/libmemdraw/memdraw.h $DSRC/libdraw/draw.h
 $LIBDRAW: $DSRC/libdraw/draw.h
 $LIBMEMLAYER: $DSRC/libmemdraw/memdraw.h $DSRC/libdraw/draw.h $DSRC/libmemlayer/memlayer.h
+$LIBSEC: $DSRC/libsec/libsec.h
 $XFILES: $DSRC/libmemdraw/xmem.h
 
 

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-FreeBSD

@@ -22,3 +22,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-FreeBSD-power

@@ -22,3 +22,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-Irix

@@ -24,3 +24,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 3 - 1
sys/src/cmd/unix/drawterm/mkfile-Linux

@@ -11,7 +11,7 @@ LDFLAGS=-g -o drawterm -static
 DEVIP=devip-unix
 DEVFS=devunixfs
 OSFILES=md-iprint.$O canlock-x86-gcc.$O
-LIBS=-lm -L/usr/X11R6/lib -lX11
+LIBS=-lm -L/usr/X11R6/lib -lX11 -lpthread
 
 ml-%.$O:	$DSRC/libmemlayer/%.c
 	$CC $CFLAGS -o ml-$stem.o $DSRC/libmemlayer/$stem.c
@@ -22,3 +22,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O: $DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-OSF1

@@ -22,3 +22,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-Solaris

@@ -24,3 +24,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -o d-$stem.o $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -o s-$stem.o $DSRC/libsec/$stem.c

+ 2 - 0
sys/src/cmd/unix/drawterm/mkfile-Windows

@@ -46,3 +46,5 @@ md-%.$O:	$DSRC/libmemdraw/%.c
 d-%.$O:	$DSRC/libdraw/%.c
 	$CC $CFLAGS -Fod-$stem $DSRC/libdraw/$stem.c
 
+s-%.$O:	$DSRC/libsec/%.c
+	$CC $CFLAGS -Fos-$stem $DSRC/libsec/$stem.c

+ 43 - 0
sys/src/cmd/unix/drawterm/pushssl.c

@@ -0,0 +1,43 @@
+#include        "lib9.h"
+
+/*
+ * Since the SSL device uses decimal file descriptors to name channels,
+ * it is impossible for a user-level file server to stand in for the kernel device.
+ * Thus we hard-code #D rather than use /net/ssl.
+ */
+
+int
+pushssl(int fd, char *alg, char *secin, char *secout, int *cfd)
+{
+	char buf[8];
+	char dname[64];
+	int n, data, ctl;
+
+	ctl = open("#D/ssl/clone", ORDWR);
+	if(ctl < 0)
+		return -1;
+	n = read(ctl, buf, sizeof(buf)-1);
+	if(n < 0)
+		goto error;
+	buf[n] = 0;
+	sprint(dname, "#D/ssl/%s/data", buf);
+	data = open(dname, ORDWR);
+	if(data < 0)
+		goto error;
+	if(fprint(ctl, "fd %d", fd) < 0 ||
+	   fprint(ctl, "secretin %s", secin) < 0 ||
+	   fprint(ctl, "secretout %s", secout) < 0 ||
+	   fprint(ctl, "alg %s", alg) < 0){
+		close(data);
+		goto error;
+	}
+	close(fd);
+	if(cfd != 0)
+		*cfd = ctl;
+	else
+		close(ctl);
+	return data;
+error:
+	close(ctl);
+	return -1;
+}

+ 29 - 14
sys/src/cmd/unix/drawterm/qio.c

@@ -97,7 +97,7 @@ freeblist(Block *b)
 ulong padblockoverhead;
 
 /*
- *  pad a block to the front
+ *  pad a block to the front (or the back if size is negative)
  */
 Block*
 padblock(Block *bp, int size)
@@ -105,23 +105,38 @@ padblock(Block *bp, int size)
 	int n;
 	Block *nbp;
 
-	if(bp->rp - bp->base > size){
-		bp->rp -= size;
-		return bp;
-	}
+	if(size >= 0){
+		if(bp->rp - bp->base >= size){
+			bp->rp -= size;
+			return bp;
+		}
 
-	n = bp->wp - bp->rp;
-	padblockoverhead += n;
-	nbp = allocb(size+n);
-	nbp->rp += size;
-	nbp->wp = nbp->rp;
-	memmove(nbp->wp, bp->rp, n);
-	nbp->wp += n;
-	freeb(bp);
-	nbp->rp -= size;
+		n = BLEN(bp);
+		padblockoverhead += size;
+		nbp = allocb(size+n);
+		nbp->rp += size;
+		nbp->wp = nbp->rp;
+		memmove(nbp->wp, bp->rp, n);
+		nbp->wp += n;
+		freeb(bp);
+		nbp->rp -= size;
+	} else {
+		size = -size;
+
+		if(bp->lim - bp->wp >= size)
+			return bp;
+
+		n = BLEN(bp);
+		padblockoverhead += size;
+		nbp = allocb(size+n);
+		memmove(nbp->wp, bp->rp, n);
+		nbp->wp += n;
+		freeb(bp);
+	}
 	return nbp;
 }
 
+
 /*
  *  return count of bytes in a string of blocks
  */

+ 11 - 0
sys/src/cmd/unix/drawterm/sys.h

@@ -490,6 +490,17 @@ extern	long	rootread(Chan*, void*, long, ulong);
 extern	long	rootwrite(Chan*, void*, long, ulong);
 extern	void	rootremove(Chan*);
 extern	void	rootwstat(Chan*, char*);
+extern	void	sslinit(void);
+extern	Chan*	sslattach(void*);
+extern	int		sslwalk(Chan*, char*);
+extern	void	sslstat(Chan*, char*);
+extern	Chan*	sslopen(Chan*, int);
+extern	void	sslclose(Chan*);
+extern	long	sslread(Chan*, void*, long, ulong);
+extern	Block*	sslbread(Chan*, long, ulong);
+extern	long	sslwrite(Chan*, void*, long, ulong);
+extern	long	sslbwrite(Chan*, Block*, ulong);
+extern	void	sslwstat(Chan*, char*);
 
 enum {
 	SnarfSize = 64*1024