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