Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/unix/drawterm/kern/devtls.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 *  devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0
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
typedef struct OneWay	OneWay;
13
typedef struct Secret		Secret;
14
typedef struct TlsRec	TlsRec;
15
typedef struct TlsErrs	TlsErrs;
16
 
17
enum {
18
	Statlen=	1024,		/* max. length of status or stats message */
19
	/* buffer limits */
20
	MaxRecLen		= 1<<14,	/* max payload length of a record layer message */
21
	MaxCipherRecLen	= MaxRecLen + 2048,
22
	RecHdrLen		= 5,
23
	MaxMacLen		= SHA1dlen,
24
 
25
	/* protocol versions we can accept */
26
	TLSVersion		= 0x0301,
27
	SSL3Version		= 0x0300,
28
	ProtocolVersion	= 0x0301,	/* maximum version we speak */
29
	MinProtoVersion	= 0x0300,	/* limits on version we accept */
30
	MaxProtoVersion	= 0x03ff,
31
 
32
	/* connection states */
33
	SHandshake	= 1 << 0,	/* doing handshake */
34
	SOpen		= 1 << 1,	/* application data can be sent */
35
	SRClose		= 1 << 2,	/* remote side has closed down */
36
	SLClose		= 1 << 3,	/* sent a close notify alert */
37
	SAlert		= 1 << 5,	/* sending or sent a fatal alert */
38
	SError		= 1 << 6,	/* some sort of error has occured */
39
	SClosed		= 1 << 7,	/* it is all over */
40
 
41
	/* record types */
42
	RChangeCipherSpec = 20,
43
	RAlert,
44
	RHandshake,
45
	RApplication,
46
 
47
	SSL2ClientHello = 1,
48
	HSSL2ClientHello = 9,  /* local convention;  see tlshand.c */
49
 
50
	/* alerts */
51
	ECloseNotify 			= 0,
52
	EUnexpectedMessage 	= 10,
53
	EBadRecordMac 		= 20,
54
	EDecryptionFailed 		= 21,
55
	ERecordOverflow 		= 22,
56
	EDecompressionFailure 	= 30,
57
	EHandshakeFailure 		= 40,
58
	ENoCertificate 			= 41,
59
	EBadCertificate 		= 42,
60
	EUnsupportedCertificate 	= 43,
61
	ECertificateRevoked 		= 44,
62
	ECertificateExpired 		= 45,
63
	ECertificateUnknown 	= 46,
64
	EIllegalParameter 		= 47,
65
	EUnknownCa 			= 48,
66
	EAccessDenied 		= 49,
67
	EDecodeError 			= 50,
68
	EDecryptError 			= 51,
69
	EExportRestriction 		= 60,
70
	EProtocolVersion 		= 70,
71
	EInsufficientSecurity 	= 71,
72
	EInternalError 			= 80,
73
	EUserCanceled 			= 90,
74
	ENoRenegotiation 		= 100,
75
 
76
	EMAX = 256
77
};
78
 
79
struct Secret
80
{
81
	char		*encalg;	/* name of encryption alg */
82
	char		*hashalg;	/* name of hash alg */
83
	int		(*enc)(Secret*, uchar*, int);
84
	int		(*dec)(Secret*, uchar*, int);
85
	int		(*unpad)(uchar*, int, int);
86
	DigestState	*(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
87
	int		block;		/* encryption block len, 0 if none */
88
	int		maclen;
89
	void		*enckey;
90
	uchar	mackey[MaxMacLen];
91
};
92
 
93
struct OneWay
94
{
95
	QLock		io;		/* locks io access */
96
	QLock		seclock;	/* locks secret paramaters */
97
	ulong		seq;
98
	Secret		*sec;		/* cipher in use */
99
	Secret		*new;		/* cipher waiting for enable */
100
};
101
 
102
struct TlsRec
103
{
104
	Chan	*c;				/* io channel */
105
	int		ref;				/* serialized by tdlock for atomic destroy */
106
	int		version;			/* version of the protocol we are speaking */
107
	char		verset;			/* version has been set */
108
	char		opened;			/* opened command every issued? */
109
	char		err[ERRMAX];		/* error message to return to handshake requests */
110
	vlong	handin;			/* bytes communicated by the record layer */
111
	vlong	handout;
112
	vlong	datain;
113
	vlong	dataout;
114
 
115
	Lock		statelk;
116
	int		state;
117
	int		debug;
118
 
119
	/* record layer mac functions for different protocol versions */
120
	void		(*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
121
 
122
	/* input side -- protected by in.io */
123
	OneWay		in;
124
	Block		*processed;	/* next bunch of application data */
125
	Block		*unprocessed;	/* data read from c but not parsed into records */
126
 
127
	/* handshake queue */
128
	Lock		hqlock;			/* protects hqref, alloc & free of handq, hprocessed */
129
	int		hqref;
130
	Queue		*handq;		/* queue of handshake messages */
131
	Block		*hprocessed;	/* remainder of last block read from handq */
132
	QLock		hqread;		/* protects reads for hprocessed, handq */
133
 
134
	/* output side */
135
	OneWay		out;
136
 
137
	/* protections */
138
	char		*user;
139
	int		perm;
140
};
141
 
142
struct TlsErrs{
143
	int	err;
144
	int	sslerr;
145
	int	tlserr;
146
	int	fatal;
147
	char	*msg;
148
};
149
 
150
static TlsErrs tlserrs[] = {
151
	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
152
	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
153
	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
154
	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
155
	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
156
	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
157
	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
158
	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
159
	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
160
	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
161
	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
162
	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
163
	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
164
	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
165
	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
166
	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
167
	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
168
	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
169
	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
170
	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
171
	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
172
	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
173
	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
174
	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
175
};
176
 
177
enum
178
{
179
	/* max. open tls connections */
180
	MaxTlsDevs	= 1024
181
};
182
 
183
static	Lock	tdlock;
184
static	int	tdhiwat;
185
static	int	maxtlsdevs = 128;
186
static	TlsRec	**tlsdevs;
187
static	char	**trnames;
188
static	char	*encalgs;
189
static	char	*hashalgs;
190
 
191
enum{
192
	Qtopdir		= 1,	/* top level directory */
193
	Qprotodir,
194
	Qclonus,
195
	Qencalgs,
196
	Qhashalgs,
197
	Qconvdir,		/* directory for a conversation */
198
	Qdata,
199
	Qctl,
200
	Qhand,
201
	Qstatus,
202
	Qstats,
203
};
204
 
205
#define TYPE(x) 	((x).path & 0xf)
206
#define CONV(x) 	(((x).path >> 5)&(MaxTlsDevs-1))
207
#define QID(c, y) 	(((c)<<5) | (y))
208
 
209
static void	checkstate(TlsRec *, int, int);
210
static void	ensure(TlsRec*, Block**, int);
211
static void	consume(Block**, uchar*, int);
212
static Chan*	buftochan(char*);
213
static void	tlshangup(TlsRec*);
214
static void	tlsError(TlsRec*, char *);
215
static void	alertHand(TlsRec*, char *);
216
static TlsRec	*newtls(Chan *c);
217
static TlsRec	*mktlsrec(void);
218
static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
219
static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
220
static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
221
static void	sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
222
static void	tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
223
static void	put64(uchar *p, vlong x);
224
static void	put32(uchar *p, u32int);
225
static void	put24(uchar *p, int);
226
static void	put16(uchar *p, int);
227
/* static u32int	get32(uchar *p); */
228
static int	get16(uchar *p);
229
static void	tlsSetState(TlsRec *tr, int new, int old);
230
static void	rcvAlert(TlsRec *tr, int err);
231
static void	sendAlert(TlsRec *tr, int err);
232
static void	rcvError(TlsRec *tr, int err, char *msg, ...);
233
static int	rc4enc(Secret *sec, uchar *buf, int n);
234
static int	des3enc(Secret *sec, uchar *buf, int n);
235
static int	des3dec(Secret *sec, uchar *buf, int n);
236
static int	noenc(Secret *sec, uchar *buf, int n);
237
static int	sslunpad(uchar *buf, int n, int block);
238
static int	tlsunpad(uchar *buf, int n, int block);
239
static void	freeSec(Secret *sec);
240
static char	*tlsstate(int s);
241
static void	pdump(int, void*, char*);
242
 
243
static char *tlsnames[] = {
244
	/* unused */ 0,
245
	/* topdir */ 0,
246
	/* protodir */ 0,
247
	"clone",
248
	"encalgs",
249
	"hashalgs",
250
	/* convdir */ 0,
251
	"data",
252
	"ctl",
253
	"hand",
254
	"status",
255
	"stats",
256
};
257
 
258
static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats };
259
 
260
static int
261
tlsgen(Chan *c, char*unused1, Dirtab *unused2, int unused3, int s, Dir *dp)
262
{
263
	Qid q;
264
	TlsRec *tr;
265
	char *name, *nm;
266
	int perm, t;
267
 
268
	q.vers = 0;
269
	q.type = QTFILE;
270
 
271
	t = TYPE(c->qid);
272
	switch(t) {
273
	case Qtopdir:
274
		if(s == DEVDOTDOT){
275
			q.path = QID(0, Qtopdir);
276
			q.type = QTDIR;
277
			devdir(c, q, "#a", 0, eve, 0555, dp);
278
			return 1;
279
		}
280
		if(s > 0)
281
			return -1;
282
		q.path = QID(0, Qprotodir);
283
		q.type = QTDIR;
284
		devdir(c, q, "tls", 0, eve, 0555, dp);
285
		return 1;
286
	case Qprotodir:
287
		if(s == DEVDOTDOT){
288
			q.path = QID(0, Qtopdir);
289
			q.type = QTDIR;
290
			devdir(c, q, ".", 0, eve, 0555, dp);
291
			return 1;
292
		}
293
		if(s < 3){
294
			switch(s) {
295
			default:
296
				return -1;
297
			case 0:
298
				q.path = QID(0, Qclonus);
299
				break;
300
			case 1:
301
				q.path = QID(0, Qencalgs);
302
				break;
303
			case 2:
304
				q.path = QID(0, Qhashalgs);
305
				break;
306
			}
307
			perm = 0444;
308
			if(TYPE(q) == Qclonus)
309
				perm = 0555;
310
			devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp);
311
			return 1;
312
		}
313
		s -= 3;
314
		if(s >= tdhiwat)
315
			return -1;
316
		q.path = QID(s, Qconvdir);
317
		q.type = QTDIR;
318
		lock(&tdlock);
319
		tr = tlsdevs[s];
320
		if(tr != nil)
321
			nm = tr->user;
322
		else
323
			nm = eve;
324
		if((name = trnames[s]) == nil){
325
			name = trnames[s] = smalloc(16);
326
			sprint(name, "%d", s);
327
		}
328
		devdir(c, q, name, 0, nm, 0555, dp);
329
		unlock(&tdlock);
330
		return 1;
331
	case Qconvdir:
332
		if(s == DEVDOTDOT){
333
			q.path = QID(0, Qprotodir);
334
			q.type = QTDIR;
335
			devdir(c, q, "tls", 0, eve, 0555, dp);
336
			return 1;
337
		}
338
		if(s < 0 || s >= nelem(convdir))
339
			return -1;
340
		lock(&tdlock);
341
		tr = tlsdevs[CONV(c->qid)];
342
		if(tr != nil){
343
			nm = tr->user;
344
			perm = tr->perm;
345
		}else{
346
			perm = 0;
347
			nm = eve;
348
		}
349
		t = convdir[s];
350
		if(t == Qstatus || t == Qstats)
351
			perm &= 0444;
352
		q.path = QID(CONV(c->qid), t);
353
		devdir(c, q, tlsnames[t], 0, nm, perm, dp);
354
		unlock(&tdlock);
355
		return 1;
356
	case Qclonus:
357
	case Qencalgs:
358
	case Qhashalgs:
359
		perm = 0444;
360
		if(t == Qclonus)
361
			perm = 0555;
362
		devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp);
363
		return 1;
364
	default:
365
		lock(&tdlock);
366
		tr = tlsdevs[CONV(c->qid)];
367
		if(tr != nil){
368
			nm = tr->user;
369
			perm = tr->perm;
370
		}else{
371
			perm = 0;
372
			nm = eve;
373
		}
374
		if(t == Qstatus || t == Qstats)
375
			perm &= 0444;
376
		devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp);
377
		unlock(&tdlock);
378
		return 1;
379
	}
380
	return -1;
381
}
382
 
383
static Chan*
384
tlsattach(char *spec)
385
{
386
	Chan *c;
387
 
388
	c = devattach('a', spec);
389
	c->qid.path = QID(0, Qtopdir);
390
	c->qid.type = QTDIR;
391
	c->qid.vers = 0;
392
	return c;
393
}
394
 
395
static Walkqid*
396
tlswalk(Chan *c, Chan *nc, char **name, int nname)
397
{
398
	return devwalk(c, nc, name, nname, nil, 0, tlsgen);
399
}
400
 
401
static int
402
tlsstat(Chan *c, uchar *db, int n)
403
{
404
	return devstat(c, db, n, nil, 0, tlsgen);
405
}
406
 
407
static Chan*
408
tlsopen(Chan *c, int omode)
409
{
410
	TlsRec *tr, **pp;
411
	int t, perm;
412
 
413
	perm = 0;
414
	omode &= 3;
415
	switch(omode) {
416
	case OREAD:
417
		perm = 4;
418
		break;
419
	case OWRITE:
420
		perm = 2;
421
		break;
422
	case ORDWR:
423
		perm = 6;
424
		break;
425
	}
426
 
427
	t = TYPE(c->qid);
428
	switch(t) {
429
	default:
430
		panic("tlsopen");
431
	case Qtopdir:
432
	case Qprotodir:
433
	case Qconvdir:
434
		if(omode != OREAD)
435
			error(Eperm);
436
		break;
437
	case Qclonus:
438
		tr = newtls(c);
439
		if(tr == nil)
440
			error(Enodev);
441
		break;
442
	case Qctl:
443
	case Qdata:
444
	case Qhand:
445
	case Qstatus:
446
	case Qstats:
447
		if((t == Qstatus || t == Qstats) && omode != OREAD)
448
			error(Eperm);
449
		if(waserror()) {
450
			unlock(&tdlock);
451
			nexterror();
452
		}
453
		lock(&tdlock);
454
		pp = &tlsdevs[CONV(c->qid)];
455
		tr = *pp;
456
		if(tr == nil)
457
			error("must open connection using clone");
458
		if((perm & (tr->perm>>6)) != perm
459
		&& (strcmp(up->user, tr->user) != 0
460
		    || (perm & tr->perm) != perm))
461
			error(Eperm);
462
		if(t == Qhand){
463
			if(waserror()){
464
				unlock(&tr->hqlock);
465
				nexterror();
466
			}
467
			lock(&tr->hqlock);
468
			if(tr->handq != nil)
469
				error(Einuse);
470
			tr->handq = qopen(2 * MaxCipherRecLen, 0, 0, nil);
471
			if(tr->handq == nil)
472
				error("cannot allocate handshake queue");
473
			tr->hqref = 1;
474
			unlock(&tr->hqlock);
475
			poperror();
476
		}
477
		tr->ref++;
478
		unlock(&tdlock);
479
		poperror();
480
		break;
481
	case Qencalgs:
482
	case Qhashalgs:
483
		if(omode != OREAD)
484
			error(Eperm);
485
		break;
486
	}
487
	c->mode = openmode(omode);
488
	c->flag |= COPEN;
489
	c->offset = 0;
490
	c->iounit = qiomaxatomic;
491
	return c;
492
}
493
 
494
static int
495
tlswstat(Chan *c, uchar *dp, int n)
496
{
497
	Dir *d;
498
	TlsRec *tr;
499
	int rv;
500
 
501
	d = nil;
502
	if(waserror()){
503
		free(d);
504
		unlock(&tdlock);
505
		nexterror();
506
	}
507
 
508
	lock(&tdlock);
509
	tr = tlsdevs[CONV(c->qid)];
510
	if(tr == nil)
511
		error(Ebadusefd);
512
	if(strcmp(tr->user, up->user) != 0)
513
		error(Eperm);
514
 
515
	d = smalloc(n + sizeof *d);
516
	rv = convM2D(dp, n, &d[0], (char*) &d[1]);
517
	if(rv == 0)
518
		error(Eshortstat);
519
	if(!emptystr(d->uid))
520
		kstrdup(&tr->user, d->uid);
521
	if(d->mode != ~0UL)
522
		tr->perm = d->mode;
523
 
524
	free(d);
525
	poperror();
526
	unlock(&tdlock);
527
 
528
	return rv;
529
}
530
 
531
static void
532
dechandq(TlsRec *tr)
533
{
534
	lock(&tr->hqlock);
535
	if(--tr->hqref == 0){
536
		if(tr->handq != nil){
537
			qfree(tr->handq);
538
			tr->handq = nil;
539
		}
540
		if(tr->hprocessed != nil){
541
			freeb(tr->hprocessed);
542
			tr->hprocessed = nil;
543
		}
544
	}
545
	unlock(&tr->hqlock);
546
}
547
 
