~kris/9p

9hist

ef27c0cca3ad4f65005f669c6fd98e1e9e57cfb3 — David du Colombier 30 years ago 287aedc
Plan 9 from Bell Labs 1995-12-17
3 files changed, 245 insertions(+), 221 deletions(-)

M port/devssl.c
M port/portfns.h
M port/qio.c
M port/devssl.c => port/devssl.c +193 -221
@@ 49,7 49,7 @@ struct Dstate
	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);	/* hash func */

	int	max;		/* maximum unpadded data per msg */
	int	maxpad;	/* maximum padded data per msg */
	int	maxpad;		/* maximum padded data per msg */

	/* input side */
	OneWay	in;


@@ 86,6 86,17 @@ Randq randq;

void producerand(void);

static void	ensure(Dstate*, Block**, int);
static void	consume(Block**, uchar*, int);
static void	setsecret(OneWay*, uchar*, int);
static Block*	encryptb(Dstate*, Block*, int);
static Block*	decryptb(Dstate*, Block*);
static Block*	digestb(Dstate*, Block*, int);
static void	checkdigestb(Dstate*, Block*);
static Chan*	buftochan(char*, long);
static void	dighangup(Dstate*);


void
sslreset(void)
{


@@ 203,24 214,83 @@ sslread(Chan *c, void *a, long n, ulong offset)
	return n;
}

static void
setsecret(OneWay *w, uchar *secret, int n)
Block*
sslbread(Chan *c, long n, ulong offset)
{
	w->secret = smalloc(n);
	memmove(w->secret, secret, n);
	w->slen = n;
	w->mid = 0;
	Block *bp, **l;
	uchar count[2];
	int len;
	int pad;

	switch(s->encryptalg){
	case DESCBC:
		w->state = smalloc(sizeof(DESstate));
		setupDESstate(w->state, secret, 0);
		break;
	case DESCBC:
		w->state = smalloc(sizeof(DESstate));
		setupDESstate(w->state, secret, secret+8);
		break;
	USED(offset);

	s = c->aux;
	if(s == 0 || s->state != Established)
		error(Ebadusefd);

	if(waserror()){
		qunlock(&s->in);
		dighangup(s);
		nexterror();
	}
	qlock(&s->in);

	if(s->processed == 0){
	
		/* read in the whole message */
		s->processed = s->unprocessed;
		s->unprocessed =- 0;
		ensure(s, &s->processed, 2);
		consume(&s->processed, count, 2);
		if(count[0] & 0x80){
			len = ((count[0] & 0x7f)<<8) | count[1];
			pad = 0;
		} else {
			len = ((count[0] & 0x3f)<<8) | count[1];
			ensure(s, &s->processed, 1);
			consume(&s->processed, count, 1);
			pad = count[0];
		}
		ensure(s, &s->processed, len);

		/* trade memory bandwidth for less processing complexity */
		b = s->processed = pullupblock(s->processed, len);

		/* put remainder on unprocessed queue */
		i = BLEN(b);
		if(i > len){
			i -= len;
			s->unprocessed = allocb(i);
			memmove(s->unprocessed->wp, b->rp+len, i);
			s->unprocessed->wp += i;
			b->wp -= i;
		}

		if(s->encrypalg)
			b = decryptb(s, b);
		else
			checkdigestb(s, b);

		/* remove pad */
		if(b->wp - b->rp > pad)
			panic("sslbread");
		b->wp -= pad;
		s->processed = b;
	}

	b = s->processed;
	if(BLEN(b) > n){
		b = allocb(n);
		memmove(b->wp, s->processed->rp, n);
		b->wp += n;
		s->processed->rp += n;
	} else 
		s->processed = b->next;

	qunlock(&s->in);
	poperror();

	return b;
}

long


@@ 326,6 396,7 @@ sslbwrite(Chan *c, Block *b, ulong offset)
	Dstate *s;
	Block *nb;
	int h, n, m, pad, rv;
	uchar *p;

	s = c->aux;
	if(s == 0 || s->state != Established)


@@ 379,19 450,26 @@ sslbwrite(Chan *c, Block *b, ulong offset)
		m += s->diglen;

		/* SSL style count */
		p = np->rp;
		if(pad){
			memset(nb->wp, 0, pad);
			m += pad;
			nb->wp += pad;
		} else
			p[0] = (m>>8);
			p[1] = m;
			p[2] = pad;
			offset = 3;
		} else {
			m |= 0x8000;
		np->rp[0] = (m>>8);
		np->rp[1] = m;
			p[0] = (m>>8);
			p[1] = m;
			offset = 2;
		}

		if(encryptalg)
			encryptb(s, nb);
			nb = encryptb(s, nb, offset);
		else
			digestb(s, nb);
			nb = digestb(s, nb, ofsetf);

		(*devtab[s->c->type].bwrite)(s->c, nb, offset);



@@ 402,113 480,6 @@ sslbwrite(Chan *c, Block *b, ulong offset)
	return rv;
}

Block*
sslbread(Chan *c, long n, ulong offset)
{
	Block *bp, **l;
	uchar count[2];
	int len;
	int pad;

	USED(offset);

	s = c->aux;
	if(s == 0 || s->state != Established)
		error(Ebadusefd);

	if(waserror()){
		qunlock(&s->in);
		dighangup(s);
		nexterror();
	}
	qlock(&s->in);

	if(s->processed == 0){
	
		/* read in the whole message */
		s->processed = s->unprocessed;
		s->unprocessed =- 0;
		ensure(s, &s->processed, 2);
		consume(&s->processed, count, 2);
		if(count[0] & 0x80){
			len = ((count[0] & 0x7f)<<8) | count[1];
			pad = 0;
		} else {
			len = ((count[0] & 0x3f)<<8) | count[1];
			ensure(s, &s->processed, 1);
			consume(&s->processed, count, 1);
			pad = count[0];
		}
		ensure(s, &s->processed, len);

		/* put remainder on unprocessed */
		i = 0;
		for(b = s->processed; b; b = b->next){
			i = BLEN(b);
			if(i >= len)
				break;
			(*s->func)(b->rp, i, 0, &ss);
			len -= i;
		}
		if(b == 0)
			panic("digestbread");
		if(i > len){
			i -= len;
			s->unprocessed = allocb(i);
			memmove(s->unprocessed->wp, b->rp+len, i);
			s->unprocessed->wp += i;
			b->wp -= i;
		}
			
		if(s->encrypalg)
			decryptb(s, len);
		else
			checkdigestb(s, len);

		if(pad){
			for(b = s->processed; b; b = b->next){
	}

	b = s->processed;
	if(BLEN(b) > n){
		b = allocb(n);
		memmove(b->wp, s->processed->rp, n);
		b->wp += n;
		s->processed->rp += n;
	} else 
		s->processed = b->next;

	qunlock(&s->in);
	poperror();

	return b;
}

Block*
decryptb(Dstate *s, Block *b, int len)
{
	ulong n, h;
	uchar *p, *ep;
	DESstate *ds;

	h = s->diglen + 2;

	switch(s->encryptalg){
	case DESEBC:
		ds = s->in.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + h; p < ep; p += 8)
			block_cipher(ds->expanded, p, 1);
		break;
	case DESCBC:
		ds = s->in.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + h; p < ep; p += 8)
			bCBCDecrypt(p, ds->ivec, ds->expanded, 8);
		break;
	}
}

/*
 *  make sure we have at least 'n' bytes in list 'l'
 */


@@ 566,86 537,78 @@ consume(Block **l, uchar *p, int n)
	}
}

static Block*
digestbread(Dstate *s, long n)
static void
setsecret(OneWay *w, uchar *secret, int n)
{
	Block *b;
	int i, m, len;
	uchar *p;
	uchar *dp;
	uchar digestin[32];
	uchar digest[32];
	DigestState ss;

	memset(&ss, 0, sizeof(ss));
	w->secret = smalloc(n);
	memmove(w->secret, secret, n);
	w->slen = n;
	w->mid = 0;

	ensure(s, &s->unprocessed, s->diglen);
		len = 0;
		for(i = 0; i < 4; i++){
			consume(&s->unprocessed, digestin+i, 1);
			m = digestin[i];
			if((m & 0x80) == 0)
				break;
			len = (len<<7) | (m & 0x7f);
		}
	
		/* digest count */
		p = &digestin[s->diglen];
		(*s->func)(p, i, 0, &ss);
		ensure(s, &s->unprocessed, s->diglen);
	switch(s->encryptalg){
	case DESCBC:
		w->state = smalloc(sizeof(DESstate));
		setupDESstate(w->state, secret, 0);
		break;
	case DESCBC:
		w->state = smalloc(sizeof(DESstate));
		setupDESstate(w->state, secret, secret+8);
		break;
	}
}

		/* get message */
		s->processed = s->unprocessed;
		s->unprocessed = 0;
		ensure(s, &s->processed, len);
static Block*
encryptb(Dstate *s, Block *b, int offset)
{
	ulong n;
	int j;
	uchar *p, *ep;
	DESstate *ds;

		/* digest message */
		i = 0;
		for(b = s->processed; b; b = b->next){
			i = BLEN(b);
			if(i >= len)
				break;
			(*s->func)(b->rp, i, 0, &ss);
			len -= i;
		}
		if(b == 0)
			panic("digestbread");
		if(i > len){
			i -= len;
			s->unprocessed = allocb(i);
			memmove(s->unprocessed->wp, b->rp+len, i);
			s->unprocessed->wp += i;
			b->wp -= i;
		}
		(*s->func)(b->rp, len, 0, &ss);

		/* digest secret & message id */
		p = s->in.secret;
		m = s->in.mid++;
		*p++ = m>>24;
		*p++ = m>>16;
		*p++ = m>>8;
		*p = m;
		(*s->func)(s->in.secret, s->in.slen, digest, &ss);

		if(memcmp(digest, digestin, s->diglen) != 0)
			error("bad digest");
	switch(s->encryptalg){
	case DESEBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + offset; p < ep; p += 8)
			block_cipher(ds->expanded, p, 0);
		break;
	case DESCBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + offset; p < ep; p += 8)
			bCBCEncrypt(p, ds->ivec, ds->expanded, 8);
		break;
	}
	return b;
}

	b = s->processed;
	if(BLEN(b) > n){
		b = allocb(n);
		memmove(b->wp, s->processed->rp, n);
		b->wp += n;
		s->processed->rp += n;
	} else 
		s->processed = b->next;
static Block*
decryptb(Dstate *s, Block *b)
{
	ulong n, h;
	int j;
	uchar *p, *ep;
	DESstate *ds;

	switch(s->encryptalg){
	case DESEBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + s->diglen; p < ep; p += 8)
			block_cipher(ds->expanded, p, 1);
		break;
	case DESCBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + s->diglen; p < ep; p += 8)
			bCBCDecrypt(p, ds->ivec, ds->expanded, 8);
		break;
	}
	return b;
}

void
digestb(Dstate *s, Block *b)
static Block*
digestb(Dstate *s, Block *b, int offset)
{
	Block *nb;
	uchar *p;


@@ 657,7 620,7 @@ digestb(Dstate *s, Block *b)
	w = &s->out;

	memset(&ss, 0, sizeof(ss));
	h = s->diglen + 2;
	h = s->diglen + offset;
	n = BLEN(b) - h;

	/* hash secret + message */


@@ 671,34 634,43 @@ digestb(Dstate *s, Block *b)
	*p++ = n>>16;
	*p++ = n>>8;
	*p = n;
	(*s->func)(msgid, 4, nb->rp + 2, &ss);
	(*s->func)(msgid, 4, nb->rp+offset, &ss);

	retrn b;
}

long
encryptb(Dstate *s, Block *b)
static void
checkdigestb(Dstate *s, Block *b)
{
	Block *nb;
	uchar *p;
	DigestState ss;
	uchar msgid[4];
	ulong n, h;
	int j;
	uchar *p, *ep, *ip;
	DESstate *ds;
	OneWay *w;
	uchar digest[128];

	h = s->diglen + 2;
	w = &s->in;

	switch(s->encryptalg){
	case DESEBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + h; p < ep; p += 8)
			block_cipher(ds->expanded, p, 0);
		break;
	case DESCBC:
		ds = s->out.state;
		ep = b->rp + BLEN(b);
		for(p = b->rp + h; p < ep; p += 8)
			bCBCEncrypt(p, ds->ivec, ds->expanded, 8);
		break;
	}
	
	memset(&ss, 0, sizeof(ss));
	h = s->diglen;
	n = BLEN(b) - h;

	/* hash secret + message */
	(*s->hf)(w->secret, w->slen, 0, &ss);
	(*s->hf)(nb->rp + h, n, 0, &ss);

	/* hash message id */
	p = msgid;
	n = w->mid++;
	*p++ = n>>24;
	*p++ = n>>16;
	*p++ = n>>8;
	*p = n;
	(*s->func)(msgid, 4, digest, &ss);

	if(memcmp(digest, nb->rp, s->diglen) != 0)
		error("bad digest");
}

/* get channel associated with an fd */

M port/portfns.h => port/portfns.h +1 -0
@@ 189,6 189,7 @@ Pte*		ptealloc(void);
Pte*		ptecpy(Pte*);
Path*		ptenter(Pthash*, Path*, char*);
int		ptpath(Path*, char*, int);
Block*		pullupblock(Block*, int);
void		putimage(Image*);
void		putmmu(ulong, ulong, Page*);
void		putpage(Page*);

M port/qio.c => port/qio.c +51 -0
@@ 773,3 773,54 @@ qstate(Queue *q)
{
	return q->state;
}

/*
 *  make sure the first block has at least n bytes
 */
Block*
pullupblock(Block *bp, int n)
{
	int i;
	Block *nbp;

	/*
	 *  this should almost always be true, the rest it
	 *  just to avoid every caller checking.
	 */
	if(BLEN(bp) >= n)
		return bp;

	/*
	 *  if not enough room in the first block,
	 *  add another to the front of the list.
	 */
	if(bp->lim - bp->rp < n){
		nbp = allocb(n);
		nbp->next = bp;
		bp = nbp;
	}

	/*
	 *  copy bytes from the trailing blocks into the first
	 */
	n -= BLEN(bp);
	while(nbp = bp->next){
		i = BLEN(nbp);
		if(i >= n) {
			memmove(bp->wp, nbp->rp, n);
			bp->wp += n;
			nbp->rp += n;
			return bp;
		}
		else {
			memmove(bp->wp, nbp->rp, i);
			bp->wp += i;
			bp->next = nbp->next;
			nbp->next = 0;
			freeb(nbp);
			n -= i;
		}
	}
	freeb(bp);
	return 0;
}