@@ 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 */