548
static void
549
tlsclose(Chan *c)
550
{
551
	TlsRec *tr;
552
	int t;
553
 
554
	t = TYPE(c->qid);
555
	switch(t) {
556
	case Qctl:
557
	case Qdata:
558
	case Qhand:
559
	case Qstatus:
560
	case Qstats:
561
		if((c->flag & COPEN) == 0)
562
			break;
563
 
564
		tr = tlsdevs[CONV(c->qid)];
565
		if(tr == nil)
566
			break;
567
 
568
		if(t == Qhand)
569
			dechandq(tr);
570
 
571
		lock(&tdlock);
572
		if(--tr->ref > 0) {
573
			unlock(&tdlock);
574
			return;
575
		}
576
		tlsdevs[CONV(c->qid)] = nil;
577
		unlock(&tdlock);
578
 
579
		if(tr->c != nil && !waserror()){
580
			checkstate(tr, 0, SOpen|SHandshake|SRClose);
581
			sendAlert(tr, ECloseNotify);
582
			poperror();
583
		}
584
		tlshangup(tr);
585
		if(tr->c != nil)
586
			cclose(tr->c);
587
		freeSec(tr->in.sec);
588
		freeSec(tr->in.new);
589
		freeSec(tr->out.sec);
590
		freeSec(tr->out.new);
591
		free(tr->user);
592
		free(tr);
593
		break;
594
	}
595
}
596
 
597
/*
598
 *  make sure we have at least 'n' bytes in list 'l'
599
 */
600
static void
601
ensure(TlsRec *s, Block **l, int n)
602
{
603
	int sofar, i;
604
	Block *b, *bl;
605
 
606
	sofar = 0;
607
	for(b = *l; b; b = b->next){
608
		sofar += BLEN(b);
609
		if(sofar >= n)
610
			return;
611
		l = &b->next;
612
	}
613
 
614
	while(sofar < n){
615
		bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0);
616
		if(bl == 0)
617
			error(Ehungup);
618
		*l = bl;
619
		i = 0;
620
		for(b = bl; b; b = b->next){
621
			i += BLEN(b);
622
			l = &b->next;
623
		}
624
		if(i == 0)
625
			error(Ehungup);
626
		sofar += i;
627
	}
628
if(s->debug) pprint("ensure read %d\n", sofar);
629
}
630
 
631
/*
632
 *  copy 'n' bytes from 'l' into 'p' and free
633
 *  the bytes in 'l'
634
 */
635
static void
636
consume(Block **l, uchar *p, int n)
637
{
638
	Block *b;
639
	int i;
640
 
641
	for(; *l && n > 0; n -= i){
642
		b = *l;
643
		i = BLEN(b);
644
		if(i > n)
645
			i = n;
646
		memmove(p, b->rp, i);
647
		b->rp += i;
648
		p += i;
649
		if(BLEN(b) < 0)
650
			panic("consume");
651
		if(BLEN(b))
652
			break;
653
		*l = b->next;
654
		freeb(b);
655
	}
656
}
657
 
658
/*
659
 *  give back n bytes
660
 */
661
static void
662
regurgitate(TlsRec *s, uchar *p, int n)
663
{
664
	Block *b;
665
 
666
	if(n <= 0)
667
		return;
668
	b = s->unprocessed;
669
	if(s->unprocessed == nil || b->rp - b->base < n) {
670
		b = allocb(n);
671
		memmove(b->wp, p, n);
672
		b->wp += n;
673
		b->next = s->unprocessed;
674
		s->unprocessed = b;
675
	} else {
676
		b->rp -= n;
677
		memmove(b->rp, p, n);
678
	}
679
}
680
 
681
/*
682
 *  remove at most n bytes from the queue
683
 */
684
static Block*
685
qgrab(Block **l, int n)
686
{
687
	Block *bb, *b;
688
	int i;
689
 
690
	b = *l;
691
	if(BLEN(b) == n){
692
		*l = b->next;
693
		b->next = nil;
694
		return b;
695
	}
696
 
697
	i = 0;
698
	for(bb = b; bb != nil && i < n; bb = bb->next)
699
		i += BLEN(bb);
700
	if(i > n)
701
		i = n;
702
 
703
	bb = allocb(i);
704
	consume(l, bb->wp, i);
705
	bb->wp += i;
706
	return bb;
707
}
708
 
709
static void
710
tlsclosed(TlsRec *tr, int new)
711
{
712
	lock(&tr->statelk);
713
	if(tr->state == SOpen || tr->state == SHandshake)
714
		tr->state = new;
715
	else if((new | tr->state) == (SRClose|SLClose))
716
		tr->state = SClosed;
717
	unlock(&tr->statelk);
718
	alertHand(tr, "close notify");
719
}
720
 
721
/*
722
 *  read and process one tls record layer message
723
 *  must be called with tr->in.io held
724
 *  We can't let Eintrs lose data, since doing so will get
725
 *  us out of sync with the sender and break the reliablity
726
 *  of the channel.  Eintr only happens during the reads in
727
 *  consume.  Therefore we put back any bytes consumed before
728
 *  the last call to ensure.
729
 */
