summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-08-27 20:50:55 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2016-08-27 20:50:55 +0200
commitf777743b7242e539a8ac806e4e15c4b527be4bb6 (patch)
treed107eba52d945ede7f157452c32e09eddaf9ca09
parent762e98d47e8d812f0dbe4b64ef2a73357bdebeee (diff)
parent0a5f81a44230cbd562b6d71a0a5be018e24a5ba6 (diff)
merge
-rw-r--r--sys/include/pool.h2
-rw-r--r--sys/man/2/pool12
-rw-r--r--sys/src/9/ip/esp.c30
-rw-r--r--sys/src/9/pc/devarch.c5
-rw-r--r--sys/src/9/pc/mkfile2
-rw-r--r--sys/src/9/pc/pcrandom.c152
-rw-r--r--sys/src/9/pc/wifi.c152
-rw-r--r--sys/src/9/pc/wifi.h13
-rw-r--r--sys/src/9/pc64/mkfile2
-rw-r--r--sys/src/9/port/alloc.c55
-rw-r--r--sys/src/9/port/devcons.c32
-rw-r--r--sys/src/9/port/devproc.c4
-rw-r--r--sys/src/9/port/devsdp.c32
-rw-r--r--sys/src/9/port/devssl.c82
-rw-r--r--sys/src/9/port/devtls.c38
-rw-r--r--sys/src/9/port/portfns.h3
-rw-r--r--sys/src/9/port/random.c158
-rw-r--r--sys/src/libc/port/pool.c13
18 files changed, 346 insertions, 441 deletions
diff --git a/sys/include/pool.h b/sys/include/pool.h
index 571373e9f..5f7fada45 100644
--- a/sys/include/pool.h
+++ b/sys/include/pool.h
@@ -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,
diff --git a/sys/man/2/pool b/sys/man/2/pool
index a44b57d4d..b637e3d7c 100644
--- a/sys/man/2/pool
+++ b/sys/man/2/pool
@@ -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
diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c
index 75c48a1ff..1e93f6f75 100644
--- a/sys/src/9/ip/esp.c
+++ b/sys/src/9/ip/esp.c
@@ -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));
}
diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c
index f3be061cb..0b4cad252 100644
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -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;
}
diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile
index 96ab2c623..c6e683e22 100644
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -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\
diff --git a/sys/src/9/pc/pcrandom.c b/sys/src/9/pc/pcrandom.c
deleted file mode 100644
index 386d7bf8e..000000000
--- a/sys/src/9/pc/pcrandom.c
+++ /dev/null
@@ -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;
-}
diff --git a/sys/src/9/pc/wifi.c b/sys/src/9/pc/wifi.c
index 8155b25e3..8325c0aa7 100644
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -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;
@@ -466,6 +468,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)
{
Ether *ether;
@@ -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(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)
- k = &wn->rxkey[ct->index - CMrxkey0];
+ kk = &wn->rxkey[ct->index - CMrxkey0];
else
- k = &wn->txkey[ct->index - CMtxkey0];
- if(cb->f[1] == nil || parsekey(k, cb->f[1]) != 0)
- error("bad key");
+ 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);
}
diff --git a/sys/src/9/pc/wifi.h b/sys/src/9/pc/wifi.h
index bca2e07e9..2171afd21 100644
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -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;
diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile
index 30b40daf1..16aae0a68 100644
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -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\
diff --git a/sys/src/9/port/alloc.c b/sys/src/9/port/alloc.c
index fc562bc55..963d60fd2 100644
--- a/sys/src/9/port/alloc.c
+++ b/sys/src/9/port/alloc.c
@@ -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)
{
diff --git a/sys/src/9/port/devcons.c b/sys/src/9/port/devcons.c
index b09df91f2..7f287610f 100644
--- a/sys/src/9/port/devcons.c
+++ b/sys/src/9/port/devcons.c
@@ -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,29 +848,20 @@ Dev consdevtab = {
static ulong randn;
-static void
-seedrand(void)
-{
- if(!waserror()){
- randomread((void*)&randn, sizeof(randn));
- poperror();
- }
-}
-
int
-nrand(int n)
+rand(void)
{
if(randn == 0)
- seedrand();
+ randomread((void*)&randn, sizeof(randn));
randn = randn*1103515245 + 12345 + MACHP(0)->ticks;
- return (randn>>16) % n;
+ return randn;
}
int
-rand(void)
+nrand(int n)
{
- nrand(1);
- return randn;
+ rand();
+ return (randn>>16) % n;
}
static uvlong uvorder = 0x0001020304050607ULL;
diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c
index 49340adbb..9f9b9380b 100644
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -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 */
diff --git a/sys/src/9/port/devsdp.c b/sys/src/9/port/devsdp.c
index 2be928d66..6443212e4 100644
--- a/sys/src/9/port/devsdp.c
+++ b/sys/src/9/port/devsdp.c
@@ -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;
diff --git a/sys/src/9/port/devssl.c b/sys/src/9/port/devssl.c
index 32b207618..ef3cd6fb6 100644
--- a/sys/src/9/port/devssl.c
+++ b/sys/src/9/port/devssl.c
@@ -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();
diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c
index 81f50d3a6..3f864a7fc 100644
--- a/sys/src/9/port/devtls.c
+++ b/sys/src/9/port/devtls.c
@@ -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;
diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h
index 4b639c3a1..6f84fc691 100644
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -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);
diff --git a/sys/src/9/port/random.c b/sys/src/9/port/random.c
index f578d68cc..012424aa6 100644
--- a/sys/src/9/port/random.c
+++ b/sys/src/9/port/random.c
@@ -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;
-
-static int
-rbnotfull(void*)
+ Chachastate;
+} *rs;
+
+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;
+
+ s = secalloc(sizeof(Seedbuf));
- while(waserror())
- ;
- for(;;){
- if(++rb.randomcount <= 100000)
+ 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;
-
- rb.bits = (rb.bits<<2) ^ rb.randomcount;
- rb.randomcount = 0;
-
- rb.next++;
- if(rb.next != 8/2)
- return;
- rb.next = 0;
+ sha2_512(s->buf, sizeof(s->buf), s->buf, &s->ds);
+ setupChachastate(rs, s->buf, 32, s->buf+32, 12, 20);
+ qunlock(rs);
- *rb.wp ^= rb.bits;
- if(rb.wp+1 == rb.ep)
- rb.wp = rb.buf;
- else
- rb.wp = rb.wp+1;
+ secfree(s);
- 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;
}
diff --git a/sys/src/libc/port/pool.c b/sys/src/libc/port/pool.c
index 25ad52c57..546d5776a 100644
--- a/sys/src/libc/port/pool.c
+++ b/sys/src/libc/port/pool.c
@@ -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
*/