| plan 9 kernel history: overview | file list | diff list |
1996/1029/port/devssl.c (diff list | history)
| 1996/0601/sys/src/9/port/devssl.c:10,20 – 1996/1029/sys/src/9/port/devssl.c:10,22 (short | long | prev | next) | ||
| 1995/1213 | ||
| 1996/0531 | #include <libcrypt.h> | |
| 1995/1213 | ||
| 1996/1029 | #define NOSPOOKS 1 | |
| 1995/1213 | typedef struct OneWay OneWay; struct OneWay { | |
| 1996/0531 | QLock q; | |
| 1996/1029 | QLock ctlq; | |
| 1995/1213 | ||
| 1996/0531 | void *state; /* encryption state */ int slen; /* hash data length */ | |
| 1996/0601/sys/src/9/port/devssl.c:25,41 – 1996/1029/sys/src/9/port/devssl.c:27,44 | ||
| 1995/1213 | enum { /* connection states */ | |
| 1996/1029 | Sincomplete= 0, Sclear, Sencrypting, Sdigesting, | |
| 1995/1213 | /* encryption algorithms */ | |
| 1995/1218 | Noencryption= 0, | |
| 1996/1029 | #ifdef NOSPOOKS | |
| 1995/1213 | DESCBC= 1, | |
| 1996/0531 |
| |
| 1996/1029 | DESECB= 2, #endif NOSPOOKS RC4= 3 | |
| 1995/1213 | }; typedef struct Dstate Dstate; | |
| 1996/0601/sys/src/9/port/devssl.c:43,48 – 1996/1029/sys/src/9/port/devssl.c:46,53 | ||
| 1995/1213 | { Chan *c; /* io channel */ uchar state; /* state of connection */ | |
| 1996/1029 | int ref; /* serialized by dslock for atomic destroy */ | |
| 1995/1213 | uchar encryptalg; /* encryption algorithm */ | |
| 1995/1218 | ushort blocklen; /* blocking length */ | |
| 1995/1213 | ||
| 1996/0601/sys/src/9/port/devssl.c:60,102 – 1996/1029/sys/src/9/port/devssl.c:65,112 | ||
| 1995/1213 | /* output side */ OneWay out; | |
| 1996/1029 | /* protections */ char user[NAMELEN]; int perm; | |
| 1995/1213 | }; | |
| 1996/1029 | Lock dslock; int dshiwat; int maxdstate = 20; Dstate** dstate; | |
| 1995/1213 | enum { | |
| 1996/0531 |
| |
| 1996/1029 | Maxdmsg= 1<<16, Maxdstate= 64 | |
| 1995/1213 | }; enum{ | |
| 1996/0531 |
| |
| 1996/1029 | Qtopdir = 1, /* top level directory */ Qclonus, Qconvdir, /* directory for a conversation */ Qdata, Qctl, Qsecretin, Qsecretout | |
| 1995/1213 | }; | |
| 1996/0103 |
| |
| 1995/1213 |
| |
| 1996/1029 | #define TYPE(x) ((x).path & 0xf) #define CONV(x) (((x).path >> 4)&(Maxdstate-1)) #define QID(c, y) (((c)<<4) | (y)) | |
| 1995/1213 |
| |
| 1995/1217 | static void ensure(Dstate*, Block**, int); static void consume(Block**, uchar*, int); | |
| 1995/1218 |
| |
| 1996/1029 | static void setsecret(OneWay*, uchar*, int); | |
| 1995/1217 | static Block* encryptb(Dstate*, Block*, int); static Block* decryptb(Dstate*, Block*); static Block* digestb(Dstate*, Block*, int); static void checkdigestb(Dstate*, Block*); | |
| 1996/1029 | static Chan* buftochan(char*); static void sslhangup(Dstate*); static Dstate* dsclone(Chan *c); static void dsnew(Chan *c, Dstate **); | |
| 1995/1217 | ||
| 1995/1213 | void sslreset(void) | |
| 1996/0601/sys/src/9/port/devssl.c:103,119 – 1996/1029/sys/src/9/port/devssl.c:113,194 | ||
| 1995/1213 | { } | |
| 1996/1029 | 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; } | |
| 1995/1213 | void sslinit(void) { | |
| 1996/0531 |
| |
| 1996/1029 | if((dstate = malloc(sizeof(Dstate*) * maxdstate)) == 0) panic("sslinit"); | |
| 1995/1213 | } Chan * | |
| 1996/0531 | sslattach(void *spec) | |
| 1995/1213 | { | |
| 1996/1029 | Chan *c; c = devattach('D', spec); c->qid.path = QID(0, Qtopdir)|CHDIR; c->qid.vers = 0; return c; | |
| 1995/1213 | } Chan * | |
| 1996/0601/sys/src/9/port/devssl.c:125,153 – 1996/1029/sys/src/9/port/devssl.c:200,276 | ||
| 1995/1213 | int sslwalk(Chan *c, char *name) { | |
| 1996/1029 | return devwalk(c, name, 0, 0, sslgen); | |
| 1995/1213 | } void sslstat(Chan *c, char *db) { | |
| 1996/1029 | devstat(c, db, 0, 0, sslgen); | |
| 1995/1213 | } Chan * sslopen(Chan *c, int omode) { | |
| 1996/1029 | Dstate *s, **pp; int perm; | |
| 1995/1213 |
| |
| 1996/0531 |
| |
| 1995/1213 |
| |
| 1996/1029 | perm = 0; omode &= 3; switch(omode) { case OREAD: perm = 4; | |
| 1995/1213 | break; | |
| 1996/1029 | case OWRITE: perm = 2; break; case ORDWR: perm = 6; break; | |
| 1995/1213 | } | |
| 1996/1029 | 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; | |
| 1995/1213 | } void | |
| 1996/0601/sys/src/9/port/devssl.c:170,178 – 1996/1029/sys/src/9/port/devssl.c:293,311 | ||
| 1995/1213 | void sslwstat(Chan *c, char *dp) { | |
| 1996/0531 |
| |
| 1995/1213 |
| |
| 1996/1029 | 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; | |
| 1995/1213 | } void | |
| 1996/0601/sys/src/9/port/devssl.c:180,188 – 1996/1029/sys/src/9/port/devssl.c:313,339 | ||
| 1995/1213 | { Dstate *s; | |
| 1996/1029 | 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); | |
| 1995/1213 | if(s->c) | |
| 1996/0601 | close(s->c); | |
| 1995/1213 | if(s->in.secret) | |
| 1996/0601/sys/src/9/port/devssl.c:189,198 – 1996/1029/sys/src/9/port/devssl.c:340,486 | ||
| 1995/1213 | free(s->in.secret); if(s->out.secret) free(s->out.secret); | |
| 1996/1029 | if(s->in.state) free(s->in.state); if(s->out.state) free(s->out.state); | |
| 1995/1213 | free(s); | |
| 1996/1029 | ||
| 1995/1213 | } } | |
| 1996/1029 | 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; } | |
| 1995/1217 | Block* sslbread(Chan *c, long n, ulong offset) | |
| 1995/1213 | { | |
| 1996/0601/sys/src/9/port/devssl.c:199,274 – 1996/1029/sys/src/9/port/devssl.c:487,558 | ||
| 1996/0531 | volatile struct { Dstate *s; } s; | |
| 1995/1218 | Block *b; | |
| 1995/1217 | uchar count[2]; | |
| 1995/1218 |
| |
| 1996/1029 | int len, pad; | |
| 1995/1213 | ||
| 1995/1217 | USED(offset); | |
| 1996/0531 |
| |
| 1996/1029 | s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslbread"); if(s.s->state == Sincomplete) | |
| 1995/1217 | error(Ebadusefd); if(waserror()){ | |
| 1996/0531 | qunlock(&s.s->in.q); | |
| 1996/1029 | sslhangup(s.s); | |
| 1995/1217 | nexterror(); | |
| 1995/1213 | } | |
| 1996/0531 | qlock(&s.s->in.q); | |
| 1995/1217 | ||
| 1996/0531 |
| |
| 1995/1218 |
| |
| 1995/1217 | ||
| 1996/1029 | if(s.s->processed == 0){ | |
| 1995/1217 | /* read in the whole message */ | |
| 1996/0531 |
| |
| 1996/1029 | ensure(s.s, &s.s->unprocessed, 2); consume(&s.s->unprocessed, count, 2); | |
| 1995/1217 | if(count[0] & 0x80){ len = ((count[0] & 0x7f)<<8) | count[1]; | |
| 1996/0531 |
| |
| 1996/1029 | ensure(s.s, &s.s->unprocessed, len); | |
| 1995/1217 | pad = 0; } else { len = ((count[0] & 0x3f)<<8) | count[1]; | |
| 1996/0531 |
| |
| 1996/1029 | ensure(s.s, &s.s->unprocessed, len+1); consume(&s.s->unprocessed, count, 1); | |
| 1995/1217 | pad = count[0]; | |
| 1996/1029 | if(pad > len){ print("pad %d buf len %d\n", pad, len); error("bad pad in ssl message"); } | |
| 1995/1217 | } | |
| 1996/0531 |
| |
| 1996/1029 | /* put extra on unprocessed queue */ s.s->processed = qremove(&s.s->unprocessed, len, 0); | |
| 1995/1217 |
| |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1996/1029 | if(waserror()){ qunlock(&s.s->in.ctlq); nexterror(); | |
| 1995/1217 | } | |
| 1996/0531 |
| |
| 1995/1218 |
| |
| 1996/0531 |
| |
| 1995/1218 |
| |
| 1996/0531 |
| |
| 1996/1029 | 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; | |
| 1995/1218 | } | |
| 1996/1029 | qunlock(&s.s->in.ctlq); poperror(); | |
| 1995/1217 | /* remove pad */ | |
| 1995/1218 |
| |
| 1995/1217 |
| |
| 1996/0531 |
| |
| 1996/1029 | if(pad) s.s->processed = qremove(&s.s->processed, len - pad, 1); | |
| 1995/1217 | } | |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1996/0531 |
| |
| 1996/1029 | /* return at most what was asked for */ b = qremove(&s.s->processed, n, 0); | |
| 1995/1217 | ||
| 1996/0531 | qunlock(&s.s->in.q); | |
| 1995/1217 | poperror(); | |
| 1996/0601/sys/src/9/port/devssl.c:280,302 – 1996/1029/sys/src/9/port/devssl.c:564,602 | ||
| 1996/0223 | sslread(Chan *c, void *a, long n, ulong offset) | |
| 1995/1213 | { | |
| 1996/0531 | volatile struct { Block *b; } b; | |
| 1996/1029 | Block *nb; uchar *va; int i; char buf[128]; | |
| 1995/1213 |
| |
| 1996/0223 |
| |
| 1996/1029 | 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; | |
| 1995/1213 | } | |
| 1996/0531 |
| |
| 1995/1213 | ||
| 1996/0223 | if(waserror()){ | |
| 1996/0531 |
| |
| 1996/1029 | freeblist(b.b); | |
| 1996/0223 | nexterror(); | |
| 1995/1213 | } | |
| 1996/0531 |
| |
| 1996/1029 | n = 0; va = a; for(nb = b.b; nb; nb = nb->next){ i = BLEN(nb); memmove(va+n, nb->rp, i); n += i; } | |
| 1996/0223 | ||
| 1996/1029 | freeblist(b.b); | |
| 1996/0223 | poperror(); | |
| 1995/1213 | return n; | |
| 1996/0601/sys/src/9/port/devssl.c:303,308 – 1996/1029/sys/src/9/port/devssl.c:603,630 | ||
| 1995/1213 | } | |
| 1995/1215 | /* | |
| 1996/1029 | * 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; } } /* | |
| 1995/1215 | * use SSL record format, add in count and digest or encrypt */ long | |
| 1996/0601/sys/src/9/port/devssl.c:315,329 – 1996/1029/sys/src/9/port/devssl.c:637,655 | ||
| 1995/1217 | uchar *p; | |
| 1995/1215 | ||
| 1996/0531 | bb.b = b; | |
| 1996/1029 | s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslbwrite"); if(s.s->state == Sincomplete){ freeb(b); | |
| 1995/1215 | error(Ebadusefd); | |
| 1996/1029 | } | |
| 1995/1215 | if(waserror()){ | |
| 1996/0531 | qunlock(&s.s->out.q); if(bb.b) freeb(bb.b); | |
| 1996/1029 | sslhangup(s.s); | |
| 1995/1215 | nexterror(); } | |
| 1996/0531 | qlock(&s.s->out.q); | |
| 1996/0601/sys/src/9/port/devssl.c:366,372 – 1996/1029/sys/src/9/port/devssl.c:692,698 | ||
| 1995/1215 | /* SSL style count */ if(pad){ | |
| 1995/1218 | nb = padblock(nb, -pad); | |
| 1995/1215 |
| |
| 1996/1029 | randfill(nb->wp, pad); | |
| 1995/1227 | nb->wp += pad; | |
| 1995/1215 | m += pad; | |
| 1995/1218 | ||
| 1996/0601/sys/src/9/port/devssl.c:382,394 – 1996/1029/sys/src/9/port/devssl.c:708,725 | ||
| 1995/1217 | offset = 2; } | |
| 1995/1213 | ||
| 1996/0531 |
| |
| 1996/1029 | switch(s.s->state){ case Sencrypting: | |
| 1996/0531 | nb = encryptb(s.s, nb, offset); | |
| 1995/1215 |
| |
| 1996/1029 | break; case Sdigesting: | |
| 1996/0531 | nb = digestb(s.s, nb, offset); | |
| 1996/1029 | break; } | |
| 1995/1213 | ||
| 1996/0531 |
| |
| 1995/1213 | ||
| 1996/1029 | m = BLEN(nb); (*devtab[s.s->c->type].bwrite)(s.s->c, nb, s.s->c->offset); s.s->c->offset += m; | |
| 1995/1215 | } | |
| 1996/0531 | qunlock(&s.s->out.q); | |
| 1995/1215 | poperror(); | |
| 1996/0601/sys/src/9/port/devssl.c:396,473 – 1996/1029/sys/src/9/port/devssl.c:727,804 | ||
| 1995/1215 | return rv; | |
| 1996/0223 | } | |
| 1996/1029 | 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); } | |
| 1996/0223 | long sslwrite(Chan *c, void *a, long n, ulong offset) { | |
| 1996/1029 | volatile struct { Dstate *s; } s; | |
| 1996/0531 | volatile struct { Block *b; } b; | |
| 1996/0223 |
| |
| 1996/1029 | int m, t; | |
| 1996/0223 | char *p, *e, buf[32]; | |
| 1996/1029 | s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslwrite"); | |
| 1996/0223 |
| |
| 1996/1029 | t = TYPE(c->qid); if(t == Qdata){ if(s.s->state == Sincomplete) error(Ebadusefd); | |
| 1996/0223 |
| |
| 1996/1029 | e = p + n; do { | |
| 1996/0223 | m = e - p; | |
| 1996/1029 | if(m > s.s->max) m = s.s->max; | |
| 1996/0223 | ||
| 1996/0531 | b.b = allocb(m); | |
| 1996/0223 | if(waserror()){ | |
| 1996/0601/sys/src/9/port/devssl.c:479,581 – 1996/1029/sys/src/9/port/devssl.c:810,946 | ||
| 1996/0531 | b.b->wp += m; | |
| 1996/0223 | ||
| 1996/0531 | sslbwrite(c, b.b, offset); | |
| 1996/0223 |
| |
| 1996/1029 | 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){ | |
| 1996/0223 | default: | |
| 1996/1029 | 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; | |
| 1996/0223 | } | |
| 1995/1213 |
| |
| 1996/1029 | 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; | |
| 1995/1213 |
| |
| 1996/1029 | if(strcmp(buf, "fd") == 0){ s.s->c = buftochan(p); | |
| 1995/1213 |
| |
| 1996/1029 | /* 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; | |
| 1995/1213 |
| |
| 1996/1029 | 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; | |
| 1995/1213 | } | |
| 1996/1029 | 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); | |
| 1995/1213 |
| |
| 1996/1029 | 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); | |
| 1995/1213 |
| |
| 1996/1029 | out: qunlock(&s.s->in.ctlq); qunlock(&s.s->out.q); poperror(); return n; | |
| 1995/1213 | } | |
| 1995/1217 |
| |
| 1995/1218 |
| |
| 1995/1213 |
| |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1995/1213 | ||
| 1995/1217 |
| |
| 1995/1218 |
| |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1995/1218 |
| |
| 1996/0531 |
| |
| 1995/1217 |
| |
| 1995/1213 | ||
| 1995/1217 | static Block* encryptb(Dstate *s, Block *b, int offset) { | |
| 1996/1029 | #ifdef NOSPOOKS | |
| 1995/1218 | uchar *p, *ep, *p2, *ip, *eip; | |
| 1995/1217 | DESstate *ds; | |
| 1996/1029 | #endif NOSPOOKS | |
| 1995/1213 | ||
| 1995/1217 | switch(s->encryptalg){ | |
| 1996/1029 | #ifdef NOSPOOKS | |
| 1995/1218 | case DESECB: | |
| 1995/1217 | ds = s->out.state; ep = b->rp + BLEN(b); | |
| 1996/0601/sys/src/9/port/devssl.c:594,633 – 1996/1029/sys/src/9/port/devssl.c:959,1026 | ||
| 1995/1218 | memmove(ds->ivec, p, 8); } | |
| 1995/1217 | break; | |
| 1996/1029 | #endif NOSPOOKS case RC4: rc4(s->out.state, b->rp + offset, BLEN(b) - offset); break; | |
| 1995/1213 | } | |
| 1995/1217 | return b; } | |
| 1995/1213 | ||
| 1995/1217 | static Block* | |
| 1996/1029 | decryptb(Dstate *s, Block *inb) | |
| 1995/1217 | { | |
| 1996/1029 | Block *b, **l; #ifdef NOSPOOKS | |
| 1995/1218 | uchar *p, *ep, *tp, *ip, *eip; | |
| 1995/1217 | DESstate *ds; | |
| 1995/1218 | uchar tmp[8]; | |
| 1996/1029 | #endif NOSPOOKS int i; | |
| 1995/1213 | ||
| 1995/1217 |
| |
| 1995/1218 |
| |
| 1995/1217 |
| |
| 1995/1218 |
| |
| 1996/1029 | 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"); | |
| 1995/1218 | } } | |
| 1995/1217 |
| |
| 1996/1029 | 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; } | |
| 1995/1217 | } | |
| 1995/1213 |
| |
| 1996/1029 | return inb; | |
| 1995/1213 | } | |
| 1995/1217 | static Block* | |
| 1996/0601/sys/src/9/port/devssl.c:662,668 – 1996/1029/sys/src/9/port/devssl.c:1055,1061 | ||
| 1995/1215 | } | |
| 1995/1213 | ||
| 1995/1217 | static void | |
| 1996/1029 | checkdigestb(Dstate *s, Block *inb) | |
| 1995/1215 | { | |
| 1995/1217 | uchar *p; DigestState ss; | |
| 1996/0601/sys/src/9/port/devssl.c:670,686 – 1996/1029/sys/src/9/port/devssl.c:1063,1087 | ||
| 1995/1218 | int n, h; | |
| 1995/1217 | OneWay *w; uchar digest[128]; | |
| 1996/1029 | Block *b; | |
| 1995/1213 | ||
| 1995/1217 | w = &s->in; | |
| 1995/1213 | ||
| 1995/1217 | memset(&ss, 0, sizeof(ss)); | |
| 1996/1029 | /* hash secret */ | |
| 1995/1217 | (*s->hf)(w->secret, w->slen, 0, &ss); | |
| 1995/1218 |
| |
| 1995/1217 | ||
| 1996/1029 | /* 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; } | |
| 1995/1217 | /* hash message id */ p = msgid; n = w->mid++; | |
| 1996/0601/sys/src/9/port/devssl.c:690,713 – 1996/1029/sys/src/9/port/devssl.c:1091,1112 | ||
| 1995/1217 | *p = n; | |
| 1995/1218 | (*s->hf)(msgid, 4, digest, &ss); | |
| 1995/1217 | ||
| 1995/1218 |
| |
| 1996/1029 | if(memcmp(digest, inb->rp, s->diglen) != 0) | |
| 1995/1217 | error("bad digest"); | |
| 1995/1213 | } | |
| 1995/1215 | /* get channel associated with an fd */ | |
| 1995/1213 | static Chan* | |
| 1996/1029 | buftochan(char *p) | |
| 1995/1213 | { Chan *c; int fd; | |
| 1996/1029 | if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); | |
| 1995/1213 | c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ return c; } | |
| 1996/0601/sys/src/9/port/devssl.c:714,720 – 1996/1029/sys/src/9/port/devssl.c:1113,1119 | ||
| 1995/1213 | ||
| 1995/1215 | /* hand up a digest connection */ static void | |
| 1996/1029 | sslhangup(Dstate *s) | |
| 1995/1213 | { | |
| 1995/1215 | Block *b; | |
| 1995/1213 | ||
| 1996/0601/sys/src/9/port/devssl.c:727,733 – 1996/1029/sys/src/9/port/devssl.c:1126,1132 | ||
| 1995/1215 | freeb(s->unprocessed); s->unprocessed = 0; | |
| 1995/1213 | } | |
| 1995/1215 |
| |
| 1996/1029 | s->state = Sincomplete; | |
| 1996/0531 | qunlock(&s->in.q); | |
| 1995/1213 | } | |
| 1996/0601/sys/src/9/port/devssl.c:739,749 – 1996/1029/sys/src/9/port/devssl.c:1138,1150 | ||
| 1995/1213 | handle_exception(int type, char *exception) { if(type == CRITICAL) | |
| 1996/0531 |
| |
| 1996/1029 | panic("crypt library: %s: %r", exception); | |
| 1995/1213 | else | |
| 1996/0531 |
| |
| 1996/1029 | print("crypt library: %s: %r\n", exception); | |
| 1995/1213 | } | |
| 1996/1029 | extern void rbcheck(char*); | |
| 1995/1213 | void* crypt_malloc(int size) { | |
| 1996/0601/sys/src/9/port/devssl.c:762,764 – 1996/1029/sys/src/9/port/devssl.c:1163,1232 | ||
| 1995/1213 | handle_exception(CRITICAL, "freeing null pointer"); free(x); } | |
| 1996/1029 | 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; } | |