730
static void
731
tlsrecread(TlsRec *tr)
732
{
733
	OneWay *volatile in;
734
	Block *volatile b;
735
	uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
736
	int volatile nconsumed;
737
	int len, type, ver, unpad_len;
738
 
739
	nconsumed = 0;
740
	if(waserror()){
741
		if(strcmp(up->errstr, Eintr) == 0 && !waserror()){
742
			regurgitate(tr, header, nconsumed);
743
			poperror();
744
		}else
745
			tlsError(tr, "channel error");
746
		nexterror();
747
	}
748
	ensure(tr, &tr->unprocessed, RecHdrLen);
749
	consume(&tr->unprocessed, header, RecHdrLen);
750
if(tr->debug)pprint("consumed %d header\n", RecHdrLen);
751
	nconsumed = RecHdrLen;
752
 
753
	if((tr->handin == 0) && (header[0] & 0x80)){
754
		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
755
			This is sent by some clients that we must interoperate
756
			with, such as Java's JSSE and Microsoft's Internet Explorer. */
757
		len = (get16(header) & ~0x8000) - 3;
758
		type = header[2];
759
		ver = get16(header + 3);
760
		if(type != SSL2ClientHello || len < 22)
761
			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
762
	}else{  /* normal SSL3 record format */
763
		type = header[0];
764
		ver = get16(header+1);
765
		len = get16(header+3);
766
	}
767
	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
768
		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
769
			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
770
	if(len > MaxCipherRecLen || len < 0)
771
		rcvError(tr, ERecordOverflow, "record message too long %d", len);
772
	ensure(tr, &tr->unprocessed, len);
773
	nconsumed = 0;
774
	poperror();
775
 
776
	/*
777
	 * If an Eintr happens after this, we'll get out of sync.
778
	 * Make sure nothing we call can sleep.
779
	 * Errors are ok, as they kill the connection.
780
	 * Luckily, allocb won't sleep, it'll just error out.
781
	 */
782
	b = nil;
783
	if(waserror()){
784
		if(b != nil)
785
			freeb(b);
786
		tlsError(tr, "channel error");
787
		nexterror();
788
	}
789
	b = qgrab(&tr->unprocessed, len);
790
if(tr->debug) pprint("consumed unprocessed %d\n", len);
791
 
792
	in = &tr->in;
793
	if(waserror()){
794
		qunlock(&in->seclock);
795
		nexterror();
796
	}
797
	qlock(&in->seclock);
798
	p = b->rp;
799
	if(in->sec != nil) {
800
		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
801
		        should look alike, including timing of the response. */
802
		unpad_len = (*in->sec->dec)(in->sec, p, len);
803
		if(unpad_len >= in->sec->maclen)
804
			len = unpad_len - in->sec->maclen;
805
if(tr->debug) pprint("decrypted %d\n", unpad_len);
806
if(tr->debug) pdump(unpad_len, p, "decrypted:");
807
 
808
		/* update length */
809
		put16(header+3, len);
810
		put64(seq, in->seq);
811
		in->seq++;
812
		(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
813
		if(unpad_len < in->sec->maclen)
814
			rcvError(tr, EBadRecordMac, "short record mac");
815
		if(memcmp(hmac, p+len, in->sec->maclen) != 0)
816
			rcvError(tr, EBadRecordMac, "record mac mismatch");
817
		b->wp = b->rp + len;
818
	}
819
	qunlock(&in->seclock);
820
	poperror();
821
	if(len < 0)
822
		rcvError(tr, EDecodeError, "runt record message");
823
 
824
	switch(type) {
825
	default:
826
		rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type);
827
		break;
828
	case RChangeCipherSpec:
829
		if(len != 1 || p[0] != 1)
830
			rcvError(tr, EDecodeError, "invalid change cipher spec");
831
		qlock(&in->seclock);
832
		if(in->new == nil){
833
			qunlock(&in->seclock);
834
			rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec");
835
		}
836
		freeSec(in->sec);
837
		in->sec = in->new;
838
		in->new = nil;
839
		in->seq = 0;
840
		qunlock(&in->seclock);
841
		break;
842
	case RAlert:
843
		if(len != 2)
844
			rcvError(tr, EDecodeError, "invalid alert");
845
		if(p[0] == 2)
846
			rcvAlert(tr, p[1]);
847
		if(p[0] != 1)
848
			rcvError(tr, EIllegalParameter, "invalid alert fatal code");
849
 
850
		/*
851
		 * propate non-fatal alerts to handshaker
852
		 */
853
		if(p[1] == ECloseNotify) {
854
			tlsclosed(tr, SRClose);
855
			if(tr->opened)
856
				error("tls hungup");
857
			error("close notify");
858
		}
859
		if(p[1] == ENoRenegotiation)
860
			alertHand(tr, "no renegotiation");
861
		else if(p[1] == EUserCanceled)
862
			alertHand(tr, "handshake canceled by user");
863
		else
864
			rcvError(tr, EIllegalParameter, "invalid alert code");
865
		break;
866
	case RHandshake:
867
		/*
868
		 * don't worry about dropping the block
869
		 * qbwrite always queues even if flow controlled and interrupted.
870
		 *
871
		 * if there isn't any handshaker, ignore the request,
872
		 * but notify the other side we are doing so.
873
		 */
874
		lock(&tr->hqlock);
875
		if(tr->handq != nil){
876
			tr->hqref++;
877
			unlock(&tr->hqlock);
878
			if(waserror()){
879
				dechandq(tr);
880
				nexterror();
881
			}
882
			b = padblock(b, 1);
883
			*b->rp = RHandshake;
884
			qbwrite(tr->handq, b);
885
			b = nil;
886
			poperror();
887
			dechandq(tr);
888
		}else{
889
			unlock(&tr->hqlock);
890
			if(tr->verset && tr->version != SSL3Version && !waserror()){
891
				sendAlert(tr, ENoRenegotiation);
892
				poperror();
893
			}
894
		}
895
		break;
896
	case SSL2ClientHello:
897
		lock(&tr->hqlock);
898
		if(tr->handq != nil){
899
			tr->hqref++;
900
			unlock(&tr->hqlock);
901
			if(waserror()){
902
				dechandq(tr);
903
				nexterror();
904
			}
905
			/* Pass the SSL2 format data, so that the handshake code can compute
906
				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
907
				unused in RFC2246. */
908
			b = padblock(b, 8);
909
			b->rp[0] = RHandshake;
910
			b->rp[1] = HSSL2ClientHello;
911
			put24(&b->rp[2], len+3);
912
			b->rp[5] = SSL2ClientHello;
913
			put16(&b->rp[6], ver);
914
			qbwrite(tr->handq, b);
915
			b = nil;
916
			poperror();
917
			dechandq(tr);
918
		}else{
919
			unlock(&tr->hqlock);
920
			if(tr->verset && tr->version != SSL3Version && !waserror()){
921
				sendAlert(tr, ENoRenegotiation);
922
				poperror();
923
			}
924
		}
925
		break;
926
	case RApplication:
927
		if(!tr->opened)
928
			rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
929
		if(BLEN(b) > 0){
930
			tr->processed = b;
931
			b = nil;
932
		}
933
		break;
934
	}
935
	if(b != nil)
936
		freeb(b);
937
	poperror();
938
}
939
 
940
/*
941
 * got a fatal alert message
942
 */
943
static void
944
rcvAlert(TlsRec *tr, int err)
945
{
946
	char *s;
947
	int i;
948
 
949
	s = "unknown error";
950
	for(i=0; i < nelem(tlserrs); i++){
951
		if(tlserrs[i].err == err){
952
			s = tlserrs[i].msg;
953
			break;
954
		}
955
	}
956
if(tr->debug) pprint("rcvAlert: %s\n", s);
957
 
958
	tlsError(tr, s);
959
	if(!tr->opened)
960
		error(s);
961
	error("tls error");
962
}
963
 
964
/*
965
 * found an error while decoding the input stream
966
 */
967
static void
968
rcvError(TlsRec *tr, int err, char *fmt, ...)
969
{
970
	char msg[ERRMAX];
971
	va_list arg;
972
 
973
	va_start(arg, fmt);
974
	vseprint(msg, msg+sizeof(msg), fmt, arg);
975
	va_end(arg);
976
if(tr->debug) pprint("rcvError: %s\n", msg);
977
 
978
	sendAlert(tr, err);
979
 
980
	if(!tr->opened)
981
		error(msg);
982
	error("tls error");
983
}
984
 
985
/*
986
 * make sure the next hand operation returns with a 'msg' error
987
 */
988
static void
989
alertHand(TlsRec *tr, char *msg)
990
{
991
	Block *b;
992
	int n;
993
 
994
	lock(&tr->hqlock);
995
	if(tr->handq == nil){
996
		unlock(&tr->hqlock);
997
		return;
998
	}
999
	tr->hqref++;
1000
	unlock(&tr->hqlock);
1001
 
1002
	n = strlen(msg);
1003
	if(waserror()){
1004
		dechandq(tr);
1005
		nexterror();
1006
	}
1007
	b = allocb(n + 2);
1008
	*b->wp++ = RAlert;
1009
	memmove(b->wp, msg, n + 1);
1010
	b->wp += n + 1;
1011
 
1012
	qbwrite(tr->handq, b);
1013
 
1014
	poperror();
1015
	dechandq(tr);
1016
}
1017
 
1018
static void
1019
checkstate(TlsRec *tr, int ishand, int ok)
1020
{
1021
	int state;
1022
 
1023
	lock(&tr->statelk);
1024
	state = tr->state;
1025
	unlock(&tr->statelk);
1026
	if(state & ok)
1027
		return;
1028
	switch(state){
1029
	case SHandshake:
1030
	case SOpen:
1031
		break;
1032
	case SError:
1033
	case SAlert:
1034
		if(ishand)
1035
			error(tr->err);
1036
		error("tls error");
1037
	case SRClose:
1038
	case SLClose:
1039
	case SClosed:
1040
		error("tls hungup");
1041
	}
1042
	error("tls improperly configured");
1043
}
1044
 
1045
static Block*
1046
tlsbread(Chan *c, long n, ulong offset)
1047
{
1048
	int ty;
1049
	Block *b;
1050
	TlsRec *volatile tr;
1051
 
1052
	ty = TYPE(c->qid);
1053
	switch(ty) {
1054
	default:
1055
		return devbread(c, n, offset);
1056
	case Qhand:
1057
	case Qdata:
1058
		break;
1059
	}
1060
 
1061
	tr = tlsdevs[CONV(c->qid)];
1062
	if(tr == nil)
1063
		panic("tlsbread");
1064
 
1065
	if(waserror()){
1066
		qunlock(&tr->in.io);
1067
		nexterror();
1068
	}
1069
	qlock(&tr->in.io);
1070
	if(ty == Qdata){
1071
		checkstate(tr, 0, SOpen);
1072
		while(tr->processed == nil)
1073
			tlsrecread(tr);
1074
 
1075
		/* return at most what was asked for */
1076
		b = qgrab(&tr->processed, n);
1077
if(tr->debug) pprint("consumed processed %d\n", BLEN(b));
1078
if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");
1079
		qunlock(&tr->in.io);
1080
		poperror();
1081
		tr->datain += BLEN(b);
1082
	}else{
1083
		checkstate(tr, 1, SOpen|SHandshake|SLClose);
1084
 
1085
		/*
1086
		 * it's ok to look at state without the lock
1087
		 * since it only protects reading records,
1088
		 * and we have that tr->in.io held.
1089
		 */
1090
		while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))
1091
			tlsrecread(tr);
1092
 
1093
		qunlock(&tr->in.io);
1094
		poperror();
1095
 
1096
		if(waserror()){
1097
			qunlock(&tr->hqread);
1098
			nexterror();
1099
		}
