xref: /plan9/sys/src/9/port/devssl.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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 }
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 NOSPOOKS
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)
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 }
1506