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