1100
		qlock(&tr->hqread);
1101
		if(tr->hprocessed == nil){
1102
			b = qbread(tr->handq, MaxRecLen + 1);
1103
			if(*b->rp++ == RAlert){
1104
				kstrcpy(up->errstr, (char*)b->rp, ERRMAX);
1105
				freeb(b);
1106
				nexterror();
1107
			}
1108
			tr->hprocessed = b;
1109
		}
1110
		b = qgrab(&tr->hprocessed, n);
1111
		poperror();
1112
		qunlock(&tr->hqread);
1113
		tr->handin += BLEN(b);
1114
	}
1115
 
1116
	return b;
1117
}
1118
 
1119
static long
1120
tlsread(Chan *c, void *a, long n, vlong off)
1121
{
1122
	Block *volatile b;
1123
	Block *nb;
1124
	uchar *va;
1125
	int i, ty;
1126
	char *buf, *s, *e;
1127
	ulong offset = off;
1128
	TlsRec * tr;
1129
 
1130
	if(c->qid.type & QTDIR)
1131
		return devdirread(c, a, n, 0, 0, tlsgen);
1132
 
1133
	tr = tlsdevs[CONV(c->qid)];
1134
	ty = TYPE(c->qid);
1135
	switch(ty) {
1136
	default:
1137
		error(Ebadusefd);
1138
	case Qstatus:
1139
		buf = smalloc(Statlen);
1140
		qlock(&tr->in.seclock);
1141
		qlock(&tr->out.seclock);
1142
		s = buf;
1143
		e = buf + Statlen;
1144
		s = seprint(s, e, "State: %s\n", tlsstate(tr->state));
1145
		s = seprint(s, e, "Version: 0x%x\n", tr->version);
1146
		if(tr->in.sec != nil)
1147
			s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);
1148
		if(tr->in.new != nil)
1149
			s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg);
1150
		if(tr->out.sec != nil)
1151
			s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg);
1152
		if(tr->out.new != nil)
1153
			seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg);
1154
		qunlock(&tr->in.seclock);
1155
		qunlock(&tr->out.seclock);
1156
		n = readstr(offset, a, n, buf);
1157
		free(buf);
1158
		return n;
1159
	case Qstats:
1160
		buf = smalloc(Statlen);
1161
		s = buf;
1162
		e = buf + Statlen;
1163
		s = seprint(s, e, "DataIn: %lld\n", tr->datain);
1164
		s = seprint(s, e, "DataOut: %lld\n", tr->dataout);
1165
		s = seprint(s, e, "HandIn: %lld\n", tr->handin);
1166
		seprint(s, e, "HandOut: %lld\n", tr->handout);
1167
		n = readstr(offset, a, n, buf);
1168
		free(buf);
1169
		return n;
1170
	case Qctl:
1171
		buf = smalloc(Statlen);
1172
		snprint(buf, Statlen, "%llud", CONV(c->qid));
1173
		n = readstr(offset, a, n, buf);
1174
		free(buf);
1175
		return n;
1176
	case Qdata:
1177
	case Qhand:
1178
		b = tlsbread(c, n, offset);
1179
		break;
1180
	case Qencalgs:
1181
		return readstr(offset, a, n, encalgs);
1182
	case Qhashalgs:
1183
		return readstr(offset, a, n, hashalgs);
1184
	}
1185
 
1186
	if(waserror()){
1187
		freeblist(b);
1188
		nexterror();
1189
	}
1190
 
1191
	n = 0;
1192
	va = a;
1193
	for(nb = b; nb; nb = nb->next){
1194
		i = BLEN(nb);
1195
		memmove(va+n, nb->rp, i);
1196
		n += i;
1197
	}
1198
 
1199
	freeblist(b);
1200
	poperror();
1201
 
1202
	return n;
1203
}
1204
 
1205
/*
1206
 *  write a block in tls records
1207
 */
1208
static void
1209
tlsrecwrite(TlsRec *tr, int type, Block *b)
1210
{
1211
	Block *volatile bb;
1212
	Block *nb;
1213
	uchar *p, seq[8];
1214
	OneWay *volatile out;
1215
	int n, maclen, pad, ok;
1216
 
1217
	out = &tr->out;
1218
	bb = b;
1219
	if(waserror()){
1220
		qunlock(&out->io);
1221
		if(bb != nil)
1222
			freeb(bb);
1223
		nexterror();
1224
	}
1225
	qlock(&out->io);
1226
if(tr->debug)pprint("send %d\n", BLEN(b));
1227
if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
1228
 
1229
 
1230
	ok = SHandshake|SOpen|SRClose;
1231
	if(type == RAlert)
1232
		ok |= SAlert;
1233
	while(bb != nil){
1234
		checkstate(tr, type != RApplication, ok);
1235
 
1236
		/*
1237
		 * get at most one maximal record's input,
1238
		 * with padding on the front for header and
1239
		 * back for mac and maximal block padding.
1240
		 */
1241
		if(waserror()){
1242
			qunlock(&out->seclock);
1243
			nexterror();
1244
		}
1245
		qlock(&out->seclock);
1246
		maclen = 0;
1247
		pad = 0;
1248
		if(out->sec != nil){
1249
			maclen = out->sec->maclen;
1250
			pad = maclen + out->sec->block;
1251
		}
1252
		n = BLEN(bb);
1253
		if(n > MaxRecLen){
1254
			n = MaxRecLen;
1255
			nb = allocb(n + pad + RecHdrLen);
1256
			memmove(nb->wp + RecHdrLen, bb->rp, n);
1257
			bb->rp += n;
1258
		}else{
1259
			/*
1260
			 * carefully reuse bb so it will get freed if we're out of memory
1261
			 */
1262
			bb = padblock(bb, RecHdrLen);
1263
			if(pad)
1264
				nb = padblock(bb, -pad);
1265
			else
1266
				nb = bb;
1267
			bb = nil;
1268
		}
1269
 
1270
		p = nb->rp;
1271
		p[0] = type;
1272
		put16(p+1, tr->version);
1273
		put16(p+3, n);
1274
 
1275
		if(out->sec != nil){
1276
			put64(seq, out->seq);
1277
			out->seq++;
1278
			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
1279
			n += maclen;
1280
 
1281
			/* encrypt */
1282
			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
1283
			nb->wp = p + RecHdrLen + n;
1284
 
1285
			/* update length */
1286
			put16(p+3, n);
1287
		}
1288
		if(type == RChangeCipherSpec){
1289
			if(out->new == nil)
1290
				error("change cipher without a new cipher");
1291
			freeSec(out->sec);
1292
			out->sec = out->new;
1293
			out->new = nil;
1294
			out->seq = 0;
1295
		}
1296
		qunlock(&out->seclock);
1297
		poperror();
1298
 
1299
		/*
1300
		 * if bwrite error's, we assume the block is queued.
1301
		 * if not, we're out of sync with the receiver and will not recover.
1302
		 */
1303
		if(waserror()){
1304
			if(strcmp(up->errstr, "interrupted") != 0)
1305
				tlsError(tr, "channel error");
1306
			nexterror();
1307
		}
1308
		devtab[tr->c->type]->bwrite(tr->c, nb, 0);
1309
		poperror();
1310
	}
1311
	qunlock(&out->io);
1312
	poperror();
1313
}
1314
 
1315
static long
1316
tlsbwrite(Chan *c, Block *b, ulong offset)
1317
{
1318
	int ty;
1319
	ulong n;
1320
	TlsRec *tr;
1321
 
1322
	n = BLEN(b);
1323
 
1324
	tr = tlsdevs[CONV(c->qid)];
1325
	if(tr == nil)
1326
		panic("tlsbread");
1327
 
1328
	ty = TYPE(c->qid);
1329
	switch(ty) {
1330
	default:
1331
		return devbwrite(c, b, offset);
1332
	case Qhand:
1333
		tlsrecwrite(tr, RHandshake, b);
1334
		tr->handout += n;
1335
		break;
1336
	case Qdata:
1337
		checkstate(tr, 0, SOpen);
1338
		tlsrecwrite(tr, RApplication, b);
1339
		tr->dataout += n;
1340
		break;
1341
	}
1342
 
1343
	return n;
1344
}
1345
 
1346
typedef struct Hashalg Hashalg;
1347
struct Hashalg
1348
{
1349
	char	*name;
1350
	int	maclen;
1351
	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
1352
};
1353
 
1354
static void
1355
initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
1356
{
1357
	s->maclen = ha->maclen;
1358
	if(version == SSL3Version)
1359
		s->mac = sslmac_md5;
1360
	else
1361
		s->mac = hmac_md5;
1362
	memmove(s->mackey, p, ha->maclen);
1363
}
1364
 
