merge
This commit is contained in:
commit
f777743b72
18 changed files with 346 additions and 441 deletions
|
@ -35,6 +35,7 @@ extern void* poolalloc(Pool*, ulong);
|
|||
extern void* poolallocalign(Pool*, ulong, ulong, long, ulong);
|
||||
extern void poolfree(Pool*, void*);
|
||||
extern ulong poolmsize(Pool*, void*);
|
||||
extern int poolisoverlap(Pool*, void*, ulong);
|
||||
extern void* poolrealloc(Pool*, void*, ulong);
|
||||
extern void poolcheck(Pool*);
|
||||
extern int poolcompact(Pool*);
|
||||
|
@ -43,6 +44,7 @@ extern void pooldump(Pool*);
|
|||
|
||||
extern Pool* mainmem;
|
||||
extern Pool* imagmem;
|
||||
extern Pool* secrmem;
|
||||
|
||||
enum { /* flags */
|
||||
POOL_ANTAGONISM = 1<<0,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.TH POOL 2
|
||||
.SH NAME
|
||||
poolalloc, poolallocalign, poolfree, poolmsize, poolrealloc, poolcompact, poolcheck, poolblockcheck,
|
||||
poolalloc, poolallocalign, poolfree, poolmsize, poolisoverlap, poolrealloc, poolcompact, poolcheck, poolblockcheck,
|
||||
pooldump \- general memory management routines
|
||||
.SH SYNOPSIS
|
||||
.B #include <u.h>
|
||||
|
@ -25,6 +25,9 @@ void poolfree(Pool* pool, void* ptr)
|
|||
ulong poolmsize(Pool* pool, void* ptr)
|
||||
.PP
|
||||
.B
|
||||
int poolisoverlap(Pool* pool, void* ptr, ulong len)
|
||||
.PP
|
||||
.B
|
||||
void* poolrealloc(Pool* pool, void* ptr, ulong size)
|
||||
.PP
|
||||
.B
|
||||
|
@ -109,6 +112,13 @@ that would usually go unused.
|
|||
.IR Poolmsize
|
||||
grows the block to encompass this extra space and returns the new size.
|
||||
.PP
|
||||
.I Poolisoverlap
|
||||
checks if the byte span
|
||||
.BR [ptr , ptr + len)
|
||||
overlaps the arenas of the specified
|
||||
.BR pool ,
|
||||
returning non-zero when there is overlap or zero if none.
|
||||
.PP
|
||||
The
|
||||
.I poolblockcheck
|
||||
and
|
||||
|
|
|
@ -261,8 +261,8 @@ espclose(Conv *c)
|
|||
ipmove(c->raddr, IPnoaddr);
|
||||
|
||||
ecb = (Espcb*)c->ptcl;
|
||||
free(ecb->espstate);
|
||||
free(ecb->ahstate);
|
||||
secfree(ecb->espstate);
|
||||
secfree(ecb->ahstate);
|
||||
memset(ecb, 0, sizeof(Espcb));
|
||||
}
|
||||
|
||||
|
@ -694,16 +694,16 @@ setalg(Espcb *ecb, char **f, int n, Algorithm *alg)
|
|||
return "non-hex character in key";
|
||||
}
|
||||
/* collapse hex digits into complete bytes in reverse order in key */
|
||||
key = smalloc(nbyte);
|
||||
key = secalloc(nbyte);
|
||||
for(i = 0; i < nchar && i/2 < nbyte; i++) {
|
||||
c = f[2][nchar-i-1];
|
||||
if(i&1)
|
||||
c <<= 4;
|
||||
key[i/2] |= c;
|
||||
}
|
||||
|
||||
memset(f[2], 0, nchar);
|
||||
alg->init(ecb, alg->name, key, alg->keylen);
|
||||
free(key);
|
||||
secfree(key);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -791,7 +791,7 @@ shaahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
|
|||
ecb->ahblklen = 1;
|
||||
ecb->ahlen = BITS2BYTES(96);
|
||||
ecb->auth = shaauth;
|
||||
ecb->ahstate = smalloc(klen);
|
||||
ecb->ahstate = secalloc(klen);
|
||||
memmove(ecb->ahstate, key, klen);
|
||||
}
|
||||
|
||||
|
@ -853,8 +853,10 @@ aescbcespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
|
|||
ecb->espblklen = Aesblk;
|
||||
ecb->espivlen = Aesblk;
|
||||
ecb->cipher = aescbccipher;
|
||||
ecb->espstate = smalloc(sizeof(AESstate));
|
||||
ecb->espstate = secalloc(sizeof(AESstate));
|
||||
setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
|
||||
memset(ivec, 0, sizeof(ivec));
|
||||
memset(key, 0, sizeof(key));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -911,8 +913,10 @@ aesctrespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
|
|||
ecb->espblklen = Aesblk;
|
||||
ecb->espivlen = Aesblk;
|
||||
ecb->cipher = aesctrcipher;
|
||||
ecb->espstate = smalloc(sizeof(AESstate));
|
||||
ecb->espstate = secalloc(sizeof(AESstate));
|
||||
setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
|
||||
memset(ivec, 0, sizeof(ivec));
|
||||
memset(key, 0, sizeof(key));
|
||||
}
|
||||
|
||||
|
||||
|
@ -963,7 +967,7 @@ md5ahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
|
|||
ecb->ahblklen = 1;
|
||||
ecb->ahlen = BITS2BYTES(96);
|
||||
ecb->auth = md5auth;
|
||||
ecb->ahstate = smalloc(klen);
|
||||
ecb->ahstate = secalloc(klen);
|
||||
memmove(ecb->ahstate, key, klen);
|
||||
}
|
||||
|
||||
|
@ -1020,8 +1024,10 @@ desespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
|
|||
ecb->espivlen = Desblk;
|
||||
|
||||
ecb->cipher = descipher;
|
||||
ecb->espstate = smalloc(sizeof(DESstate));
|
||||
ecb->espstate = secalloc(sizeof(DESstate));
|
||||
setupDESstate(ecb->espstate, key, ivec);
|
||||
memset(ivec, 0, sizeof(ivec));
|
||||
memset(key, 0, sizeof(key));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1042,8 +1048,10 @@ des3espinit(Espcb *ecb, char *name, uchar *k, unsigned n)
|
|||
ecb->espivlen = Desblk;
|
||||
|
||||
ecb->cipher = des3cipher;
|
||||
ecb->espstate = smalloc(sizeof(DES3state));
|
||||
ecb->espstate = secalloc(sizeof(DES3state));
|
||||
setupDES3state(ecb->espstate, key, ivec);
|
||||
memset(ivec, 0, sizeof(ivec));
|
||||
memset(key, 0, sizeof(key));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -872,6 +872,11 @@ cpuidentify(void)
|
|||
fprestore = fpx87restore;
|
||||
}
|
||||
|
||||
if(strcmp(m->cpuidid, "GenuineIntel") == 0 && (m->cpuidcx & Rdrnd) != 0)
|
||||
hwrandbuf = rdrandbuf;
|
||||
else
|
||||
hwrandbuf = nil;
|
||||
|
||||
cputype = t;
|
||||
return t->family;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ PORT=\
|
|||
proc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
random.$O\
|
||||
rdb.$O\
|
||||
rebootcmd.$O\
|
||||
segment.$O\
|
||||
|
@ -52,7 +53,6 @@ OBJ=\
|
|||
memory.$O\
|
||||
mmu.$O\
|
||||
trap.$O\
|
||||
pcrandom.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
static int haverdrand;
|
||||
|
||||
struct Rb
|
||||
{
|
||||
QLock;
|
||||
Rendez producer;
|
||||
Rendez consumer;
|
||||
ulong randomcount;
|
||||
uchar buf[128];
|
||||
uchar *ep;
|
||||
uchar *rp;
|
||||
uchar *wp;
|
||||
uchar next;
|
||||
uchar wakeme;
|
||||
ushort bits;
|
||||
ulong randn;
|
||||
} rb;
|
||||
|
||||
static int
|
||||
rbnotfull(void*)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = rb.rp - rb.wp;
|
||||
return i != 1 && i != (1 - sizeof(rb.buf));
|
||||
}
|
||||
|
||||
static int
|
||||
rbnotempty(void*)
|
||||
{
|
||||
return rb.wp != rb.rp;
|
||||
}
|
||||
|
||||
static void
|
||||
genrandom(void*)
|
||||
{
|
||||
up->basepri = PriNormal;
|
||||
up->priority = up->basepri;
|
||||
|
||||
while(waserror())
|
||||
;
|
||||
for(;;){
|
||||
if(++rb.randomcount <= 100000)
|
||||
continue;
|
||||
if(anyhigher())
|
||||
sched();
|
||||
if(!rbnotfull(0))
|
||||
sleep(&rb.producer, rbnotfull, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* produce random bits in a circular buffer
|
||||
*/
|
||||
static void
|
||||
randomclock(void)
|
||||
{
|
||||
if(rb.randomcount == 0 || !rbnotfull(0))
|
||||
return;
|
||||
|
||||
rb.bits = (rb.bits<<2) ^ rb.randomcount;
|
||||
rb.randomcount = 0;
|
||||
|
||||
rb.next++;
|
||||
if(rb.next != 8/2)
|
||||
return;
|
||||
rb.next = 0;
|
||||
|
||||
*rb.wp ^= rb.bits;
|
||||
if(rb.wp+1 == rb.ep)
|
||||
rb.wp = rb.buf;
|
||||
else
|
||||
rb.wp = rb.wp+1;
|
||||
|
||||
if(rb.wakeme)
|
||||
wakeup(&rb.consumer);
|
||||
}
|
||||
|
||||
void
|
||||
randominit(void)
|
||||
{
|
||||
if(!strcmp(m->cpuidid, "GenuineIntel")
|
||||
&& (m->cpuidcx & Rdrnd)){
|
||||
haverdrand = 1;
|
||||
}
|
||||
else{
|
||||
/* Frequency close but not equal to HZ */
|
||||
addclock0link(randomclock, MS2HZ+3);
|
||||
rb.ep = rb.buf + sizeof(rb.buf);
|
||||
rb.rp = rb.wp = rb.buf;
|
||||
kproc("genrandom", genrandom, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* consume random bytes from a circular buffer
|
||||
*/
|
||||
ulong
|
||||
randomread(void *xp, ulong n)
|
||||
{
|
||||
uchar *e, *p;
|
||||
ulong x;
|
||||
|
||||
p = xp;
|
||||
|
||||
if(haverdrand){
|
||||
rdrandbuf(p, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
if(waserror()){
|
||||
qunlock(&rb);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
qlock(&rb);
|
||||
for(e = p + n; p < e; ){
|
||||
if(rb.wp == rb.rp){
|
||||
rb.wakeme = 1;
|
||||
wakeup(&rb.producer);
|
||||
sleep(&rb.consumer, rbnotempty, 0);
|
||||
rb.wakeme = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* beating clocks will be predictable if
|
||||
* they are synchronized. Use a cheap pseudo-
|
||||
* random number generator to obscure any cycles.
|
||||
*/
|
||||
x = rb.randn*1103515245 ^ *rb.rp;
|
||||
*p++ = rb.randn = x;
|
||||
|
||||
if(rb.rp+1 == rb.ep)
|
||||
rb.rp = rb.buf;
|
||||
else
|
||||
rb.rp = rb.rp+1;
|
||||
}
|
||||
qunlock(&rb);
|
||||
poperror();
|
||||
|
||||
wakeup(&rb.producer);
|
||||
|
||||
return n;
|
||||
}
|
|
@ -48,6 +48,7 @@ static uchar basicrates[] = {
|
|||
|
||||
static Block* wifidecrypt(Wifi *, Wnode *, Block *);
|
||||
static Block* wifiencrypt(Wifi *, Wnode *, Block *);
|
||||
static void freewifikeys(Wifi *, Wnode *);
|
||||
|
||||
static uchar*
|
||||
srcaddr(Wifipkt *w)
|
||||
|
@ -197,6 +198,7 @@ nodelookup(Wifi *wifi, uchar *bssid, int new)
|
|||
}
|
||||
if(!new)
|
||||
return nil;
|
||||
freewifikeys(wifi, nn);
|
||||
memset(nn, 0, sizeof(Wnode));
|
||||
memmove(nn->bssid, bssid, Eaddrlen);
|
||||
nn->lastseen = MACHP(0)->ticks;
|
||||
|
@ -465,6 +467,23 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
freewifikeys(Wifi *wifi, Wnode *wn)
|
||||
{
|
||||
int i;
|
||||
|
||||
wlock(&wifi->crypt);
|
||||
for(i=0; i<nelem(wn->rxkey); i++){
|
||||
secfree(wn->rxkey[i]);
|
||||
wn->rxkey[i] = nil;
|
||||
}
|
||||
for(i=0; i<nelem(wn->txkey); i++){
|
||||
secfree(wn->txkey[i]);
|
||||
wn->txkey[i] = nil;
|
||||
}
|
||||
wunlock(&wifi->crypt);
|
||||
}
|
||||
|
||||
static void
|
||||
wifideauth(Wifi *wifi, Wnode *wn)
|
||||
{
|
||||
|
@ -474,8 +493,7 @@ wifideauth(Wifi *wifi, Wnode *wn)
|
|||
|
||||
/* deassociate node, clear keys */
|
||||
setstatus(wifi, wn, Sunauth);
|
||||
memset(wn->rxkey, 0, sizeof(wn->rxkey));
|
||||
memset(wn->txkey, 0, sizeof(wn->txkey));
|
||||
freewifikeys(wifi, wn);
|
||||
wn->aid = 0;
|
||||
|
||||
if(wn == wifi->bss){
|
||||
|
@ -789,11 +807,13 @@ static char *ciphers[] = {
|
|||
[CCMP] "ccmp",
|
||||
};
|
||||
|
||||
static int
|
||||
parsekey(Wkey *k, char *s)
|
||||
static Wkey*
|
||||
parsekey(char *s)
|
||||
{
|
||||
char buf[256], *p;
|
||||
int i;
|
||||
uchar key[32];
|
||||
int i, n;
|
||||
Wkey *k;
|
||||
|
||||
strncpy(buf, s, sizeof(buf)-1);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
|
@ -801,20 +821,35 @@ parsekey(Wkey *k, char *s)
|
|||
*p++ = 0;
|
||||
else
|
||||
p = buf;
|
||||
for(i=0; i<nelem(ciphers); i++){
|
||||
if(ciphers[i] == nil)
|
||||
continue;
|
||||
n = hextob(p, &p, key, sizeof(key));
|
||||
for(i=0; i<nelem(ciphers); i++)
|
||||
if(strcmp(ciphers[i], buf) == 0)
|
||||
break;
|
||||
switch(i){
|
||||
case 0:
|
||||
k = secalloc(sizeof(Wkey));
|
||||
break;
|
||||
case TKIP:
|
||||
if(n != 32)
|
||||
return nil;
|
||||
k = secalloc(sizeof(Wkey) + n);
|
||||
memmove(k->key, key, n);
|
||||
break;
|
||||
case CCMP:
|
||||
if(n != 16)
|
||||
return nil;
|
||||
k = secalloc(sizeof(Wkey) + sizeof(AESstate));
|
||||
setupAESstate((AESstate*)k->key, key, n, nil);
|
||||
break;
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
if(i >= nelem(ciphers))
|
||||
return -1;
|
||||
memset(k, 0, sizeof(Wkey));
|
||||
k->len = hextob(p, &p, k->key, sizeof(k->key));
|
||||
memset(key, 0, sizeof(key));
|
||||
if(*p == '@')
|
||||
k->tsc = strtoull(++p, nil, 16);
|
||||
k->len = n;
|
||||
k->cipher = i;
|
||||
return 0;
|
||||
return k;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -874,7 +909,7 @@ wifictl(Wifi *wifi, void *buf, long n)
|
|||
Cmdbuf *cb;
|
||||
Cmdtab *ct;
|
||||
Wnode *wn;
|
||||
Wkey *k;
|
||||
Wkey *k, **kk;
|
||||
|
||||
cb = nil;
|
||||
if(waserror()){
|
||||
|
@ -931,8 +966,7 @@ wifictl(Wifi *wifi, void *buf, long n)
|
|||
memmove(wifi->bssid, addr, Eaddrlen);
|
||||
goto Findbss;
|
||||
case CMauth:
|
||||
memset(wn->rxkey, 0, sizeof(wn->rxkey));
|
||||
memset(wn->txkey, 0, sizeof(wn->txkey));
|
||||
freewifikeys(wifi, wn);
|
||||
if(cb->f[1] == nil)
|
||||
wn->rsnelen = 0;
|
||||
else
|
||||
|
@ -947,12 +981,24 @@ wifictl(Wifi *wifi, void *buf, long n)
|
|||
break;
|
||||
case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
|
||||
case CMtxkey0:
|
||||
if(ct->index < CMtxkey0)
|
||||
k = &wn->rxkey[ct->index - CMrxkey0];
|
||||
else
|
||||
k = &wn->txkey[ct->index - CMtxkey0];
|
||||
if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
|
||||
if(cb->f[1] == nil)
|
||||
error(Ebadarg);
|
||||
k = parsekey(cb->f[1]);
|
||||
if(k == nil)
|
||||
error("bad key");
|
||||
memset(cb->f[1], 0, strlen(cb->f[1]));
|
||||
if(k->cipher == 0){
|
||||
secfree(k);
|
||||
k = nil;
|
||||
}
|
||||
if(ct->index < CMtxkey0)
|
||||
kk = &wn->rxkey[ct->index - CMrxkey0];
|
||||
else
|
||||
kk = &wn->txkey[ct->index - CMtxkey0];
|
||||
wlock(&wifi->crypt);
|
||||
secfree(*kk);
|
||||
*kk = k;
|
||||
wunlock(&wifi->crypt);
|
||||
if(ct->index >= CMtxkey0 && wn->status == Sblocked)
|
||||
setstatus(wifi, wn, Sassoc);
|
||||
break;
|
||||
|
@ -968,6 +1014,7 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
|
|||
static uchar zeros[Eaddrlen];
|
||||
char *s, *p, *e;
|
||||
Wnode *wn;
|
||||
Wkey *k;
|
||||
long now;
|
||||
int i;
|
||||
|
||||
|
@ -982,12 +1029,18 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
|
|||
p = seprint(p, e, "channel: %.2d\n", wn->channel);
|
||||
|
||||
/* only print key ciphers and key length */
|
||||
for(i = 0; i<nelem(wn->rxkey); i++)
|
||||
p = seprint(p, e, "rxkey%d: %s:[%d]\n", i,
|
||||
ciphers[wn->rxkey[i].cipher], wn->rxkey[i].len);
|
||||
for(i = 0; i<nelem(wn->txkey); i++)
|
||||
p = seprint(p, e, "txkey%d: %s:[%d]\n", i,
|
||||
ciphers[wn->txkey[i].cipher], wn->txkey[i].len);
|
||||
rlock(&wifi->crypt);
|
||||
for(i = 0; i<nelem(wn->rxkey); i++){
|
||||
if((k = wn->rxkey[i]) != nil)
|
||||
p = seprint(p, e, "rxkey%d: %s:[%d]\n", i,
|
||||
ciphers[k->cipher], k->len);
|
||||
}
|
||||
for(i = 0; i<nelem(wn->txkey); i++){
|
||||
if((k = wn->txkey[i]) != nil)
|
||||
p = seprint(p, e, "txkey%d: %s:[%d]\n", i,
|
||||
ciphers[k->cipher], k->len);
|
||||
}
|
||||
runlock(&wifi->crypt);
|
||||
|
||||
if(wn->brsnelen > 0){
|
||||
p = seprint(p, e, "brsne: ");
|
||||
|
@ -1018,17 +1071,21 @@ static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
|
|||
static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
|
||||
|
||||
static Block*
|
||||
wifiencrypt(Wifi *, Wnode *wn, Block *b)
|
||||
wifiencrypt(Wifi *wifi, Wnode *wn, Block *b)
|
||||
{
|
||||
uvlong tsc;
|
||||
int n, kid;
|
||||
Wifipkt *w;
|
||||
Wkey *k;
|
||||
|
||||
rlock(&wifi->crypt);
|
||||
|
||||
kid = 0;
|
||||
k = &wn->txkey[kid];
|
||||
if(k->cipher == 0)
|
||||
k = wn->txkey[kid];
|
||||
if(k == nil){
|
||||
runlock(&wifi->crypt);
|
||||
return b;
|
||||
}
|
||||
|
||||
n = wifihdrlen((Wifipkt*)b->rp);
|
||||
|
||||
|
@ -1052,8 +1109,6 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
|
|||
b->rp[6] = tsc>>32;
|
||||
b->rp[7] = tsc>>40;
|
||||
b->rp += 8;
|
||||
if(k->len != 32)
|
||||
goto drop;
|
||||
tkipencrypt(k, w, b, tsc);
|
||||
break;
|
||||
case CCMP:
|
||||
|
@ -1066,15 +1121,10 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
|
|||
b->rp[6] = tsc>>32;
|
||||
b->rp[7] = tsc>>40;
|
||||
b->rp += 8;
|
||||
if(k->len != 16)
|
||||
goto drop;
|
||||
ccmpencrypt(k, w, b, tsc);
|
||||
break;
|
||||
default:
|
||||
drop:
|
||||
free(b);
|
||||
return nil;
|
||||
}
|
||||
runlock(&wifi->crypt);
|
||||
|
||||
b->rp = (uchar*)w;
|
||||
w->fc[1] |= 0x40;
|
||||
|
@ -1082,13 +1132,15 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
|
|||
}
|
||||
|
||||
static Block*
|
||||
wifidecrypt(Wifi *, Wnode *wn, Block *b)
|
||||
wifidecrypt(Wifi *wifi, Wnode *wn, Block *b)
|
||||
{
|
||||
uvlong tsc;
|
||||
int n, kid;
|
||||
Wifipkt *w;
|
||||
Wkey *k;
|
||||
|
||||
rlock(&wifi->crypt);
|
||||
|
||||
w = (Wifipkt*)b->rp;
|
||||
n = wifihdrlen(w);
|
||||
b->rp += n;
|
||||
|
@ -1101,7 +1153,9 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
|
|||
if((w->a1[0] & 1) == 0)
|
||||
kid = 4; /* use peerwise key for non-unicast */
|
||||
|
||||
k = &wn->rxkey[kid];
|
||||
k = wn->rxkey[kid];
|
||||
if(k == nil)
|
||||
goto drop;
|
||||
switch(k->cipher){
|
||||
case TKIP:
|
||||
tsc = (uvlong)b->rp[7]<<40 |
|
||||
|
@ -1111,7 +1165,7 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
|
|||
(uvlong)b->rp[0]<<8 |
|
||||
(uvlong)b->rp[2];
|
||||
b->rp += 8;
|
||||
if(tsc <= k->tsc || k->len != 32)
|
||||
if(tsc <= k->tsc)
|
||||
goto drop;
|
||||
if(tkipdecrypt(k, w, b, tsc) != 0)
|
||||
goto drop;
|
||||
|
@ -1124,16 +1178,18 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
|
|||
(uvlong)b->rp[1]<<8 |
|
||||
(uvlong)b->rp[0];
|
||||
b->rp += 8;
|
||||
if(tsc <= k->tsc || k->len != 16)
|
||||
if(tsc <= k->tsc)
|
||||
goto drop;
|
||||
if(ccmpdecrypt(k, w, b, tsc) != 0)
|
||||
goto drop;
|
||||
break;
|
||||
default:
|
||||
drop:
|
||||
runlock(&wifi->crypt);
|
||||
freeb(b);
|
||||
return nil;
|
||||
}
|
||||
runlock(&wifi->crypt);
|
||||
|
||||
k->tsc = tsc;
|
||||
b->rp -= n;
|
||||
|
@ -1564,12 +1620,10 @@ aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
|
|||
}
|
||||
|
||||
static int
|
||||
setupCCMP(Wkey *k, Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32], AESstate *as)
|
||||
setupCCMP(Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32])
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
setupAESstate(as, k->key, k->len, nil);
|
||||
|
||||
nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4;
|
||||
memmove(&nonce[1], w->a2, Eaddrlen);
|
||||
nonce[7] = tsc >> 40;
|
||||
|
@ -1599,11 +1653,10 @@ static void
|
|||
ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
|
||||
{
|
||||
uchar auth[32], nonce[13];
|
||||
AESstate as;
|
||||
|
||||
aesCCMencrypt(2, 8, nonce, auth,
|
||||
setupCCMP(k, w, tsc, nonce, auth, &as),
|
||||
b->rp, BLEN(b), &as);
|
||||
setupCCMP(w, tsc, nonce, auth),
|
||||
b->rp, BLEN(b), (AESstate*)k->key);
|
||||
b->wp += 8;
|
||||
}
|
||||
|
||||
|
@ -1611,13 +1664,12 @@ static int
|
|||
ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
|
||||
{
|
||||
uchar auth[32], nonce[13];
|
||||
AESstate as;
|
||||
|
||||
if(BLEN(b) < 8)
|
||||
return -1;
|
||||
|
||||
b->wp -= 8;
|
||||
return aesCCMdecrypt(2, 8, nonce, auth,
|
||||
setupCCMP(k, w, tsc, nonce, auth, &as),
|
||||
b->rp, BLEN(b), &as);
|
||||
setupCCMP(w, tsc, nonce, auth),
|
||||
b->rp, BLEN(b), (AESstate*)k->key);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ enum {
|
|||
|
||||
struct Wkey
|
||||
{
|
||||
int cipher;
|
||||
int len;
|
||||
uchar key[32];
|
||||
uvlong tsc;
|
||||
int cipher;
|
||||
int len;
|
||||
uvlong tsc;
|
||||
uchar key[];
|
||||
};
|
||||
|
||||
struct Wnode
|
||||
|
@ -30,8 +30,8 @@ struct Wnode
|
|||
|
||||
int rsnelen;
|
||||
uchar rsne[258];
|
||||
Wkey txkey[1];
|
||||
Wkey rxkey[5];
|
||||
Wkey *txkey[1];
|
||||
Wkey *rxkey[5];
|
||||
|
||||
int aid; /* association id */
|
||||
ulong lastsend;
|
||||
|
@ -58,6 +58,7 @@ struct Wifi
|
|||
|
||||
int debug;
|
||||
|
||||
RWlock crypt;
|
||||
Queue *iq;
|
||||
ulong watchdog;
|
||||
ulong lastauth;
|
||||
|
|
|
@ -29,6 +29,7 @@ PORT=\
|
|||
proc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
random.$O\
|
||||
rdb.$O\
|
||||
rebootcmd.$O\
|
||||
segment.$O\
|
||||
|
@ -49,7 +50,6 @@ OBJ=\
|
|||
memory.$O\
|
||||
mmu.$O\
|
||||
trap.$O\
|
||||
pcrandom.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
|
|
|
@ -53,8 +53,27 @@ static Pool pimagmem = {
|
|||
.private= &pimagpriv,
|
||||
};
|
||||
|
||||
static Private psecrpriv;
|
||||
static Pool psecrmem = {
|
||||
.name= "Secrets",
|
||||
.maxsize= 16*1024*1024,
|
||||
.minarena= 64*1024,
|
||||
.quantum= 32,
|
||||
.alloc= xalloc,
|
||||
.merge= xmerge,
|
||||
.flags= POOL_ANTAGONISM,
|
||||
|
||||
.lock= plock,
|
||||
.unlock= punlock,
|
||||
.print= poolprint,
|
||||
.panic= ppanic,
|
||||
|
||||
.private= &psecrpriv,
|
||||
};
|
||||
|
||||
Pool* mainmem = &pmainmem;
|
||||
Pool* imagmem = &pimagmem;
|
||||
Pool* secrmem = &psecrmem;
|
||||
|
||||
/*
|
||||
* because we can't print while we're holding the locks,
|
||||
|
@ -129,6 +148,7 @@ mallocsummary(void)
|
|||
{
|
||||
poolsummary(mainmem);
|
||||
poolsummary(imagmem);
|
||||
poolsummary(secrmem);
|
||||
}
|
||||
|
||||
/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
|
||||
|
@ -171,12 +191,9 @@ smalloc(ulong size)
|
|||
{
|
||||
void *v;
|
||||
|
||||
for(;;) {
|
||||
v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
|
||||
if(v != nil)
|
||||
break;
|
||||
while((v = poolalloc(mainmem, size+Npadlong*sizeof(ulong))) == nil){
|
||||
if(!waserror()){
|
||||
resrcwait(0);
|
||||
resrcwait(nil);
|
||||
poperror();
|
||||
}
|
||||
}
|
||||
|
@ -278,6 +295,34 @@ calloc(ulong n, ulong szelem)
|
|||
return v;
|
||||
}
|
||||
|
||||
/* secret memory, used to back cryptographic keys and cipher states */
|
||||
void*
|
||||
secalloc(ulong size)
|
||||
{
|
||||
void *v;
|
||||
|
||||
while((v = poolalloc(secrmem, size+Npadlong*sizeof(ulong))) == nil){
|
||||
if(!waserror()){
|
||||
resrcwait(nil);
|
||||
poperror();
|
||||
}
|
||||
}
|
||||
if(Npadlong){
|
||||
v = (ulong*)v+Npadlong;
|
||||
setmalloctag(v, getcallerpc(&size));
|
||||
setrealloctag(v, 0);
|
||||
}
|
||||
memset(v, 0, size);
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
secfree(void *v)
|
||||
{
|
||||
if(v != nil)
|
||||
poolfree(secrmem, (ulong*)v-Npadlong);
|
||||
}
|
||||
|
||||
void
|
||||
setmalloctag(void *v, uintptr pc)
|
||||
{
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
#include "pool.h"
|
||||
|
||||
#include <pool.h>
|
||||
#include <authsrv.h>
|
||||
|
||||
void (*consdebug)(void) = nil;
|
||||
|
@ -21,7 +21,6 @@ int panicking;
|
|||
char *sysname;
|
||||
vlong fasthz;
|
||||
|
||||
static void seedrand(void);
|
||||
static int readtime(ulong, char*, int);
|
||||
static int readbintime(char*, int);
|
||||
static int writetime(char*, int);
|
||||
|
@ -616,7 +615,8 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
"%lud/%lud user\n"
|
||||
"%lud/%lud swap\n"
|
||||
"%llud/%llud/%llud kernel malloc\n"
|
||||
"%llud/%llud/%llud kernel draw\n",
|
||||
"%llud/%llud/%llud kernel draw\n"
|
||||
"%llud/%llud/%llud kernel secret\n",
|
||||
(uvlong)conf.npage*BY2PG,
|
||||
(uvlong)BY2PG,
|
||||
conf.npage-conf.upages,
|
||||
|
@ -627,7 +627,10 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
(uvlong)mainmem->maxsize,
|
||||
(uvlong)imagmem->curalloc,
|
||||
(uvlong)imagmem->cursize,
|
||||
(uvlong)imagmem->maxsize);
|
||||
(uvlong)imagmem->maxsize,
|
||||
(uvlong)secrmem->curalloc,
|
||||
(uvlong)secrmem->cursize,
|
||||
(uvlong)secrmem->maxsize);
|
||||
|
||||
return readstr((ulong)offset, buf, n, tmp);
|
||||
|
||||
|
@ -845,31 +848,22 @@ Dev consdevtab = {
|
|||
|
||||
static ulong randn;
|
||||
|
||||
static void
|
||||
seedrand(void)
|
||||
int
|
||||
rand(void)
|
||||
{
|
||||
if(!waserror()){
|
||||
if(randn == 0)
|
||||
randomread((void*)&randn, sizeof(randn));
|
||||
poperror();
|
||||
}
|
||||
randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
|
||||
return randn;
|
||||
}
|
||||
|
||||
int
|
||||
nrand(int n)
|
||||
{
|
||||
if(randn == 0)
|
||||
seedrand();
|
||||
randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
|
||||
rand();
|
||||
return (randn>>16) % n;
|
||||
}
|
||||
|
||||
int
|
||||
rand(void)
|
||||
{
|
||||
nrand(1);
|
||||
return randn;
|
||||
}
|
||||
|
||||
static uvlong uvorder = 0x0001020304050607ULL;
|
||||
|
||||
static uchar*
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "ureg.h"
|
||||
#include "edf.h"
|
||||
|
||||
#include <pool.h>
|
||||
|
||||
enum
|
||||
{
|
||||
Qdir,
|
||||
|
@ -789,7 +791,7 @@ procread(Chan *c, void *va, long n, vlong off)
|
|||
if(addr < KZERO)
|
||||
return procctlmemio(c, p, addr, va, n, 1);
|
||||
|
||||
if(!iseve())
|
||||
if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
|
||||
error(Eperm);
|
||||
|
||||
/* validate kernel addresses */
|
||||
|
|
|
@ -1056,10 +1056,8 @@ onewaycleanup(OneWay *ow)
|
|||
{
|
||||
if(ow->controlpkt)
|
||||
freeb(ow->controlpkt);
|
||||
if(ow->authstate)
|
||||
free(ow->authstate);
|
||||
if(ow->cipherstate)
|
||||
free(ow->cipherstate);
|
||||
secfree(ow->authstate);
|
||||
secfree(ow->cipherstate);
|
||||
if(ow->compstate)
|
||||
free(ow->compstate);
|
||||
memset(ow, 0, sizeof(OneWay));
|
||||
|
@ -1920,14 +1918,10 @@ cipherfree(Conv *c)
|
|||
static void
|
||||
authfree(Conv *c)
|
||||
{
|
||||
if(c->in.authstate) {
|
||||
free(c->in.authstate);
|
||||
c->in.authstate = nil;
|
||||
}
|
||||
if(c->out.authstate) {
|
||||
free(c->out.authstate);
|
||||
c->out.authstate = nil;
|
||||
}
|
||||
secfree(c->in.authstate);
|
||||
secfree(c->out.authstate);
|
||||
c->in.authstate = nil;
|
||||
c->out.authstate = nil;
|
||||
c->in.auth = nil;
|
||||
c->in.authlen = 0;
|
||||
c->out.authlen = 0;
|
||||
|
@ -2019,7 +2013,7 @@ descipherinit(Conv *c)
|
|||
c->in.cipherblklen = 8;
|
||||
c->in.cipherivlen = 8;
|
||||
c->in.cipher = desdecrypt;
|
||||
c->in.cipherstate = smalloc(sizeof(DESstate));
|
||||
c->in.cipherstate = secalloc(sizeof(DESstate));
|
||||
setupDESstate(c->in.cipherstate, key, ivec);
|
||||
|
||||
/* out */
|
||||
|
@ -2030,7 +2024,7 @@ descipherinit(Conv *c)
|
|||
c->out.cipherblklen = 8;
|
||||
c->out.cipherivlen = 8;
|
||||
c->out.cipher = desencrypt;
|
||||
c->out.cipherstate = smalloc(sizeof(DESstate));
|
||||
c->out.cipherstate = secalloc(sizeof(DESstate));
|
||||
setupDESstate(c->out.cipherstate, key, ivec);
|
||||
}
|
||||
|
||||
|
@ -2129,7 +2123,7 @@ rc4cipherinit(Conv *c)
|
|||
c->in.cipherblklen = 1;
|
||||
c->in.cipherivlen = 4;
|
||||
c->in.cipher = rc4decrypt;
|
||||
cr = smalloc(sizeof(CipherRc4));
|
||||
cr = secalloc(sizeof(CipherRc4));
|
||||
memset(cr, 0, sizeof(*cr));
|
||||
setupRC4state(&cr->current, key, n);
|
||||
c->in.cipherstate = cr;
|
||||
|
@ -2140,7 +2134,7 @@ rc4cipherinit(Conv *c)
|
|||
c->out.cipherblklen = 1;
|
||||
c->out.cipherivlen = 4;
|
||||
c->out.cipher = rc4encrypt;
|
||||
cr = smalloc(sizeof(CipherRc4));
|
||||
cr = secalloc(sizeof(CipherRc4));
|
||||
memset(cr, 0, sizeof(*cr));
|
||||
setupRC4state(&cr->current, key, n);
|
||||
c->out.cipherstate = cr;
|
||||
|
@ -2195,7 +2189,7 @@ md5auth(OneWay *ow, uchar *t, int tlen)
|
|||
|
||||
memset(hash, 0, MD5dlen);
|
||||
seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16);
|
||||
r = memcmp(t+tlen, hash, ow->authlen) == 0;
|
||||
r = tsmemcmp(t+tlen, hash, ow->authlen) == 0;
|
||||
memmove(t+tlen, hash, ow->authlen);
|
||||
return r;
|
||||
}
|
||||
|
@ -2212,14 +2206,14 @@ md5authinit(Conv *c)
|
|||
keylen = 16;
|
||||
|
||||
/* in */
|
||||
c->in.authstate = smalloc(16);
|
||||
c->in.authstate = secalloc(16);
|
||||
memset(c->in.authstate, 0, 16);
|
||||
setkey(c->in.authstate, keylen, &c->in, "auth");
|
||||
c->in.authlen = 12;
|
||||
c->in.auth = md5auth;
|
||||
|
||||
/* out */
|
||||
c->out.authstate = smalloc(16);
|
||||
c->out.authstate = secalloc(16);
|
||||
memset(c->out.authstate, 0, 16);
|
||||
setkey(c->out.authstate, keylen, &c->out, "auth");
|
||||
c->out.authlen = 12;
|
||||
|
|
|
@ -373,14 +373,10 @@ sslclose(Chan *c)
|
|||
sslhangup(s);
|
||||
if(s->c)
|
||||
cclose(s->c);
|
||||
if(s->in.secret)
|
||||
free(s->in.secret);
|
||||
if(s->out.secret)
|
||||
free(s->out.secret);
|
||||
if(s->in.state)
|
||||
free(s->in.state);
|
||||
if(s->out.state)
|
||||
free(s->out.state);
|
||||
secfree(s->in.secret);
|
||||
secfree(s->out.secret);
|
||||
secfree(s->in.state);
|
||||
secfree(s->out.state);
|
||||
free(s);
|
||||
|
||||
}
|
||||
|
@ -826,10 +822,8 @@ sslput(Dstate *s, Block * volatile b)
|
|||
static void
|
||||
setsecret(OneWay *w, uchar *secret, int n)
|
||||
{
|
||||
if(w->secret)
|
||||
free(w->secret);
|
||||
|
||||
w->secret = smalloc(n);
|
||||
secfree(w->secret);
|
||||
w->secret = secalloc(n);
|
||||
memmove(w->secret, secret, n);
|
||||
w->slen = n;
|
||||
}
|
||||
|
@ -837,12 +831,8 @@ setsecret(OneWay *w, uchar *secret, int n)
|
|||
static void
|
||||
initDESkey(OneWay *w)
|
||||
{
|
||||
if(w->state){
|
||||
free(w->state);
|
||||
w->state = 0;
|
||||
}
|
||||
|
||||
w->state = smalloc(sizeof(DESstate));
|
||||
secfree(w->state);
|
||||
w->state = secalloc(sizeof(DESstate));
|
||||
if(w->slen >= 16)
|
||||
setupDESstate(w->state, w->secret, w->secret+8);
|
||||
else if(w->slen >= 8)
|
||||
|
@ -860,11 +850,6 @@ initDESkey_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;
|
||||
|
@ -872,25 +857,14 @@ initDESkey_40(OneWay *w)
|
|||
key[4] &= 0x0f;
|
||||
key[6] &= 0x0f;
|
||||
}
|
||||
|
||||
w->state = smalloc(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");
|
||||
initDESkey(w);
|
||||
}
|
||||
|
||||
static void
|
||||
initRC4key(OneWay *w)
|
||||
{
|
||||
if(w->state){
|
||||
free(w->state);
|
||||
w->state = 0;
|
||||
}
|
||||
|
||||
w->state = smalloc(sizeof(RC4state));
|
||||
secfree(w->state);
|
||||
w->state = secalloc(sizeof(RC4state));
|
||||
setupRC4state(w->state, w->secret, w->slen);
|
||||
}
|
||||
|
||||
|
@ -901,16 +875,9 @@ initRC4key(OneWay *w)
|
|||
static void
|
||||
initRC4key_40(OneWay *w)
|
||||
{
|
||||
if(w->state){
|
||||
free(w->state);
|
||||
w->state = 0;
|
||||
}
|
||||
|
||||
if(w->slen > 5)
|
||||
w->slen = 5;
|
||||
|
||||
w->state = smalloc(sizeof(RC4state));
|
||||
setupRC4state(w->state, w->secret, w->slen);
|
||||
initRC4key(w);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -920,16 +887,9 @@ initRC4key_40(OneWay *w)
|
|||
static void
|
||||
initRC4key_128(OneWay *w)
|
||||
{
|
||||
if(w->state){
|
||||
free(w->state);
|
||||
w->state = 0;
|
||||
}
|
||||
|
||||
if(w->slen > 16)
|
||||
w->slen = 16;
|
||||
|
||||
w->state = smalloc(sizeof(RC4state));
|
||||
setupRC4state(w->state, w->secret, w->slen);
|
||||
initRC4key(w);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1177,27 +1137,29 @@ sslwrite(Chan *c, void *a, long n, vlong)
|
|||
break;
|
||||
case Csin:
|
||||
p = cb->f[1];
|
||||
m = (strlen(p)*3)/2;
|
||||
x = smalloc(m);
|
||||
m = (strlen(p)*3)/2 + 1;
|
||||
x = secalloc(m);
|
||||
t = dec64(x, m, p, strlen(p));
|
||||
memset(p, 0, strlen(p));
|
||||
if(t <= 0){
|
||||
free(x);
|
||||
secfree(x);
|
||||
error(Ebadarg);
|
||||
}
|
||||
setsecret(&s->in, x, t);
|
||||
free(x);
|
||||
secfree(x);
|
||||
break;
|
||||
case Csout:
|
||||
p = cb->f[1];
|
||||
m = (strlen(p)*3)/2 + 1;
|
||||
x = smalloc(m);
|
||||
x = secalloc(m);
|
||||
t = dec64(x, m, p, strlen(p));
|
||||
memset(p, 0, strlen(p));
|
||||
if(t <= 0){
|
||||
free(x);
|
||||
secfree(x);
|
||||
error(Ebadarg);
|
||||
}
|
||||
setsecret(&s->out, x, t);
|
||||
free(x);
|
||||
secfree(x);
|
||||
break;
|
||||
}
|
||||
poperror();
|
||||
|
|
|
@ -1471,7 +1471,7 @@ struct Encalg
|
|||
static void
|
||||
initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
|
||||
{
|
||||
s->enckey = smalloc(sizeof(RC4state));
|
||||
s->enckey = secalloc(sizeof(RC4state));
|
||||
s->enc = rc4enc;
|
||||
s->dec = rc4enc;
|
||||
setupRC4state(s->enckey, p, ea->keylen);
|
||||
|
@ -1480,7 +1480,7 @@ initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
|
|||
static void
|
||||
initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
|
||||
{
|
||||
s->enckey = smalloc(sizeof(DES3state));
|
||||
s->enckey = secalloc(sizeof(DES3state));
|
||||
s->enc = des3enc;
|
||||
s->dec = des3dec;
|
||||
s->block = 8;
|
||||
|
@ -1490,7 +1490,7 @@ initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
|
|||
static void
|
||||
initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
|
||||
{
|
||||
s->enckey = smalloc(sizeof(AESstate));
|
||||
s->enckey = secalloc(sizeof(AESstate));
|
||||
s->enc = aesenc;
|
||||
s->dec = aesdec;
|
||||
s->block = 16;
|
||||
|
@ -1500,7 +1500,7 @@ initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
|
|||
static void
|
||||
initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
|
||||
{
|
||||
s->enckey = smalloc(sizeof(Chachastate));
|
||||
s->enckey = secalloc(sizeof(Chachastate));
|
||||
s->aead_enc = ccpoly_aead_enc;
|
||||
s->aead_dec = ccpoly_aead_dec;
|
||||
s->maclen = Poly1305dlen;
|
||||
|
@ -1517,7 +1517,7 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
|
|||
static void
|
||||
initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
|
||||
{
|
||||
s->enckey = smalloc(sizeof(AESGCMstate));
|
||||
s->enckey = secalloc(sizeof(AESGCMstate));
|
||||
s->aead_enc = aesgcm_aead_enc;
|
||||
s->aead_dec = aesgcm_aead_dec;
|
||||
s->maclen = 16;
|
||||
|
@ -1673,18 +1673,19 @@ tlswrite(Chan *c, void *a, long n, vlong off)
|
|||
ea = parseencalg(cb->f[2]);
|
||||
|
||||
p = cb->f[4];
|
||||
m = (strlen(p)*3)/2;
|
||||
x = smalloc(m);
|
||||
tos = smalloc(sizeof(Secret));
|
||||
toc = smalloc(sizeof(Secret));
|
||||
m = (strlen(p)*3)/2 + 1;
|
||||
x = secalloc(m);
|
||||
tos = secalloc(sizeof(Secret));
|
||||
toc = secalloc(sizeof(Secret));
|
||||
if(waserror()){
|
||||
secfree(x);
|
||||
freeSec(tos);
|
||||
freeSec(toc);
|
||||
free(x);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
m = dec64(x, m, p, strlen(p));
|
||||
memset(p, 0, strlen(p));
|
||||
if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
|
||||
error("not enough secret data provided");
|
||||
|
||||
|
@ -1719,7 +1720,7 @@ tlswrite(Chan *c, void *a, long n, vlong off)
|
|||
tos->encalg = ea->name;
|
||||
tos->hashalg = ha->name;
|
||||
|
||||
free(x);
|
||||
secfree(x);
|
||||
poperror();
|
||||
}else if(strcmp(cb->f[0], "changecipher") == 0){
|
||||
if(cb->nf != 1)
|
||||
|
@ -2048,17 +2049,10 @@ tlsstate(int s)
|
|||
static void
|
||||
freeSec(Secret *s)
|
||||
{
|
||||
void *k;
|
||||
|
||||
if(s == nil)
|
||||
return;
|
||||
k = s->enckey;
|
||||
if(k != nil){
|
||||
memset(k, 0, msize(k));
|
||||
free(k);
|
||||
}
|
||||
memset(s, 0, sizeof(*s));
|
||||
free(s);
|
||||
secfree(s->enckey);
|
||||
secfree(s);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2162,6 +2156,8 @@ ccpoly_aead_setiv(Secret *sec, uchar seq[8])
|
|||
iv[i+(ChachaIVlen-8)] ^= seq[i];
|
||||
|
||||
chacha_setiv(cs, iv);
|
||||
|
||||
memset(iv, 0, sizeof(iv));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2196,6 +2192,7 @@ aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data,
|
|||
for(i=0; i<8; i++) iv[4+i] ^= aad[i];
|
||||
memmove(reciv, iv+4, 8);
|
||||
aesgcm_setiv(sec->enckey, iv, 12);
|
||||
memset(iv, 0, sizeof(iv));
|
||||
aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
|
||||
return len + sec->maclen;
|
||||
}
|
||||
|
@ -2211,6 +2208,7 @@ aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data,
|
|||
memmove(iv, sec->mackey, 4);
|
||||
memmove(iv+4, reciv, 8);
|
||||
aesgcm_setiv(sec->enckey, iv, 12);
|
||||
memset(iv, 0, sizeof(iv));
|
||||
if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
|
||||
return -1;
|
||||
return len;
|
||||
|
|
|
@ -126,6 +126,7 @@ void gotolabel(Label*);
|
|||
char* getconfenv(void);
|
||||
long hostdomainwrite(char*, int);
|
||||
long hostownerwrite(char*, int);
|
||||
void (*hwrandbuf)(void*, ulong);
|
||||
void hzsched(void);
|
||||
Block* iallocb(int);
|
||||
void iallocsummary(void);
|
||||
|
@ -308,6 +309,8 @@ void sched(void);
|
|||
void scheddump(void);
|
||||
void schedinit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
void* secalloc(ulong);
|
||||
void secfree(void*);
|
||||
long seconds(void);
|
||||
uintptr segattach(int, char *, uintptr, uintptr);
|
||||
void segclock(uintptr);
|
||||
|
|
|
@ -5,135 +5,103 @@
|
|||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
struct Rb
|
||||
#include <libsec.h>
|
||||
|
||||
/* machine specific hardware random number generator */
|
||||
void (*hwrandbuf)(void*, ulong) = nil;
|
||||
|
||||
static struct
|
||||
{
|
||||
QLock;
|
||||
Rendez producer;
|
||||
Rendez consumer;
|
||||
ulong randomcount;
|
||||
uchar buf[128];
|
||||
uchar *ep;
|
||||
uchar *rp;
|
||||
uchar *wp;
|
||||
uchar next;
|
||||
uchar wakeme;
|
||||
ushort bits;
|
||||
ulong randn;
|
||||
} rb;
|
||||
Chachastate;
|
||||
} *rs;
|
||||
|
||||
static int
|
||||
rbnotfull(void*)
|
||||
typedef struct Seedbuf Seedbuf;
|
||||
struct Seedbuf
|
||||
{
|
||||
int i;
|
||||
ulong randomcount;
|
||||
uchar buf[64];
|
||||
uchar nbuf;
|
||||
uchar next;
|
||||
ushort bits;
|
||||
|
||||
i = rb.rp - rb.wp;
|
||||
return i != 1 && i != (1 - sizeof(rb.buf));
|
||||
}
|
||||
SHA2_512state ds;
|
||||
};
|
||||
|
||||
static int
|
||||
rbnotempty(void*)
|
||||
static void
|
||||
randomsample(Ureg*, Timer *t)
|
||||
{
|
||||
return rb.wp != rb.rp;
|
||||
Seedbuf *s = t->ta;
|
||||
|
||||
if(s->randomcount == 0 || s->nbuf >= sizeof(s->buf))
|
||||
return;
|
||||
s->bits = (s->bits<<2) ^ s->randomcount;
|
||||
s->randomcount = 0;
|
||||
if(++s->next < 8/2)
|
||||
return;
|
||||
s->next = 0;
|
||||
s->buf[s->nbuf++] ^= s->bits;
|
||||
}
|
||||
|
||||
static void
|
||||
genrandom(void*)
|
||||
randomseed(void*)
|
||||
{
|
||||
up->basepri = PriNormal;
|
||||
up->priority = up->basepri;
|
||||
Seedbuf *s;
|
||||
|
||||
while(waserror())
|
||||
;
|
||||
for(;;){
|
||||
if(++rb.randomcount <= 100000)
|
||||
s = secalloc(sizeof(Seedbuf));
|
||||
|
||||
if(hwrandbuf != nil)
|
||||
(*hwrandbuf)(s->buf, sizeof(s->buf));
|
||||
|
||||
/* Frequency close but not equal to HZ */
|
||||
up->tns = (vlong)(MS2HZ+3)*1000000LL;
|
||||
up->tmode = Tperiodic;
|
||||
up->tt = nil;
|
||||
up->ta = s;
|
||||
up->tf = randomsample;
|
||||
timeradd(up);
|
||||
while(s->nbuf < sizeof(s->buf)){
|
||||
if(++s->randomcount <= 100000)
|
||||
continue;
|
||||
if(anyhigher())
|
||||
sched();
|
||||
if(!rbnotfull(0))
|
||||
sleep(&rb.producer, rbnotfull, 0);
|
||||
}
|
||||
}
|
||||
timerdel(up);
|
||||
|
||||
/*
|
||||
* produce random bits in a circular buffer
|
||||
*/
|
||||
static void
|
||||
randomclock(void)
|
||||
{
|
||||
if(rb.randomcount == 0 || !rbnotfull(0))
|
||||
return;
|
||||
sha2_512(s->buf, sizeof(s->buf), s->buf, &s->ds);
|
||||
setupChachastate(rs, s->buf, 32, s->buf+32, 12, 20);
|
||||
qunlock(rs);
|
||||
|
||||
rb.bits = (rb.bits<<2) ^ rb.randomcount;
|
||||
rb.randomcount = 0;
|
||||
secfree(s);
|
||||
|
||||
rb.next++;
|
||||
if(rb.next != 8/2)
|
||||
return;
|
||||
rb.next = 0;
|
||||
|
||||
*rb.wp ^= rb.bits;
|
||||
if(rb.wp+1 == rb.ep)
|
||||
rb.wp = rb.buf;
|
||||
else
|
||||
rb.wp = rb.wp+1;
|
||||
|
||||
if(rb.wakeme)
|
||||
wakeup(&rb.consumer);
|
||||
pexit("", 1);
|
||||
}
|
||||
|
||||
void
|
||||
randominit(void)
|
||||
{
|
||||
/* Frequency close but not equal to HZ */
|
||||
addclock0link(randomclock, MS2HZ+3);
|
||||
rb.ep = rb.buf + sizeof(rb.buf);
|
||||
rb.rp = rb.wp = rb.buf;
|
||||
kproc("genrandom", genrandom, 0);
|
||||
rs = secalloc(sizeof(*rs));
|
||||
qlock(rs); /* randomseed() unlocks once seeded */
|
||||
kproc("randomseed", randomseed, nil);
|
||||
}
|
||||
|
||||
/*
|
||||
* consume random bytes from a circular buffer
|
||||
*/
|
||||
ulong
|
||||
randomread(void *xp, ulong n)
|
||||
{
|
||||
uchar *e, *p;
|
||||
ulong x;
|
||||
if(n == 0)
|
||||
return 0;
|
||||
|
||||
p = xp;
|
||||
if(hwrandbuf != nil)
|
||||
(*hwrandbuf)(xp, n);
|
||||
|
||||
if(waserror()){
|
||||
qunlock(&rb);
|
||||
qunlock(rs);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
qlock(&rb);
|
||||
for(e = p + n; p < e; ){
|
||||
if(rb.wp == rb.rp){
|
||||
rb.wakeme = 1;
|
||||
wakeup(&rb.producer);
|
||||
sleep(&rb.consumer, rbnotempty, 0);
|
||||
rb.wakeme = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* beating clocks will be predictable if
|
||||
* they are synchronized. Use a cheap pseudo-
|
||||
* random number generator to obscure any cycles.
|
||||
*/
|
||||
x = rb.randn*1103515245 ^ *rb.rp;
|
||||
*p++ = rb.randn = x;
|
||||
|
||||
if(rb.rp+1 == rb.ep)
|
||||
rb.rp = rb.buf;
|
||||
else
|
||||
rb.rp = rb.rp+1;
|
||||
}
|
||||
qunlock(&rb);
|
||||
qlock(rs);
|
||||
chacha_encrypt((uchar*)xp, n, rs);
|
||||
qunlock(rs);
|
||||
poperror();
|
||||
|
||||
wakeup(&rb.producer);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -1332,6 +1332,19 @@ poolmsize(Pool *p, void *v)
|
|||
return dsize;
|
||||
}
|
||||
|
||||
int
|
||||
poolisoverlap(Pool *p, void *v, ulong n)
|
||||
{
|
||||
Arena *a;
|
||||
|
||||
p->lock(p);
|
||||
for(a = p->arenalist; a != nil; a = a->down)
|
||||
if((uchar*)v+n > (uchar*)a && (uchar*)v < (uchar*)a+a->asize)
|
||||
break;
|
||||
p->unlock(p);
|
||||
return a != nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue