From ef27c0cca3ad4f65005f669c6fd98e1e9e57cfb3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 17 Dec 1995 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1995-12-17 --- port/devssl.c | 414 +++++++++++++++++++++++-------------------------- port/portfns.h | 1 + port/qio.c | 51 ++++++ 3 files changed, 245 insertions(+), 221 deletions(-) diff --git a/port/devssl.c b/port/devssl.c index 98ce6247c8fcffbebd07a569d0dfeccf179f811c..a89a8d895ce9278f8edae020c7d802f2d1539ea5 100644 --- a/port/devssl.c +++ b/port/devssl.c @@ -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 */ diff --git a/port/portfns.h b/port/portfns.h index 5ab08f43963fb066b5388538a90fe3bc5f52603c..fc9124387134d919eadb7a11c9a65527ec748cf9 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -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*); diff --git a/port/qio.c b/port/qio.c index 2c3684a841b27a4bb551392002791d571e5fe589..71650e8f5be66dbe2a3b588c566831e104bab9df 100644 --- a/port/qio.c +++ b/port/qio.c @@ -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; +}