1365
static void
1366
initclearmac(Hashalg *unused1, int unused2, Secret *s, uchar *unused3)
1367
{
1368
	s->maclen = 0;
1369
	s->mac = nomac;
1370
}
1371
 
1372
static void
1373
initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
1374
{
1375
	s->maclen = ha->maclen;
1376
	if(version == SSL3Version)
1377
		s->mac = sslmac_sha1;
1378
	else
1379
		s->mac = hmac_sha1;
1380
	memmove(s->mackey, p, ha->maclen);
1381
}
1382
 
1383
static Hashalg hashtab[] =
1384
{
1385
	{ "clear", 0, initclearmac, },
1386
	{ "md5", MD5dlen, initmd5key, },
1387
	{ "sha1", SHA1dlen, initsha1key, },
1388
	{ 0 }
1389
};
1390
 
1391
static Hashalg*
1392
parsehashalg(char *p)
1393
{
1394
	Hashalg *ha;
1395
 
1396
	for(ha = hashtab; ha->name; ha++)
1397
		if(strcmp(p, ha->name) == 0)
1398
			return ha;
1399
	error("unsupported hash algorithm");
1400
	return nil;
1401
}
1402
 
1403
typedef struct Encalg Encalg;
1404
struct Encalg
1405
{
1406
	char	*name;
1407
	int	keylen;
1408
	int	ivlen;
1409
	void	(*initkey)(Encalg *ea, Secret *, uchar*, uchar*);
1410
};
1411
 
1412
static void
1413
initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *unused1)
1414
{
1415
	s->enckey = smalloc(sizeof(RC4state));
1416
	s->enc = rc4enc;
1417
	s->dec = rc4enc;
1418
	s->block = 0;
1419
	setupRC4state(s->enckey, p, ea->keylen);
1420
}
1421
 
1422
static void
1423
initDES3key(Encalg *unused1, Secret *s, uchar *p, uchar *iv)
1424
{
1425
	s->enckey = smalloc(sizeof(DES3state));
1426
	s->enc = des3enc;
1427
	s->dec = des3dec;
1428
	s->block = 8;
1429
	setupDES3state(s->enckey, (uchar(*)[8])p, iv);
1430
}
1431
 
1432
static void
1433
initclearenc(Encalg *unused1, Secret *s, uchar *unused2, uchar *unused3)
1434
{
1435
	s->enc = noenc;
1436
	s->dec = noenc;
1437
	s->block = 0;
1438
}
1439
 
1440
static Encalg encrypttab[] =
1441
{
1442
	{ "clear", 0, 0, initclearenc },
1443
	{ "rc4_128", 128/8, 0, initRC4key },
1444
	{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
1445
	{ 0 }
1446
};
1447
 
1448
static Encalg*
1449
parseencalg(char *p)
1450
{
1451
	Encalg *ea;
1452
 
1453
	for(ea = encrypttab; ea->name; ea++)
1454
		if(strcmp(p, ea->name) == 0)
1455
			return ea;
1456
	error("unsupported encryption algorithm");
1457
	return nil;
1458
}
1459
 
1460
static long
1461
tlswrite(Chan *c, void *a, long n, vlong off)
1462
{
1463
	Encalg *ea;
1464
	Hashalg *ha;
1465
	TlsRec *volatile tr;
1466
	Secret *volatile tos, *volatile toc;
1467
	Block *volatile b;
1468
	Cmdbuf *volatile cb;
1469
	int m, ty;
1470
	char *p, *e;
1471
	uchar *volatile x;
1472
	ulong offset = off;
1473
 
1474
	tr = tlsdevs[CONV(c->qid)];
1475
	if(tr == nil)
1476
		panic("tlswrite");
1477
 
1478
	ty = TYPE(c->qid);
1479
	switch(ty){
1480
	case Qdata:
1481
	case Qhand:
1482
		p = a;
1483
		e = p + n;
1484
		do{
1485
			m = e - p;
1486
			if(m > MaxRecLen)
1487
				m = MaxRecLen;
1488
 
1489
			b = allocb(m);
1490
			if(waserror()){
1491
				freeb(b);
1492
				nexterror();
1493
			}
1494
			memmove(b->wp, p, m);
1495
			poperror();
1496
			b->wp += m;
1497
 
1498
			tlsbwrite(c, b, offset);
1499
 
1500
			p += m;
1501
		}while(p < e);
1502
		return n;
1503
	case Qctl:
1504
		break;
1505
	default:
1506
		error(Ebadusefd);
1507
		return -1;
1508
	}
1509
 
1510
	cb = parsecmd(a, n);
1511
	if(waserror()){
1512
		free(cb);
1513
		nexterror();
1514
	}
1515
	if(cb->nf < 1)
1516
		error("short control request");
1517
 
1518
	/* mutex with operations using what we're about to change */
1519
	if(waserror()){
1520
		qunlock(&tr->in.seclock);
1521
		qunlock(&tr->out.seclock);
1522
		nexterror();
1523
	}
1524
	qlock(&tr->in.seclock);
1525
	qlock(&tr->out.seclock);
1526
 
1527
	if(strcmp(cb->f[0], "fd") == 0){
1528
		if(cb->nf != 3)
1529
			error("usage: fd open-fd version");
1530
		if(tr->c != nil)
1531
			error(Einuse);
1532
		m = strtol(cb->f[2], nil, 0);
1533
		if(m < MinProtoVersion || m > MaxProtoVersion)
1534
			error("unsupported version");
1535
		tr->c = buftochan(cb->f[1]);
1536
		tr->version = m;
1537
		tlsSetState(tr, SHandshake, SClosed);
1538
	}else if(strcmp(cb->f[0], "version") == 0){
1539
		if(cb->nf != 2)
1540
			error("usage: version vers");
1541
		if(tr->c == nil)
1542
			error("must set fd before version");
1543
		if(tr->verset)
1544
			error("version already set");
1545
		m = strtol(cb->f[1], nil, 0);
1546
		if(m == SSL3Version)
1547
			tr->packMac = sslPackMac;
1548
		else if(m == TLSVersion)
1549
			tr->packMac = tlsPackMac;
1550
		else
1551
			error("unsupported version");
1552
		tr->verset = 1;
1553
		tr->version = m;
1554
	}else if(strcmp(cb->f[0], "secret") == 0){
1555
		if(cb->nf != 5)
1556
			error("usage: secret hashalg encalg isclient secretdata");
1557
		if(tr->c == nil || !tr->verset)
1558
			error("must set fd and version before secrets");
1559
 
1560
		if(tr->in.new != nil){
1561
			freeSec(tr->in.new);
1562
			tr->in.new = nil;
1563
		}
1564
		if(tr->out.new != nil){
1565
			freeSec(tr->out.new);
1566
			tr->out.new = nil;
1567
		}
1568
 
1569
		ha = parsehashalg(cb->f[1]);
1570
		ea = parseencalg(cb->f[2]);
1571
 
1572
		p = cb->f[4];
1573
		m = (strlen(p)*3)/2;
1574
		x = smalloc(m);
1575
		tos = nil;
1576
		toc = nil;
1577
		if(waserror()){
1578
			freeSec(tos);
1579
			freeSec(toc);
1580
			free(x);
1581
			nexterror();
1582
		}
1583
		m = dec64(x, m, p, strlen(p));
1584
		if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
1585
			error("not enough secret data provided");
1586
 
1587
		tos = smalloc(sizeof(Secret));
1588
		toc = smalloc(sizeof(Secret));
1589
		if(!ha->initkey || !ea->initkey)
1590
			error("misimplemented secret algorithm");
1591
		(*ha->initkey)(ha, tr->version, tos, &x[0]);
1592
		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
1593
		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
1594
		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
1595
 
1596
		if(!tos->mac || !tos->enc || !tos->dec
1597
		|| !toc->mac || !toc->enc || !toc->dec)
1598
			error("missing algorithm implementations");
1599
		if(strtol(cb->f[3], nil, 0) == 0){
1600
			tr->in.new = tos;
1601
			tr->out.new = toc;
1602
		}else{
1603
			tr->in.new = toc;
1604
			tr->out.new = tos;
1605
		}
1606
		if(tr->version == SSL3Version){
1607
			toc->unpad = sslunpad;
1608
			tos->unpad = sslunpad;
1609
		}else{
1610
			toc->unpad = tlsunpad;
1611
			tos->unpad = tlsunpad;
1612
		}
1613
		toc->encalg = ea->name;
1614
		toc->hashalg = ha->name;
1615
		tos->encalg = ea->name;
1616
		tos->hashalg = ha->name;
1617
 
1618
		free(x);
1619
		poperror();
1620
	}else if(strcmp(cb->f[0], "changecipher") == 0){
1621
		if(cb->nf != 1)
1622
			error("usage: changecipher");
1623
		if(tr->out.new == nil)
1624
			error("cannot change cipher spec without setting secret");
1625
 
1626
		qunlock(&tr->in.seclock);
1627
		qunlock(&tr->out.seclock);
1628
		poperror();
1629
		free(cb);
1630
		poperror();
1631
 
1632
		/*
1633
		 * the real work is done as the message is written
1634
		 * so the stream is encrypted in sync.
1635
		 */
1636
		b = allocb(1);
1637
		*b->wp++ = 1;
1638
		tlsrecwrite(tr, RChangeCipherSpec, b);
1639
		return n;
1640
	}else if(strcmp(cb->f[0], "opened") == 0){
1641
		if(cb->nf != 1)
1642
			error("usage: opened");
1643
		if(tr->in.sec == nil || tr->out.sec == nil)
1644
			error("cipher must be configured before enabling data messages");
1645
		lock(&tr->statelk);
1646
		if(tr->state != SHandshake && tr->state != SOpen){
1647
			unlock(&tr->statelk);
1648
			error("cannot enable data messages");
1649
		}
1650
		tr->state = SOpen;
1651
		unlock(&tr->statelk);
1652
		tr->opened = 1;
1653
	}else if(strcmp(cb->f[0], "alert") == 0){
1654
		if(cb->nf != 2)
1655
			error("usage: alert n");
1656
		if(tr->c == nil)
1657
			error("must set fd before sending alerts");
1658
		m = strtol(cb->f[1], nil, 0);
1659
 
1660
		qunlock(&tr->in.seclock);
1661
		qunlock(&tr->out.seclock);
1662
		poperror();
1663
		free(cb);
1664
		poperror();
1665
 
1666
		sendAlert(tr, m);
1667
 
1668
		if(m == ECloseNotify)
1669
			tlsclosed(tr, SLClose);
1670
 
1671
		return n;
1672
	} else if(strcmp(cb->f[0], "debug") == 0){
1673
		if(cb->nf == 2){
1674
			if(strcmp(cb->f[1], "on") == 0)
1675
				tr->debug = 1;
1676
			else
1677
				tr->debug = 0;
1678
		} else
1679
			tr->debug = 1;
1680
	} else
1681
		error(Ebadarg);
1682
 
1683
	qunlock(&tr->in.seclock);
1684
	qunlock(&tr->out.seclock);
1685
	poperror();
1686
	free(cb);
1687
	poperror();
1688
 
1689
	return n;
1690
}
1691
 
1692
static void
1693
tlsinit(void)
1694
{
1695
	struct Encalg *e;
1696
	struct Hashalg *h;
1697
	int n;
1698
	char *cp;
1699
	static int already;
1700
 
1701
	if(!already){
1702
		fmtinstall('H', encodefmt);
1703
		already = 1;
1704
	}
1705
 
1706
	tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs);
1707
	trnames = smalloc((sizeof *trnames) * maxtlsdevs);
1708
 
1709
	n = 1;
1710
	for(e = encrypttab; e->name != nil; e++)
1711
		n += strlen(e->name) + 1;
1712
	cp = encalgs = smalloc(n);
1713
	for(e = encrypttab;;){
1714
		strcpy(cp, e->name);
1715
		cp += strlen(e->name);
1716
		e++;
1717
		if(e->name == nil)
1718
			break;
1719
		*cp++ = ' ';
1720
	}
1721
	*cp = 0;
1722
 
1723
	n = 1;
1724
	for(h = hashtab; h->name != nil; h++)
1725
		n += strlen(h->name) + 1;
1726
	cp = hashalgs = smalloc(n);
1727
	for(h = hashtab;;){
1728
		strcpy(cp, h->name);
1729
		cp += strlen(h->name);
1730
		h++;
1731
		if(h->name == nil)
1732
			break;
1733
		*cp++ = ' ';
1734
	}
1735
	*cp = 0;
1736
}
1737
 
1738
Dev tlsdevtab = {
1739
	'a',
1740
	"tls",
1741
 
1742
	devreset,
1743
	tlsinit,
1744
	devshutdown,
1745
	tlsattach,
1746
	tlswalk,
1747
	tlsstat,
1748
	tlsopen,
1749
	devcreate,
1750
	tlsclose,
1751
	tlsread,
1752
	tlsbread,
1753
	tlswrite,
1754
	tlsbwrite,
1755
	devremove,
1756
	tlswstat,
1757
};
1758
 
1759
/* get channel associated with an fd */
1760
static Chan*
1761
buftochan(char *p)
1762
{
1763
	Chan *c;
1764
	int fd;
1765
 
1766
	if(p == 0)
1767
		error(Ebadarg);
1768
	fd = strtoul(p, 0, 0);
1769
	if(fd < 0)
1770
		error(Ebadarg);
1771
	c = fdtochan(fd, -1, 0, 1);	/* error check and inc ref */
1772
	return c;
1773
}
1774
 
1775
static void
1776
sendAlert(TlsRec *tr, int err)
1777
{
1778
	Block *b;
1779
	int i, fatal;
1780
	char *msg;
1781
 
1782
if(tr->debug)pprint("sendAlert %d\n", err);
1783
	fatal = 1;
1784
	msg = "tls unknown alert";
1785
	for(i=0; i < nelem(tlserrs); i++) {
1786
		if(tlserrs[i].err == err) {
1787
			msg = tlserrs[i].msg;
1788
			if(tr->version == SSL3Version)
1789
				err = tlserrs[i].sslerr;
1790
			else
1791
				err = tlserrs[i].tlserr;
1792
			fatal = tlserrs[i].fatal;
1793
			break;
1794
		}
1795
	}
1796
 
1797
	if(!waserror()){
1798
		b = allocb(2);
1799
		*b->wp++ = fatal + 1;
1800
		*b->wp++ = err;
1801
		if(fatal)
1802
			tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose);
1803
		tlsrecwrite(tr, RAlert, b);
1804
		poperror();
1805
	}
1806
	if(fatal)
1807
		tlsError(tr, msg);
1808
}
1809
 
1810
static void
1811
tlsError(TlsRec *tr, char *msg)
1812
{
1813
	int s;
1814
 
1815
if(tr->debug)pprint("tleError %s\n", msg);
1816
	lock(&tr->statelk);
1817
	s = tr->state;
1818
	tr->state = SError;
1819
	if(s != SError){
1820
		strncpy(tr->err, msg, ERRMAX - 1);
1821
		tr->err[ERRMAX - 1] = '\0';
1822
	}
1823
	unlock(&tr->statelk);
1824
	if(s != SError)
1825
		alertHand(tr, msg);
1826
}
1827
 
1828
static void
1829
tlsSetState(TlsRec *tr, int new, int old)
1830
{
1831
	lock(&tr->statelk);
1832
	if(tr->state & old)
1833
		tr->state = new;
1834
	unlock(&tr->statelk);
1835
}
1836
 
1837
/* hand up a digest connection */
1838
static void
1839
tlshangup(TlsRec *tr)
1840
{
1841
	Block *b;
1842
 
1843
	qlock(&tr->in.io);
1844
	for(b = tr->processed; b; b = tr->processed){
1845
		tr->processed = b->next;
1846
		freeb(b);
1847
	}
1848
	if(tr->unprocessed != nil){
1849
		freeb(tr->unprocessed);
1850
		tr->unprocessed = nil;
1851
	}
1852
	qunlock(&tr->in.io);
1853
 
1854
	tlsSetState(tr, SClosed, ~0);
1855
}
1856
 
1857
static TlsRec*
1858
newtls(Chan *ch)
1859
{
1860
	TlsRec **pp, **ep, **np;
1861
	char **nmp;
1862
	int t, newmax;
1863
 
1864
	if(waserror()) {
1865
		unlock(&tdlock);
1866
		nexterror();
1867
	}
1868
	lock(&tdlock);
1869
	ep = &tlsdevs[maxtlsdevs];
1870
	for(pp = tlsdevs; pp < ep; pp++)
1871
		if(*pp == nil)
1872
			break;
1873
	if(pp >= ep) {
1874
		if(maxtlsdevs >= MaxTlsDevs) {
1875
			unlock(&tdlock);
1876
			poperror();
1877
			return nil;
1878
		}
1879
		newmax = 2 * maxtlsdevs;
1880
		if(newmax > MaxTlsDevs)
1881
			newmax = MaxTlsDevs;
1882
		np = smalloc(sizeof(TlsRec*) * newmax);
1883
		memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);
1884
		tlsdevs = np;
1885
		pp = &tlsdevs[maxtlsdevs];
1886
		memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));
