## diffname port/devssl.c 1995/1213 ## diff -e /dev/null /n/fornaxdump/1995/1213/sys/src/brazil/port/devssl.c 0a /* * template for making a new device */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include #include "devtab.h" typedef struct OneWay OneWay; struct OneWay { QLock; void *state; /* encryption state */ int slen; /* hash data length */ uchar *secret; /* secret */ ulong mid; /* message id */ }; enum { /* connection states */ Algwait= 0, /* waiting for user to write algorithm */ Fdwait= 1, /* waiting for user to write fd */ Secretinwait= 2, /* waiting for user to write input secret */ Secretoutwait= 3, /* waiting for user to write output secret */ Established= 4, Closed= 5, /* encryption algorithms */ DESCBC= 1, }; typedef struct Dstate Dstate; struct Dstate { Chan *c; /* io channel */ uchar state; /* state of connection */ uchar encryptalg; /* encryption algorithm */ ushort blocking; /* blocking length */ ushort diglen; /* length of digest */ DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); /* hash func */ int max; /* maximum unpadded data per msg */ int maxpad; /* maximum padded data per msg */ /* input side */ OneWay in; Block *processed; Block *unprocessed; /* output side */ OneWay out; }; enum { Maxdmsg= 1<<16, }; enum{ Qdir, Qclone, }; Dirtab digesttab[]={ "digestclone", {Qclone, 0}, 0, 0600, }; #define Ndigesttab (sizeof(digesttab)/sizeof(Dirtab)) /* a circular list of random numbers */ typedef struct { uchar *rp; uchar *wp; uchar buf[1024]; uchar *ep; } Randq; Randq randq; void producerand(void); void sslreset(void) { randq.ep = randq.buf + sizeof(randq.buf); randq.rp = randq.wp = randq.buf; } void sslinit(void) { } Chan * sslattach(char *spec) { return devattach('D', spec); } Chan * sslclone(Chan *c, Chan *nc) { return devclone(c, nc); } int sslwalk(Chan *c, char *name) { return devwalk(c, name, digesttab, Ndigesttab, devgen); } void sslstat(Chan *c, char *db) { devstat(c, db, digesttab, Ndigesttab, devgen); } Chan * sslopen(Chan *c, int omode) { Dstate *s; switch(c->qid.path & ~CHDIR){ case Qclone: s = smalloc(sizeof(Dstate)); memset(s, 0, sizeof(*s)); s->state = Algwait; c->aux = s; break; } return devopen(c, omode, digesttab, Ndigesttab, devgen); } void sslcreate(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); error(Eperm); } void sslremove(Chan *c) { USED(c); error(Eperm); } void sslwstat(Chan *c, char *dp) { USED(c, dp); error(Eperm); } static void dighangup(Dstate *s) { Block *b; qlock(&s->in); for(b = s->processed; b; b = s->processed){ s->processed = b->next; freeb(b); } if(s->unprocessed){ freeb(s->unprocessed); s->unprocessed = 0; } s->state = Closed; qunlock(&s->in); } void sslclose(Chan *c) { Dstate *s; if(c->aux){ s = c->aux; dighangup(s); if(s->c) close(s->c); if(s->in.secret) free(s->in.secret); if(s->out.secret) free(s->out.secret); free(s); } } long sslread(Chan *c, void *a, long n, ulong offset) { Block *b; switch(c->qid.path & ~CHDIR){ case Qdir: return devdirread(c, a, n, digesttab, Ndigesttab, devgen); } b = sslbread(c, n, offset); if(waserror()){ freeb(b); nexterror(); } n = BLEN(b); memmove(a, b->rp, n); freeb(b); poperror(); return n; } static void setsecret(OneWay *w, uchar *secret, int n) { w->secret = smalloc(n); memmove(w->secret, secret, n); w->slen = n; w->mid = 0; 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; } } long sslwrite(Chan *c, char *a, long n, ulong offset) { Dstate *s; Block *b; int m, sofar; char buf[32]; switch(c->qid.path & ~CHDIR){ case Qclone: break; default: error(Ebadusefd); } s = c->aux; if(s == 0) error(Ebadusefd); switch(s->state){ case Algwait: /* get algorithm */ if(n >= sizeof(buf)) Ebadarg; strncpy(buf, a, n); buf[n] = 0; s->blocklen = 1; s->diglen = 0; if(strcmp(buf, "md5") == 0){ s->hf = md5; s->diglen = MD5dlen; } else if(strcmp(buf, "sha") == 0){ s->hf = sha; s->diglen = SHAdlen; } else if(strcmp(buf, "descbc") == 0){ s->encryptalg = DESCBC; s->blocklen = 8; } else if(strcmp(buf, "desebc") == 0){ s->encryptalg = DESEBC; s->blocklen = 8; } else error(Ebadarg); s->state = Fdwait; break; case Fdwait: /* get communications channel */ s->c = buftochan(a, n); s->state = Secretinwait; break; case Secretinwait: /* get secret for incoming messages */ setsecret(&s->in, a, n); s->state = Secretoutwait; break; case Secretoutwait: /* get secret for outgoing messages */ setsecret(&s->out, a, n); if(s->blocklen != 1){ s->max = (1<<15) - s->diglen; s->max -= s->max % s->blocklen; s->maxpad = (1<<14) - s->diglen; s->maxpad -= s->maxpad % s->blocklen; } else s->maxpad = s->max = (1<<15) - s->diglen; s->state = Established; break; case Established: sofar = 0; do { m = n - sofar; if(m > s->max) m = s->max; b = allocb(m); if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, a+sofar, m); poperror(); b->wp += m; sslbwrite(c, b, offset); sofar += m; } while(sofar < n); break; default: error(Ebadusefd); } return n; } void digestb(Dstate *s, Block *b, OneWay *w) { Block *nb; uchar *p; DigestState ss; uchar msgid[4]; ulong n, h; memset(&ss, 0, sizeof(ss)); h = s->diglen + 2; 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, nb->rp + 2, &ss); } long encryptb(Dstate *s, Block *b) { ulong n, h; int j; uchar *p, *ep, *ip; DESstate *ds; h = s->diglen + 2; 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; } } long decryptb(Dstate *s, Block *b) { 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' */ static void ensure(Dstate *s, Block **l, int n) { int i, sofar; Block *b; b = *l; if(b){ sofar = BLEN(b); l = &b->next; } else sofar = 0; while(sofar < n){ b = (*devtab[s->c->type].bread)(s->c, Maxdmsg, 0); if(b == 0) error(Ehungup); i = BLEN(b); if(i <= 0){ freeb(b); continue; } *l = b; l = &b->next; sofar += i; } } /* * copy 'n' bytes from 'l' into 'p' and free * the bytes in 'l' */ static void consume(Block **l, uchar *p, int n) { Block *b; int i; for(; *l && n > 0; n -= i){ b = *l; i = BLEN(b); if(i > n) i = n; memmove(p, b->rp, i); b->rp += i; p += i; if(BLEN(b)) break; *l = b->next; freeb(b); } } static Block* digestbread(Dstate *s, long n) { Block *b; int i, m, len; uchar *p; uchar *dp; uchar digestin[32]; uchar digest[32]; DigestState ss; memset(&ss, 0, sizeof(ss)); 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); /* get message */ s->processed = s->unprocessed; s->unprocessed = 0; ensure(s, &s->processed, len); /* 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"); } 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; return b; } static Block* sslbread(Chan *c, long n, ulong offset) { Block *bp; 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); /* get the whole message */ ensure(s, &s->unprocessed, 2); consume(&s->unprocessed, 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->unprocessed, 1); consume(&s->unprocessed, count, 1); pad = count[0]; } ensure(s, &s->unprocessed, len); if(s->encrypalg) b = decryptb(s, len); else b = digestb(s, len); if(pad) qunlock(&s->in); poperror(); return b; } static Chan* buftochan(char *a, long n) { Chan *c; int fd; char buf[32]; if(n >= sizeof buf) error(Egreg); memmove(buf, a, n); /* so we can NUL-terminate */ buf[n] = 0; fd = strtoul(buf, 0, 0); c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ return c; } /* * use SSL record format, add in count and digest or encrypt */ long sslbwrite(Chan *c, Block *b, ulong offset) { Dstate *s; Block *nb; int h, n, m, pad, rv; s = c->aux; if(s == 0 || s->state != Established) error(Ebadusefd); if(waserror()){ qunlock(&s->out); if(b) freeb(b); dighangup(s); nexterror(); } qlock(&s->out); rv = 0; while(b){ m = n = BLEN(b); h = s->diglen + 2; /* padded blocks are shorter than unpadded ones (strange) */ pad = 0; if(m > s->max){ m = s->max; } else if(s->blocklen != 1){ pad = m%s->blocklen; if(pad){ pad = s->blocklen - pad; if(m > s->maxpad){ pad = 0; m = s->maxpad; } } } rv += m; if(m != n){ nb = allocb(m + h + pad); memmove(nb->wp + h, m, nb->rptr); nb->wp += m + h; b->rp += m; } else { /* add header */ nb = padblock(b, h); nb->rp -= h; /* add pad */ if(pad) nb = padblock(nb, -pad); b = 0; } /* SSL style count */ if(pad){ memset(nb->wp, 0, pad); m += pad; nb->wp += pad; } else m |= 0x8000; np->rp[0] = (m>>8); np->rp[1] = m; if(encryptalg) encryptb(s, nb); else digestb(s, nb); (*devtab[s->c->type].bwrite)(s->c, nb, offset); } qunlock(&s->out); poperror(); return rv; } /* * crypt's interface to system, included here to override the * library version */ void handle_exception(int type, char *exception) { if(type == CRITICAL) panic("kernel ssl: %s", exception); else print("kernel ssl: %s\n", exception); } void* crypt_malloc(int size) { void *x; x = smalloc(size); if(x == 0) handle_exception(CRITICAL, "out of memory"); return x; } void crypt_free(void *x) { if(x == 0) handle_exception(CRITICAL, "freeing null pointer"); free(x); } . ## diffname port/devssl.c 1995/1215 ## diff -e /n/fornaxdump/1995/1213/sys/src/brazil/port/devssl.c /n/fornaxdump/1995/1215/sys/src/brazil/port/devssl.c 696,699c s->state = Closed; qunlock(&s->in); . 639,694c if(s->unprocessed){ freeb(s->unprocessed); s->unprocessed = 0; . 628,637c qlock(&s->in); for(b = s->processed; b; b = s->processed){ s->processed = b->next; freeb(b); . 624,626c Block *b; . 618,622c /* hand up a digest connection */ static void dighangup(Dstate *s) . 600a /* get channel associated with an fd */ . 595,598c 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; } . 593c h = s->diglen + 2; . 574,591c long encryptb(Dstate *s, Block *b) { ulong n, h; int j; uchar *p, *ep, *ip; DESstate *ds; . 572c /* hash message id */ p = msgid; n = w->mid++; *p++ = n>>24; *p++ = n>>16; *p++ = n>>8; *p = n; (*s->func)(msgid, 4, nb->rp + 2, &ss); } . 566,570c /* hash secret + message */ (*s->hf)(w->secret, w->slen, 0, &ss); (*s->hf)(nb->rp + h, n, 0, &ss); . 562,564c memset(&ss, 0, sizeof(ss)); h = s->diglen + 2; n = BLEN(b) - h; . 560c w = &s->out; . 555,558c Block *nb; uchar *p; DigestState ss; uchar msgid[4]; ulong n, h; OneWay *w; . 552,553c void digestb(Dstate *s, Block *b) . 392,393c Block* decryptb(Dstate *s, Block *b, int len) . 389a /* 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; . 388a qlock(&s->in); if(s->processed == 0){ . 375,387c s = c->aux; if(s == 0 || s->state != Established) error(Ebadusefd); if(waserror()){ qunlock(&s->in); dighangup(s); nexterror(); . 373c USED(offset); . 368,371c Block *bp, **l; uchar count[2]; int len; int pad; . 365,366c Block* sslbread(Chan *c, long n, ulong offset) . 355,362c } qunlock(&s->out); poperror(); return rv; . 351,353c (*devtab[s->c->type].bwrite)(s->c, nb, offset); . 347,349c if(encryptalg) encryptb(s, nb); else digestb(s, nb); . 342,345c int h, n, m, pad, rv; s = c->aux; if(s == 0 || s->state != Established) error(Ebadusefd); if(waserror()){ qunlock(&s->out); if(b) freeb(b); dighangup(s); nexterror(); } qlock(&s->out); rv = 0; while(b){ m = n = BLEN(b); h = s->diglen + 2; /* padded blocks are shorter than unpadded ones (strange) */ pad = 0; if(m > s->max){ m = s->max; } else if(s->blocklen != 1){ pad = m%s->blocklen; if(pad){ pad = s->blocklen - pad; if(m > s->maxpad){ pad = 0; m = s->maxpad; } } } rv += m; if(m != n){ nb = allocb(m + h + pad); memmove(nb->wp + h, m, b->rp); nb->wp += m + h; b->rp += m; } else { /* add header */ nb = padblock(b, h); nb->rp -= h; /* add pad */ if(pad) nb = padblock(nb, -pad); b = 0; } m += s->diglen; /* SSL style count */ if(pad){ memset(nb->wp, 0, pad); m += pad; nb->wp += pad; } else m |= 0x8000; np->rp[0] = (m>>8); np->rp[1] = m; . 340a Dstate *s; . 338,339c /* * use SSL record format, add in count and digest or encrypt */ long sslbwrite(Chan *c, Block *b, ulong offset) . 162,179d ## diffname port/devssl.c 1995/1217 ## diff -e /n/fornaxdump/1995/1215/sys/src/brazil/port/devssl.c /n/fornaxdump/1995/1217/sys/src/brazil/port/devssl.c 687,701c 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"); . 685c w = &s->in; . 681,683c OneWay *w; uchar digest[128]; . 679a Block *nb; uchar *p; DigestState ss; uchar msgid[4]; . 677,678c static void checkdigestb(Dstate *s, Block *b) . 674c (*s->func)(msgid, 4, nb->rp+offset, &ss); retrn b; . 660c h = s->diglen + offset; . 647,648c static Block* digestb(Dstate *s, Block *b, int offset) . 643a 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; } . 635,642c static Block* decryptb(Dstate *s, Block *b) { ulong n, h; int j; uchar *p, *ep; DESstate *ds; . 633a return b; } . 597,632c 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; . 582,595c static Block* encryptb(Dstate *s, Block *b, int offset) { ulong n; int j; uchar *p, *ep; DESstate *ds; . 580c 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; } } . 572,578c w->secret = smalloc(n); memmove(w->secret, secret, n); w->slen = n; w->mid = 0; . 569,570c static void setsecret(OneWay *w, uchar *secret, int n) . 405,511d 394c nb = digestb(s, nb, ofsetf); . 392c nb = encryptb(s, nb, offset); . 388,389c p[0] = (m>>8); p[1] = m; offset = 2; } . 386c p[0] = (m>>8); p[1] = m; p[2] = pad; offset = 3; } else { . 381a p = np->rp; . 328a uchar *p; . 223a 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; . 214,222c USED(offset); s = c->aux; if(s == 0 || s->state != Established) error(Ebadusefd); if(waserror()){ qunlock(&s->in); dighangup(s); nexterror(); . 209,212c Block *bp, **l; uchar count[2]; int len; int pad; . 206,207c Block* sslbread(Chan *c, long n, ulong offset) . 88a 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*); . 52c int maxpad; /* maximum padded data per msg */ . ## diffname port/devssl.c 1995/1218 ## diff -e /n/fornaxdump/1995/1217/sys/src/brazil/port/devssl.c /n/fornaxdump/1995/1218/sys/src/brazil/port/devssl.c 672c if(memcmp(digest, b->rp, s->diglen) != 0) . 670c (*s->hf)(msgid, 4, digest, &ss); . 661c (*s->hf)(b->rp + h, n, 0, &ss); . 649c int n, h; . 645d 639c return b; . 637c (*s->hf)(msgid, 4, b->rp + offset, &ss); . 628c (*s->hf)(b->rp + h, n, 0, &ss); . 613d 603,604c for(p = b->rp + s->diglen; p < ep;){ memmove(tmp, p, 8); block_cipher(ds->expanded, p, 1); tp = tmp; ip = ds->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } . 594c case DESECB: . 591a uchar tmp[8]; . 588,590c uchar *p, *ep, *tp, *ip, *eip; . 578,579c for(p = b->rp + offset; p < ep; p += 8){ p2 = p; ip = ds->ivec; for(eip = ip+8; ip < eip; ) *p2++ ^= *ip++; block_cipher(ds->expanded, p, 0); memmove(ds->ivec, p, 8); } . 569c case DESECB: . 563,565c uchar *p, *ep, *p2, *ip, *eip; . 553a if(n < 16) error("secret too small"); . 549c case DESECB: if(n < 8) error("secret too small"); . 541c setsecret(Dstate *s, OneWay *w, uchar *secret, int n) . 472c nb = digestb(s, nb, offset); . 469c if(s->encryptalg) . 463,464c p = nb->rp; p[0] = (m>>8) | 0x80; . 457c p = nb->rp; . 455a b->wp += pad; . 454a nb = padblock(nb, -pad); . 453d 444,447d 441c /* add header space */ . 437c memmove(nb->wp + h, b->rp, m); . 429a } else { pad = s->blocklen - pad; h++; . 426d 419c /* trim to maximum block size */ . 379,381c } . 374c memmove(b->wp, p, m); . 363,365c p = a; for(e = p + n; p < e; p += m){ m = e - p; . 352c setsecret(s, &s->out, a, n); . 347c setsecret(s, &s->in, a, n); . 333,334c } else if(strcmp(buf, "desecb") == 0){ s->encryptalg = DESECB; . 301,302c int m; char *p, *e, buf[32]; . 297c sslwrite(Chan *c, void *a, long n, ulong offset) . 281d 275c if(b->wp - b->rp < pad) . 272a b->rp += s->diglen; } . 271c else { if(BLEN(b) < s->diglen) error("baddigest"); . 269c if(s->encryptalg) . 254d 250c ensure(s, &s->processed, len+1); . 246a ensure(s, &s->processed, len); . 242c s->unprocessed = 0; . 238c b = s->processed; if(b == 0){ . 222,223c int i, len, pad; . 220c Dstate *s; Block *b; . 91c static void setsecret(Dstate*, OneWay*, uchar*, int); . 50a /* for SSL format */ . 46c ushort blocklen; /* blocking length */ . 37a DESECB= 2, . 36a Noencryption= 0, . ## diffname port/devssl.c 1995/1221 ## diff -e /n/fornaxdump/1995/1218/sys/src/brazil/port/devssl.c /n/fornaxdump/1995/1221/sys/src/brazil/port/devssl.c 76c "ssl", {Qclone, 0}, 0, 0600, . ## diffname port/devssl.c 1995/1227 ## diff -e /n/fornaxdump/1995/1221/sys/src/brazil/port/devssl.c /n/fornaxdump/1995/1227/sys/src/brazil/port/devssl.c 459c nb->wp += pad; . ## diffname port/devssl.c 1996/0103 ## diff -e /n/fornaxdump/1995/1227/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/0103/sys/src/brazil/port/devssl.c 76c "ssl", {Qclone, 0}, 0, 0666, . ## diffname port/devssl.c 1996/0202 ## diff -e /n/fornaxdump/1996/0103/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/0202/sys/src/brazil/port/devssl.c 326c error(Ebadarg); . ## diffname port/devssl.c 1996/0223 ## diff -e /n/fornaxdump/1996/0202/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devssl.c 485a } long sslwrite(Chan *c, void *a, long n, ulong offset) { Dstate *s; Block *b; int m; char *p, *e, buf[32]; switch(c->qid.path & ~CHDIR){ case Qclone: break; default: error(Ebadusefd); } s = c->aux; if(s == 0) error(Ebadusefd); switch(s->state){ case Algwait: /* get algorithm */ if(n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; s->blocklen = 1; s->diglen = 0; if(strcmp(buf, "md5") == 0){ s->hf = md5; s->diglen = MD5dlen; } else if(strcmp(buf, "sha") == 0){ s->hf = sha; s->diglen = SHAdlen; } else if(strcmp(buf, "descbc") == 0){ s->encryptalg = DESCBC; s->blocklen = 8; } else if(strcmp(buf, "desecb") == 0){ s->encryptalg = DESECB; s->blocklen = 8; } else error(Ebadarg); s->state = Fdwait; break; case Fdwait: /* get communications channel */ s->c = buftochan(a, n); s->state = Secretinwait; break; case Secretinwait: /* get secret for incoming messages */ setsecret(s, &s->in, a, n); s->state = Secretoutwait; break; case Secretoutwait: /* get secret for outgoing messages */ setsecret(s, &s->out, a, n); if(s->blocklen != 1){ s->max = (1<<15) - s->diglen; s->max -= s->max % s->blocklen; s->maxpad = (1<<14) - s->diglen; s->maxpad -= s->maxpad % s->blocklen; } else s->maxpad = s->max = (1<<15) - s->diglen; s->state = Established; break; case Established: p = a; for(e = p + n; p < e; p += m){ m = e - p; if(m > s->max) m = s->max; b = allocb(m); if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, p, m); poperror(); b->wp += m; sslbwrite(c, b, offset); } break; default: error(Ebadusefd); } return n; . 391a n = BLEN(b); memmove(a, b->rp, n); freeb(b); poperror(); . 322,389c if(waserror()){ freeb(b); nexterror(); . 318,320c b = sslbread(c, n, offset); . 312,315c case Qdir: return devdirread(c, a, n, digesttab, Ndigesttab, devgen); . 308,309d 306d 304c sslread(Chan *c, void *a, long n, ulong offset) . 194,219d 13d ## diffname port/devssl.c 1996/0531 ## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/0531/sys/src/brazil/port/devssl.c 761d 748c x = malloc(size); . 740c print("crypt library (devssl): %s\n", exception); . 738c panic("crypt library (devssl): %s", exception); . 727c qunlock(&s->in.q); . 717c qlock(&s->in.q); . 562c w->state = malloc(sizeof(DESstate)); . 556c w->state = malloc(sizeof(DESstate)); . 547c w->secret = malloc(n); . 477c sslbwrite(c, b.b, offset); . 475c b.b->wp += m; . 473c memmove(b.b->wp, p, m); . 470c freeb(b.b); . 468c b.b = allocb(m); . 399c volatile struct { Block *b; } b; . 389c qunlock(&s.s->out.q); . 386c (*devtab[s.s->c->type].bwrite)(s.s->c, nb, offset); . 384c nb = digestb(s.s, nb, offset); . 381,382c if(s.s->encryptalg) nb = encryptb(s.s, nb, offset); . 360c m += s.s->diglen; . 356,358c nb = padblock(bb.b, h); bb.b = 0; . 353c bb.b->rp += m; . 351c memmove(nb->wp + h, bb.b->rp, m); . 342c pad = s.s->blocklen - pad; . 340c m = s.s->maxpad; . 338c if(m > s.s->maxpad){ . 333,336c if(m > s.s->max){ m = s.s->max; } else if(s.s->blocklen != 1){ pad = m%s.s->blocklen; . 327,329c while(bb.b){ m = n = BLEN(bb.b); h = s.s->diglen + 2; . 324c qlock(&s.s->out.q); . 318,321c qunlock(&s.s->out.q); if(bb.b) freeb(bb.b); dighangup(s.s); . 313,314c bb.b = b; s.s = c->aux; if(s.s == 0 || s.s->state != Established) . 308c volatile struct { Dstate *s; } s; volatile struct { Block *b; } bb; . 293,295c n = BLEN(b.b); memmove(a, b.b->rp, n); freeb(b.b); . 289c freeb(b.b); . 286c b.b = sslbread(c, n, offset); . 279c volatile struct { Block *b; } b; . 270c qunlock(&s.s->in.q); . 268c s.s->processed = b->next; . 266c s.s->processed->rp += n; . 264c memmove(b->wp, s.s->processed->rp, n); . 259c s.s->processed = b; . 251,252c checkdigestb(s.s, b); b->rp += s.s->diglen; . 249c if(BLEN(b) < s.s->diglen) . 246,247c if(s.s->encryptalg) b = decryptb(s.s, b); . 240,242c s.s->unprocessed = allocb(i); memmove(s.s->unprocessed->wp, b->rp+len, i); s.s->unprocessed->wp += i; . 234c b = s.s->processed = pullupblock(s.s->processed, len); . 228,229c ensure(s.s, &s.s->processed, len+1); consume(&s.s->processed, count, 1); . 224c ensure(s.s, &s.s->processed, len); . 218,221c s.s->processed = s.s->unprocessed; s.s->unprocessed = 0; ensure(s.s, &s.s->processed, 2); consume(&s.s->processed, count, 2); . 214c b = s.s->processed; . 212c qlock(&s.s->in.q); . 208,209c qunlock(&s.s->in.q); dighangup(s.s); . 203,204c s.s = c->aux; if(s.s == 0 || s.s->state != Established) . 196c volatile struct { Dstate *s; } s; . 184c cclose(s->c); . 171c USED(c); USED(dp); . 157c USED(c); USED(name); USED(omode); USED(perm); . 145c s = malloc(sizeof(Dstate)); . 115c sslattach(void *spec) . 111a randq.ep = randq.buf + sizeof(randq.buf); randq.rp = randq.wp = randq.buf; . 105,106d 101d 72c Qclone . 67c Maxdmsg= 1<<16 . 38c DESECB= 2 . 19,22c void *state; /* encryption state */ int slen; /* hash data length */ uchar *secret; /* secret */ ulong mid; /* message id */ . 17c QLock q; . 5,11c #include . 3a #include "u.h" #include "../port/lib.h" #include "../port/error.h" #include "mem.h" #include "dat.h" #include "fns.h" . 2c * devssl - secure sockets layer emulation . ## diffname port/devssl.c 1996/0601 ## diff -e /n/fornaxdump/1996/0531/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/0601/sys/src/brazil/port/devssl.c 187c close(s->c); . ## diffname port/devssl.c 1996/1029 ## diff -e /n/fornaxdump/1996/0601/sys/src/brazil/port/devssl.c /n/fornaxdump/1996/1029/sys/src/brazil/port/devssl.c 764a static Dstate* dsclone(Chan *ch) { Dstate **pp, **ep, **np; int newmax; if(waserror()) { unlock(&dslock); nexterror(); } lock(&dslock); ep = &dstate[maxdstate]; for(pp = dstate; pp < ep; pp++) { if(*pp == 0) { dsnew(ch, pp); break; } } if(pp >= ep) { if(maxdstate >= Maxdstate) { unlock(&dslock); poperror(); return 0; } newmax = 2 * maxdstate; if(newmax > Maxdstate) newmax = Maxdstate; np = smalloc(sizeof(Dstate*) * newmax); if(np == 0) error(Enomem); memmove(np, dstate, sizeof(Dstate*) * maxdstate); dstate = np; pp = &dstate[maxdstate]; memset(pp, 0, sizeof(Dstate*)*(newmax - maxdstate)); maxdstate = newmax; dsnew(ch, pp); } unlock(&dslock); poperror(); return *pp; } static void dsnew(Chan *ch, Dstate **pp) { Dstate *s; int t; *pp = s = malloc(sizeof(*s)); if(!s) error(Enomem); if(pp - dstate >= dshiwat) dshiwat++; memset(s, 0, sizeof(*s)); s->state = Sincomplete; s->ref = 1; strncpy(s->user, up->user, sizeof(s->user)); s->perm = 0660; t = TYPE(ch->qid); if(t == Qclonus) t = Qctl; ch->qid.path = QID(pp - dstate, t); ch->qid.vers = 0; } . 746a extern void rbcheck(char*); . 744c print("crypt library: %s: %r\n", exception); . 742c panic("crypt library: %s: %r", exception); . 730c s->state = Sincomplete; . 717c sslhangup(Dstate *s) . 705,710c if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); . 703d 699c buftochan(char *p) . 693c if(memcmp(digest, inb->rp, s->diglen) != 0) . 683a /* hash message */ h = s->diglen; for(b = inb; b; b = b->next){ n = BLEN(b) - h; if(n < 0) panic("checkdigestb"); (*s->hf)(b->rp + h, n, 0, &ss); h = 0; } . 682d 680c /* hash secret */ . 677,678d 672a Block *b; . 665c checkdigestb(Dstate *s, Block *inb) . 630c return inb; . 628c l = &b->next; /* decrypt */ switch(s->encryptalg){ #ifdef NOSPOOKS case DESECB: ds = s->in.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->in.state; ep = b->rp + BLEN(b); for(p = b->rp + s->diglen; p < ep;){ memmove(tmp, p, 8); block_cipher(ds->expanded, p, 1); tp = tmp; ip = ds->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } break; #endif NOSPOOKS case RC4: rc4(s->in.state, b->rp, BLEN(b)); break; } . 608,625c l = &inb; for(b = inb; b; b = b->next){ /* make sure we have a multiple of s->blocklen */ if(s->blocklen > 1){ i = BLEN(b); if(i % s->blocklen){ *l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen)); if(b == 0) error("ssl encrypted message too short"); . 606a #endif NOSPOOKS int i; . 603a Block *b, **l; #ifdef NOSPOOKS . 602c decryptb(Dstate *s, Block *inb) . 596a #endif NOSPOOKS case RC4: rc4(s->out.state, b->rp + offset, BLEN(b) - offset); break; . 578a #ifdef NOSPOOKS . 576a #endif NOSPOOKS . 574a #ifdef NOSPOOKS . 556,571d 548,554d 533,545c out: qunlock(&s.s->in.ctlq); qunlock(&s.s->out.q); poperror(); return n; . 523,531c 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; } else s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; } else error(Ebadarg); . 517,521c 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(strcmp(p, "md5") == 0){ s.s->hf = md5; s.s->diglen = MD5dlen; s.s->state = Sdigesting; } else if(strcmp(p, "sha") == 0){ s.s->hf = sha; s.s->diglen = SHAdlen; s.s->state = Sdigesting; #ifdef NOSPOOKS } else if(strcmp(p, "descbc") == 0){ if(s.s->in.secret == 0 || s.s->out.secret == 0) error(Ebadarg); s.s->encryptalg = DESCBC; s.s->blocklen = 8; initDESkey(&s.s->in); initDESkey(&s.s->out); s.s->state = Sencrypting; } else if(strcmp(p, "desecb") == 0){ if(s.s->in.secret == 0 || s.s->out.secret == 0) error(Ebadarg); s.s->encryptalg = DESECB; s.s->blocklen = 8; initDESkey(&s.s->in); initDESkey(&s.s->out); s.s->state = Sencrypting; #endif NOSPOOKS } else if(strcmp(p, "rc4") == 0){ if(s.s->in.secret == 0 || s.s->out.secret == 0) error(Ebadarg); s.s->encryptalg = RC4; s.s->blocklen = 1; initRC4key(&s.s->in); initRC4key(&s.s->out); s.s->state = Sencrypting; } else error(Ebadarg); . 507,514c if(s.s->c == 0) error("must set fd before algorithm"); if(strcmp(p, "clear") == 0){ s.s->state = Sclear; s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; goto out; . 500,505c /* 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; } else if(strcmp(buf, "alg") == 0 && p != 0){ s.s->blocklen = 1; s.s->diglen = 0; . 491,498c if(strcmp(buf, "fd") == 0){ s.s->c = buftochan(p); . 488,489c if(n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; p = strchr(buf, '\n'); if(p) *p = 0; p = strchr(buf, ' '); if(p) *p++ = 0; . 485c panic("sslwrite"); case Qsecretin: setsecret(&s.s->in, a, n); goto out; return n; case Qsecretout: setsecret(&s.s->out, a, n); goto out; return n; case Qctl: break; . 482,483c p += m; } while(p < e); return n; } /* mutex with operations using what we're about to change */ if(waserror()){ qunlock(&s.s->in.ctlq); qunlock(&s.s->out.q); nexterror(); } qlock(&s.s->in.ctlq); qlock(&s.s->out.q); switch(t){ . 469,470c if(m > s.s->max) m = s.s->max; . 467c e = p + n; do { . 418,465d 414,416c t = TYPE(c->qid); if(t == Qdata){ if(s.s->state == Sincomplete) error(Ebadusefd); . 407,412c s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslwrite"); . 404c int m, t; . 402c volatile struct { Dstate *s; } s; . 398a static void setsecret(OneWay *w, uchar *secret, int n) { if(w->secret) free(w->secret); w->secret = malloc(n); memmove(w->secret, secret, n); w->slen = n; w->mid = 0; } #ifdef NOSPOOKS static void initDESkey(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } w->state = malloc(sizeof(DESstate)); if(w->slen >= 16) setupDESstate(w->state, w->secret, w->secret+8); else if(w->slen >= 8) setupDESstate(w->state, w->secret, 0); else error("secret too short"); } #endif NOSPOOKS static void initRC4key(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } #ifndef NOSPOOKS if(w->slen > 5) w->slen = 5; #endif NOSPOOKS w->state = malloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } . 390,391c m = BLEN(nb); (*devtab[s.s->c->type].bwrite)(s.s->c, nb, s.s->c->offset); s.s->c->offset += m; . 388a break; } . 387c break; case Sdigesting: . 385c switch(s.s->state){ case Sencrypting: . 369c randfill(nb->wp, pad); . 326c sslhangup(s.s); . 320a } . 318,319c s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslbwrite"); if(s.s->state == Sincomplete){ freeb(b); . 305a * this algorithm doesn't have to be great since we're just * trying to obscure the block fill */ static void randfill(uchar *buf, int len) { int j; ushort rn; j = 0; rn = 0; while(len-- > 0){ if(j == 0){ rn = nrand(1<<16); *buf++ = rn; } else *buf++ = rn>>8; j ^= 1; } } /* . 299a freeblist(b.b); . 296,298c n = 0; va = a; for(nb = b.b; nb; nb = nb->next){ i = BLEN(nb); memmove(va+n, nb->rp, i); n += i; } . 292c freeblist(b.b); . 289,290d 284,286c if(c->qid.path & CHDIR) return devdirread(c, a, n, 0, 0, sslgen); switch(TYPE(c->qid)) { default: error(Ebadusefd); case Qctl: sprint(buf, "%d", CONV(c->qid)); return readstr(offset, a, n, buf); case Qdata: b.b = sslbread(c, n, offset); break; . 282a Block *nb; uchar *va; int i; char buf[128]; . 265,271c /* return at most what was asked for */ b = qremove(&s.s->processed, n, 0); . 259,262c if(pad) s.s->processed = qremove(&s.s->processed, len - pad, 1); . 256a qunlock(&s.s->in.ctlq); poperror(); . 248,255c qlock(&s.s->in.ctlq); switch(s.s->state){ case Sencrypting: s.s->processed = decryptb(s.s, s.s->processed); break; case Sdigesting: s.s->processed = pullupblock(s.s->processed, s.s->diglen); if(s.s->processed == 0) error("ssl message too short"); checkdigestb(s.s, s.s->processed); s.s->processed->rp += s.s->diglen; break; . 239,246c if(waserror()){ qunlock(&s.s->in.ctlq); nexterror(); . 236,237c /* put extra on unprocessed queue */ s.s->processed = qremove(&s.s->unprocessed, len, 0); . 233a if(pad > len){ print("pad %d buf len %d\n", pad, len); error("bad pad in ssl message"); } . 231,232c ensure(s.s, &s.s->unprocessed, len+1); consume(&s.s->unprocessed, count, 1); . 227c ensure(s.s, &s.s->unprocessed, len); . 221,224c ensure(s.s, &s.s->unprocessed, 2); consume(&s.s->unprocessed, count, 2); . 217,219c if(s.s->processed == 0){ . 212c sslhangup(s.s); . 206,207c s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslbread"); if(s.s->state == Sincomplete) . 202c int len, pad; . 195a static int blen(Block *bp) { int i = 0; for(; bp; bp = bp->next) i += BLEN(bp); return i; } /* * make sure we have at least 'n' bytes in list 'l' */ static void ensure(Dstate *s, Block **l, int n) { int sofar, i; Block *b, *bl; sofar = 0; for(b = *l; b; b = b->next){ sofar += BLEN(b); if(sofar >= n) return; l = &b->next; } while(sofar < n){ bl = (*devtab[s->c->type].bread)(s->c, Maxdmsg, 0); if(bl == 0) error(Ehungup); *l = bl; i = 0; for(b = bl; b; b = b->next){ i += BLEN(b); l = &b->next; } if(i == 0) error(Ehungup); sofar += i; } } /* * copy 'n' bytes from 'l' into 'p' and free * the bytes in 'l' */ static void consume(Block **l, uchar *p, int n) { Block *b; int i; for(; *l && n > 0; n -= i){ b = *l; i = BLEN(b); if(i > n) i = n; memmove(p, b->rp, i); b->rp += i; p += i; if(BLEN(b) < 0) panic("consume"); if(BLEN(b)) break; *l = b->next; freeb(b); } } /* * free a list of blocks */ void freeblist(Block *b) { Block *next; for(; b != 0; b = next){ next = b->next; freeb(b); } } /* * remove at most n bytes from the queue, if discard is set * dump the remainder */ static Block* qremove(Block **l, int n, int discard) { Block *nb, *b, *first; int i; first = *l; for(b = first; b; b = b->next){ i = BLEN(b); if(i == n){ if(discard){ freeblist(b->next); *l = 0; } else *l = b->next; b->next = 0; break; } else if(i > n){ i -= n; if(discard){ freeblist(b->next); b->wp -= i; *l = 0; } else { nb = allocb(i); memmove(nb->wp, b->rp+n, i); nb->wp += i; b->wp -= i; nb->next = b->next; *l = nb; } b->next = 0; if(BLEN(b) < 0) panic("qremove"); return first; } else n -= i; if(BLEN(b) < 0) panic("qremove"); } *l = 0; return first; } . 192a . 191a if(s->in.state) free(s->in.state); if(s->out.state) free(s->out.state); . 183,185c switch(TYPE(c->qid)) { case Qctl: case Qdata: case Qsecretin: case Qsecretout: if((c->flag & COPEN) == 0) break; s = dstate[CONV(c->qid)]; if(s == 0) break; lock(&dslock); if(--s->ref > 0) { unlock(&dslock); break; } dstate[CONV(c->qid)] = 0; unlock(&dslock); sslhangup(s); . 173,175c Dir d; Dstate *s; convM2D(dp, &d); s = dstate[CONV(c->qid)]; if(s == 0) error(Ebadusefd); if(strcmp(s->user, up->user) != 0) error(Eperm); memmove(s->user, d.uid, NAMELEN); s->perm = d.mode; . 150c switch(TYPE(c->qid)) { default: panic("sslopen"); case Qtopdir: case Qconvdir: if(omode != OREAD) error(Eperm); break; case Qclonus: s = dsclone(c); if(s == 0) error(Enodev); break; case Qctl: case Qdata: case Qsecretin: case Qsecretout: if(waserror()) { unlock(&dslock); nexterror(); } lock(&dslock); pp = &dstate[CONV(c->qid)]; s = *pp; if(s == 0) dsnew(c, pp); else { if((perm & (s->perm>>6)) != perm && (strcmp(up->user, s->user) != 0 || (perm & s->perm) != perm)) error(Eperm); s->ref++; } unlock(&dslock); poperror(); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; . 148a case OWRITE: perm = 2; break; case ORDWR: perm = 6; break; . 142,147c perm = 0; omode &= 3; switch(omode) { case OREAD: perm = 4; . 140c Dstate *s, **pp; int perm; . 134c devstat(c, db, 0, 0, sslgen); . 128c return devwalk(c, name, 0, 0, sslgen); . 116c Chan *c; c = devattach('D', spec); c->qid.path = QID(0, Qtopdir)|CHDIR; c->qid.vers = 0; return c; . 109,110c if((dstate = malloc(sizeof(Dstate*) * maxdstate)) == 0) panic("sslinit"); . 105a int sslgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp) { Qid q; Dstate *ds; char name[16], *p, *nm; USED(nd); USED(d); q.vers = 0; switch(TYPE(c->qid)) { case Qtopdir: if(s < dshiwat) { sprint(name, "%d", s); q.path = QID(s, Qconvdir)|CHDIR; ds = dstate[s]; if(ds != 0) nm = ds->user; else nm = eve; devdir(c, q, name, 0, nm, CHDIR|0555, dp); return 1; } if(s > dshiwat) return -1; q.path = QID(0, Qclonus); devdir(c, q, "clone", 0, eve, 0555, dp); return 1; case Qconvdir: ds = dstate[CONV(c->qid)]; if(ds != 0) nm = ds->user; else nm = eve; switch(s) { default: return -1; case 0: q.path = QID(CONV(c->qid), Qctl); p = "ctl"; break; case 1: q.path = QID(CONV(c->qid), Qdata); p = "data"; break; case 2: q.path = QID(CONV(c->qid), Qsecretin); p = "secretin"; break; case 3: q.path = QID(CONV(c->qid), Qsecretout); p = "secretout"; break; } devdir(c, q, p, 0, nm, 0660, dp); return 1; } return -1; } . 98,99c static Chan* buftochan(char*); static void sslhangup(Dstate*); static Dstate* dsclone(Chan *c); static void dsnew(Chan *c, Dstate **); . 93c static void setsecret(OneWay*, uchar*, int); . 89,90d 79,87c #define TYPE(x) ((x).path & 0xf) #define CONV(x) (((x).path >> 4)&(Maxdstate-1)) #define QID(c, y) (((c)<<4) | (y)) . 74,77d 71,72c Qtopdir = 1, /* top level directory */ Qclonus, Qconvdir, /* directory for a conversation */ Qdata, Qctl, Qsecretin, Qsecretout . 67c Maxdmsg= 1<<16, Maxdstate= 64 . 64a Lock dslock; int dshiwat; int maxdstate = 20; Dstate** dstate; . 62a /* protections */ char user[NAMELEN]; int perm; . 45a int ref; /* serialized by dslock for atomic destroy */ . 38c DESECB= 2, #endif NOSPOOKS RC4= 3 . 36a #ifdef NOSPOOKS . 28,33c Sincomplete= 0, Sclear, Sencrypting, Sdigesting, . 17a QLock ctlq; . 12a #define NOSPOOKS 1 . ## diffname port/devssl.c 1997/0327 ## diff -e /n/fornaxdump/1996/1029/sys/src/brazil/port/devssl.c /n/emeliedump/1997/0327/sys/src/brazil/port/devssl.c 1092c s->hf(msgid, 4, digest, &ss); . 1081c s->hf(b->rp + h, n, 0, &ss); . 1073c s->hf(w->secret, w->slen, 0, &ss); . 1052c s->hf(msgid, 4, b->rp + offset, &ss); . 1042,1043c s->hf(w->secret, w->slen, 0, &ss); s->hf(b->rp + h, n, 0, &ss); . 932a Dev ssldevtab = { devreset, sslinit, sslattach, devclone, sslwalk, sslstat, sslopen, devcreate, sslclose, sslread, sslbread, sslwrite, sslbwrite, devremove, sslwstat, }; . 779c static long . 721c devtab[s.s->c->type]->bwrite(s.s->c, nb, s.s->c->offset); . 630c static long . 563c static long . 484c static Block* . 422,435d 380c bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0); . 352,361d 338c cclose(s->c); . 311c static void . 276,293c static void . 212c static Chan* . 206c static void . 194,200c static int . 183c static Chan* . 176c static void . 111,116c static int . ## diffname port/devssl.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devssl.c /n/emeliedump/1997/0408/sys/src/brazil/port/devssl.c 881a 'D', "ssl", . ## diffname port/devssl.c 1997/0618 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devssl.c /n/emeliedump/1997/0618/sys/src/brazil/port/devssl.c 1200d 1131c return; . 1119,1124c return smalloc(size); . 1060c (*s->hf)(msgid, 4, digest, &ss); . 1055c n = w->mid; . 1049c (*s->hf)(b->rp + h, n, 0, &ss); . 1041c (*s->hf)(w->secret, w->slen, 0, &ss); . 1020c (*s->hf)(msgid, 4, b->rp + offset, &ss); . 1015c n = w->mid; . 1010,1011c (*s->hf)(w->secret, w->slen, 0, &ss); (*s->hf)(b->rp + h, n, 0, &ss); . 985d 964d 946d 942d 930d 911d 908d 905d 839,861c if(np == 0) break; p = np; } if(s.s->hf == 0 && s.s->encryptalg == Noencryption) . 827,837c if(s.s->in.secret == 0 || s.s->out.secret == 0) error("algorithm but no secret"); s.s->hf = 0; s.s->encryptalg = Noencryption; s.s->blocklen = 1; for(;;){ np = strchr(p, ' '); if(np) *np++ = 0; if(parsehashalg(p, s.s) < 0) if(parseencryptalg(p, s.s) < 0) . 809a s.s->in.mid = 0; s.s->out.mid = 0; . 733c char *p, *np, *e, buf[32]; . 726a struct Hashalg { char *name; int diglen; DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); } hashtab[] = { { "md4", MD4dlen, md4, }, { "md5", MD5dlen, md5, }, { "sha", SHAdlen, sha, }, { 0 } }; static int parsehashalg(char *p, Dstate *s) { struct Hashalg *ha; for(ha = hashtab; ha->name; ha++){ if(strcmp(p, ha->name) == 0){ s->hf = ha->hf; s->diglen = ha->diglen; s->state &= ~Sclear; s->state |= Sdigesting; return 0; } } return -1; } struct Encalg { char *name; int blocklen; int alg; void (*keyinit)(OneWay*); } encrypttab[] = { { "descbc", 8, DESCBC, initDESkey, }, { "desebc", 8, DESECB, initDESkey, }, { "rc4", 1, RC4, initRC4key, }, { 0 } }; static int parseencryptalg(char *p, Dstate *s) { struct Encalg *ea; for(ea = encrypttab; ea->name; ea++){ if(strcmp(p, ea->name) == 0){ s->encryptalg = ea->alg; s->blocklen = ea->blocklen; (*ea->keyinit)(&s->in); (*ea->keyinit)(&s->out); s->state &= ~Sclear; s->state |= Sencrypting; return 0; } } return -1; } . 723c w->state = smalloc(sizeof(RC4state)); . 721d 718d 708d 700c w->state = smalloc(sizeof(DESstate)); . 691d 687,688d 684c w->secret = smalloc(n); . 667a s.s->out.mid++; . 665a case Sdigenc: nb = digestb(s.s, nb, offset); nb = encryptb(s.s, nb, offset); break; . 560,572c while(len-- > 0) *buf++ = nrand(256); . 493a s.s->in.mid++; . 492a case Sdigenc: s.s->processed = decryptb(s.s, s.s->processed); s.s->processed = pullupblock(s.s->processed, s.s->diglen); if(s.s->processed == 0) error("ssl message too short"); checkdigestb(s.s, s.s->processed); s.s->processed->rp += s.s->diglen; break; . 174c if((dstate = smalloc(sizeof(Dstate*) * maxdstate)) == 0) . 40d 37d 31,33c Sclear= 1, Sencrypting= 2, Sdigesting= 4, Sdigenc= Sencrypting|Sdigesting, . 13,14d 11c #include . 4,9c #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" . ## diffname port/devssl.c 1997/0619 ## diff -e /n/emeliedump/1997/0618/sys/src/brazil/port/devssl.c /n/emeliedump/1997/0619/sys/src/brazil/port/devssl.c 715,717d ## diffname port/devssl.c 1998/0319 ## diff -e /n/emeliedump/1997/0619/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0319/sys/src/brazil/port/devssl.c 788a ulong offset = off; . 783c sslwrite(Chan *c, void *a, long n, vlong off) . 524a ulong offset = off; . 518c sslread(Chan *c, void *a, long n, vlong off) . ## diffname port/devssl.c 1998/0327 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0327/sys/src/brazil/port/devssl.c 436,437d 430c sslbread(Chan *c, long n, ulong) . ## diffname port/devssl.c 1998/0417 ## diff -e /n/emeliedump/1998/0327/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0417/sys/src/brazil/port/devssl.c 922a } static void sslinit(void) { struct Encalg *e; struct Hashalg *h; int n; char *cp; if((dstate = smalloc(sizeof(Dstate*) * maxdstate)) == 0) panic("sslinit"); n = 1; for(e = encrypttab; e->name != nil; e++) n += strlen(e->name) + 1; cp = encalgs = smalloc(n); for(e = encrypttab;;){ strcpy(cp, e->name); cp += strlen(e->name); e++; if(e->name == nil) break; *cp++ = ' '; } *cp = 0; n = 1; for(h = hashtab; h->name != nil; h++) n += strlen(h->name) + 1; cp = hashalgs = smalloc(n); for(h = hashtab;;){ strcpy(cp, h->name); cp += strlen(h->name); h++; if(h->name == nil) break; *cp++ = ' '; } *cp = 0; . 536a case Qencalgs: return readstr(offset, a, n, encalgs); break; case Qhashalgs: return readstr(offset, a, n, hashalgs); break; . 254a case Qencalgs: case Qhashalgs: if(omode != OREAD) error(Eperm); break; . 221a case Qprotodir: . 168,174d 160a case 4: q.path = QID(CONV(c->qid), Qencalgs); p = "encalgs"; break; case 5: q.path = QID(CONV(c->qid), Qhashalgs); p = "hashalgs"; break; . 119a if(s > 0) return -1; q.path = QID(0, Qprotodir)|CHDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); return 1; case Qprotodir: . 89c Qsecretout, Qencalgs, Qhashalgs, . 83a Qprotodir, . 74a char *encalgs; char *hashalgs; . ## diffname port/devssl.c 1998/0501 ## diff -e /n/emeliedump/1998/0417/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0501/sys/src/brazil/port/devssl.c 1075c for(p = b->rp; p < ep;){ . 1069c for(p = b->rp; p < ep; p += 8) . 633c pad = (m + s.s->diglen)%s.s->blocklen; . 512a len -= s.s->diglen; . ## diffname port/devssl.c 1998/0512 ## diff -e /n/emeliedump/1998/0501/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0512/sys/src/brazil/port/devssl.c 839c . 830c . ## diffname port/devssl.c 1998/0806 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0806/sys/src/brazil/port/devssl.c 790c Encalg *ea; . 785a #else Encalg encrypttab[] = { { "descbc", 8, DESCBC, initDESkey_40, }, { "desebc", 8, DESECB, initDESkey_40, }, { "descbc_40", 8, DESCBC, initDESkey_40, }, { "desebc_40", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, { "rc4_40", 1, RC4, initRC4key_40, }, { 0 } }; #endif NOSPOOKS . 783a { "rc4_40", 1, RC4, initRC4key_40, }, . 782a { "descbc_40", 8, DESCBC, initDESkey_40, }, { "desebc_40", 8, DESECB, initDESkey_40, }, . 779c }; #ifdef NOSPOOKS Encalg encrypttab[] = . 772a typedef struct Encalg Encalg; . 759c Hashalg *ha; . 748c }; Hashalg hashtab[] = . 742a /* * 40 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 40 bits of the key. */ static void initRC4key_40(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } if(w->slen > 5) w->slen = 5; w->state = malloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } typedef struct Hashalg Hashalg; . 731a initDESkey_40(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } if(w->slen >= 16) { w->secret[8] &= 0x0f; w->secret[10] &= 0x0f; w->secret[12] &= 0x0f; w->secret[14] &= 0x0f; } if(w->slen >= 8) { w->secret[0] &= 0x0f; w->secret[2] &= 0x0f; w->secret[4] &= 0x0f; w->secret[6] &= 0x0f; } w->state = malloc(sizeof(DESstate)); if(w->slen >= 16) setupDESstate(w->state, w->secret, w->secret+8); else if(w->slen >= 8) setupDESstate(w->state, w->secret, 0); else error("secret too short"); } static void . 730a /* * 40 bit DES is the same as 56 bit DES. However, * 16 bits of the key are masked to zero. */ . 12a #define NOSPOOKS 1 . ## diffname port/devssl.c 1998/0807 ## diff -e /n/emeliedump/1998/0806/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0807/sys/src/brazil/port/devssl.c 857c { "desecb_40", 8, DESECB, initDESkey_40, }, . 855c { "desecb", 8, DESECB, initDESkey_40, }, . 846c { "desecb_40", 8, DESECB, initDESkey_40, }, . 844c { "desecb", 8, DESECB, initDESkey, }, . 752,755c w->secret[0] &= 0x0f; w->secret[2] &= 0x0f; w->secret[4] &= 0x0f; w->secret[6] &= 0x0f; . 745,750d ## diffname port/devssl.c 1998/0825 ## diff -e /n/emeliedump/1998/0807/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0825/sys/src/brazil/port/devssl.c 553c sprint(buf, "%lud", CONV(c->qid)); . ## diffname port/devssl.c 1998/0910 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/devssl.c /n/emeliedump/1998/0910/sys/src/brazil/port/devssl.c 848,852c { "des_40_cbc", 8, DESCBC, initDESkey_40, }, { "des_40_ecb", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ . 837,841c { "descbc", 8, DESCBC, initDESkey, }, /* DEPRECATED -- use des_56_cbc */ { "desecb", 8, DESECB, initDESkey, }, /* DEPRECATED -- use des_56_ecb */ { "des_56_cbc", 8, DESCBC, initDESkey, }, { "des_56_ecb", 8, DESECB, initDESkey, }, { "des_40_cbc", 8, DESCBC, initDESkey_40, }, { "des_40_ecb", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ { "rc4_256", 1, RC4, initRC4key, }, { "rc4_128", 1, RC4, initRC4key_128, }, . 791a /* * 128 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 128 bits of the key. */ static void initRC4key_128(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } if(w->slen > 16) w->slen = 16; w->state = malloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } . ## diffname port/devssl.c 1999/0302 ## diff -e /n/emeliedump/1998/0910/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0302/sys/src/brazil/port/devssl.c 421c return first; . ## diffname port/devssl.c 1999/0320 ## diff -e /n/emeliedump/1999/0302/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0320/sys/src/brazil/port/devssl.c 190c sslattach(char *spec) . ## diffname port/devssl.c 1999/0414 ## diff -e /n/emeliedump/1999/0320/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0414/sys/src/brazil/port/devssl.c 1256c if(memcmp(digest, bin->rp, s->diglen) != 0) . 1239c for(b = bin; b; b = b->next){ . 1220c checkdigestb(Dstate *s, Block *bin) . 1185c return bin; . 1145,1146c l = &bin; for(b = bin; b; b = b->next){ . 1137c decryptb(Dstate *s, Block *bin) . ## diffname port/devssl.c 1999/0415 ## diff -e /n/emeliedump/1999/0414/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0415/sys/src/brazil/port/devssl.c 756c setupDESstate(w->state, key, 0); . 754c setupDESstate(w->state, key, w->secret+8); . 745,749c if(w->slen >= 8){ memmove(key, w->secret, 8); key[0] &= 0x0f; key[2] &= 0x0f; key[4] &= 0x0f; key[6] &= 0x0f; . 739a uchar key[8]; . ## diffname port/devssl.c 1999/0527 ## diff -e /n/emeliedump/1999/0415/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0527/sys/src/brazil/port/devssl.c 996,997d 994a s.s->state = Sclear; s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; . ## diffname port/devssl.c 1999/0804 ## diff -e /n/emeliedump/1999/0527/sys/src/brazil/port/devssl.c /n/emeliedump/1999/0804/sys/src/brazil/port/devssl.c 1035a } else if(strcmp(buf, "secretin") == 0 && p != 0) { m = (strlen(p)*3)/2; x = smalloc(m); n = dec64(x, m, p, strlen(p)); setsecret(&s.s->in, x, n); free(x); } else if(strcmp(buf, "secretout") == 0 && p != 0) { m = (strlen(p)*3)/2 + 1; x = smalloc(m); n = dec64(x, m, p, strlen(p)); setsecret(&s.s->out, x, n); free(x); . 1027c error("bad algorithm"); . 1019c error("bad algorithm"); . 968c error("arg too long"); . 962d 958d 908c char *p, *np, *e, buf[128]; uchar *x; . ## diffname port/devssl.c 1999/1230 ## diff -e /n/emeliedump/1999/0804/sys/src/brazil/port/devssl.c /n/emeliedump/1999/1230/sys/src/9/port/devssl.c 149a if(s == DEVDOTDOT){ q.path = QID(0, Qprotodir)|CHDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); return 1; } . 141c devdir(c, q, name, 0, nm, 0555, dp); . 132a if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir)|CHDIR; devdir(c, q, ".", 0, eve, 0555, dp); return 1; } . 126a if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir)|CHDIR; devdir(c, q, "#D", 0, eve, 0555, dp); return 1; } . ## diffname port/devssl.c 2000/0112 ## diff -e /n/emeliedump/1999/1230/sys/src/9/port/devssl.c /n/emeliedump/2000/0112/sys/src/9/port/devssl.c 1323,1352d 842c { "sha1", SHA1dlen, sha1, }, . 11c #include #include . ## diffname port/devssl.c 2000/0113 ## diff -e /n/emeliedump/2000/0112/sys/src/9/port/devssl.c /n/emeliedump/2000/0113/sys/src/9/port/devssl.c 11d ## diffname port/devssl.c 2000/0204 ## diff -e /n/emeliedump/2000/0113/sys/src/9/port/devssl.c /n/emeliedump/2000/0204/sys/src/9/port/devssl.c 842a { "sha", SHA1dlen, sha1, }, . ## diffname port/devssl.c 2000/0325 ## diff -e /n/emeliedump/2000/0204/sys/src/9/port/devssl.c /n/emeliedump/2000/0325/sys/src/9/port/devssl.c 198a return 1; case Qclonus: devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp); return 1; default: ds = dstate[CONV(c->qid)]; devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, ds->user, 0660, dp); . 162c devdir(c, q, "ssl", 0, eve, CHDIR|0555, dp); . 151c devdir(c, q, name, 0, nm, CHDIR|0555, dp); . 140c devdir(c, q, ".", 0, eve, CHDIR|0555, dp); . 135c devdir(c, q, "ssl", 0, eve, CHDIR|0555, dp); . 129c devdir(c, q, "#D", 0, eve, CHDIR|0555, dp); . 114a char *sslnames[] = { [Qclonus] "clone", [Qdata] "data", [Qctl] "ctl", [Qsecretin] "secretin", [Qsecretout] "secretout", [Qencalgs] "encalgs", [Qhashalgs] "hashalgs", }; . 100,101c #define CONV(x) (((x).path >> 5)&(Maxdstate-1)) #define QID(c, y) (((c)<<5) | (y)) . ## diffname port/devssl.c 2000/0913 ## diff -e /n/emeliedump/2000/0325/sys/src/9/port/devssl.c /n/emeliedump/2000/0913/sys/src/9/port/devssl.c 653c if(nb != nil) freeb(nb); . 651c if(bb.b != nil) . 648a nb = nil; . 629c * use SSL record format, add in count, digest and/or encrypt. * the write is interruptable. if it is interrupted, we'll * get out of sync with the far side. not much we can do about * it since we don't know if any bytes have been written. . 556c s.s->processed = qremove(&b, len - pad, 1); else s.s->processed = b; b = nil; s.s->in.mid++; qunlock(&s.s->in.ctlq); poperror(); USED(nconsumed); . 550,552d 545,546c checkdigestb(s.s, b); b->rp += s.s->diglen; . 541,543c b = decryptb(s.s, b); b = pullupblock(b, s.s->diglen); if(b == nil) . 537,538c checkdigestb(s.s, b); b->rp += s.s->diglen; . 534,535c b = pullupblock(b, s.s->diglen); if(b == nil) . 531c b = decryptb(s.s, b); . 525a if(b != nil) freeb(b); . 523a /* grab the next message and decode/decrypt it */ b = qremove(&s.s->unprocessed, len, 0); . 521,522c /* if an Eintr happens after this, we screwed. Make * sure nothing we call can sleep. Luckily, allocb * won't sleep, it'll just error out. */ . 519a USED(nconsumed); nconsumed = 0; . 513,514c consume(&s.s->unprocessed, &consumed[2], 1); pad = consumed[2]; . 511c len = ((consumed[0] & 0x3f)<<8) | consumed[1]; . 505,507c consume(&s.s->unprocessed, consumed, 2); nconsumed = 2; if(consumed[0] & 0x80){ len = ((consumed[0] & 0x7f)<<8) | consumed[1]; . 497d 495a if(strcmp(up->error, Eintr) != 0 && nconsumed) regurgitate(s.s, consumed, nconsumed); . 494a nconsumed = 0; . 486c uchar consumed[3]; int nconsumed; . 480a /* * We can't let Eintr's lose data since the program * doing the read may be able to handle it. The only * places Eintr is possible is during the read's in consume. * Therefore, we make sure we can always put back the bytes * consumed before the last ensure. */ . 433a * give back n bytes */ static void regurgitate(Dstate *s, uchar *p, int n) { Block *b; if(n <= 0) return; b = s->unprocessed; if(s->unprocessed == nil || b->rp - b->base < n) { b = allocb(n); memmove(p, b->wp, n); b->wp += n; b->next = s->unprocessed; s->unprocessed = b; } else { b->rp -= n; memmove(p, b->rp, n); } } /* . 75c int maxdstate = 128; . ## diffname port/devssl.c 2000/0914 ## diff -e /n/emeliedump/2000/0913/sys/src/9/port/devssl.c /n/emeliedump/2000/0914/sys/src/9/port/devssl.c 704,705d 452c memmove(b->rp, p, n); . 446c memmove(b->wp, p, n); . ## diffname port/devssl.c 2000/0915 ## diff -e /n/emeliedump/2000/0914/sys/src/9/port/devssl.c /n/emeliedump/2000/0915/sys/src/9/port/devssl.c 699d ## diffname port/devssl.c 2000/0919 ## diff -e /n/emeliedump/2000/0915/sys/src/9/port/devssl.c /n/emeliedump/2000/0919/sys/src/9/port/devssl.c 557c /* if an Eintr happens after this, we're screwed. Make . 528c if(strcmp(up->error, Eintr) != 0) . ## diffname port/devssl.c 2001/0331 ## diff -e /n/emeliedump/2000/0919/sys/src/9/port/devssl.c /n/emeliedump/2001/0331/sys/src/9/port/devssl.c 778d 776d 528c if(strcmp(up->error, Eintr) == 0) . ## diffname port/devssl.c 2001/0504 ## diff -e /n/emeliedump/2001/0331/sys/src/9/port/devssl.c /n/emeliedump/2001/0504/sys/src/9/port/devssl.c 529a poperror(); } . 528c if(strcmp(up->error, Eintr) == 0 && !waserror()){ . 505,509c * We can't let Eintrs lose data, since doing so will get * us out of sync with the sender and break the reliablity * of the channel. Eintr only happens during the reads in * consume. Therefore we put back any bytes consumed before * the last call to ensure. . ## diffname port/devssl.c 2001/0515 ## diff -e /n/emeliedump/2001/0504/sys/src/9/port/devssl.c /n/emeliedump/2001/0515/sys/src/9/port/devssl.c 644d 641d 215c if(ds != nil) nm = ds->user; else nm = eve; devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp); . ## diffname port/devssl.c 2001/0527 ## diff -e /n/emeliedump/2001/0515/sys/src/9/port/devssl.c /n/emeliedump/2001/0527/sys/src/9/port/devssl.c 1449c kstrdup(&s->user, up->user); . 1426c names = smalloc(sizeof(char*) * newmax); if(names == 0) error(Enomem); memmove(names, dsname, sizeof(char*) * maxdstate); dsname = names; . 1419a . 1396a char **names; . 1188d 1151a if((dsname = smalloc(sizeof(char*) * maxdstate)) == 0) panic("sslinit"); . 780a s.s->c->offset += m; . 779a m = BLEN(nb); . 646a break; . 644a break; . 638c ft = CONV(c->qid); sprint(buf, "%d", ft); . 634c ft = TYPE(c->qid); switch(ft) { . 631c if(c->qid.type & QTDIR) . 629a int ft; . 534,535d 532c if(strcmp(up->error, Eintr) != 0) . 509,513c * We can't let Eintr's lose data since the program * doing the read may be able to handle it. The only * places Eintr is possible is during the read's in consume. * Therefore, we make sure we can always put back the bytes * consumed before the last ensure. . 360a if(s->user != nil) free(s->user); . 341c ft = TYPE(c->qid); switch(ft) { . 339a int ft; . 332,333c dir = smalloc(sizeof(Dir)+n); m = convM2D(db, n, &dir[0], (char*)&dir[1]); if(m > 0){ kstrdup(&s->user, dir->uid); s->perm = dir->mode; } free(dir); return m; . 324,325d 322a int m; . 321c Dir *dir; . 318,319c static int sslwstat(Chan *c, uchar *db, int n) . 268c ft = TYPE(c->qid); switch(ft) { . 252a int ft; . 245c return devstat(c, db, n, nil, 0, sslgen); . 242,243c static int sslstat(Chan *c, uchar *db, int n) . 239c return devwalk(c, nc, name, nname, nil, 0, sslgen); . 236,237c static Walkqid* sslwalk(Chan *c, Chan *nc, char **name, int nname) . 232a c->qid.type = QTDIR; . 231c c->qid.path = QID(0, Qtopdir); . 215,219c devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, ds->user, 0660, dp); . 171,172c q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); . 161c if(dsname[s] == nil){ sprint(name, "%d", s); kstrdup(&dsname[s], name); } devdir(c, q, dsname[s], 0, nm, 0555, dp); . 154,155c q.path = QID(s, Qconvdir); q.type = QTDIR; . 149,150c q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); . 144,145c q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); . 138,139c q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, "#D", 0, eve, 0555, dp); . 135c ft = TYPE(c->qid); switch(ft) { . 133a q.type = QTFILE; . 130a int ft; . 126c sslgen(Chan *c, char*, Dirtab *d, int nd, int s, Dir *dp) . 76c char **dsname; Dstate **dstate; . 69c char *user; . ## diffname port/devssl.c 2001/0602 ## diff -e /n/emeliedump/2001/0527/sys/src/9/port/devssl.c /n/emeliedump/2001/0602/sys/src/9/port/devssl.c 633c b = qtake(&s.s->processed, n, 0); . 622c s.s->processed = qtake(&b, len - pad, 1); . 589c b = qtake(&s.s->unprocessed, len, 0); . 524c panic("qtake"); . 519c panic("qtake"); . 487c qtake(Block **l, int n, int discard) . ## diffname port/devssl.c 2001/0823 ## diff -e /n/emeliedump/2001/0602/sys/src/9/port/devssl.c /n/emeliedump/2001/0823/sys/src/9/port/devssl.c 1469c return ret; . 1441,1466d 1434,1437c ret = nil; for(i=0; itype] == &ssldevtab){ cclose(c); error("cannot ssl encrypt devssl files"); } . 1176,1181d 86a Lock dslock; int dshiwat; char *dsname[Maxdstate]; Dstate *dstate[Maxdstate]; char *encalgs; char *hashalgs; . 84c Maxdstate= 128, /* must be a power of 2 */ . 73,80d ## diffname port/devssl.c 2001/0825 ## diff -e /n/emeliedump/2001/0823/sys/src/9/port/devssl.c /n/emeliedump/2001/0825/sys/src/9/port/devssl.c 628c poperror(); . 612c error("ssl message too short (dig+enc)"); . 604c error("ssl message too short (digesting)"); . 598a if(b == nil) error("ssl message too short (encrypting)"); . 589a if(blocklen(b) != len+pad) print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); . 588c b = qtake(&s.s->unprocessed, len+pad, 0); . 586a if(waserror()){ print("devssl: unhandled allocation failure\n"); nexterror(); } /* skip header */ consume(&s.s->unprocessed, consumed, toconsume); . 582,584c /* * Now we have a full SSL packet in the unprocessed list. * Start processing. We can't get Eintr's here. * The only cause for errors from here until the end of the * loop is allocation failures in the block manipulation. * We'll worry about that when we come across it. . 579,580c ensure(s.s, &s.s->unprocessed, toconsume+len+pad); . 577a toconsume = 3; . 570,573c len = ((p[0] & 0x3f)<<8) | p[1]; pad = p[2]; . 568a toconsume = 2; . 561,566c /* * Read in the whole message. Until we've got it all, * it stays on s.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; if(p[0] & 0x80){ len = ((p[0] & 0x7f)<<8) | p[1]; . 558d 553,554d 551c qlock(&s.s->in.q); . 541,542c uchar consumed[3], *p; int toconsume; . 479a */ . 460d 418c nexterror(); . ## diffname port/devssl.c 2001/1106 ## diff -e /n/emeliedump/2001/0825/sys/src/9/port/devssl.c /n/emeliedump/2001/1106/sys/src/9/port/devssl.c 348c . 346a if(dir->mode != ~0UL) . 345c if(m == 0){ free(dir); error(Eshortstat); } if(!emptystr(dir->uid)) . ## diffname port/devssl.c 2002/0109 ## diff -e /n/emeliedump/2001/1106/sys/src/9/port/devssl.c /n/emeliedump/2002/0109/sys/src/9/port/devssl.c 1231a devshutdown, . ## diffname port/devssl.c 2002/0306 ## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devssl.c /n/emeliedump/2002/0306/sys/src/9/port/devssl.c 1176,1177c t = dec64(x, m, p, strlen(p)); setsecret(&s.s->out, x, t); . 1170,1171c t = dec64(x, m, p, strlen(p)); setsecret(&s.s->in, x, t); . 607c if(blocklen(b) != len) . 605c b = qtake(&s.s->unprocessed, len, 0); . 586c ensure(s.s, &s.s->unprocessed, toconsume+len); . 577a s.s->unprocessed = pullupblock(s.s->unprocessed, 3); . 2c * devssl - secure sockets layer . ## diffname port/devssl.c 2002/0307 ## diff -e /n/emeliedump/2002/0306/sys/src/9/port/devssl.c /n/emeliedump/2002/0307/sys/src/9/port/devssl.c 1184,1185c qunlock(&s->in.ctlq); qunlock(&s->out.q); . 1178c setsecret(&s->out, x, t); . 1172c setsecret(&s->in, x, t); . 1167c s->maxpad = s->max = (1<<15) - s->diglen - 1; . 1161,1165c 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; . 1158c if(s->hf == 0 && s->encryptalg == Noencryption) . 1149,1150c if(parsehashalg(p, s) < 0) if(parseencryptalg(p, s) < 0) . 1140,1142c s->hf = 0; s->encryptalg = Noencryption; s->blocklen = 1; . 1133,1137c 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) . 1127,1128c s->state = Sclear; s->maxpad = s->max = (1<<15) - s->diglen - 1; . 1124c if(s->c == 0) . 1121,1122c s->blocklen = 1; s->diglen = 0; . 1114,1119c 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; . 1111c s->c = buftochan(p); . 1093c setsecret(&s->out, a, n); . 1090c setsecret(&s->in, a, n); . 1083,1084c qlock(&s->in.ctlq); qlock(&s->out.q); . 1079,1080c qunlock(&s->in.ctlq); qunlock(&s->out.q); . 1073a poperror(); qunlock(&s->out.q); . 1070c sslput(s, b); . 1068c b->wp += m; . 1066c memmove(b->wp, p, m); . 1063c freeb(b); . 1061c b = allocb(m); . 1058,1059c if(m > s->max) m = s->max; . 1053a /* lock should a write gets split over multiple records */ if(waserror()){ qunlock(&s->out.q); nexterror(); } qlock(&s->out.q); . 1051c if(s->state == Sincomplete) . 1045,1046c s = dstate[CONV(c->qid)]; if(s == 0) . 1043d 1038,1039c Dstate * volatile s; Block * volatile b; . 1036c sslwrite(Chan *c, void *a, long n, vlong) . 833a poperror(); . 831,832d 828,829c devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); s->c->offset += m; . 825c s->out.mid++; . 820,821c nb = digestb(s, nb, offset); nb = encryptb(s, nb, offset); . 817c nb = digestb(s, nb, offset); . 814c nb = encryptb(s, nb, offset); . 812c switch(s->state){ . 791c m += s->diglen; . 788,789c nb = padblock(b, h); b = 0; . 785c b->rp += m; . 783c memmove(nb->wp + h, b->rp, m); . 774c pad = s->blocklen - pad; . 772c m = s->maxpad; . 770c if(m > s->maxpad){ . 765,768c if(m > s->max){ m = s->max; } else if(s->blocklen != 1){ pad = (m + s->diglen)%s->blocklen; . 759,761c while(b != nil){ m = n = BLEN(b); h = s->diglen + 2; . 756d 751,753c if(b != nil) free(b); . 741,749d 739a int offset; . 735,736d 733c sslput(Dstate *s, Block * volatile b) . 725a 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; } . 709c freeblist(b); . 703c for(nb = b; nb; nb = nb->next){ . 697c freeblist(b); . 686c b = sslbread(c, n, offset); . 666c Block * volatile b; . 657c qunlock(&s->in.q); . 655c b = qtake(&s->processed, n, 0); . 648,649c s->in.mid++; qunlock(&s->in.ctlq); . 646c s->processed = b; . 644c s->processed = qtake(&b, len - pad, 1); . 636,638c checkdigestb(s, b); b->rp += s->diglen; len -= s->diglen; . 632,633c b = decryptb(s, b); b = pullupblock(b, s->diglen); . 628,629c checkdigestb(s, b); b->rp += s->diglen; . 625c b = pullupblock(b, s->diglen); . 622c b = decryptb(s, b); . 617,618c qlock(&s->in.ctlq); switch(s->state){ . 612c qunlock(&s->in.ctlq); . 606c b = qtake(&s->unprocessed, len, 0); . 603c consume(&s->unprocessed, consumed, toconsume); . 587c ensure(s, &s->unprocessed, toconsume+len); . 578c s->unprocessed = pullupblock(s->unprocessed, 3); . 574c ensure(s, &s->unprocessed, len); . 569,571c ensure(s, &s->unprocessed, 3); s->unprocessed = pullupblock(s->unprocessed, 2); p = s->unprocessed->rp; . 566c * it stays on s->unprocessed, so that if we get Eintr, . 563c if(s->processed == 0){ . 559c qunlock(&s->in.q); . 557c qlock(&s->in.q); . 554c if(s->state == Sincomplete) . 551,552c s = dstate[CONV(c->qid)]; if(s == 0) . 545c Dstate * volatile s; . 113a static long sslput(Dstate *s, Block * volatile b); . ## diffname port/devssl.c 2002/0522 ## diff -e /n/emeliedump/2002/0307/sys/src/9/port/devssl.c /n/emeliedump/2002/0522/sys/src/9/port/devssl.c 229c if(ds != 0) nm = ds->user; else nm = eve; devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp); . ## diffname port/devssl.c 2003/0211 ## diff -e /n/emeliedump/2002/0522/sys/src/9/port/devssl.c /n/emeliedump/2003/0211/sys/src/9/port/devssl.c 655d 594,606d