This commit is contained in:
cinap_lenrek 2016-08-27 20:50:55 +02:00
commit f777743b72
18 changed files with 346 additions and 441 deletions

View file

@ -35,6 +35,7 @@ extern void* poolalloc(Pool*, ulong);
extern void* poolallocalign(Pool*, ulong, ulong, long, ulong); extern void* poolallocalign(Pool*, ulong, ulong, long, ulong);
extern void poolfree(Pool*, void*); extern void poolfree(Pool*, void*);
extern ulong poolmsize(Pool*, void*); extern ulong poolmsize(Pool*, void*);
extern int poolisoverlap(Pool*, void*, ulong);
extern void* poolrealloc(Pool*, void*, ulong); extern void* poolrealloc(Pool*, void*, ulong);
extern void poolcheck(Pool*); extern void poolcheck(Pool*);
extern int poolcompact(Pool*); extern int poolcompact(Pool*);
@ -43,6 +44,7 @@ extern void pooldump(Pool*);
extern Pool* mainmem; extern Pool* mainmem;
extern Pool* imagmem; extern Pool* imagmem;
extern Pool* secrmem;
enum { /* flags */ enum { /* flags */
POOL_ANTAGONISM = 1<<0, POOL_ANTAGONISM = 1<<0,

View file

@ -1,6 +1,6 @@
.TH POOL 2 .TH POOL 2
.SH NAME .SH NAME
poolalloc, poolallocalign, poolfree, poolmsize, poolrealloc, poolcompact, poolcheck, poolblockcheck, poolalloc, poolallocalign, poolfree, poolmsize, poolisoverlap, poolrealloc, poolcompact, poolcheck, poolblockcheck,
pooldump \- general memory management routines pooldump \- general memory management routines
.SH SYNOPSIS .SH SYNOPSIS
.B #include <u.h> .B #include <u.h>
@ -25,6 +25,9 @@ void poolfree(Pool* pool, void* ptr)
ulong poolmsize(Pool* pool, void* ptr) ulong poolmsize(Pool* pool, void* ptr)
.PP .PP
.B .B
int poolisoverlap(Pool* pool, void* ptr, ulong len)
.PP
.B
void* poolrealloc(Pool* pool, void* ptr, ulong size) void* poolrealloc(Pool* pool, void* ptr, ulong size)
.PP .PP
.B .B
@ -109,6 +112,13 @@ that would usually go unused.
.IR Poolmsize .IR Poolmsize
grows the block to encompass this extra space and returns the new size. grows the block to encompass this extra space and returns the new size.
.PP .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 The
.I poolblockcheck .I poolblockcheck
and and

View file

@ -261,8 +261,8 @@ espclose(Conv *c)
ipmove(c->raddr, IPnoaddr); ipmove(c->raddr, IPnoaddr);
ecb = (Espcb*)c->ptcl; ecb = (Espcb*)c->ptcl;
free(ecb->espstate); secfree(ecb->espstate);
free(ecb->ahstate); secfree(ecb->ahstate);
memset(ecb, 0, sizeof(Espcb)); memset(ecb, 0, sizeof(Espcb));
} }
@ -694,16 +694,16 @@ setalg(Espcb *ecb, char **f, int n, Algorithm *alg)
return "non-hex character in key"; return "non-hex character in key";
} }
/* collapse hex digits into complete bytes in reverse order 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++) { for(i = 0; i < nchar && i/2 < nbyte; i++) {
c = f[2][nchar-i-1]; c = f[2][nchar-i-1];
if(i&1) if(i&1)
c <<= 4; c <<= 4;
key[i/2] |= c; key[i/2] |= c;
} }
memset(f[2], 0, nchar);
alg->init(ecb, alg->name, key, alg->keylen); alg->init(ecb, alg->name, key, alg->keylen);
free(key); secfree(key);
return nil; return nil;
} }
@ -791,7 +791,7 @@ shaahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
ecb->ahblklen = 1; ecb->ahblklen = 1;
ecb->ahlen = BITS2BYTES(96); ecb->ahlen = BITS2BYTES(96);
ecb->auth = shaauth; ecb->auth = shaauth;
ecb->ahstate = smalloc(klen); ecb->ahstate = secalloc(klen);
memmove(ecb->ahstate, key, klen); memmove(ecb->ahstate, key, klen);
} }
@ -853,8 +853,10 @@ aescbcespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
ecb->espblklen = Aesblk; ecb->espblklen = Aesblk;
ecb->espivlen = Aesblk; ecb->espivlen = Aesblk;
ecb->cipher = aescbccipher; ecb->cipher = aescbccipher;
ecb->espstate = smalloc(sizeof(AESstate)); ecb->espstate = secalloc(sizeof(AESstate));
setupAESstate(ecb->espstate, key, n /* keybytes */, ivec); setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
memset(ivec, 0, sizeof(ivec));
memset(key, 0, sizeof(key));
} }
static int static int
@ -911,8 +913,10 @@ aesctrespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
ecb->espblklen = Aesblk; ecb->espblklen = Aesblk;
ecb->espivlen = Aesblk; ecb->espivlen = Aesblk;
ecb->cipher = aesctrcipher; ecb->cipher = aesctrcipher;
ecb->espstate = smalloc(sizeof(AESstate)); ecb->espstate = secalloc(sizeof(AESstate));
setupAESstate(ecb->espstate, key, n /* keybytes */, ivec); 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->ahblklen = 1;
ecb->ahlen = BITS2BYTES(96); ecb->ahlen = BITS2BYTES(96);
ecb->auth = md5auth; ecb->auth = md5auth;
ecb->ahstate = smalloc(klen); ecb->ahstate = secalloc(klen);
memmove(ecb->ahstate, key, klen); memmove(ecb->ahstate, key, klen);
} }
@ -1020,8 +1024,10 @@ desespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
ecb->espivlen = Desblk; ecb->espivlen = Desblk;
ecb->cipher = descipher; ecb->cipher = descipher;
ecb->espstate = smalloc(sizeof(DESstate)); ecb->espstate = secalloc(sizeof(DESstate));
setupDESstate(ecb->espstate, key, ivec); setupDESstate(ecb->espstate, key, ivec);
memset(ivec, 0, sizeof(ivec));
memset(key, 0, sizeof(key));
} }
static void static void
@ -1042,8 +1048,10 @@ des3espinit(Espcb *ecb, char *name, uchar *k, unsigned n)
ecb->espivlen = Desblk; ecb->espivlen = Desblk;
ecb->cipher = des3cipher; ecb->cipher = des3cipher;
ecb->espstate = smalloc(sizeof(DES3state)); ecb->espstate = secalloc(sizeof(DES3state));
setupDES3state(ecb->espstate, key, ivec); setupDES3state(ecb->espstate, key, ivec);
memset(ivec, 0, sizeof(ivec));
memset(key, 0, sizeof(key));
} }