1887
 
1888
		nmp = smalloc(sizeof *nmp * newmax);
1889
		memmove(nmp, trnames, sizeof *nmp * maxtlsdevs);
1890
		trnames = nmp;
1891
 
1892
		maxtlsdevs = newmax;
1893
	}
1894
	*pp = mktlsrec();
1895
	if(pp - tlsdevs >= tdhiwat)
1896
		tdhiwat++;
1897
	t = TYPE(ch->qid);
1898
	if(t == Qclonus)
1899
		t = Qctl;
1900
	ch->qid.path = QID(pp - tlsdevs, t);
1901
	ch->qid.vers = 0;
1902
	unlock(&tdlock);
1903
	poperror();
1904
	return *pp;
1905
}
1906
 
1907
static TlsRec *
1908
mktlsrec(void)
1909
{
1910
	TlsRec *tr;
1911
 
1912
	tr = mallocz(sizeof(*tr), 1);
1913
	if(tr == nil)
1914
		error(Enomem);
1915
	tr->state = SClosed;
1916
	tr->ref = 1;
1917
	kstrdup(&tr->user, up->user);
1918
	tr->perm = 0660;
1919
	return tr;
1920
}
1921
 
1922
static char*
1923
tlsstate(int s)
1924
{
1925
	switch(s){
1926
	case SHandshake:
1927
		return "Handshaking";
1928
	case SOpen:
1929
		return "Established";
1930
	case SRClose:
1931
		return "RemoteClosed";
1932
	case SLClose:
1933
		return "LocalClosed";
1934
	case SAlert:
1935
		return "Alerting";
1936
	case SError:
1937
		return "Errored";
1938
	case SClosed:
1939
		return "Closed";
1940
	}
1941
	return "Unknown";
1942
}
1943
 
1944
static void
1945
freeSec(Secret *s)
1946
{
1947
	if(s != nil){
1948
		free(s->enckey);
1949
		free(s);
1950
	}
1951
}
1952
 
1953
static int
1954
noenc(Secret *unused1, uchar *unused2, int n)
1955
{
1956
	return n;
1957
}
1958
 
1959
static int
1960
rc4enc(Secret *sec, uchar *buf, int n)
1961
{
1962
	rc4(sec->enckey, buf, n);
1963
	return n;
1964
}
1965
 
1966
static int
1967
tlsunpad(uchar *buf, int n, int block)
1968
{
1969
	int pad, nn;
1970
 
1971
	pad = buf[n - 1];
1972
	nn = n - 1 - pad;
1973
	if(nn <= 0 || n % block)
1974
		return -1;
1975
	while(--n > nn)
1976
		if(pad != buf[n - 1])
1977
			return -1;
1978
	return nn;
1979
}
1980
 
1981
static int
1982
sslunpad(uchar *buf, int n, int block)
1983
{
1984
	int pad, nn;
1985
 
1986
	pad = buf[n - 1];
1987
	nn = n - 1 - pad;
1988
	if(nn <= 0 || n % block)
1989
		return -1;
1990
	return nn;
1991
}
1992
 
1993
static int
1994
blockpad(uchar *buf, int n, int block)
1995
{
1996
	int pad, nn;
1997
 
1998
	nn = n + block;
1999
	nn -= nn % block;
2000
	pad = nn - (n + 1);
2001
	while(n < nn)
2002
		buf[n++] = pad;
2003
	return nn;
2004
}
2005
 
2006
static int
2007
des3enc(Secret *sec, uchar *buf, int n)
2008
{
2009
	n = blockpad(buf, n, 8);
2010
	des3CBCencrypt(buf, n, sec->enckey);
2011
	return n;
2012
}
2013
 
2014
static int
2015
des3dec(Secret *sec, uchar *buf, int n)
2016
{
2017
	des3CBCdecrypt(buf, n, sec->enckey);
2018
	return (*sec->unpad)(buf, n, 8);
2019
}
2020
static DigestState*
2021
nomac(uchar *unused1, ulong unused2, uchar *unused3, ulong unused4,
2022
	uchar *unused5, DigestState *unused6)
2023
{
2024
	return nil;
2025
}
2026
 
2027
/*
2028
 * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
2029
 */
2030
static DigestState*
2031
sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
2032
	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
2033
{
2034
	int i;
2035
	uchar pad[48], innerdigest[20];
2036
 
2037
	if(xlen > sizeof(innerdigest)
2038
	|| padlen > sizeof(pad))
2039
		return nil;
2040
 
2041
	if(klen>64)
2042
		return nil;
2043
 
2044
	/* first time through */
2045
	if(s == nil){
2046
		for(i=0; i<padlen; i++)
2047
			pad[i] = 0x36;
2048
		s = (*x)(key, klen, nil, nil);
2049
		s = (*x)(pad, padlen, nil, s);
2050
		if(s == nil)
2051
			return nil;
2052
	}
2053
 
2054
	s = (*x)(p, len, nil, s);
2055
	if(digest == nil)
2056
		return s;
2057
 
2058
	/* last time through */
2059
	for(i=0; i<padlen; i++)
2060
		pad[i] = 0x5c;
2061
	(*x)(nil, 0, innerdigest, s);
2062
	s = (*x)(key, klen, nil, nil);
2063
	s = (*x)(pad, padlen, nil, s);
2064
	(*x)(innerdigest, xlen, digest, s);
2065
	return nil;
2066
}
2067
 
2068
static DigestState*
2069
sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
2070
{
2071
	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
2072
}
2073
 
2074
static DigestState*
2075
sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
2076
{
2077
	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
2078
}
2079
 
2080
static void
2081
sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
2082
{
2083
	DigestState *s;
2084
	uchar buf[11];
2085
 
2086
	memmove(buf, seq, 8);
2087
	buf[8] = header[0];
2088
	buf[9] = header[3];
2089
	buf[10] = header[4];
2090
 
2091
	s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
2092
	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);
2093
}
2094
 
2095
static void
2096
tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
2097
{
2098
	DigestState *s;
2099
	uchar buf[13];
2100
 
2101
	memmove(buf, seq, 8);
2102
	memmove(&buf[8], header, 5);
2103
 
2104
	s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
2105
	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);
2106
}
2107
 
2108
static void
2109
put32(uchar *p, u32int x)
2110
{
2111
	p[0] = x>>24;
2112
	p[1] = x>>16;
2113
	p[2] = x>>8;
2114
	p[3] = x;
2115
}
2116
 
2117
static void
2118
put64(uchar *p, vlong x)
2119
{
2120
	put32(p, (u32int)(x >> 32));
2121
	put32(p+4, (u32int)x);
2122
}
2123
 
2124
static void
2125
put24(uchar *p, int x)
2126
{
2127
	p[0] = x>>16;
2128
	p[1] = x>>8;
2129
	p[2] = x;
2130
}
2131
 
2132
static void
2133
put16(uchar *p, int x)
2134
{
2135
	p[0] = x>>8;
2136
	p[1] = x;
2137
}
2138
 
2139
/*
2140
static u32int
2141
get32(uchar *p)
2142
{
2143
	return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
2144
}
2145
*/
2146
 
2147
static int
2148
get16(uchar *p)
2149
{
2150
	return (p[0]<<8)|p[1];
2151
}
2152
 
2153
static char *charmap = "0123456789abcdef";
2154
 
2155
static void
2156
pdump(int len, void *a, char *tag)
2157
{
2158
	uchar *p;
2159
	int i;
2160
	char buf[65+32];
2161
	char *q;
2162
 
2163
	p = a;
2164
	strcpy(buf, tag);
2165
	while(len > 0){
2166
		q = buf + strlen(tag);
2167
		for(i = 0; len > 0 && i < 32; i++){
2168
			if(*p >= ' ' && *p < 0x7f){
2169
				*q++ = ' ';
2170
				*q++ = *p;
2171
			} else {
2172
				*q++ = charmap[*p>>4];
2173
				*q++ = charmap[*p & 0xf];
2174
			}
2175
			len--;
2176
			p++;
2177
		}
2178
		*q = 0;
2179
 
2180
		if(len > 0)
2181
			pprint("%s...\n", buf);
2182
		else
2183
			pprint("%s\n", buf);
2184
	}
2185
}