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 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,

View file

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

View file

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

View file

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

View file

@ -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\

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* 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);
}

View file

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

View file

@ -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\

View file

@ -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)
{

View file

@ -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*

View file

@ -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 */

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

@ -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
*/