View file

@ -872,6 +872,11 @@ cpuidentify(void)
fprestore = fpx87restore; fprestore = fpx87restore;
} }
if(strcmp(m->cpuidid, "GenuineIntel") == 0 && (m->cpuidcx & Rdrnd) != 0)
hwrandbuf = rdrandbuf;
else
hwrandbuf = nil;
cputype = t; cputype = t;
return t->family; return t->family;
} }

View file

@ -32,6 +32,7 @@ PORT=\
proc.$O\ proc.$O\
qio.$O\ qio.$O\
qlock.$O\ qlock.$O\
random.$O\
rdb.$O\ rdb.$O\
rebootcmd.$O\ rebootcmd.$O\
segment.$O\ segment.$O\
@ -52,7 +53,6 @@ OBJ=\
memory.$O\ memory.$O\
mmu.$O\ mmu.$O\
trap.$O\ trap.$O\
pcrandom.$O\
$CONF.root.$O\ $CONF.root.$O\
$CONF.rootc.$O\ $CONF.rootc.$O\
$DEVS\ $DEVS\

View file

@ -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;
}

View file

@ -48,6 +48,7 @@ static uchar basicrates[] = {
static Block* wifidecrypt(Wifi *, Wnode *, Block *); static Block* wifidecrypt(Wifi *, Wnode *, Block *);
static Block* wifiencrypt(Wifi *, Wnode *, Block *); static Block* wifiencrypt(Wifi *, Wnode *, Block *);
static void freewifikeys(Wifi *, Wnode *);
static uchar* static uchar*
srcaddr(Wifipkt *w) srcaddr(Wifipkt *w)
@ -197,6 +198,7 @@ nodelookup(Wifi *wifi, uchar *bssid, int new)
} }
if(!new) if(!new)
return nil; return nil;
freewifikeys(wifi, nn);
memset(nn, 0, sizeof(Wnode)); memset(nn, 0, sizeof(Wnode));
memmove(nn->bssid, bssid, Eaddrlen); memmove(nn->bssid, bssid, Eaddrlen);
nn->lastseen = MACHP(0)->ticks; 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 static void
wifideauth(Wifi *wifi, Wnode *wn) wifideauth(Wifi *wifi, Wnode *wn)
{ {
@ -474,8 +493,7 @@ wifideauth(Wifi *wifi, Wnode *wn)
/* deassociate node, clear keys */ /* deassociate node, clear keys */
setstatus(wifi, wn, Sunauth); setstatus(wifi, wn, Sunauth);
memset(wn->rxkey, 0, sizeof(wn->rxkey)); freewifikeys(wifi, wn);
memset(wn->txkey, 0, sizeof(wn->txkey));
wn->aid = 0; wn->aid = 0;
if(wn == wifi->bss){ if(wn == wifi->bss){
@ -789,11 +807,13 @@ static char *ciphers[] = {
[CCMP] "ccmp", [CCMP] "ccmp",
}; };
static int static Wkey*
parsekey(Wkey *k, char *s) parsekey(char *s)
{ {
char buf[256], *p; char buf[256], *p;
int i; uchar key[32];
int i, n;
Wkey *k;
strncpy(buf, s, sizeof(buf)-1); strncpy(buf, s, sizeof(buf)-1);
buf[sizeof(buf)-1] = 0; buf[sizeof(buf)-1] = 0;
@ -801,20 +821,35 @@ parsekey(Wkey *k, char *s)
*p++ = 0; *p++ = 0;
else else
p = buf; p = buf;
for(i=0; i<nelem(ciphers); i++){ n = hextob(p, &p, key, sizeof(key));
if(ciphers[i] == nil) for(i=0; i<nelem(ciphers); i++)
continue;
if(strcmp(ciphers[i], buf) == 0) if(strcmp(ciphers[i], buf) == 0)
break; 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)) memset(key, 0, sizeof(key));
return -1;
memset(k, 0, sizeof(Wkey));
k->len = hextob(p, &p, k->key, sizeof(k->key));
if(*p == '@') if(*p == '@')
k->tsc = strtoull(++p, nil, 16); k->tsc = strtoull(++p, nil, 16);
k->len = n;
k->cipher = i; k->cipher = i;
return 0; return k;
} }
void void
@ -874,7 +909,7 @@ wifictl(Wifi *wifi, void *buf, long n)
Cmdbuf *cb; Cmdbuf *cb;
Cmdtab *ct; Cmdtab *ct;
Wnode *wn; Wnode *wn;
Wkey *k; Wkey *k, **kk;
cb = nil; cb = nil;
if(waserror()){ if(waserror()){
@ -931,8 +966,7 @@ wifictl(Wifi *wifi, void *buf, long n)
memmove(wifi->bssid, addr, Eaddrlen); memmove(wifi->bssid, addr, Eaddrlen);
goto Findbss; goto Findbss;
case CMauth: case CMauth:
memset(wn->rxkey, 0, sizeof(wn->rxkey)); freewifikeys(wifi, wn);
memset(wn->txkey, 0, sizeof(wn->txkey));
if(cb->f[1] == nil) if(cb->f[1] == nil)
wn->rsnelen = 0; wn->rsnelen = 0;
else else
@ -947,12 +981,24 @@ wifictl(Wifi *wifi, void *buf, long n)
break; break;
case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4: case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
case CMtxkey0: case CMtxkey0:
if(ct->index < CMtxkey0) if(cb->f[1] == nil)
k = &wn->rxkey[ct->index - CMrxkey0]; error(Ebadarg);
else k = parsekey(cb->f[1]);
k = &wn->txkey[ct->index - CMtxkey0]; if(k == nil)
if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
error("bad key"); 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) if(ct->index >= CMtxkey0 && wn->status == Sblocked)
setstatus(wifi, wn, Sassoc); setstatus(wifi, wn, Sassoc);
break; break;
@ -968,6 +1014,7 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
static uchar zeros[Eaddrlen]; static uchar zeros[Eaddrlen];
char *s, *p, *e; char *s, *p, *e;
Wnode *wn; Wnode *wn;
Wkey *k;
long now; long now;
int i; int i;
@ -982,12 +1029,18 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
p = seprint(p, e, "channel: %.2d\n", wn->channel); p = seprint(p, e, "channel: %.2d\n", wn->channel);
/* only print key ciphers and key length */ /* only print key ciphers and key length */
for(i = 0; i<nelem(wn->rxkey); i++) rlock(&wifi->crypt);
p = seprint(p, e, "rxkey%d: %s:[%d]\n", i, for(i = 0; i<nelem(wn->rxkey); i++){
ciphers[wn->rxkey[i].cipher], wn->rxkey[i].len); if((k = wn->rxkey[i]) != nil)
for(i = 0; i<nelem(wn->txkey); i++) p = seprint(p, e, "rxkey%d: %s:[%d]\n", i,
p = seprint(p, e, "txkey%d: %s:[%d]\n", i, ciphers[k->cipher], k->len);
ciphers[wn->txkey[i].cipher], wn->txkey[i].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){ if(wn->brsnelen > 0){
p = seprint(p, e, "brsne: "); 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 int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc);
static Block* static Block*
wifiencrypt(Wifi *, Wnode *wn, Block *b) wifiencrypt(Wifi *wifi, Wnode *wn, Block *b)
{ {
uvlong tsc; uvlong tsc;
int n, kid; int n, kid;
Wifipkt *w; Wifipkt *w;
Wkey *k; Wkey *k;
rlock(&wifi->crypt);
kid = 0; kid = 0;
k = &wn->txkey[kid]; k = wn->txkey[kid];
if(k->cipher == 0) if(k == nil){
runlock(&wifi->crypt);
return b; return b;
}
n = wifihdrlen((Wifipkt*)b->rp); n = wifihdrlen((Wifipkt*)b->rp);
@ -1052,8 +1109,6 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
b->rp[6] = tsc>>32; b->rp[6] = tsc>>32;
b->rp[7] = tsc>>40; b->rp[7] = tsc>>40;
b->rp += 8; b->rp += 8;
if(k->len != 32)
goto drop;
tkipencrypt(k, w, b, tsc); tkipencrypt(k, w, b, tsc);
break; break;
case CCMP: case CCMP:
@ -1066,15 +1121,10 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
b->rp[6] = tsc>>32; b->rp[6] = tsc>>32;
b->rp[7] = tsc>>40; b->rp[7] = tsc>>40;
b->rp += 8; b->rp += 8;
if(k->len != 16)
goto drop;
ccmpencrypt(k, w, b, tsc); ccmpencrypt(k, w, b, tsc);
break; break;
default:
drop:
free(b);
return nil;
} }
runlock(&wifi->crypt);
b->rp = (uchar*)w; b->rp = (uchar*)w;
w->fc[1] |= 0x40; w->fc[1] |= 0x40;
@ -1082,13 +1132,15 @@ wifiencrypt(Wifi *, Wnode *wn, Block *b)
} }
static Block* static Block*
wifidecrypt(Wifi *, Wnode *wn, Block *b) wifidecrypt(Wifi *wifi, Wnode *wn, Block *b)
{ {
uvlong tsc; uvlong tsc;
int n, kid; int n, kid;
Wifipkt *w; Wifipkt *w;
Wkey *k; Wkey *k;
rlock(&wifi->crypt);
w = (Wifipkt*)b->rp; w = (Wifipkt*)b->rp;
n = wifihdrlen(w); n = wifihdrlen(w);
b->rp += n; b->rp += n;
@ -1101,7 +1153,9 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
if((w->a1[0] & 1) == 0) if((w->a1[0] & 1) == 0)
kid = 4; /* use peerwise key for non-unicast */ kid = 4; /* use peerwise key for non-unicast */
k = &wn->rxkey[kid]; k = wn->rxkey[kid];
if(k == nil)
goto drop;
switch(k->cipher){ switch(k->cipher){
case TKIP: case TKIP:
tsc = (uvlong)b->rp[7]<<40 | tsc = (uvlong)b->rp[7]<<40 |
@ -1111,7 +1165,7 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
(uvlong)b->rp[0]<<8 | (uvlong)b->rp[0]<<8 |
(uvlong)b->rp[2]; (uvlong)b->rp[2];
b->rp += 8; b->rp += 8;
if(tsc <= k->tsc || k->len != 32) if(tsc <= k->tsc)
goto drop; goto drop;
if(tkipdecrypt(k, w, b, tsc) != 0) if(tkipdecrypt(k, w, b, tsc) != 0)
goto drop; goto drop;
@ -1124,16 +1178,18 @@ wifidecrypt(Wifi *, Wnode *wn, Block *b)
(uvlong)b->rp[1]<<8 | (uvlong)b->rp[1]<<8 |
(uvlong)b->rp[0]; (uvlong)b->rp[0];
b->rp += 8; b->rp += 8;
if(tsc <= k->tsc || k->len != 16) if(tsc <= k->tsc)
goto drop; goto drop;
if(ccmpdecrypt(k, w, b, tsc) != 0) if(ccmpdecrypt(k, w, b, tsc) != 0)
goto drop; goto drop;
break; break;
default: default:
drop: drop:
runlock(&wifi->crypt);
freeb(b); freeb(b);
return nil; return nil;
} }
runlock(&wifi->crypt);
k->tsc = tsc; k->tsc = tsc;
b->rp -= n; b->rp -= n;
@ -1564,12 +1620,10 @@ aesCCMdecrypt(int L, int M, uchar *N /* N[15-L] */,
} }
static int 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; uchar *p;
setupAESstate(as, k->key, k->len, nil);
nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4; nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4;
memmove(&nonce[1], w->a2, Eaddrlen); memmove(&nonce[1], w->a2, Eaddrlen);
nonce[7] = tsc >> 40; nonce[7] = tsc >> 40;
@ -1599,11 +1653,10 @@ static void
ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
{ {
uchar auth[32], nonce[13]; uchar auth[32], nonce[13];
AESstate as;
aesCCMencrypt(2, 8, nonce, auth, aesCCMencrypt(2, 8, nonce, auth,
setupCCMP(k, w, tsc, nonce, auth, &as), setupCCMP(w, tsc, nonce, auth),
b->rp, BLEN(b), &as); b->rp, BLEN(b), (AESstate*)k->key);
b->wp += 8; b->wp += 8;
} }
@ -1611,13 +1664,12 @@ static int
ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc)
{ {
uchar auth[32], nonce[13]; uchar auth[32], nonce[13];
AESstate as;
if(BLEN(b) < 8) if(BLEN(b) < 8)
return -1; return -1;
b->wp -= 8; b->wp -= 8;
return aesCCMdecrypt(2, 8, nonce, auth, return aesCCMdecrypt(2, 8, nonce, auth,
setupCCMP(k, w, tsc, nonce, auth, &as), setupCCMP(w, tsc, nonce, auth),
b->rp, BLEN(b), &as); b->rp, BLEN(b), (AESstate*)k->key);
} }

View file

@ -15,10 +15,10 @@ enum {
struct Wkey struct Wkey
{ {
int cipher; int cipher;
int len; int len;
uchar key[32]; uvlong tsc;
uvlong tsc; uchar key[];
}; };
struct Wnode struct Wnode
@ -30,8 +30,8 @@ struct Wnode
int rsnelen; int rsnelen;
uchar rsne[258]; uchar rsne[258];
Wkey txkey[1]; Wkey *txkey[1];
Wkey rxkey[5]; Wkey *rxkey[5];
int aid; /* association id */ int aid; /* association id */
ulong lastsend; ulong lastsend;
@ -58,6 +58,7 @@ struct Wifi
int debug; int debug;
RWlock crypt;
Queue *iq; Queue *iq;
ulong watchdog; ulong watchdog;
ulong lastauth; ulong lastauth;

View file

@ -29,6 +29,7 @@ PORT=\
proc.$O\ proc.$O\
qio.$O\ qio.$O\
qlock.$O\ qlock.$O\
random.$O\
rdb.$O\ rdb.$O\
rebootcmd.$O\ rebootcmd.$O\
segment.$O\ segment.$O\
@ -49,7 +50,6 @@ OBJ=\
memory.$O\ memory.$O\
mmu.$O\ mmu.$O\
trap.$O\ trap.$O\
pcrandom.$O\
$CONF.root.$O\ $CONF.root.$O\
$CONF.rootc.$O\ $CONF.rootc.$O\
$DEVS\ $DEVS\

View file

@ -53,8 +53,27 @@ static Pool pimagmem = {
.private= &pimagpriv, .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* mainmem = &pmainmem;
Pool* imagmem = &pimagmem; Pool* imagmem = &pimagmem;
Pool* secrmem = &psecrmem;
/* /*
* because we can't print while we're holding the locks, * because we can't print while we're holding the locks,
@ -129,6 +148,7 @@ mallocsummary(void)
{ {
poolsummary(mainmem); poolsummary(mainmem);
poolsummary(imagmem); poolsummary(imagmem);
poolsummary(secrmem);
} }
/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */ /* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
@ -171,12 +191,9 @@ smalloc(ulong size)
{ {
void *v; void *v;
for(;;) { while((v = poolalloc(mainmem, size+Npadlong*sizeof(ulong))) == nil){
v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
if(v != nil)
break;
if(!waserror()){ if(!waserror()){
resrcwait(0); resrcwait(nil);
poperror(); poperror();
} }
} }
@ -278,6 +295,34 @@ calloc(ulong n, ulong szelem)
return v; 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 void
setmalloctag(void *v, uintptr pc) setmalloctag(void *v, uintptr pc)
{ {

View file

@ -4,8 +4,8 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
#include "../port/error.h" #include "../port/error.h"
#include "pool.h"
#include <pool.h>
#include <authsrv.h> #include <authsrv.h>
void (*consdebug)(void) = nil; void (*consdebug)(void) = nil;
@ -21,7 +21,6 @@ int panicking;
char *sysname; char *sysname;
vlong fasthz; vlong fasthz;
static void seedrand(void);
static int readtime(ulong, char*, int); static int readtime(ulong, char*, int);
static int readbintime(char*, int); static int readbintime(char*, int);
static int writetime(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 user\n"
"%lud/%lud swap\n" "%lud/%lud swap\n"
"%llud/%llud/%llud kernel malloc\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)conf.npage*BY2PG,
(uvlong)BY2PG, (uvlong)BY2PG,
conf.npage-conf.upages, conf.npage-conf.upages,
@ -627,7 +627,10 @@ consread(Chan *c, void *buf, long n, vlong off)
(uvlong)mainmem->maxsize, (uvlong)mainmem->maxsize,
(uvlong)imagmem->curalloc, (uvlong)imagmem->curalloc,
(uvlong)imagmem->cursize, (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); return readstr((ulong)offset, buf, n, tmp);
@ -845,31 +848,22 @@ Dev consdevtab = {
static ulong randn; static ulong randn;
static void int
seedrand(void) rand(void)
{ {
if(!waserror()){ if(randn == 0)
randomread((void*)&randn, sizeof(randn)); randomread((void*)&randn, sizeof(randn));
poperror(); randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
} return randn;
} }
int int
nrand(int n) nrand(int n)
{ {
if(randn == 0) rand();
seedrand();
randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
return (randn>>16) % n; return (randn>>16) % n;
} }
int
rand(void)
{
nrand(1);
return randn;
}
static uvlong uvorder = 0x0001020304050607ULL; static uvlong uvorder = 0x0001020304050607ULL;
static uchar* static uchar*

View file

@ -9,6 +9,8 @@
#include "ureg.h" #include "ureg.h"
#include "edf.h" #include "edf.h"
#include <pool.h>
enum enum
{ {
Qdir, Qdir,
@ -789,7 +791,7 @@ procread(Chan *c, void *va, long n, vlong off)
if(addr < KZERO) if(addr < KZERO)
return procctlmemio(c, p, addr, va, n, 1); return procctlmemio(c, p, addr, va, n, 1);
if(!iseve()) if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
error(Eperm); error(Eperm);
/* validate kernel addresses */ /* validate kernel addresses */

View file

@ -1056,10 +1056,8 @@ onewaycleanup(OneWay *ow)
{ {
if(ow->controlpkt) if(ow->controlpkt)
freeb(ow->controlpkt); freeb(ow->controlpkt);
if(ow->authstate) secfree(ow->authstate);
free(ow->authstate); secfree(ow->cipherstate);
if(ow->cipherstate)
free(ow->cipherstate);
if(ow->compstate) if(ow->compstate)
free(ow->compstate); free(ow->compstate);
memset(ow, 0, sizeof(OneWay)); memset(ow, 0, sizeof(OneWay));
@ -1920,14 +1918,10 @@ cipherfree(Conv *c)
static void static void
authfree(Conv *c) authfree(Conv *c)
{ {
if(c->in.authstate) { secfree(c->in.authstate);
free(c->in.authstate); secfree(c->out.authstate);
c->in.authstate = nil; c->in.authstate = nil;
} c->out.authstate = nil;
if(c->out.authstate) {
free(c->out.authstate);
c->out.authstate = nil;
}
c->in.auth = nil; c->in.auth = nil;
c->in.authlen = 0; c->in.authlen = 0;
c->out.authlen = 0; c->out.authlen = 0;
@ -2019,7 +2013,7 @@ descipherinit(Conv *c)
c->in.cipherblklen = 8; c->in.cipherblklen = 8;
c->in.cipherivlen = 8; c->in.cipherivlen = 8;
c->in.cipher = desdecrypt; c->in.cipher = desdecrypt;
c->in.cipherstate = smalloc(sizeof(DESstate)); c->in.cipherstate = secalloc(sizeof(DESstate));
setupDESstate(c->in.cipherstate, key, ivec); setupDESstate(c->in.cipherstate, key, ivec);
/* out */ /* out */
@ -2030,7 +2024,7 @@ descipherinit(Conv *c)
c->out.cipherblklen = 8; c->out.cipherblklen = 8;
c->out.cipherivlen = 8; c->out.cipherivlen = 8;
c->out.cipher = desencrypt; c->out.cipher = desencrypt;
c->out.cipherstate = smalloc(sizeof(DESstate)); c->out.cipherstate = secalloc(sizeof(DESstate));
setupDESstate(c->out.cipherstate, key, ivec); setupDESstate(c->out.cipherstate, key, ivec);
} }
@ -2129,7 +2123,7 @@ rc4cipherinit(Conv *c)
c->in.cipherblklen = 1; c->in.cipherblklen = 1;
c->in.cipherivlen = 4; c->in.cipherivlen = 4;
c->in.cipher = rc4decrypt; c->in.cipher = rc4decrypt;
cr = smalloc(sizeof(CipherRc4)); cr = secalloc(sizeof(CipherRc4));
memset(cr, 0, sizeof(*cr)); memset(cr, 0, sizeof(*cr));
setupRC4state(&cr->current, key, n); setupRC4state(&cr->current, key, n);
c->in.cipherstate = cr; c->in.cipherstate = cr;
@ -2140,7 +2134,7 @@ rc4cipherinit(Conv *c)
c->out.cipherblklen = 1; c->out.cipherblklen = 1;
c->out.cipherivlen = 4; c->out.cipherivlen = 4;
c->out.cipher = rc4encrypt; c->out.cipher = rc4encrypt;
cr = smalloc(sizeof(CipherRc4)); cr = secalloc(sizeof(CipherRc4));
memset(cr, 0, sizeof(*cr)); memset(cr, 0, sizeof(*cr));
setupRC4state(&cr->current, key, n); setupRC4state(&cr->current, key, n);
c->out.cipherstate = cr; c->out.cipherstate = cr;
@ -2195,7 +2189,7 @@ md5auth(OneWay *ow, uchar *t, int tlen)
memset(hash, 0, MD5dlen); memset(hash, 0, MD5dlen);
seanq_hmac_md5(hash, ow->seqwrap, t, tlen, (uchar*)ow->authstate, 16); 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); memmove(t+tlen, hash, ow->authlen);
return r; return r;
} }
@ -2212,14 +2206,14 @@ md5authinit(Conv *c)
keylen = 16; keylen = 16;
/* in */ /* in */
c->in.authstate = smalloc(16); c->in.authstate = secalloc(16);
memset(c->in.authstate, 0, 16); memset(c->in.authstate, 0, 16);
setkey(c->in.authstate, keylen, &c->in, "auth"); setkey(c->in.authstate, keylen, &c->in, "auth");
c->in.authlen = 12; c->in.authlen = 12;
c->in.auth = md5auth; c->in.auth = md5auth;
/* out */ /* out */
c->out.authstate = smalloc(16); c->out.authstate = secalloc(16);
memset(c->out.authstate, 0, 16); memset(c->out.authstate, 0, 16);
setkey(c->out.authstate, keylen, &c->out, "auth"); setkey(c->out.authstate, keylen, &c->out, "auth");
c->out.authlen = 12; c->out.authlen = 12;

View file

@ -373,14 +373,10 @@ sslclose(Chan *c)
sslhangup(s); sslhangup(s);
if(s->c) if(s->c)
cclose(s->c); cclose(s->c);
if(s->in.secret) secfree(s->in.secret);
free(s->in.secret); secfree(s->out.secret);
if(s->out.secret) secfree(s->in.state);
free(s->out.secret); secfree(s->out.state);
if(s->in.state)
free(s->in.state);
if(s->out.state)
free(s->out.state);
free(s); free(s);
} }
@ -826,10 +822,8 @@ sslput(Dstate *s, Block * volatile b)
static void static void
setsecret(OneWay *w, uchar *secret, int n) setsecret(OneWay *w, uchar *secret, int n)
{ {
if(w->secret) secfree(w->secret);
free(w->secret); w->secret = secalloc(n);
w->secret = smalloc(n);
memmove(w->secret, secret, n); memmove(w->secret, secret, n);
w->slen = n; w->slen = n;
} }
@ -837,12 +831,8 @@ setsecret(OneWay *w, uchar *secret, int n)
static void static void
initDESkey(OneWay *w) initDESkey(OneWay *w)
{ {
if(w->state){ secfree(w->state);
free(w->state); w->state = secalloc(sizeof(DESstate));
w->state = 0;
}
w->state = smalloc(sizeof(DESstate));
if(w->slen >= 16) if(w->slen >= 16)
setupDESstate(w->state, w->secret, w->secret+8); setupDESstate(w->state, w->secret, w->secret+8);
else if(w->slen >= 8) else if(w->slen >= 8)
@ -860,11 +850,6 @@ initDESkey_40(OneWay *w)
{ {
uchar key[8]; uchar key[8];
if(w->state){
free(w->state);
w->state = 0;
}
if(w->slen >= 8){ if(w->slen >= 8){
memmove(key, w->secret, 8); memmove(key, w->secret, 8);
key[0] &= 0x0f; key[0] &= 0x0f;
@ -872,25 +857,14 @@ initDESkey_40(OneWay *w)
key[4] &= 0x0f; key[4] &= 0x0f;
key[6] &= 0x0f; key[6] &= 0x0f;
} }
initDESkey(w);
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");
} }
static void static void
initRC4key(OneWay *w) initRC4key(OneWay *w)
{ {
if(w->state){ secfree(w->state);
free(w->state); w->state = secalloc(sizeof(RC4state));
w->state = 0;
}
w->state = smalloc(sizeof(RC4state));
setupRC4state(w->state, w->secret, w->slen); setupRC4state(w->state, w->secret, w->slen);
} }
@ -901,16 +875,9 @@ initRC4key(OneWay *w)
static void static void
initRC4key_40(OneWay *w) initRC4key_40(OneWay *w)
{ {
if(w->state){
free(w->state);
w->state = 0;
}
if(w->slen > 5) if(w->slen > 5)
w->slen = 5; w->slen = 5;
initRC4key(w);
w->state = smalloc(sizeof(RC4state));
setupRC4state(w->state, w->secret, w->slen);
} }
/* /*
@ -920,16 +887,9 @@ initRC4key_40(OneWay *w)
static void static void
initRC4key_128(OneWay *w) initRC4key_128(OneWay *w)
{ {
if(w->state){
free(w->state);
w->state = 0;
}
if(w->slen > 16) if(w->slen > 16)
w->slen = 16; w->slen = 16;
initRC4key(w);
w->state = smalloc(sizeof(RC4state));
setupRC4state(w->state, w->secret, w->slen);
} }
@ -1177,27 +1137,29 @@ sslwrite(Chan *c, void *a, long n, vlong)
break; break;
case Csin: case Csin:
p = cb->f[1]; p = cb->f[1];
m = (strlen(p)*3)/2; m = (strlen(p)*3)/2 + 1;
x = smalloc(m); x = secalloc(m);
t = dec64(x, m, p, strlen(p)); t = dec64(x, m, p, strlen(p));
memset(p, 0, strlen(p));
if(t <= 0){ if(t <= 0){
free(x); secfree(x);
error(Ebadarg); error(Ebadarg);
} }
setsecret(&s->in, x, t); setsecret(&s->in, x, t);
free(x); secfree(x);
break; break;
case Csout: case Csout:
p = cb->f[1]; p = cb->f[1];
m = (strlen(p)*3)/2 + 1; m = (strlen(p)*3)/2 + 1;
x = smalloc(m); x = secalloc(m);
t = dec64(x, m, p, strlen(p)); t = dec64(x, m, p, strlen(p));
memset(p, 0, strlen(p));
if(t <= 0){ if(t <= 0){
free(x); secfree(x);
error(Ebadarg); error(Ebadarg);
} }
setsecret(&s->out, x, t); setsecret(&s->out, x, t);
free(x); secfree(x);
break; break;
} }
poperror(); poperror();

View file

@ -1471,7 +1471,7 @@ struct Encalg
static void static void
initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *) initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
{ {
s->enckey = smalloc(sizeof(RC4state)); s->enckey = secalloc(sizeof(RC4state));
s->enc = rc4enc; s->enc = rc4enc;
s->dec = rc4enc; s->dec = rc4enc;
setupRC4state(s->enckey, p, ea->keylen); setupRC4state(s->enckey, p, ea->keylen);
@ -1480,7 +1480,7 @@ initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
static void static void
initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv) initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
{ {
s->enckey = smalloc(sizeof(DES3state)); s->enckey = secalloc(sizeof(DES3state));
s->enc = des3enc; s->enc = des3enc;
s->dec = des3dec; s->dec = des3dec;
s->block = 8; s->block = 8;
@ -1490,7 +1490,7 @@ initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
static void static void
initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{ {
s->enckey = smalloc(sizeof(AESstate)); s->enckey = secalloc(sizeof(AESstate));
s->enc = aesenc; s->enc = aesenc;
s->dec = aesdec; s->dec = aesdec;
s->block = 16; s->block = 16;
@ -1500,7 +1500,7 @@ initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
static void static void
initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv) 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_enc = ccpoly_aead_enc;
s->aead_dec = ccpoly_aead_dec; s->aead_dec = ccpoly_aead_dec;
s->maclen = Poly1305dlen; s->maclen = Poly1305dlen;
@ -1517,7 +1517,7 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
static void static void
initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) 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_enc = aesgcm_aead_enc;
s->aead_dec = aesgcm_aead_dec; s->aead_dec = aesgcm_aead_dec;
s->maclen = 16; s->maclen = 16;
@ -1673,18 +1673,19 @@ tlswrite(Chan *c, void *a, long n, vlong off)
ea = parseencalg(cb->f[2]); ea = parseencalg(cb->f[2]);
p = cb->f[4]; p = cb->f[4];
m = (strlen(p)*3)/2; m = (strlen(p)*3)/2 + 1;
x = smalloc(m); x = secalloc(m);
tos = smalloc(sizeof(Secret)); tos = secalloc(sizeof(Secret));
toc = smalloc(sizeof(Secret)); toc = secalloc(sizeof(Secret));
if(waserror()){ if(waserror()){
secfree(x);
freeSec(tos); freeSec(tos);
freeSec(toc); freeSec(toc);
free(x);
nexterror(); nexterror();
} }
m = dec64(x, m, p, strlen(p)); m = dec64(x, m, p, strlen(p));
memset(p, 0, strlen(p));
if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen) if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
error("not enough secret data provided"); error("not enough secret data provided");
@ -1719,7 +1720,7 @@ tlswrite(Chan *c, void *a, long n, vlong off)
tos->encalg = ea->name; tos->encalg = ea->name;
tos->hashalg = ha->name; tos->hashalg = ha->name;
free(x); secfree(x);
poperror(); poperror();
}else if(strcmp(cb->f[0], "changecipher") == 0){ }else if(strcmp(cb->f[0], "changecipher") == 0){
if(cb->nf != 1) if(cb->nf != 1)
@ -2048,17 +2049,10 @@ tlsstate(int s)
static void static void
freeSec(Secret *s) freeSec(Secret *s)
{ {
void *k;
if(s == nil) if(s == nil)
return; return;
k = s->enckey; secfree(s->enckey);
if(k != nil){ secfree(s);
memset(k, 0, msize(k));
free(k);
}
memset(s, 0, sizeof(*s));
free(s);
} }
static int static int
@ -2162,6 +2156,8 @@ ccpoly_aead_setiv(Secret *sec, uchar seq[8])
iv[i+(ChachaIVlen-8)] ^= seq[i]; iv[i+(ChachaIVlen-8)] ^= seq[i];
chacha_setiv(cs, iv); chacha_setiv(cs, iv);
memset(iv, 0, sizeof(iv));
} }
static int 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]; for(i=0; i<8; i++) iv[4+i] ^= aad[i];
memmove(reciv, iv+4, 8); memmove(reciv, iv+4, 8);
aesgcm_setiv(sec->enckey, iv, 12); aesgcm_setiv(sec->enckey, iv, 12);
memset(iv, 0, sizeof(iv));
aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey); aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey);
return len + sec->maclen; 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, sec->mackey, 4);
memmove(iv+4, reciv, 8); memmove(iv+4, reciv, 8);
aesgcm_setiv(sec->enckey, iv, 12); aesgcm_setiv(sec->enckey, iv, 12);
memset(iv, 0, sizeof(iv));
if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0) if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
return -1; return -1;
return len; return len;

View file

@ -126,6 +126,7 @@ void gotolabel(Label*);
char* getconfenv(void); char* getconfenv(void);
long hostdomainwrite(char*, int); long hostdomainwrite(char*, int);
long hostownerwrite(char*, int); long hostownerwrite(char*, int);
void (*hwrandbuf)(void*, ulong);
void hzsched(void); void hzsched(void);
Block* iallocb(int); Block* iallocb(int);
void iallocsummary(void); void iallocsummary(void);
@ -308,6 +309,8 @@ void sched(void);
void scheddump(void); void scheddump(void);
void schedinit(void); void schedinit(void);
void (*screenputs)(char*, int); void (*screenputs)(char*, int);
void* secalloc(ulong);
void secfree(void*);
long seconds(void); long seconds(void);
uintptr segattach(int, char *, uintptr, uintptr); uintptr segattach(int, char *, uintptr, uintptr);
void segclock(uintptr); void segclock(uintptr);

View file

@ -5,135 +5,103 @@
#include "fns.h" #include "fns.h"
#include "../port/error.h" #include "../port/error.h"
struct Rb #include <libsec.h>
/* machine specific hardware random number generator */
void (*hwrandbuf)(void*, ulong) = nil;
static struct
{ {
QLock; QLock;
Rendez producer; Chachastate;
Rendez consumer; } *rs;
ulong randomcount;
uchar buf[128];
uchar *ep;
uchar *rp;
uchar *wp;
uchar next;
uchar wakeme;
ushort bits;
ulong randn;
} rb;
static int typedef struct Seedbuf Seedbuf;
rbnotfull(void*) struct Seedbuf
{ {
int i; ulong randomcount;
uchar buf[64];
uchar nbuf;
uchar next;
ushort bits;
i = rb.rp - rb.wp; SHA2_512state ds;
return i != 1 && i != (1 - sizeof(rb.buf)); };
}
static int static void
rbnotempty(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 static void
genrandom(void*) randomseed(void*)
{ {
up->basepri = PriNormal; Seedbuf *s;
up->priority = up->basepri;
while(waserror()) s = secalloc(sizeof(Seedbuf));
;
for(;;){ if(hwrandbuf != nil)
if(++rb.randomcount <= 100000) (*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; continue;
if(anyhigher()) if(anyhigher())
sched(); sched();
if(!rbnotfull(0))
sleep(&rb.producer, rbnotfull, 0);
} }
} timerdel(up);
/* sha2_512(s->buf, sizeof(s->buf), s->buf, &s->ds);
* produce random bits in a circular buffer setupChachastate(rs, s->buf, 32, s->buf+32, 12, 20);
*/ qunlock(rs);
static void
randomclock(void)
{
if(rb.randomcount == 0 || !rbnotfull(0))
return;
rb.bits = (rb.bits<<2) ^ rb.randomcount; secfree(s);
rb.randomcount = 0;
rb.next++; pexit("", 1);
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 void
randominit(void) randominit(void)
{ {
/* Frequency close but not equal to HZ */ rs = secalloc(sizeof(*rs));
addclock0link(randomclock, MS2HZ+3); qlock(rs); /* randomseed() unlocks once seeded */
rb.ep = rb.buf + sizeof(rb.buf); kproc("randomseed", randomseed, nil);
rb.rp = rb.wp = rb.buf;
kproc("genrandom", genrandom, 0);
} }
/*
* consume random bytes from a circular buffer
*/
ulong ulong
randomread(void *xp, ulong n) randomread(void *xp, ulong n)
{ {
uchar *e, *p; if(n == 0)
ulong x; return 0;
p = xp; if(hwrandbuf != nil)
(*hwrandbuf)(xp, n);
if(waserror()){ if(waserror()){
qunlock(&rb); qunlock(rs);
nexterror(); nexterror();
} }
qlock(rs);
qlock(&rb); chacha_encrypt((uchar*)xp, n, rs);
for(e = p + n; p < e; ){ qunlock(rs);
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(); poperror();
wakeup(&rb.producer);
return n; return n;
} }

View file

@ -1332,6 +1332,19 @@ poolmsize(Pool *p, void *v)
return dsize; 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 * Debugging
*/ */