vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

devssl.c (26110B)


      1 /*
      2  *  devssl - secure sockets layer
      3  */
      4 #include	"u.h"
      5 #include	"lib.h"
      6 #include	"mem.h"
      7 #include	"dat.h"
      8 #include	"fns.h"
      9 #include	"error.h"
     10 
     11 #include	"libsec.h"
     12 
     13 #define NOSPOOKS 1
     14 
     15 typedef struct OneWay OneWay;
     16 struct OneWay
     17 {
     18 	QLock	q;
     19 	QLock	ctlq;
     20 
     21 	void	*state;		/* encryption state */
     22 	int	slen;		/* hash data length */
     23 	uchar	*secret;	/* secret */
     24 	ulong	mid;		/* message id */
     25 };
     26 
     27 enum
     28 {
     29 	/* connection states */
     30 	Sincomplete=	0,
     31 	Sclear=		1,
     32 	Sencrypting=	2,
     33 	Sdigesting=	4,
     34 	Sdigenc=	Sencrypting|Sdigesting,
     35 
     36 	/* encryption algorithms */
     37 	Noencryption=	0,
     38 	DESCBC=		1,
     39 	DESECB=		2,
     40 	RC4=		3
     41 };
     42 
     43 typedef struct Dstate Dstate;
     44 struct Dstate
     45 {
     46 	Chan	*c;		/* io channel */
     47 	uchar	state;		/* state of connection */
     48 	int	ref;		/* serialized by dslock for atomic destroy */
     49 
     50 	uchar	encryptalg;	/* encryption algorithm */
     51 	ushort	blocklen;	/* blocking length */
     52 
     53 	ushort	diglen;		/* length of digest */
     54 	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);	/* hash func */
     55 
     56 	/* for SSL format */
     57 	int	max;		/* maximum unpadded data per msg */
     58 	int	maxpad;		/* maximum padded data per msg */
     59 
     60 	/* input side */
     61 	OneWay	in;
     62 	Block	*processed;
     63 	Block	*unprocessed;
     64 
     65 	/* output side */
     66 	OneWay	out;
     67 
     68 	/* protections */
     69 	char	*user;
     70 	int	perm;
     71 };
     72 
     73 enum
     74 {
     75 	Maxdmsg=	1<<16,
     76 	Maxdstate=	128,	/* must be a power of 2 */
     77 };
     78 
     79 Lock	dslock;
     80 int	dshiwat;
     81 char	*dsname[Maxdstate];
     82 Dstate	*dstate[Maxdstate];
     83 char	*encalgs;
     84 char	*hashalgs;
     85 
     86 enum{
     87 	Qtopdir		= 1,	/* top level directory */
     88 	Qprotodir,
     89 	Qclonus,
     90 	Qconvdir,		/* directory for a conversation */
     91 	Qdata,
     92 	Qctl,
     93 	Qsecretin,
     94 	Qsecretout,
     95 	Qencalgs,
     96 	Qhashalgs,
     97 };
     98 
     99 #define TYPE(x) 	((x).path & 0xf)
    100 #define CONV(x) 	(((x).path >> 5)&(Maxdstate-1))
    101 #define QID(c, y) 	(((c)<<5) | (y))
    102 
    103 static void	ensure(Dstate*, Block**, int);
    104 static void	consume(Block**, uchar*, int);
    105 static void	setsecret(OneWay*, uchar*, int);
    106 static Block*	encryptb(Dstate*, Block*, int);
    107 static Block*	decryptb(Dstate*, Block*);
    108 static Block*	digestb(Dstate*, Block*, int);
    109 static void	checkdigestb(Dstate*, Block*);
    110 static Chan*	buftochan(char*);
    111 static void	sslhangup(Dstate*);
    112 static Dstate*	dsclone(Chan *c);
    113 static void	dsnew(Chan *c, Dstate **);
    114 static long	sslput(Dstate *s, Block * volatile b);
    115 
    116 char *sslnames[] = {
    117 [Qclonus]	"clone",
    118 [Qdata]		"data",
    119 [Qctl]		"ctl",
    120 [Qsecretin]	"secretin",
    121 [Qsecretout]	"secretout",
    122 [Qencalgs]	"encalgs",
    123 [Qhashalgs]	"hashalgs",
    124 };
    125 
    126 static int
    127 sslgen(Chan *c, char *_, Dirtab *d, int nd, int s, Dir *dp)
    128 {
    129 	Qid q;
    130 	Dstate *ds;
    131 	char name[16], *p, *nm;
    132 	int ft;
    133 
    134 	USED(nd);
    135 	USED(d);
    136 
    137 	q.type = QTFILE;
    138 	q.vers = 0;
    139 
    140 	ft = TYPE(c->qid);
    141 	switch(ft) {
    142 	case Qtopdir:
    143 		if(s == DEVDOTDOT){
    144 			q.path = QID(0, Qtopdir);
    145 			q.type = QTDIR;
    146 			devdir(c, q, "#D", 0, eve, 0555, dp);
    147 			return 1;
    148 		}
    149 		if(s > 0)
    150 			return -1;
    151 		q.path = QID(0, Qprotodir);
    152 		q.type = QTDIR;
    153 		devdir(c, q, "ssl", 0, eve, 0555, dp);
    154 		return 1;
    155 	case Qprotodir:
    156 		if(s == DEVDOTDOT){
    157 			q.path = QID(0, Qtopdir);
    158 			q.type = QTDIR;
    159 			devdir(c, q, ".", 0, eve, 0555, dp);
    160 			return 1;
    161 		}
    162 		if(s < dshiwat) {
    163 			q.path = QID(s, Qconvdir);
    164 			q.type = QTDIR;
    165 			ds = dstate[s];
    166 			if(ds != 0)
    167 				nm = ds->user;
    168 			else
    169 				nm = eve;
    170 			if(dsname[s] == nil){
    171 				sprint(name, "%d", s);
    172 				kstrdup(&dsname[s], name);
    173 			}
    174 			devdir(c, q, dsname[s], 0, nm, 0555, dp);
    175 			return 1;
    176 		}
    177 		if(s > dshiwat)
    178 			return -1;
    179 		q.path = QID(0, Qclonus);
    180 		devdir(c, q, "clone", 0, eve, 0555, dp);
    181 		return 1;
    182 	case Qconvdir:
    183 		if(s == DEVDOTDOT){
    184 			q.path = QID(0, Qprotodir);
    185 			q.type = QTDIR;
    186 			devdir(c, q, "ssl", 0, eve, 0555, dp);
    187 			return 1;
    188 		}
    189 		ds = dstate[CONV(c->qid)];
    190 		if(ds != 0)
    191 			nm = ds->user;
    192 		else
    193 			nm = eve;
    194 		switch(s) {
    195 		default:
    196 			return -1;
    197 		case 0:
    198 			q.path = QID(CONV(c->qid), Qctl);
    199 			p = "ctl";
    200 			break;
    201 		case 1:
    202 			q.path = QID(CONV(c->qid), Qdata);
    203 			p = "data";
    204 			break;
    205 		case 2:
    206 			q.path = QID(CONV(c->qid), Qsecretin);
    207 			p = "secretin";
    208 			break;
    209 		case 3:
    210 			q.path = QID(CONV(c->qid), Qsecretout);
    211 			p = "secretout";
    212 			break;
    213 		case 4:
    214 			q.path = QID(CONV(c->qid), Qencalgs);
    215 			p = "encalgs";
    216 			break;
    217 		case 5:
    218 			q.path = QID(CONV(c->qid), Qhashalgs);
    219 			p = "hashalgs";
    220 			break;
    221 		}
    222 		devdir(c, q, p, 0, nm, 0660, dp);
    223 		return 1;
    224 	case Qclonus:
    225 		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp);
    226 		return 1;
    227 	default:
    228 		ds = dstate[CONV(c->qid)];
    229 		if(ds != 0)
    230 			nm = ds->user;
    231 		else
    232 			nm = eve;
    233 		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp);
    234 		return 1;
    235 	}
    236 }
    237 
    238 static Chan*
    239 sslattach(char *spec)
    240 {
    241 	Chan *c;
    242 
    243 	c = devattach('D', spec);
    244 	c->qid.path = QID(0, Qtopdir);
    245 	c->qid.vers = 0;
    246 	c->qid.type = QTDIR;
    247 	return c;
    248 }
    249 
    250 static Walkqid*
    251 sslwalk(Chan *c, Chan *nc, char **name, int nname)
    252 {
    253 	return devwalk(c, nc, name, nname, nil, 0, sslgen);
    254 }
    255 
    256 static int
    257 sslstat(Chan *c, uchar *db, int n)
    258 {
    259 	return devstat(c, db, n, nil, 0, sslgen);
    260 }
    261 
    262 static Chan*
    263 sslopen(Chan *c, int omode)
    264 {
    265 	Dstate *s, **pp;
    266 	int perm;
    267 	int ft;
    268 
    269 	perm = 0;
    270 	omode &= 3;
    271 	switch(omode) {
    272 	case OREAD:
    273 		perm = 4;
    274 		break;
    275 	case OWRITE:
    276 		perm = 2;
    277 		break;
    278 	case ORDWR:
    279 		perm = 6;
    280 		break;
    281 	}
    282 
    283 	ft = TYPE(c->qid);
    284 	switch(ft) {
    285 	default:
    286 		panic("sslopen");
    287 	case Qtopdir:
    288 	case Qprotodir:
    289 	case Qconvdir:
    290 		if(omode != OREAD)
    291 			error(Eperm);
    292 		break;
    293 	case Qclonus:
    294 		s = dsclone(c);
    295 		if(s == 0)
    296 			error(Enodev);
    297 		break;
    298 	case Qctl:
    299 	case Qdata:
    300 	case Qsecretin:
    301 	case Qsecretout:
    302 		if(waserror()) {
    303 			unlock(&dslock);
    304 			nexterror();
    305 		}
    306 		lock(&dslock);
    307 		pp = &dstate[CONV(c->qid)];
    308 		s = *pp;
    309 		if(s == 0)
    310 			dsnew(c, pp);
    311 		else {
    312 			if((perm & (s->perm>>6)) != perm
    313 			   && (strcmp(up->user, s->user) != 0
    314 			     || (perm & s->perm) != perm))
    315 				error(Eperm);
    316 
    317 			s->ref++;
    318 		}
    319 		unlock(&dslock);
    320 		poperror();
    321 		break;
    322 	case Qencalgs:
    323 	case Qhashalgs:
    324 		if(omode != OREAD)
    325 			error(Eperm);
    326 		break;
    327 	}
    328 	c->mode = openmode(omode);
    329 	c->flag |= COPEN;
    330 	c->offset = 0;
    331 	return c;
    332 }
    333 
    334 static int
    335 sslwstat(Chan *c, uchar *db, int n)
    336 {
    337 	Dir *dir;
    338 	Dstate *s;
    339 	int m;
    340 
    341 	s = dstate[CONV(c->qid)];
    342 	if(s == 0)
    343 		error(Ebadusefd);
    344 	if(strcmp(s->user, up->user) != 0)
    345 		error(Eperm);
    346 
    347 	dir = smalloc(sizeof(Dir)+n);
    348 	m = convM2D(db, n, &dir[0], (char*)&dir[1]);
    349 	if(m == 0){
    350 		free(dir);
    351 		error(Eshortstat);
    352 	}
    353 
    354 	if(!emptystr(dir->uid))
    355 		kstrdup(&s->user, dir->uid);
    356 	if(dir->mode != ~0UL)
    357 		s->perm = dir->mode;
    358 
    359 	free(dir);
    360 	return m;
    361 }
    362 
    363 static void
    364 sslclose(Chan *c)
    365 {
    366 	Dstate *s;
    367 	int ft;
    368 
    369 	ft = TYPE(c->qid);
    370 	switch(ft) {
    371 	case Qctl:
    372 	case Qdata:
    373 	case Qsecretin:
    374 	case Qsecretout:
    375 		if((c->flag & COPEN) == 0)
    376 			break;
    377 
    378 		s = dstate[CONV(c->qid)];
    379 		if(s == 0)
    380 			break;
    381 
    382 		lock(&dslock);
    383 		if(--s->ref > 0) {
    384 			unlock(&dslock);
    385 			break;
    386 		}
    387 		dstate[CONV(c->qid)] = 0;
    388 		unlock(&dslock);
    389 
    390 		if(s->user != nil)
    391 			free(s->user);
    392 		sslhangup(s);
    393 		if(s->c)
    394 			cclose(s->c);
    395 		if(s->in.secret)
    396 			free(s->in.secret);
    397 		if(s->out.secret)
    398 			free(s->out.secret);
    399 		if(s->in.state)
    400 			free(s->in.state);
    401 		if(s->out.state)
    402 			free(s->out.state);
    403 		free(s);
    404 
    405 	}
    406 }
    407 
    408 /*
    409  *  make sure we have at least 'n' bytes in list 'l'
    410  */
    411 static void
    412 ensure(Dstate *s, Block **l, int n)
    413 {
    414 	int sofar, i;
    415 	Block *b, *bl;
    416 
    417 	sofar = 0;
    418 	for(b = *l; b; b = b->next){
    419 		sofar += BLEN(b);
    420 		if(sofar >= n)
    421 			return;
    422 		l = &b->next;
    423 	}
    424 
    425 	while(sofar < n){
    426 		bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0);
    427 		if(bl == 0)
    428 			nexterror();
    429 		*l = bl;
    430 		i = 0;
    431 		for(b = bl; b; b = b->next){
    432 			i += BLEN(b);
    433 			l = &b->next;
    434 		}
    435 		if(i == 0)
    436 			error(Ehungup);
    437 		sofar += i;
    438 	}
    439 }
    440 
    441 /*
    442  *  copy 'n' bytes from 'l' into 'p' and free
    443  *  the bytes in 'l'
    444  */
    445 static void
    446 consume(Block **l, uchar *p, int n)
    447 {
    448 	Block *b;
    449 	int i;
    450 
    451 	for(; *l && n > 0; n -= i){
    452 		b = *l;
    453 		i = BLEN(b);
    454 		if(i > n)
    455 			i = n;
    456 		memmove(p, b->rp, i);
    457 		b->rp += i;
    458 		p += i;
    459 		if(BLEN(b) < 0)
    460 			panic("consume");
    461 		if(BLEN(b))
    462 			break;
    463 		*l = b->next;
    464 		freeb(b);
    465 	}
    466 }
    467 
    468 /*
    469  *  give back n bytes
    470 static void
    471 regurgitate(Dstate *s, uchar *p, int n)
    472 {
    473 	Block *b;
    474 
    475 	if(n <= 0)
    476 		return;
    477 	b = s->unprocessed;
    478 	if(s->unprocessed == nil || b->rp - b->base < n) {
    479 		b = allocb(n);
    480 		memmove(b->wp, p, n);
    481 		b->wp += n;
    482 		b->next = s->unprocessed;
    483 		s->unprocessed = b;
    484 	} else {
    485 		b->rp -= n;
    486 		memmove(b->rp, p, n);
    487 	}
    488 }
    489  */
    490 
    491 /*
    492  *  remove at most n bytes from the queue, if discard is set
    493  *  dump the remainder
    494  */
    495 static Block*
    496 qtake(Block **l, int n, int discard)
    497 {
    498 	Block *nb, *b, *first;
    499 	int i;
    500 
    501 	first = *l;
    502 	for(b = first; b; b = b->next){
    503 		i = BLEN(b);
    504 		if(i == n){
    505 			if(discard){
    506 				freeblist(b->next);
    507 				*l = 0;
    508 			} else
    509 				*l = b->next;
    510 			b->next = 0;
    511 			return first;
    512 		} else if(i > n){
    513 			i -= n;
    514 			if(discard){
    515 				freeblist(b->next);
    516 				b->wp -= i;
    517 				*l = 0;
    518 			} else {
    519 				nb = allocb(i);
    520 				memmove(nb->wp, b->rp+n, i);
    521 				nb->wp += i;
    522 				b->wp -= i;
    523 				nb->next = b->next;
    524 				*l = nb;
    525 			}
    526 			b->next = 0;
    527 			if(BLEN(b) < 0)
    528 				panic("qtake");
    529 			return first;
    530 		} else
    531 			n -= i;
    532 		if(BLEN(b) < 0)
    533 			panic("qtake");
    534 	}
    535 	*l = 0;
    536 	return first;
    537 }
    538 
    539 /*
    540  *  We can't let Eintr's lose data since the program
    541  *  doing the read may be able to handle it.  The only
    542  *  places Eintr is possible is during the read's in consume.
    543  *  Therefore, we make sure we can always put back the bytes
    544  *  consumed before the last ensure.
    545  */
    546 static Block*
    547 sslbread(Chan *c, long n, ulong _)
    548 {
    549 	Dstate * volatile s;
    550 	Block *b;
    551 	uchar consumed[3], *p;
    552 	int toconsume;
    553 	int len, pad;
    554 
    555 	s = dstate[CONV(c->qid)];
    556 	if(s == 0)
    557 		panic("sslbread");
    558 	if(s->state == Sincomplete)
    559 		error(Ebadusefd);
    560 
    561 	qlock(&s->in.q);
    562 	if(waserror()){
    563 		qunlock(&s->in.q);
    564 		nexterror();
    565 	}
    566 
    567 	if(s->processed == 0){
    568 		/*
    569 		 * Read in the whole message.  Until we've got it all,
    570 		 * it stays on s->unprocessed, so that if we get Eintr,
    571 		 * we'll pick up where we left off.
    572 		 */
    573 		ensure(s, &s->unprocessed, 3);
    574 		s->unprocessed = pullupblock(s->unprocessed, 2);
    575 		p = s->unprocessed->rp;
    576 		if(p[0] & 0x80){
    577 			len = ((p[0] & 0x7f)<<8) | p[1];
    578 			ensure(s, &s->unprocessed, len);
    579 			pad = 0;
    580 			toconsume = 2;
    581 		} else {
    582 			s->unprocessed = pullupblock(s->unprocessed, 3);
    583 			len = ((p[0] & 0x3f)<<8) | p[1];
    584 			pad = p[2];
    585 			if(pad > len){
    586 				print("pad %d buf len %d\n", pad, len);
    587 				error("bad pad in ssl message");
    588 			}
    589 			toconsume = 3;
    590 		}
    591 		ensure(s, &s->unprocessed, toconsume+len);
    592 
    593 		/* skip header */
    594 		consume(&s->unprocessed, consumed, toconsume);
    595 
    596 		/* grab the next message and decode/decrypt it */
    597 		b = qtake(&s->unprocessed, len, 0);
    598 
    599 		if(blocklen(b) != len)
    600 			print("devssl: sslbread got wrong count %d != %d", blocklen(b), len);
    601 
    602 		if(waserror()){
    603 			qunlock(&s->in.ctlq);
    604 			if(b != nil)
    605 				freeb(b);
    606 			nexterror();
    607 		}
    608 		qlock(&s->in.ctlq);
    609 		switch(s->state){
    610 		case Sencrypting:
    611 			if(b == nil)
    612 				error("ssl message too short (encrypting)");
    613 			b = decryptb(s, b);
    614 			break;
    615 		case Sdigesting:
    616 			b = pullupblock(b, s->diglen);
    617 			if(b == nil)
    618 				error("ssl message too short (digesting)");
    619 			checkdigestb(s, b);
    620 			pullblock(&b, s->diglen);
    621 			len -= s->diglen;
    622 			break;
    623 		case Sdigenc:
    624 			b = decryptb(s, b);
    625 			b = pullupblock(b, s->diglen);
    626 			if(b == nil)
    627 				error("ssl message too short (dig+enc)");
    628 			checkdigestb(s, b);
    629 			pullblock(&b, s->diglen);
    630 			len -= s->diglen;
    631 			break;
    632 		}
    633 
    634 		/* remove pad */
    635 		if(pad)
    636 			s->processed = qtake(&b, len - pad, 1);
    637 		else
    638 			s->processed = b;
    639 		b = nil;
    640 		s->in.mid++;
    641 		qunlock(&s->in.ctlq);
    642 		poperror();
    643 	}
    644 
    645 	/* return at most what was asked for */
    646 	b = qtake(&s->processed, n, 0);
    647 
    648 	qunlock(&s->in.q);
    649 	poperror();
    650 
    651 	return b;
    652 }
    653 
    654 static long
    655 sslread(Chan *c, void *a, long n, vlong off)
    656 {
    657 	Block * volatile b;
    658 	Block *nb;
    659 	uchar *va;
    660 	int i;
    661 	char buf[128];
    662 	ulong offset = off;
    663 	int ft;
    664 
    665 	if(c->qid.type & QTDIR)
    666 		return devdirread(c, a, n, 0, 0, sslgen);
    667 
    668 	ft = TYPE(c->qid);
    669 	switch(ft) {
    670 	default:
    671 		error(Ebadusefd);
    672 	case Qctl:
    673 		ft = CONV(c->qid);
    674 		sprint(buf, "%d", ft);
    675 		return readstr(offset, a, n, buf);
    676 	case Qdata:
    677 		b = sslbread(c, n, offset);
    678 		break;
    679 	case Qencalgs:
    680 		return readstr(offset, a, n, encalgs);
    681 		break;
    682 	case Qhashalgs:
    683 		return readstr(offset, a, n, hashalgs);
    684 		break;
    685 	}
    686 
    687 	if(waserror()){
    688 		freeblist(b);
    689 		nexterror();
    690 	}
    691 
    692 	n = 0;
    693 	va = a;
    694 	for(nb = b; nb; nb = nb->next){
    695 		i = BLEN(nb);
    696 		memmove(va+n, nb->rp, i);
    697 		n += i;
    698 	}
    699 
    700 	freeblist(b);
    701 	poperror();
    702 
    703 	return n;
    704 }
    705 
    706 /*
    707  *  this algorithm doesn't have to be great since we're just
    708  *  trying to obscure the block fill
    709  */
    710 static void
    711 randfill(uchar *buf, int len)
    712 {
    713 	while(len-- > 0)
    714 		*buf++ = nrand(256);
    715 }
    716 
    717 static long
    718 sslbwrite(Chan *c, Block *b, ulong _)
    719 {
    720 	Dstate * volatile s;
    721 	long rv;
    722 
    723 	s = dstate[CONV(c->qid)];
    724 	if(s == nil)
    725 		panic("sslbwrite");
    726 
    727 	if(s->state == Sincomplete){
    728 		freeb(b);
    729 		error(Ebadusefd);
    730 	}
    731 
    732 	/* lock so split writes won't interleave */
    733 	if(waserror()){
    734 		qunlock(&s->out.q);
    735 		nexterror();
    736 	}
    737 	qlock(&s->out.q);
    738 
    739 	rv = sslput(s, b);
    740 
    741 	poperror();
    742 	qunlock(&s->out.q);
    743 
    744 	return rv;
    745 }
    746 
    747 /*
    748  *  use SSL record format, add in count, digest and/or encrypt.
    749  *  the write is interruptable.  if it is interrupted, we'll
    750  *  get out of sync with the far side.  not much we can do about
    751  *  it since we don't know if any bytes have been written.
    752  */
    753 static long
    754 sslput(Dstate *s, Block * volatile b)
    755 {
    756 	Block *nb;
    757 	int h, n, m, pad, rv;
    758 	uchar *p;
    759 	int offset;
    760 
    761 	if(waserror()){
    762 		if(b != nil)
    763 			free(b);
    764 		nexterror();
    765 	}
    766 
    767 	rv = 0;
    768 	while(b != nil){
    769 		m = n = BLEN(b);
    770 		h = s->diglen + 2;
    771 
    772 		/* trim to maximum block size */
    773 		pad = 0;
    774 		if(m > s->max){
    775 			m = s->max;
    776 		} else if(s->blocklen != 1){
    777 			pad = (m + s->diglen)%s->blocklen;
    778 			if(pad){
    779 				if(m > s->maxpad){
    780 					pad = 0;
    781 					m = s->maxpad;
    782 				} else {
    783 					pad = s->blocklen - pad;
    784 					h++;
    785 				}
    786 			}
    787 		}
    788 
    789 		rv += m;
    790 		if(m != n){
    791 			nb = allocb(m + h + pad);
    792 			memmove(nb->wp + h, b->rp, m);
    793 			nb->wp += m + h;
    794 			b->rp += m;
    795 		} else {
    796 			/* add header space */
    797 			nb = padblock(b, h);
    798 			b = 0;
    799 		}
    800 		m += s->diglen;
    801 
    802 		/* SSL style count */
    803 		if(pad){
    804 			nb = padblock(nb, -pad);
    805 			randfill(nb->wp, pad);
    806 			nb->wp += pad;
    807 			m += pad;
    808 
    809 			p = nb->rp;
    810 			p[0] = (m>>8);
    811 			p[1] = m;
    812 			p[2] = pad;
    813 			offset = 3;
    814 		} else {
    815 			p = nb->rp;
    816 			p[0] = (m>>8) | 0x80;
    817 			p[1] = m;
    818 			offset = 2;
    819 		}
    820 
    821 		switch(s->state){
    822 		case Sencrypting:
    823 			nb = encryptb(s, nb, offset);
    824 			break;
    825 		case Sdigesting:
    826 			nb = digestb(s, nb, offset);
    827 			break;
    828 		case Sdigenc:
    829 			nb = digestb(s, nb, offset);
    830 			nb = encryptb(s, nb, offset);
    831 			break;
    832 		}
    833 
    834 		s->out.mid++;
    835 
    836 		m = BLEN(nb);
    837 		devtab[s->c->type]->bwrite(s->c, nb, s->c->offset);
    838 		s->c->offset += m;
    839 	}
    840 
    841 	poperror();
    842 	return rv;
    843 }
    844 
    845 static void
    846 setsecret(OneWay *w, uchar *secret, int n)
    847 {
    848 	if(w->secret)
    849 		free(w->secret);
    850 
    851 	w->secret = smalloc(n);
    852 	memmove(w->secret, secret, n);
    853 	w->slen = n;
    854 }
    855 
    856 static void
    857 initDESkey(OneWay *w)
    858 {
    859 	if(w->state){
    860 		free(w->state);
    861 		w->state = 0;
    862 	}
    863 
    864 	w->state = smalloc(sizeof(DESstate));
    865 	if(w->slen >= 16)
    866 		setupDESstate(w->state, w->secret, w->secret+8);
    867 	else if(w->slen >= 8)
    868 		setupDESstate(w->state, w->secret, 0);
    869 	else
    870 		error("secret too short");
    871 }
    872 
    873 /*
    874  *  40 bit DES is the same as 56 bit DES.  However,
    875  *  16 bits of the key are masked to zero.
    876  */
    877 static void
    878 initDESkey_40(OneWay *w)
    879 {
    880 	uchar key[8];
    881 
    882 	if(w->state){
    883 		free(w->state);
    884 		w->state = 0;
    885 	}
    886 
    887 	if(w->slen >= 8){
    888 		memmove(key, w->secret, 8);
    889 		key[0] &= 0x0f;
    890 		key[2] &= 0x0f;
    891 		key[4] &= 0x0f;
    892 		key[6] &= 0x0f;
    893 	}
    894 
    895 	w->state = malloc(sizeof(DESstate));
    896 	if(w->slen >= 16)
    897 		setupDESstate(w->state, key, w->secret+8);
    898 	else if(w->slen >= 8)
    899 		setupDESstate(w->state, key, 0);
    900 	else
    901 		error("secret too short");
    902 }
    903 
    904 static void
    905 initRC4key(OneWay *w)
    906 {
    907 	if(w->state){
    908 		free(w->state);
    909 		w->state = 0;
    910 	}
    911 
    912 	w->state = smalloc(sizeof(RC4state));
    913 	setupRC4state(w->state, w->secret, w->slen);
    914 }
    915 
    916 /*
    917  *  40 bit RC4 is the same as n-bit RC4.  However,
    918  *  we ignore all but the first 40 bits of the key.
    919  */
    920 static void
    921 initRC4key_40(OneWay *w)
    922 {
    923 	if(w->state){
    924 		free(w->state);
    925 		w->state = 0;
    926 	}
    927 
    928 	if(w->slen > 5)
    929 		w->slen = 5;
    930 
    931 	w->state = malloc(sizeof(RC4state));
    932 	setupRC4state(w->state, w->secret, w->slen);
    933 }
    934 
    935 /*
    936  *  128 bit RC4 is the same as n-bit RC4.  However,
    937  *  we ignore all but the first 128 bits of the key.
    938  */
    939 static void
    940 initRC4key_128(OneWay *w)
    941 {
    942 	if(w->state){
    943 		free(w->state);
    944 		w->state = 0;
    945 	}
    946 
    947 	if(w->slen > 16)
    948 		w->slen = 16;
    949 
    950 	w->state = malloc(sizeof(RC4state));
    951 	setupRC4state(w->state, w->secret, w->slen);
    952 }
    953 
    954 
    955 typedef struct Hashalg Hashalg;
    956 struct Hashalg
    957 {
    958 	char	*name;
    959 	int	diglen;
    960 	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);
    961 };
    962 
    963 Hashalg hashtab[] =
    964 {
    965 	{ "md4", MD4dlen, md4, },
    966 	{ "md5", MD5dlen, md5, },
    967 	{ "sha1", SHA1dlen, sha1, },
    968 	{ "sha", SHA1dlen, sha1, },
    969 	{ 0 }
    970 };
    971 
    972 static int
    973 parsehashalg(char *p, Dstate *s)
    974 {
    975 	Hashalg *ha;
    976 
    977 	for(ha = hashtab; ha->name; ha++){
    978 		if(strcmp(p, ha->name) == 0){
    979 			s->hf = ha->hf;
    980 			s->diglen = ha->diglen;
    981 			s->state &= ~Sclear;
    982 			s->state |= Sdigesting;
    983 			return 0;
    984 		}
    985 	}
    986 	return -1;
    987 }
    988 
    989 typedef struct Encalg Encalg;
    990 struct Encalg
    991 {
    992 	char	*name;
    993 	int	blocklen;
    994 	int	alg;
    995 	void	(*keyinit)(OneWay*);
    996 };
    997 
    998 #ifdef NOSPOOKS
    999 Encalg encrypttab[] =
   1000 {
   1001 	{ "descbc", 8, DESCBC, initDESkey, },           /* DEPRECATED -- use des_56_cbc */
   1002 	{ "desecb", 8, DESECB, initDESkey, },           /* DEPRECATED -- use des_56_ecb */
   1003 	{ "des_56_cbc", 8, DESCBC, initDESkey, },
   1004 	{ "des_56_ecb", 8, DESECB, initDESkey, },
   1005 	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
   1006 	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
   1007 	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
   1008 	{ "rc4_256", 1, RC4, initRC4key, },
   1009 	{ "rc4_128", 1, RC4, initRC4key_128, },
   1010 	{ "rc4_40", 1, RC4, initRC4key_40, },
   1011 	{ 0 }
   1012 };
   1013 #else
   1014 Encalg encrypttab[] =
   1015 {
   1016 	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
   1017 	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
   1018 	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
   1019 	{ "rc4_40", 1, RC4, initRC4key_40, },
   1020 	{ 0 }
   1021 };
   1022 #endif 
   1023 
   1024 static int
   1025 parseencryptalg(char *p, Dstate *s)
   1026 {
   1027 	Encalg *ea;
   1028 
   1029 	for(ea = encrypttab; ea->name; ea++){
   1030 		if(strcmp(p, ea->name) == 0){
   1031 			s->encryptalg = ea->alg;
   1032 			s->blocklen = ea->blocklen;
   1033 			(*ea->keyinit)(&s->in);
   1034 			(*ea->keyinit)(&s->out);
   1035 			s->state &= ~Sclear;
   1036 			s->state |= Sencrypting;
   1037 			return 0;
   1038 		}
   1039 	}
   1040 	return -1;
   1041 }
   1042 
   1043 static long
   1044 sslwrite(Chan *c, void *a, long n, vlong offset)
   1045 {
   1046 	Dstate * volatile s;
   1047 	Block * volatile b;
   1048 	int m, t;
   1049 	char *p, *np, *e, buf[128];
   1050 	uchar *x;
   1051 
   1052 	s = dstate[CONV(c->qid)];
   1053 	if(s == 0)
   1054 		panic("sslwrite");
   1055 
   1056 	t = TYPE(c->qid);
   1057 	if(t == Qdata){
   1058 		if(s->state == Sincomplete)
   1059 			error(Ebadusefd);
   1060 
   1061 		/* lock should a write gets split over multiple records */
   1062 		if(waserror()){
   1063 			qunlock(&s->out.q);
   1064 			nexterror();
   1065 		}
   1066 		qlock(&s->out.q);
   1067 
   1068 		p = a;
   1069 		e = p + n;
   1070 		do {
   1071 			m = e - p;
   1072 			if(m > s->max)
   1073 				m = s->max;
   1074 
   1075 			b = allocb(m);
   1076 			if(waserror()){
   1077 				freeb(b);
   1078 				nexterror();
   1079 			}
   1080 			memmove(b->wp, p, m);
   1081 			poperror();
   1082 			b->wp += m;
   1083 
   1084 			sslput(s, b);
   1085 
   1086 			p += m;
   1087 		} while(p < e);
   1088 
   1089 		poperror();
   1090 		qunlock(&s->out.q);
   1091 		return n;
   1092 	}
   1093 
   1094 	/* mutex with operations using what we're about to change */
   1095 	if(waserror()){
   1096 		qunlock(&s->in.ctlq);
   1097 		qunlock(&s->out.q);
   1098 		nexterror();
   1099 	}
   1100 	qlock(&s->in.ctlq);
   1101 	qlock(&s->out.q);
   1102 
   1103 	switch(t){
   1104 	default:
   1105 		panic("sslwrite");
   1106 	case Qsecretin:
   1107 		setsecret(&s->in, a, n);
   1108 		goto out;
   1109 	case Qsecretout:
   1110 		setsecret(&s->out, a, n);
   1111 		goto out;
   1112 	case Qctl:
   1113 		break;
   1114 	}
   1115 
   1116 	if(n >= sizeof(buf))
   1117 		error("arg too long");
   1118 	strncpy(buf, a, n);
   1119 	buf[n] = 0;
   1120 	p = strchr(buf, '\n');
   1121 	if(p)
   1122 		*p = 0;
   1123 	p = strchr(buf, ' ');
   1124 	if(p)
   1125 		*p++ = 0;
   1126 
   1127 	if(strcmp(buf, "fd") == 0){
   1128 		s->c = buftochan(p);
   1129 
   1130 		/* default is clear (msg delimiters only) */
   1131 		s->state = Sclear;
   1132 		s->blocklen = 1;
   1133 		s->diglen = 0;
   1134 		s->maxpad = s->max = (1<<15) - s->diglen - 1;
   1135 		s->in.mid = 0;
   1136 		s->out.mid = 0;
   1137 	} else if(strcmp(buf, "alg") == 0 && p != 0){
   1138 		s->blocklen = 1;
   1139 		s->diglen = 0;
   1140 
   1141 		if(s->c == 0)
   1142 			error("must set fd before algorithm");
   1143 
   1144 		s->state = Sclear;
   1145 		s->maxpad = s->max = (1<<15) - s->diglen - 1;
   1146 		if(strcmp(p, "clear") == 0){
   1147 			goto out;
   1148 		}
   1149 
   1150 		if(s->in.secret && s->out.secret == 0)
   1151 			setsecret(&s->out, s->in.secret, s->in.slen);
   1152 		if(s->out.secret && s->in.secret == 0)
   1153 			setsecret(&s->in, s->out.secret, s->out.slen);
   1154 		if(s->in.secret == 0 || s->out.secret == 0)
   1155 			error("algorithm but no secret");
   1156 
   1157 		s->hf = 0;
   1158 		s->encryptalg = Noencryption;
   1159 		s->blocklen = 1;
   1160 
   1161 		for(;;){
   1162 			np = strchr(p, ' ');
   1163 			if(np)
   1164 				*np++ = 0;
   1165 
   1166 			if(parsehashalg(p, s) < 0)
   1167 			if(parseencryptalg(p, s) < 0)
   1168 				error("bad algorithm");
   1169 
   1170 			if(np == 0)
   1171 				break;
   1172 			p = np;
   1173 		}
   1174 
   1175 		if(s->hf == 0 && s->encryptalg == Noencryption)
   1176 			error("bad algorithm");
   1177 
   1178 		if(s->blocklen != 1){
   1179 			s->max = (1<<15) - s->diglen - 1;
   1180 			s->max -= s->max % s->blocklen;
   1181 			s->maxpad = (1<<14) - s->diglen - 1;
   1182 			s->maxpad -= s->maxpad % s->blocklen;
   1183 		} else
   1184 			s->maxpad = s->max = (1<<15) - s->diglen - 1;
   1185 	} else if(strcmp(buf, "secretin") == 0 && p != 0) {
   1186 		m = (strlen(p)*3)/2;
   1187 		x = smalloc(m);
   1188 		t = dec64(x, m, p, strlen(p));
   1189 		setsecret(&s->in, x, t);
   1190 		free(x);
   1191 	} else if(strcmp(buf, "secretout") == 0 && p != 0) {
   1192 		m = (strlen(p)*3)/2 + 1;
   1193 		x = smalloc(m);
   1194 		t = dec64(x, m, p, strlen(p));
   1195 		setsecret(&s->out, x, t);
   1196 		free(x);
   1197 	} else
   1198 		error(Ebadarg);
   1199 
   1200 out:
   1201 	qunlock(&s->in.ctlq);
   1202 	qunlock(&s->out.q);
   1203 	poperror();
   1204 	return n;
   1205 }
   1206 
   1207 static void
   1208 sslinit(void)
   1209 {
   1210 	struct Encalg *e;
   1211 	struct Hashalg *h;
   1212 	int n;
   1213 	char *cp;
   1214 
   1215 	n = 1;
   1216 	for(e = encrypttab; e->name != nil; e++)
   1217 		n += strlen(e->name) + 1;
   1218 	cp = encalgs = smalloc(n);
   1219 	for(e = encrypttab;;){
   1220 		strcpy(cp, e->name);
   1221 		cp += strlen(e->name);
   1222 		e++;
   1223 		if(e->name == nil)
   1224 			break;
   1225 		*cp++ = ' ';
   1226 	}
   1227 	*cp = 0;
   1228 
   1229 	n = 1;
   1230 	for(h = hashtab; h->name != nil; h++)
   1231 		n += strlen(h->name) + 1;
   1232 	cp = hashalgs = smalloc(n);
   1233 	for(h = hashtab;;){
   1234 		strcpy(cp, h->name);
   1235 		cp += strlen(h->name);
   1236 		h++;
   1237 		if(h->name == nil)
   1238 			break;
   1239 		*cp++ = ' ';
   1240 	}
   1241 	*cp = 0;
   1242 }
   1243 
   1244 Dev ssldevtab = {
   1245 	'D',
   1246 	"ssl",
   1247 
   1248 	devreset,
   1249 	sslinit,
   1250 	devshutdown,
   1251 	sslattach,
   1252 	sslwalk,
   1253 	sslstat,
   1254 	sslopen,
   1255 	devcreate,
   1256 	sslclose,
   1257 	sslread,
   1258 	sslbread,
   1259 	sslwrite,
   1260 	sslbwrite,
   1261 	devremove,
   1262 	sslwstat,
   1263 };
   1264 
   1265 static Block*
   1266 encryptb(Dstate *s, Block *b, int offset)
   1267 {
   1268 	uchar *p, *ep, *p2, *ip, *eip;
   1269 	DESstate *ds;
   1270 
   1271 	switch(s->encryptalg){
   1272 	case DESECB:
   1273 		ds = s->out.state;
   1274 		ep = b->rp + BLEN(b);
   1275 		for(p = b->rp + offset; p < ep; p += 8)
   1276 			block_cipher(ds->expanded, p, 0);
   1277 		break;
   1278 	case DESCBC:
   1279 		ds = s->out.state;
   1280 		ep = b->rp + BLEN(b);
   1281 		for(p = b->rp + offset; p < ep; p += 8){
   1282 			p2 = p;
   1283 			ip = ds->ivec;
   1284 			for(eip = ip+8; ip < eip; )
   1285 				*p2++ ^= *ip++;
   1286 			block_cipher(ds->expanded, p, 0);
   1287 			memmove(ds->ivec, p, 8);
   1288 		}
   1289 		break;
   1290 	case RC4:
   1291 		rc4(s->out.state, b->rp + offset, BLEN(b) - offset);
   1292 		break;
   1293 	}
   1294 	return b;
   1295 }
   1296 
   1297 static Block*
   1298 decryptb(Dstate *s, Block *bin)
   1299 {
   1300 	Block *b, **l;
   1301 	uchar *p, *ep, *tp, *ip, *eip;
   1302 	DESstate *ds;
   1303 	uchar tmp[8];
   1304 	int i;
   1305 
   1306 	l = &bin;
   1307 	for(b = bin; b; b = b->next){
   1308 		/* make sure we have a multiple of s->blocklen */
   1309 		if(s->blocklen > 1){
   1310 			i = BLEN(b);
   1311 			if(i % s->blocklen){
   1312 				*l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen));
   1313 				if(b == 0)
   1314 					error("ssl encrypted message too short");
   1315 			}
   1316 		}
   1317 		l = &b->next;
   1318 
   1319 		/* decrypt */
   1320 		switch(s->encryptalg){
   1321 		case DESECB:
   1322 			ds = s->in.state;
   1323 			ep = b->rp + BLEN(b);
   1324 			for(p = b->rp; p < ep; p += 8)
   1325 				block_cipher(ds->expanded, p, 1);
   1326 			break;
   1327 		case DESCBC:
   1328 			ds = s->in.state;
   1329 			ep = b->rp + BLEN(b);
   1330 			for(p = b->rp; p < ep;){
   1331 				memmove(tmp, p, 8);
   1332 				block_cipher(ds->expanded, p, 1);
   1333 				tp = tmp;
   1334 				ip = ds->ivec;
   1335 				for(eip = ip+8; ip < eip; ){
   1336 					*p++ ^= *ip;
   1337 					*ip++ = *tp++;
   1338 				}
   1339 			}
   1340 			break;
   1341 		case RC4:
   1342 			rc4(s->in.state, b->rp, BLEN(b));
   1343 			break;
   1344 		}
   1345 	}
   1346 	return bin;
   1347 }
   1348 
   1349 static Block*
   1350 digestb(Dstate *s, Block *b, int offset)
   1351 {
   1352 	uchar *p;
   1353 	DigestState ss;
   1354 	uchar msgid[4];
   1355 	ulong n, h;
   1356 	OneWay *w;
   1357 
   1358 	w = &s->out;
   1359 
   1360 	memset(&ss, 0, sizeof(ss));
   1361 	h = s->diglen + offset;
   1362 	n = BLEN(b) - h;
   1363 
   1364 	/* hash secret + message */
   1365 	(*s->hf)(w->secret, w->slen, 0, &ss);
   1366 	(*s->hf)(b->rp + h, n, 0, &ss);
   1367 
   1368 	/* hash message id */
   1369 	p = msgid;
   1370 	n = w->mid;
   1371 	*p++ = n>>24;
   1372 	*p++ = n>>16;
   1373 	*p++ = n>>8;
   1374 	*p = n;
   1375 	(*s->hf)(msgid, 4, b->rp + offset, &ss);
   1376 
   1377 	return b;
   1378 }
   1379 
   1380 static void
   1381 checkdigestb(Dstate *s, Block *bin)
   1382 {
   1383 	uchar *p;
   1384 	DigestState ss;
   1385 	uchar msgid[4];
   1386 	int n, h;
   1387 	OneWay *w;
   1388 	uchar digest[128];
   1389 	Block *b;
   1390 
   1391 	w = &s->in;
   1392 
   1393 	memset(&ss, 0, sizeof(ss));
   1394 
   1395 	/* hash secret */
   1396 	(*s->hf)(w->secret, w->slen, 0, &ss);
   1397 
   1398 	/* hash message */
   1399 	h = s->diglen;
   1400 	for(b = bin; b; b = b->next){
   1401 		n = BLEN(b) - h;
   1402 		if(n < 0)
   1403 			panic("checkdigestb");
   1404 		(*s->hf)(b->rp + h, n, 0, &ss);
   1405 		h = 0;
   1406 	}
   1407 
   1408 	/* hash message id */
   1409 	p = msgid;
   1410 	n = w->mid;
   1411 	*p++ = n>>24;
   1412 	*p++ = n>>16;
   1413 	*p++ = n>>8;
   1414 	*p = n;
   1415 	(*s->hf)(msgid, 4, digest, &ss);
   1416 
   1417 	if(memcmp(digest, bin->rp, s->diglen) != 0)
   1418 		error("bad digest");
   1419 }
   1420 
   1421 /* get channel associated with an fd */
   1422 static Chan*
   1423 buftochan(char *p)
   1424 {
   1425 	Chan *c;
   1426 	int fd;
   1427 
   1428 	if(p == 0)
   1429 		error(Ebadarg);
   1430 	fd = strtoul(p, 0, 0);
   1431 	if(fd < 0)
   1432 		error(Ebadarg);
   1433 	c = fdtochan(fd, -1, 0, 1);	/* error check and inc ref */
   1434 	if(devtab[c->type] == &ssldevtab){
   1435 		cclose(c);
   1436 		error("cannot ssl encrypt devssl files");
   1437 	}
   1438 	return c;
   1439 }
   1440 
   1441 /* hand up a digest connection */
   1442 static void
   1443 sslhangup(Dstate *s)
   1444 {
   1445 	Block *b;
   1446 
   1447 	qlock(&s->in.q);
   1448 	for(b = s->processed; b; b = s->processed){
   1449 		s->processed = b->next;
   1450 		freeb(b);
   1451 	}
   1452 	if(s->unprocessed){
   1453 		freeb(s->unprocessed);
   1454 		s->unprocessed = 0;
   1455 	}
   1456 	s->state = Sincomplete;
   1457 	qunlock(&s->in.q);
   1458 }
   1459 
   1460 static Dstate*
   1461 dsclone(Chan *ch)
   1462 {
   1463 	int i;
   1464 	Dstate *ret;
   1465 
   1466 	if(waserror()) {
   1467 		unlock(&dslock);
   1468 		nexterror();
   1469 	}
   1470 	lock(&dslock);
   1471 	ret = nil;
   1472 	for(i=0; i<Maxdstate; i++){
   1473 		if(dstate[i] == nil){
   1474 			dsnew(ch, &dstate[i]);
   1475 			ret = dstate[i];
   1476 			break;
   1477 		}
   1478 	}
   1479 	unlock(&dslock);
   1480 	poperror();
   1481 	return ret;
   1482 }
   1483 
   1484 static void
   1485 dsnew(Chan *ch, Dstate **pp)
   1486 {
   1487 	Dstate *s;
   1488 	int t;
   1489 
   1490 	*pp = s = malloc(sizeof(*s));
   1491 	if(!s)
   1492 		error(Enomem);
   1493 	if(pp - dstate >= dshiwat)
   1494 		dshiwat++;
   1495 	memset(s, 0, sizeof(*s));
   1496 	s->state = Sincomplete;
   1497 	s->ref = 1;
   1498 	kstrdup(&s->user, up->user);
   1499 	s->perm = 0660;
   1500 	t = TYPE(ch->qid);
   1501 	if(t == Qclonus)
   1502 		t = Qctl;
   1503 	ch->qid.path = QID(pp - dstate, t);
   1504 	ch->qid.vers = 0;
   1505 }