📄 devssl.c
字号:
offset = 3; } else { p = nb->rp; p[0] = (m>>8) | 0x80; p[1] = m; offset = 2; } switch(s.s->state){ case Sencrypting: nb = encryptb(s.s, nb, offset); break; case Sdigesting: nb = digestb(s.s, nb, offset); break; case Sdigenc: nb = digestb(s.s, nb, offset); nb = encryptb(s.s, nb, offset); break; } s.s->out.mid++; m = BLEN(nb); devtab[s.s->c->type]->bwrite(s.s->c, nb, s.s->c->offset); s.s->c->offset += m; } qunlock(&s.s->out.q); poperror(); return rv;}static voidsetsecret(OneWay *w, uchar *secret, int n){ if(w->secret) free(w->secret); w->secret = smalloc(n); memmove(w->secret, secret, n); w->slen = n;}static voidinitDESkey(OneWay *w){ if(w->state){ free(w->state); w->state = 0; } w->state = smalloc(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");}/* * 40 bit DES is the same as 56 bit DES. However, * 16 bits of the key are masked to zero. */static voidinitDESkey_40(OneWay *w){ uchar key[8]; if(w->state){ free(w->state); w->state = 0; } if(w->slen >= 8){ memmove(key, w->secret, 8); key[0] &= 0x0f; key[2] &= 0x0f; key[4] &= 0x0f; key[6] &= 0x0f; } w->state = malloc(sizeof(DESstate)); if(w->slen >= 16) setupDESstate(w->state, key, w->secret+8); else if(w->slen >= 8) setupDESstate(w->state, key, 0); else error("secret too short");}static voidinitRC4key(OneWay *w){ if(w->state){ free(w->state); w->state = 0; } w->state = smalloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen);}/* * 40 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 40 bits of the key. */static voidinitRC4key_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);}/* * 128 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 128 bits of the key. */static voidinitRC4key_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);}typedef struct Hashalg Hashalg;struct Hashalg{ char *name; int diglen; DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);};Hashalg hashtab[] ={ { "md4", MD4dlen, md4, }, { "md5", MD5dlen, md5, }, { "sha1", SHA1dlen, sha1, }, { "sha", SHA1dlen, sha1, }, { 0 }};static intparsehashalg(char *p, Dstate *s){ 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;}typedef struct Encalg Encalg;struct Encalg{ char *name; int blocklen; int alg; void (*keyinit)(OneWay*);};#ifdef NOSPOOKSEncalg encrypttab[] ={ { "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, }, { "rc4_40", 1, RC4, initRC4key_40, }, { 0 }};#elseEncalg encrypttab[] ={ { "des_40_cbc", 8, DESCBC, initDESkey_40, }, { "des_40_ecb", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ { "rc4_40", 1, RC4, initRC4key_40, }, { 0 }};#endif NOSPOOKSstatic intparseencryptalg(char *p, Dstate *s){ 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;}static longsslwrite(Chan *c, void *a, long n, vlong off){ volatile struct { Dstate *s; } s; volatile struct { Block *b; } b; int m, t; char *p, *np, *e, buf[128]; uchar *x; ulong offset = off; s.s = dstate[CONV(c->qid)]; if(s.s == 0) panic("sslwrite"); t = TYPE(c->qid); if(t == Qdata){ if(s.s->state == Sincomplete) error(Ebadusefd); p = a; e = p + n; do { m = e - p; if(m > s.s->max) m = s.s->max; b.b = allocb(m); if(waserror()){ freeb(b.b); nexterror(); } memmove(b.b->wp, p, m); poperror(); b.b->wp += m; sslbwrite(c, b.b, offset); 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){ default: panic("sslwrite"); case Qsecretin: setsecret(&s.s->in, a, n); goto out; case Qsecretout: setsecret(&s.s->out, a, n); goto out; case Qctl: break; } if(n >= sizeof(buf)) error("arg too long"); strncpy(buf, a, n); buf[n] = 0; p = strchr(buf, '\n'); if(p) *p = 0; p = strchr(buf, ' '); if(p) *p++ = 0; if(strcmp(buf, "fd") == 0){ s.s->c = buftochan(p); /* default is clear (msg delimiters only) */ s.s->state = Sclear; s.s->blocklen = 1; s.s->diglen = 0; s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; s.s->in.mid = 0; s.s->out.mid = 0; } else if(strcmp(buf, "alg") == 0 && p != 0){ s.s->blocklen = 1; s.s->diglen = 0; if(s.s->c == 0) error("must set fd before algorithm"); s.s->state = Sclear; s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; if(strcmp(p, "clear") == 0){ goto out; } if(s.s->in.secret && s.s->out.secret == 0) setsecret(&s.s->out, s.s->in.secret, s.s->in.slen); if(s.s->out.secret && s.s->in.secret == 0) setsecret(&s.s->in, s.s->out.secret, s.s->out.slen); if(s.s->in.secret == 0 || s.s->out.secret == 0) 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) error("bad algorithm"); if(np == 0) break; p = np; } if(s.s->hf == 0 && s.s->encryptalg == Noencryption) error("bad algorithm"); if(s.s->blocklen != 1){ s.s->max = (1<<15) - s.s->diglen - 1; s.s->max -= s.s->max % s.s->blocklen; s.s->maxpad = (1<<14) - s.s->diglen - 1; s.s->maxpad -= s.s->maxpad % s.s->blocklen; } else s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; } 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); } else error(Ebadarg);out: qunlock(&s.s->in.ctlq); qunlock(&s.s->out.q); poperror(); return n;}static voidsslinit(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;}Dev ssldevtab = { 'D', "ssl", devreset, sslinit, sslattach, devclone, sslwalk, sslstat, sslopen, devcreate, sslclose, sslread, sslbread, sslwrite, sslbwrite, devremove, sslwstat,};static Block*encryptb(Dstate *s, Block *b, int offset){ uchar *p, *ep, *p2, *ip, *eip; DESstate *ds; switch(s->encryptalg){ case DESECB: 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){ p2 = p; ip = ds->ivec; for(eip = ip+8; ip < eip; ) *p2++ ^= *ip++; block_cipher(ds->expanded, p, 0); memmove(ds->ivec, p, 8); } break; case RC4: rc4(s->out.state, b->rp + offset, BLEN(b) - offset); break; } return b;}static Block*decryptb(Dstate *s, Block *bin){ Block *b, **l; uchar *p, *ep, *tp, *ip, *eip; DESstate *ds; uchar tmp[8]; int i; l = &bin; for(b = bin; 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"); } } l = &b->next; /* decrypt */ switch(s->encryptalg){ case DESECB: ds = s->in.state; ep = b->rp + BLEN(b); for(p = b->rp; 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; 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; case RC4: rc4(s->in.state, b->rp, BLEN(b)); break; } } return bin;}static Block*digestb(Dstate *s, Block *b, int offset){ uchar *p; DigestState ss; uchar msgid[4]; ulong n, h; OneWay *w; w = &s->out; memset(&ss, 0, sizeof(ss)); h = s->diglen + offset; n = BLEN(b) - h; /* hash secret + message */ (*s->hf)(w->secret, w->slen, 0, &ss); (*s->hf)(b->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->hf)(msgid, 4, b->rp + offset, &ss); return b;}static voidcheckdigestb(Dstate *s, Block *bin){ uchar *p; DigestState ss; uchar msgid[4]; int n, h; OneWay *w; uchar digest[128]; Block *b; w = &s->in; memset(&ss, 0, sizeof(ss)); /* hash secret */ (*s->hf)(w->secret, w->slen, 0, &ss); /* hash message */ h = s->diglen; for(b = bin; b; b = b->next){ n = BLEN(b) - h; if(n < 0) panic("checkdigestb"); (*s->hf)(b->rp + h, n, 0, &ss); h = 0; } /* hash message id */ p = msgid; n = w->mid; *p++ = n>>24; *p++ = n>>16; *p++ = n>>8; *p = n; (*s->hf)(msgid, 4, digest, &ss); if(memcmp(digest, bin->rp, s->diglen) != 0) error("bad digest");}/* get channel associated with an fd */static Chan*buftochan(char *p){ Chan *c; int fd; if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ return c;}/* hand up a digest connection */static voidsslhangup(Dstate *s){ Block *b; qlock(&s->in.q); 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 = Sincomplete; qunlock(&s->in.q);}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 voiddsnew(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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -