From 22b4419718fe23075553c15dcd9b4180f6009968 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 7 Mar 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-03-07 --- port/devssl.c | 293 +++++++++++++++++++++++++++----------------------- 1 file changed, 160 insertions(+), 133 deletions(-) diff --git a/port/devssl.c b/port/devssl.c index 04f4aeeca3177d938334e4af106486a9a26cfe1d..4c3360cf07470abcfa27d3de3a6c032106fad883 100644 --- a/port/devssl.c +++ b/port/devssl.c @@ -111,6 +111,7 @@ static Chan* buftochan(char*); static void sslhangup(Dstate*); static Dstate* dsclone(Chan *c); static void dsnew(Chan *c, Dstate **); +static long sslput(Dstate *s, Block * volatile b); char *sslnames[] = { [Qclonus] "clone", @@ -542,40 +543,40 @@ qtake(Block **l, int n, int discard) static Block* sslbread(Chan *c, long n, ulong) { - volatile struct { Dstate *s; } s; + Dstate * volatile s; Block *b; uchar consumed[3], *p; int toconsume; int len, pad; - s.s = dstate[CONV(c->qid)]; - if(s.s == 0) + s = dstate[CONV(c->qid)]; + if(s == 0) panic("sslbread"); - if(s.s->state == Sincomplete) + if(s->state == Sincomplete) error(Ebadusefd); - qlock(&s.s->in.q); + qlock(&s->in.q); if(waserror()){ - qunlock(&s.s->in.q); + qunlock(&s->in.q); nexterror(); } - if(s.s->processed == 0){ + if(s->processed == 0){ /* * Read in the whole message. Until we've got it all, - * it stays on s.s->unprocessed, so that if we get Eintr, + * it stays on s->unprocessed, so that if we get Eintr, * we'll pick up where we left off. */ - ensure(s.s, &s.s->unprocessed, 3); - s.s->unprocessed = pullupblock(s.s->unprocessed, 2); - p = s.s->unprocessed->rp; + ensure(s, &s->unprocessed, 3); + s->unprocessed = pullupblock(s->unprocessed, 2); + p = s->unprocessed->rp; if(p[0] & 0x80){ len = ((p[0] & 0x7f)<<8) | p[1]; - ensure(s.s, &s.s->unprocessed, len); + ensure(s, &s->unprocessed, len); pad = 0; toconsume = 2; } else { - s.s->unprocessed = pullupblock(s.s->unprocessed, 3); + s->unprocessed = pullupblock(s->unprocessed, 3); len = ((p[0] & 0x3f)<<8) | p[1]; pad = p[2]; if(pad > len){ @@ -584,7 +585,7 @@ sslbread(Chan *c, long n, ulong) } toconsume = 3; } - ensure(s.s, &s.s->unprocessed, toconsume+len); + ensure(s, &s->unprocessed, toconsume+len); /* * Now we have a full SSL packet in the unprocessed list. @@ -600,61 +601,61 @@ sslbread(Chan *c, long n, ulong) } /* skip header */ - consume(&s.s->unprocessed, consumed, toconsume); + consume(&s->unprocessed, consumed, toconsume); /* grab the next message and decode/decrypt it */ - b = qtake(&s.s->unprocessed, len, 0); + b = qtake(&s->unprocessed, len, 0); if(blocklen(b) != len) print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); if(waserror()){ - qunlock(&s.s->in.ctlq); + qunlock(&s->in.ctlq); if(b != nil) freeb(b); nexterror(); } - qlock(&s.s->in.ctlq); - switch(s.s->state){ + qlock(&s->in.ctlq); + switch(s->state){ case Sencrypting: if(b == nil) error("ssl message too short (encrypting)"); - b = decryptb(s.s, b); + b = decryptb(s, b); break; case Sdigesting: - b = pullupblock(b, s.s->diglen); + b = pullupblock(b, s->diglen); if(b == nil) error("ssl message too short (digesting)"); - checkdigestb(s.s, b); - b->rp += s.s->diglen; + checkdigestb(s, b); + b->rp += s->diglen; break; case Sdigenc: - b = decryptb(s.s, b); - b = pullupblock(b, s.s->diglen); + b = decryptb(s, b); + b = pullupblock(b, s->diglen); if(b == nil) error("ssl message too short (dig+enc)"); - checkdigestb(s.s, b); - b->rp += s.s->diglen; - len -= s.s->diglen; + checkdigestb(s, b); + b->rp += s->diglen; + len -= s->diglen; break; } /* remove pad */ if(pad) - s.s->processed = qtake(&b, len - pad, 1); + s->processed = qtake(&b, len - pad, 1); else - s.s->processed = b; + s->processed = b; b = nil; - s.s->in.mid++; - qunlock(&s.s->in.ctlq); + s->in.mid++; + qunlock(&s->in.ctlq); poperror(); poperror(); } /* return at most what was asked for */ - b = qtake(&s.s->processed, n, 0); + b = qtake(&s->processed, n, 0); - qunlock(&s.s->in.q); + qunlock(&s->in.q); poperror(); return b; @@ -663,7 +664,7 @@ sslbread(Chan *c, long n, ulong) static long sslread(Chan *c, void *a, long n, vlong off) { - volatile struct { Block *b; } b; + Block * volatile b; Block *nb; uchar *va; int i; @@ -683,7 +684,7 @@ sslread(Chan *c, void *a, long n, vlong off) sprint(buf, "%d", ft); return readstr(offset, a, n, buf); case Qdata: - b.b = sslbread(c, n, offset); + b = sslbread(c, n, offset); break; case Qencalgs: return readstr(offset, a, n, encalgs); @@ -694,19 +695,19 @@ sslread(Chan *c, void *a, long n, vlong off) } if(waserror()){ - freeblist(b.b); + freeblist(b); nexterror(); } n = 0; va = a; - for(nb = b.b; nb; nb = nb->next){ + for(nb = b; nb; nb = nb->next){ i = BLEN(nb); memmove(va+n, nb->rp, i); n += i; } - freeblist(b.b); + freeblist(b); poperror(); return n; @@ -723,6 +724,36 @@ randfill(uchar *buf, int len) *buf++ = nrand(256); } +static long +sslbwrite(Chan *c, Block *b, ulong) +{ + Dstate * volatile s; + long rv; + + s = dstate[CONV(c->qid)]; + if(s == nil) + panic("sslbwrite"); + + if(s->state == Sincomplete){ + freeb(b); + error(Ebadusefd); + } + + /* lock so split writes won't interleave */ + if(waserror()){ + qunlock(&s->out.q); + nexterror(); + } + qlock(&s->out.q); + + rv = sslput(s, b); + + poperror(); + qunlock(&s->out.q); + + return rv; +} + /* * use SSL record format, add in count, digest and/or encrypt. * the write is interruptable. if it is interrupted, we'll @@ -730,48 +761,36 @@ randfill(uchar *buf, int len) * it since we don't know if any bytes have been written. */ static long -sslbwrite(Chan *c, Block *b, ulong offset) +sslput(Dstate *s, Block * volatile b) { - volatile struct { Dstate *s; } s; - volatile struct { Block *b; } bb; Block *nb; int h, n, m, pad, rv; uchar *p; - - bb.b = b; - s.s = dstate[CONV(c->qid)]; - if(s.s == 0) - panic("sslbwrite"); - if(s.s->state == Sincomplete){ - freeb(b); - error(Ebadusefd); - } + int offset; if(waserror()){ - qunlock(&s.s->out.q); - if(bb.b != nil) - freeb(bb.b); + if(b != nil) + free(b); nexterror(); } - qlock(&s.s->out.q); rv = 0; - while(bb.b){ - m = n = BLEN(bb.b); - h = s.s->diglen + 2; + while(b != nil){ + m = n = BLEN(b); + h = s->diglen + 2; /* trim to maximum block size */ pad = 0; - if(m > s.s->max){ - m = s.s->max; - } else if(s.s->blocklen != 1){ - pad = (m + s.s->diglen)%s.s->blocklen; + if(m > s->max){ + m = s->max; + } else if(s->blocklen != 1){ + pad = (m + s->diglen)%s->blocklen; if(pad){ - if(m > s.s->maxpad){ + if(m > s->maxpad){ pad = 0; - m = s.s->maxpad; + m = s->maxpad; } else { - pad = s.s->blocklen - pad; + pad = s->blocklen - pad; h++; } } @@ -780,15 +799,15 @@ sslbwrite(Chan *c, Block *b, ulong offset) rv += m; if(m != n){ nb = allocb(m + h + pad); - memmove(nb->wp + h, bb.b->rp, m); + memmove(nb->wp + h, b->rp, m); nb->wp += m + h; - bb.b->rp += m; + b->rp += m; } else { /* add header space */ - nb = padblock(bb.b, h); - bb.b = 0; + nb = padblock(b, h); + b = 0; } - m += s.s->diglen; + m += s->diglen; /* SSL style count */ if(pad){ @@ -809,28 +828,27 @@ sslbwrite(Chan *c, Block *b, ulong offset) offset = 2; } - switch(s.s->state){ + switch(s->state){ case Sencrypting: - nb = encryptb(s.s, nb, offset); + nb = encryptb(s, nb, offset); break; case Sdigesting: - nb = digestb(s.s, nb, offset); + nb = digestb(s, nb, offset); break; case Sdigenc: - nb = digestb(s.s, nb, offset); - nb = encryptb(s.s, nb, offset); + nb = digestb(s, nb, offset); + nb = encryptb(s, nb, offset); break; } - s.s->out.mid++; + s->out.mid++; m = BLEN(nb); - devtab[s.s->c->type]->bwrite(s.s->c, nb, s.s->c->offset); - s.s->c->offset += m; + devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); + s->c->offset += m; } - qunlock(&s.s->out.q); - poperror(); + poperror(); return rv; } @@ -1033,64 +1051,73 @@ parseencryptalg(char *p, Dstate *s) } static long -sslwrite(Chan *c, void *a, long n, vlong off) +sslwrite(Chan *c, void *a, long n, vlong) { - volatile struct { Dstate *s; } s; - volatile struct { Block *b; } b; + Dstate * volatile s; + Block * volatile b; int m, t; char *p, *np, *e, buf[128]; uchar *x; - ulong offset = off; - s.s = dstate[CONV(c->qid)]; - if(s.s == 0) + s = dstate[CONV(c->qid)]; + if(s == 0) panic("sslwrite"); t = TYPE(c->qid); if(t == Qdata){ - if(s.s->state == Sincomplete) + if(s->state == Sincomplete) error(Ebadusefd); + /* lock should a write gets split over multiple records */ + if(waserror()){ + qunlock(&s->out.q); + nexterror(); + } + qlock(&s->out.q); + p = a; e = p + n; do { m = e - p; - if(m > s.s->max) - m = s.s->max; + if(m > s->max) + m = s->max; - b.b = allocb(m); + b = allocb(m); if(waserror()){ - freeb(b.b); + freeb(b); nexterror(); } - memmove(b.b->wp, p, m); + memmove(b->wp, p, m); poperror(); - b.b->wp += m; + b->wp += m; - sslbwrite(c, b.b, offset); + sslput(s, b); p += m; } while(p < e); + + poperror(); + qunlock(&s->out.q); return n; } /* mutex with operations using what we're about to change */ if(waserror()){ - qunlock(&s.s->in.ctlq); - qunlock(&s.s->out.q); + qunlock(&s->in.ctlq); + qunlock(&s->out.q); nexterror(); } - qlock(&s.s->in.ctlq); - qlock(&s.s->out.q); + qlock(&s->in.ctlq); + qlock(&s->out.q); switch(t){ default: panic("sslwrite"); case Qsecretin: - setsecret(&s.s->in, a, n); + setsecret(&s->in, a, n); goto out; case Qsecretout: - setsecret(&s.s->out, a, n); + setsecret(&s->out, a, n); goto out; case Qctl: break; @@ -1108,46 +1135,46 @@ sslwrite(Chan *c, void *a, long n, vlong off) *p++ = 0; if(strcmp(buf, "fd") == 0){ - s.s->c = buftochan(p); + s->c = buftochan(p); /* default is clear (msg delimiters only) */ - s.s->state = Sclear; - s.s->blocklen = 1; - s.s->diglen = 0; - s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; - s.s->in.mid = 0; - s.s->out.mid = 0; + s->state = Sclear; + s->blocklen = 1; + s->diglen = 0; + s->maxpad = s->max = (1<<15) - s->diglen - 1; + s->in.mid = 0; + s->out.mid = 0; } else if(strcmp(buf, "alg") == 0 && p != 0){ - s.s->blocklen = 1; - s.s->diglen = 0; + s->blocklen = 1; + s->diglen = 0; - if(s.s->c == 0) + if(s->c == 0) error("must set fd before algorithm"); - s.s->state = Sclear; - s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; + s->state = Sclear; + s->maxpad = s->max = (1<<15) - s->diglen - 1; if(strcmp(p, "clear") == 0){ goto out; } - if(s.s->in.secret && s.s->out.secret == 0) - setsecret(&s.s->out, s.s->in.secret, s.s->in.slen); - if(s.s->out.secret && s.s->in.secret == 0) - setsecret(&s.s->in, s.s->out.secret, s.s->out.slen); - if(s.s->in.secret == 0 || s.s->out.secret == 0) + if(s->in.secret && s->out.secret == 0) + setsecret(&s->out, s->in.secret, s->in.slen); + if(s->out.secret && s->in.secret == 0) + setsecret(&s->in, s->out.secret, s->out.slen); + if(s->in.secret == 0 || s->out.secret == 0) error("algorithm but no secret"); - s.s->hf = 0; - s.s->encryptalg = Noencryption; - s.s->blocklen = 1; + s->hf = 0; + s->encryptalg = Noencryption; + s->blocklen = 1; for(;;){ np = strchr(p, ' '); if(np) *np++ = 0; - if(parsehashalg(p, s.s) < 0) - if(parseencryptalg(p, s.s) < 0) + if(parsehashalg(p, s) < 0) + if(parseencryptalg(p, s) < 0) error("bad algorithm"); if(np == 0) @@ -1155,34 +1182,34 @@ sslwrite(Chan *c, void *a, long n, vlong off) p = np; } - if(s.s->hf == 0 && s.s->encryptalg == Noencryption) + if(s->hf == 0 && s->encryptalg == Noencryption) error("bad algorithm"); - if(s.s->blocklen != 1){ - s.s->max = (1<<15) - s.s->diglen - 1; - s.s->max -= s.s->max % s.s->blocklen; - s.s->maxpad = (1<<14) - s.s->diglen - 1; - s.s->maxpad -= s.s->maxpad % s.s->blocklen; + if(s->blocklen != 1){ + s->max = (1<<15) - s->diglen - 1; + s->max -= s->max % s->blocklen; + s->maxpad = (1<<14) - s->diglen - 1; + s->maxpad -= s->maxpad % s->blocklen; } else - s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; + s->maxpad = s->max = (1<<15) - s->diglen - 1; } else if(strcmp(buf, "secretin") == 0 && p != 0) { m = (strlen(p)*3)/2; x = smalloc(m); t = dec64(x, m, p, strlen(p)); - setsecret(&s.s->in, x, t); + setsecret(&s->in, x, t); free(x); } else if(strcmp(buf, "secretout") == 0 && p != 0) { m = (strlen(p)*3)/2 + 1; x = smalloc(m); t = dec64(x, m, p, strlen(p)); - setsecret(&s.s->out, x, t); + setsecret(&s->out, x, t); free(x); } else error(Ebadarg); out: - qunlock(&s.s->in.ctlq); - qunlock(&s.s->out.q); + qunlock(&s->in.ctlq); + qunlock(&s->out.q); poperror(); return n; }