## 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 <libcrypt.h>
#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 <libcrypt.h>
.
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 <libcrypt.h>
.
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 <mp.h>
#include <libsec.h>
.
## 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; i<Maxdstate; i++){
if(dstate[i] == nil){
dsnew(ch, &dstate[i]);
ret = dstate[i];
.
1425,1427c
int i;
Dstate *ret;
.
1399a
if(devtab[c->type] == &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
|