Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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