introduce AES key into nvram and keyfs

This commit is contained in:
cinap_lenrek 2015-08-21 02:43:31 +02:00
parent e48a5832b2
commit 63b18e7925
10 changed files with 366 additions and 245 deletions

View file

@ -20,6 +20,7 @@ enum
AERRLEN= 64, /* errstr max size in previous proto */
DOMLEN= 48, /* authentication domain name length */
DESKEYLEN= 7, /* encrypt/decrypt des key length */
AESKEYLEN= 16,
CHALLEN= 8, /* plan9 sk1 challenge length */
NETCHLEN= 16, /* max network challenge length (used in AS protocol) */
CONFIGLEN= 14,
@ -115,6 +116,7 @@ struct OMSchapreply
struct Authkey
{
char des[DESKEYLEN];
uchar aes[AESKEYLEN];
};
/*
@ -132,7 +134,7 @@ extern int convM2PR(char*, int, Passwordreq*, Ticket*);
/*
* convert ascii password to DES key
*/
extern int passtokey(Authkey*, char*);
extern void passtokey(Authkey*, char*);
/*
* Nvram interface
@ -147,7 +149,7 @@ enum {
/* storage layout */
struct Nvrsafe
{
char machkey[DESKEYLEN]; /* was file server's authid's des key */
char machkey[DESKEYLEN]; /* file server's authid's des key */
uchar machsum;
char authkey[DESKEYLEN]; /* authid's des key from password */
uchar authsum;
@ -159,8 +161,11 @@ struct Nvrsafe
uchar configsum;
char authid[ANAMELEN]; /* auth userid, e.g., bootes */
uchar authidsum;
char authdom[DOMLEN]; /* auth domain, e.g., cs.bell-labs.com */
char authdom[DOMLEN]; /* auth domain, e.g., cs.bell-labs.com */
uchar authdomsum;
uchar aesmachkey[AESKEYLEN];
uchar aesmachsum;
};
extern uchar nvcsum(void*, int);

View file

@ -15,7 +15,7 @@ authdial, passtokey, nvcsum, readnvram, convT2M, convM2T, convTR2M, convM2TR, co
int authdial(char *netroot, char *ad);
.PP
.B
int passtokey(Authkey *key, char *password)
void passtokey(Authkey *key, char *password)
.PP
.B
uchar nvcsum(void *mem, int len)
@ -109,10 +109,6 @@ into a set of cryptographic keys and stores them in the
.I Authkey
structure
.IR key .
It returns 0 if
.I password
could not be converted,
and 1 otherwise.
.PP
.I Readnvram
reads authentication information into the structure:

View file

@ -41,7 +41,7 @@ reads and decrypts file
.I keyfile
(default
.BR /adm/keys )
using the DES key,
using the DES or AES key,
which is by default read from
.B #r/nvram
(see
@ -51,13 +51,14 @@ With option
.I keyfs
prompts for a password from which the key is derived.
.I Keyfile
holds a 41-byte record for each user in the database.
Each record is encrypted separately
and contains the user's name,
holds a 41-byte (57-byte for AES) record for each user in the database.
Each record contains the user's name,
DES key,
status,
host status,
and expiration date.
warning status,
expiration date,
secret password
and AES key.
The name is a
null-terminated
.SM UTF
@ -67,14 +68,18 @@ bytes long.
The status is a byte containing
binary 0 if the account is enabled,
1 if it is disabled.
Host status is a byte containing
binary 1 if the user is a host,
0 otherwise.
Warning status is a byte containing
the number of user expiration notifications.
The expiration date is four-byte little-endian integer
which represents the time in seconds since the epoch
(see
.IR date (1))
at which the account will expire.
The secret password is a null-terminated
.SM UTF
string
.B SECRETLEN
bytes long.
If any changes are made to the database that affect the information stored in
.IR keyfile ,
a new version of the file is written.
@ -111,6 +116,8 @@ does not allow duplicate names when creating or renaming user entries.
.PP
All files in the user directories except for
.B key
and
.B aeskey
contain
.SM UTF
strings with a trailing newline when read,
@ -121,6 +128,10 @@ strings with or without a trailing newline.
contains the
.BR DESKEYLEN -byte
encryption key for the user.
.B Aeskey
contains the
.BR AESKEYLEN -byte
encryption key.
.PP
The following files appear in the user directories.
.TF expire
@ -133,6 +144,12 @@ Writing
.I key
changes the key in the database.
.TP
.B aeskey
The AES encryption key for the user.
.TP
.B secret
The secret password.
.TP
.B log
The number of consecutive failed authentication attempts for the user.
Writing the string

View file

@ -7,7 +7,7 @@ changeuser, convkeys, convkeys2, printnetkey, status, enable, disable, authsrv,
.I user
.PP
.B auth/convkeys
.RB [ -p ]
.RB [ -pa ]
.I keyfile
.PP
.B auth/convkeys2
@ -151,6 +151,9 @@ The
forces
.I convkeys
to also prompt for the old password.
The
.B -a
option converts the file into AES format.
The format of
.I keyfile
is described in

View file

@ -7,18 +7,21 @@
#include <bio.h>
#include "authcmdlib.h"
Authkey authkey;
Authkey okey, nkey;
int verb;
int usepass;
int convaes;
int convert(char*, Authkey*, int);
uchar zeros[16];
int convert(char**, int);
void usage(void);
void
main(int argc, char *argv[])
{
Dir *d;
Authkey key;
char *p, *file;
int fd, len;
@ -29,6 +32,9 @@ main(int argc, char *argv[])
case 'v':
verb = 1;
break;
case 'a':
convaes = 1;
break;
default:
usage();
}ARGEND
@ -40,12 +46,13 @@ main(int argc, char *argv[])
/* get original key */
if(usepass){
print("enter password file is encoded with\n");
getpass(&authkey, nil, 0, 1);
} else
getauthkey(&authkey);
getpass(&okey, nil, 0, 1);
} else {
getauthkey(&okey);
}
if(!verb){
print("enter password to reencode with\n");
getpass(&key, nil, 0, 1);
getpass(&nkey, nil, 0, 1);
}
fd = open(file, ORDWR);
@ -56,17 +63,15 @@ main(int argc, char *argv[])
error("can't stat %s: %r\n", file);
len = d->length;
p = malloc(len);
if(!p)
if(p == nil)
error("out of memory");
if(read(fd, p, len) != len)
error("can't read key file: %r\n");
len = convert(p, &key, len);
if(verb)
exits(0);
len = convert(&p, len);
if(pwrite(fd, p, len, 0) != len)
error("can't write key file: %r\n");
close(fd);
exits(0);
exits(nil);
}
void
@ -76,7 +81,7 @@ randombytes(uchar *p, int len)
fd = open("/dev/random", OREAD);
if(fd < 0){
fprint(2, "convkeys: can't open /dev/random, using rand()\n");
fprint(2, "%s: can't open /dev/random, using rand()\n", argv0);
srand(time(0));
for(i = 0; i < len; i++)
p[i] = rand();
@ -86,34 +91,7 @@ randombytes(uchar *p, int len)
close(fd);
}
void
oldCBCencrypt(char *key7, char *p, int len)
{
uchar ivec[8];
uchar key[8];
DESstate s;
memset(ivec, 0, 8);
des56to64((uchar*)key7, key);
setupDESstate(&s, key, ivec);
desCBCencrypt((uchar*)p, len, &s);
}
void
oldCBCdecrypt(char *key7, char *p, int len)
{
uchar ivec[8];
uchar key[8];
DESstate s;
memset(ivec, 0, 8);
des56to64((uchar*)key7, key);
setupDESstate(&s, key, ivec);
desCBCdecrypt((uchar*)p, len, &s);
}
static int
int
badname(char *s)
{
int n;
@ -128,35 +106,102 @@ badname(char *s)
}
int
convert(char *p, Authkey *key, int len)
convert(char **db, int len)
{
int i;
int i, nu, keydblen, keydboff, keydbaes;
char *p = *db;
len -= KEYDBOFF;
if(len % KEYDBLEN){
fprint(2, "convkeys: file odd length; not converting %d bytes\n",
len % KEYDBLEN);
len -= len % KEYDBLEN;
keydblen = KEYDBLEN;
keydboff = KEYDBOFF;
keydbaes = len > 24 && memcmp(p, "AES KEYS", 8) == 0;
if(keydbaes){
keydblen += AESKEYLEN;
keydboff = 8+16; /* signature[8] + iv[16] */
}
len += KEYDBOFF;
oldCBCdecrypt(authkey.des, p, len);
for(i = KEYDBOFF; i < len; i += KEYDBLEN)
if (badname(&p[i])) {
print("bad name %.30s... - aborting\n", &p[i]);
return 0;
}
if(verb)
for(i = KEYDBOFF; i < len; i += KEYDBLEN)
print("%s\n", &p[i]);
randombytes((uchar*)p, 8);
oldCBCencrypt(key->des, p, len);
len -= keydboff;
if(len % keydblen){
fprint(2, "%s: file odd length; not converting %d bytes\n", argv0, len % keydblen);
len -= len % keydblen;
}
len += keydboff;
if(keydbaes){
AESstate s;
/* make sure we have aes key for decryption */
if(memcmp(okey.aes, zeros, AESKEYLEN) == 0){
fprint(2, "%s: no aes key in NVRAM\n", argv0);
exits("no aes key");
}
setupAESstate(&s, okey.aes, AESKEYLEN, zeros);
aesCBCdecrypt((uchar*)p+8, len-8, &s);
} else {
DESstate s;
uchar k[8];
des56to64((uchar*)okey.des, k);
setupDESstate(&s, k, zeros);
desCBCdecrypt((uchar*)p, len, &s);
}
nu = 0;
for(i = keydboff; i < len; i += keydblen) {
if (badname(&p[i])) {
fprint(2, "%s: bad name %.30s... - aborting\n", argv0, &p[i]);
exits("bad name");
}
nu++;
}
if(verb){
for(i = keydboff; i < len; i += keydblen)
print("%s\n", &p[i]);
exits(nil);
}
if(convaes && !keydbaes){
char *s, *d;
keydboff = 8+16;
keydblen += AESKEYLEN;
len = keydboff + keydblen*nu;
p = realloc(p, len);
if(p == nil)
error("out of memory");
*db = p;
s = p + KEYDBOFF + nu*KEYDBLEN;
d = p + keydboff + nu*keydblen;
for(i=0; i<nu; i++){
s -= KEYDBLEN;
d -= keydblen;
memmove(d, s, KEYDBLEN);
memset(d + KEYDBLEN, 0, keydblen-KEYDBLEN);
}
keydbaes = 1;
}
randombytes((uchar*)p, keydboff);
if(keydbaes){
AESstate s;
memmove(p, "AES KEYS", 8);
setupAESstate(&s, nkey.aes, AESKEYLEN, zeros);
aesCBCencrypt((uchar*)p+8, len-8, &s);
} else {
DESstate s;
uchar k[8];
des56to64((uchar*)nkey.des, k);
setupDESstate(&s, k, zeros);
desCBCencrypt((uchar*)p, len, &s);
}
return len;
}
void
usage(void)
{
fprint(2, "usage: convkeys keyfile\n");
fprint(2, "usage: %s [-pva] keyfile\n", argv0);
exits("usage");
}

View file

@ -14,6 +14,8 @@
#pragma varargck type "W" char*
Authkey authkey;
int keydbaes;
uchar zeros[16];
typedef struct Fid Fid;
typedef struct User User;
@ -22,6 +24,7 @@ enum {
Qroot,
Quser,
Qkey,
Qaeskey,
Qsecret,
Qlog,
Qstatus,
@ -52,6 +55,7 @@ struct Fid {
struct User {
char *name;
char key[DESKEYLEN];
uchar aeskey[AESKEYLEN];
char secret[SECRETLEN];
ulong expire; /* 0 == never */
uchar status;
@ -68,6 +72,7 @@ char *qinfo[Qmax] = {
[Qroot] "keys",
[Quser] ".",
[Qkey] "key",
[Qaeskey] "aeskey",
[Qsecret] "secret",
[Qlog] "log",
[Qexpire] "expire",
@ -85,8 +90,7 @@ User *users[Nuser];
char *userkeys;
int nuser;
ulong uniq = 1;
Fcall rhdr,
thdr;
Fcall rhdr, thdr;
int usepass;
char *warnarg;
uchar mdata[8192 + IOHDRSZ];
@ -102,6 +106,7 @@ void insertuser(User*);
void writeusers(void);
void io(int, int);
void *emalloc(ulong);
char *estrdup(char*);
Qid mkqid(User*, ulong);
int dostat(User*, ulong, void*, int);
int newkeys(void);
@ -136,6 +141,12 @@ usage(void)
exits("usage");
}
static int
haveaeskey(void)
{
return memcmp(authkey.aes, zeros, 16) != 0;
}
void
main(int argc, char *argv[])
{
@ -169,11 +180,22 @@ main(int argc, char *argv[])
if(pipe(p) < 0)
error("can't make pipe: %r");
if(usepass) {
if(usepass)
getpass(&authkey, nil, 0, 0);
} else {
else {
if(!getauthkey(&authkey))
print("keyfs: warning: can't read NVRAM\n");
fprint(2, "keyfs: warning: can't read NVRAM\n");
}
keydbaes = 0;
if(!newkeys() || !readusers()){
if(!keydbaes)
keydbaes = haveaeskey();
else if(!haveaeskey()){
fprint(2, "keyfs: no aes key in NVRAM\n");
getpass(&authkey, nil, 0, 0);
readusers();
}
}
switch(rfork(RFPROC|RFNAMEG|RFNOTEG|RFNOWAIT|RFENVG|RFFDG)){
@ -209,7 +231,7 @@ Attach(Fid *f)
{
if(f->busy)
Clunk(f);
f->user = 0;
f->user = nil;
f->qtype = Qroot;
f->busy = 1;
thdr.qid = mkqid(f->user, f->qtype);
@ -272,7 +294,7 @@ Walk(Fid *f)
if(strcmp(name, "..") == 0)
goto Accept;
user = finduser(name);
if(!user)
if(user == nil)
goto Out;
qtype = Quser;
@ -283,7 +305,7 @@ Walk(Fid *f)
case Quser:
if(strcmp(name, "..") == 0) {
qtype = Qroot;
user = 0;
user = nil;
goto Accept;
}
max = Qmax;
@ -314,14 +336,16 @@ Walk(Fid *f)
if(rhdr.fid != rhdr.newfid && i == rhdr.nwname){
nf->busy = 1;
nf->qtype = qtype;
if(nf->user = user)
nf->user->ref++;
nf->user = user;
if(user != nil)
user->ref++;
}else if(nf == nil && rhdr.nwname > 0){ /* walk without clone (rare) */
Clunk(f);
f->busy = 1;
f->qtype = qtype;
if(f->user = user)
f->user->ref++;
f->user = user;
if(user != nil)
user->ref++;
}
thdr.nwqid = i;
@ -332,12 +356,12 @@ char *
Clunk(Fid *f)
{
f->busy = 0;
if(f->user && --f->user->ref == 0 && f->user->removed) {
if(f->user != nil && --f->user->ref == 0 && f->user->removed) {
free(f->user->name);
free(f->user);
}
f->user = 0;
return 0;
f->user = nil;
return nil;
}
char *
@ -350,6 +374,8 @@ Open(Fid *f)
mode = rhdr.mode;
if(f->qtype == Quser && (mode & (OWRITE|OTRUNC)))
return "user already exists";
if(f->qtype == Qaeskey && !keydbaes)
return "keyfile not in aes format";
thdr.qid = mkqid(f->user, f->qtype);
thdr.iounit = messagesize - IOHDRSZ;
return 0;
@ -364,7 +390,7 @@ Create(Fid *f)
if(!f->busy)
return "create of unused fid";
name = rhdr.name;
if(f->user){
if(f->user != nil){
return "permission denied";
}else{
perm = rhdr.perm;
@ -374,7 +400,7 @@ Create(Fid *f)
return "empty file name";
if(strlen(name) >= Namelen)
return "file name too long";
if(finduser(name))
if(finduser(name) != nil)
return "user already exists";
f->user = installuser(name);
f->user->ref++;
@ -404,7 +430,7 @@ Read(Fid *f)
case Qroot:
j = 0;
for(i = 0; i < Nuser; i++)
for(u = users[i]; u; j += m, u = u->link){
for(u = users[i]; u != nil; j += m, u = u->link){
m = dostat(u, Quser, data, n);
if(m <= BIT16SZ)
break;
@ -431,19 +457,7 @@ Read(Fid *f)
thdr.count = data - thdr.data;
return 0;
case Qkey:
if(f->user->status != Sok)
return "user disabled";
if(f->user->purgatory > time(0))
return "user in purgatory";
if(f->user->expire != 0 && f->user->expire < time(0))
return "user expired";
if(off != 0)
return 0;
if(n > DESKEYLEN)
n = DESKEYLEN;
memmove(thdr.data, f->user->key, n);
thdr.count = n;
return 0;
case Qaeskey:
case Qsecret:
if(f->user->status != Sok)
return "user disabled";
@ -451,57 +465,52 @@ Read(Fid *f)
return "user in purgatory";
if(f->user->expire != 0 && f->user->expire < time(0))
return "user expired";
if(off != 0)
return 0;
if(n > strlen(f->user->secret))
n = strlen(f->user->secret);
memmove(thdr.data, f->user->secret, n);
m = 0;
switch(f->qtype){
case Qkey:
data = f->user->key;
m = DESKEYLEN;
break;
case Qaeskey:
data = (char*)f->user->aeskey;
m = AESKEYLEN;
break;
case Qsecret:
data = f->user->secret;
Readstr:
m = strlen(data);
break;
}
if(off >= m)
n = 0;
else {
data += off;
m -= off;
if(n > m)
n = m;
}
if(data != thdr.data)
memmove(thdr.data, data, n);
thdr.count = n;
return 0;
case Qstatus:
if(off != 0){
thdr.count = 0;
return 0;
}
if(f->user->status == Sok && f->user->expire && f->user->expire < time(0))
sprint(thdr.data, "expired\n");
sprint(data, "expired\n");
else
sprint(thdr.data, "%s\n", status[f->user->status]);
thdr.count = strlen(thdr.data);
return 0;
sprint(data, "%s\n", status[f->user->status]);
goto Readstr;
case Qexpire:
if(off != 0){
thdr.count = 0;
return 0;
}
if(!f->user->expire)
strcpy(data, "never\n");
else
sprint(data, "%lud\n", f->user->expire);
if(n > strlen(data))
n = strlen(data);
thdr.count = n;
return 0;
goto Readstr;
case Qlog:
if(off != 0){
thdr.count = 0;
return 0;
}
sprint(data, "%lud\n", f->user->bad);
if(n > strlen(data))
n = strlen(data);
thdr.count = n;
return 0;
goto Readstr;
case Qwarnings:
if(off != 0){
thdr.count = 0;
return 0;
}
sprint(data, "%ud\n", f->user->warnings);
if(n > strlen(data))
n = strlen(data);
thdr.count = n;
return 0;
goto Readstr;
default:
return "permission denied: unknown qid";
}
@ -525,11 +534,17 @@ Write(Fid *f)
memmove(f->user->key, data, DESKEYLEN);
thdr.count = DESKEYLEN;
break;
case Qaeskey:
if(n != AESKEYLEN)
return "garbled write data";
memmove(f->user->aeskey, data, AESKEYLEN);
thdr.count = AESKEYLEN;
break;
case Qsecret:
if(n >= SECRETLEN)
return "garbled write data";
memmove(f->user->secret, data, n);
f->user->secret[n] = 0;
f->user->secret[n] = '\0';
thdr.count = n;
break;
case Qstatus:
@ -639,9 +654,7 @@ Wstat(Fid *f)
if(!removeuser(f->user))
return "user previously removed";
free(f->user->name);
f->user->name = strdup(d.name);
if(f->user->name == nil)
error("wstat: malloc failed: %r");
f->user->name = estrdup(d.name);
insertuser(f->user);
writeusers();
return 0;
@ -683,17 +696,6 @@ dostat(User *user, ulong qtype, void *p, int n)
return convD2M(&d, p, n);
}
int
passline(Biobuf *b, void *vbuf)
{
char *buf = vbuf;
if(Bread(b, buf, KEYDBLEN) != KEYDBLEN)
return 0;
decrypt(authkey.des, buf, KEYDBLEN);
buf[Namelen-1] = '\0';
return 1;
}
void
randombytes(uchar *p, int len)
@ -712,58 +714,36 @@ randombytes(uchar *p, int len)
close(fd);
}
void
oldCBCencrypt(char *key7, uchar *p, int len)
{
uchar ivec[8];
uchar key[8];
DESstate s;
memset(ivec, 0, 8);
des56to64((uchar*)key7, key);
setupDESstate(&s, key, ivec);
desCBCencrypt((uchar*)p, len, &s);
}
void
oldCBCdecrypt(char *key7, uchar *p, int len)
{
uchar ivec[8];
uchar key[8];
DESstate s;
memset(ivec, 0, 8);
des56to64((uchar*)key7, key);
setupDESstate(&s, key, ivec);
desCBCdecrypt((uchar*)p, len, &s);
}
void
writeusers(void)
{
int keydblen, keydboff;
int fd, i, nu;
User *u;
uchar *p, *buf;
ulong expire;
/* what format to use */
keydblen = KEYDBLEN;
keydboff = KEYDBOFF;
if(keydbaes){
keydblen += AESKEYLEN;
keydboff = 8+16; /* segnature[8] + iv[16] */
}
/* count users */
nu = 0;
for(i = 0; i < Nuser; i++)
for(u = users[i]; u; u = u->link)
for(u = users[i]; u != nil; u = u->link)
nu++;
/* pack into buffer */
buf = malloc(KEYDBOFF + nu*KEYDBLEN);
if(buf == 0){
fprint(2, "keyfs: can't write keys file, out of memory\n");
return;
}
buf = emalloc(keydboff + nu*keydblen);
p = buf;
randombytes(p, KEYDBOFF);
p += KEYDBOFF;
randombytes(p, keydboff);
p += keydboff;
for(i = 0; i < Nuser; i++)
for(u = users[i]; u; u = u->link){
for(u = users[i]; u != nil; u = u->link){
strncpy((char*)p, u->name, Namelen);
p += Namelen;
memmove(p, u->key, DESKEYLEN);
@ -777,10 +757,27 @@ writeusers(void)
*p++ = expire >> 24;
memmove(p, u->secret, SECRETLEN);
p += SECRETLEN;
if(keydbaes){
memmove(p, u->aeskey, AESKEYLEN);
p += AESKEYLEN;
}
}
/* encrypt */
oldCBCencrypt(authkey.des, buf, p - buf);
if(keydbaes){
AESstate s;
memmove(buf, "AES KEYS", 8);
setupAESstate(&s, authkey.aes, AESKEYLEN, zeros);
aesCBCencrypt(buf+8, (p - (buf+8)), &s);
} else {
uchar key[8];
DESstate s;
des56to64((uchar*)authkey.des, key);
setupDESstate(&s, key, zeros);
desCBCencrypt(buf, p - buf, &s);
}
/* write file */
fd = create(userkeys, OWRITE, 0660);
@ -858,6 +855,7 @@ userok(char *user, int nu)
int
readusers(void)
{
int keydblen, keydboff;
int fd, i, n, nu;
uchar *p, *buf, *ep;
User *u;
@ -872,12 +870,7 @@ readusers(void)
close(fd);
return 0;
}
buf = malloc(d->length);
if(buf == 0){
close(fd);
free(d);
return 0;
}
buf = emalloc(d->length);
n = readn(fd, buf, d->length);
close(fd);
free(d);
@ -886,18 +879,41 @@ readusers(void)
return 0;
}
keydblen = KEYDBLEN;
keydboff = KEYDBOFF;
keydbaes = n > 24 && memcmp(buf, "AES KEYS", 8) == 0;
/* decrypt */
n -= n % KEYDBLEN;
oldCBCdecrypt(authkey.des, buf, n);
if(keydbaes){
AESstate s;
/* make sure we have AES encryption key */
if(!haveaeskey()){
free(buf);
return 0;
}
keydblen += AESKEYLEN;
keydboff = 8+16; /* signature[8] + iv[16] */
setupAESstate(&s, authkey.aes, AESKEYLEN, zeros);
aesCBCdecrypt(buf+8, n-8, &s);
} else {
uchar key[8];
DESstate s;
des56to64((uchar*)authkey.des, key);
setupDESstate(&s, key, zeros);
desCBCdecrypt(buf, n, &s);
}
/* unpack */
nu = 0;
for(i = KEYDBOFF; i < n; i += KEYDBLEN){
ep = buf + i;
if(userok((char*)ep, i/KEYDBLEN) < 0)
n = (n - keydboff) / keydblen;
ep = buf + keydboff;
for(i = 0; i < n; ep += keydblen, i++){
if(userok((char*)ep, i) < 0)
continue;
u = finduser((char*)ep);
if(u == 0)
if(u == nil)
u = installuser((char*)ep);
memmove(u->key, ep + Namelen, DESKEYLEN);
p = ep + Namelen + DESKEYLEN;
@ -909,11 +925,14 @@ readusers(void)
p += 4;
memmove(u->secret, p, SECRETLEN);
u->secret[SECRETLEN-1] = 0;
p += SECRETLEN;
if(keydbaes)
memmove(u->aeskey, p, AESKEYLEN);
nu++;
}
free(buf);
print("%d keys read\n", nu);
print("%d keys read in %s foarmat\n", nu, keydbaes ? "AES" : "DES");
return 1;
}
@ -925,9 +944,7 @@ installuser(char *name)
h = hash(name);
u = emalloc(sizeof *u);
u->name = strdup(name);
if(u->name == nil)
error("malloc failed: %r");
u->name = estrdup(name);
u->removed = 0;
u->ref = 0;
u->purgatory = 0;
@ -946,10 +963,10 @@ finduser(char *name)
{
User *u;
for(u = users[hash(name)]; u; u = u->link)
for(u = users[hash(name)]; u != nil; u = u->link)
if(strcmp(name, u->name) == 0)
return u;
return 0;
return nil;
}
int
@ -961,7 +978,7 @@ removeuser(User *user)
user->removed = 1;
name = user->name;
last = &users[hash(name)];
for(u = *last; u; u = *last){
for(u = *last; u != nil; u = *last){
if(strcmp(name, u->name) == 0){
*last = u->link;
return 1;
@ -998,20 +1015,20 @@ findfid(int fid)
{
Fid *f, *ff;
ff = 0;
for(f = fids; f; f = f->next)
ff = nil;
for(f = fids; f != nil; f = f->next)
if(f->fid == fid)
return f;
else if(!ff && !f->busy)
ff = f;
if(ff){
if(ff != nil){
ff->fid = fid;
return ff;
}
f = emalloc(sizeof *f);
f->fid = fid;
f->busy = 0;
f->user = 0;
f->user = nil;
f->next = fids;
fids = f;
return f;
@ -1088,10 +1105,24 @@ emalloc(ulong n)
{
void *p;
if(p = malloc(n))
if((p = malloc(n)) != nil){
memset(p, 0, n);
return p;
}
error("out of memory");
return 0; /* not reached */
return nil; /* not reached */
}
char *
estrdup(char *s)
{
char *d;
int n;
n = strlen(s)+1;
d = emalloc(n);
memmove(d, s, n);
return d;
}
void

View file

@ -5,13 +5,14 @@
#include "authcmdlib.h"
static int
getkey(char *authkey)
getkey(Authkey *authkey)
{
Nvrsafe safe;
if(readnvram(&safe, 0) < 0)
return -1;
memmove(authkey, safe.machkey, DESKEYLEN);
memmove(authkey->des, safe.machkey, DESKEYLEN);
memmove(authkey->aes, safe.aesmachkey, AESKEYLEN);
memset(&safe, 0, sizeof safe);
return 0;
}
@ -20,7 +21,7 @@ int
getauthkey(Authkey *authkey)
{
memset(authkey, 0, sizeof(Authkey));
if(getkey(authkey->des) == 0)
if(getkey(authkey) == 0)
return 1;
print("can't read NVRAM, please enter machine key\n");
getpass(authkey, nil, 0, 1);

View file

@ -22,15 +22,12 @@ getpass(Authkey *key, char *pass, int check, int confirm)
continue;
}
}
if(!passtokey(key, pass)){
print("bad password, try again\n");
continue;
}
if(check)
if(err = okpasswd(pass)){
print("%s, try again\n", err);
continue;
}
passtokey(key, pass);
break;
}
}

View file

@ -1,9 +1,10 @@
#include <u.h>
#include <libc.h>
#include <authsrv.h>
#include <libsec.h>
int
passtokey(Authkey *key, char *p)
static void
passtodeskey(char *key, char *p)
{
uchar buf[ANAMELEN], *t;
int i, n;
@ -15,18 +16,33 @@ passtokey(Authkey *key, char *p)
t = buf;
strncpy((char*)t, p, n);
t[n] = 0;
memset(key, 0, sizeof(Authkey));
memset(key, 0, DESKEYLEN);
for(;;){
for(i = 0; i < DESKEYLEN; i++)
key->des[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1)));
key[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1)));
if(n <= 8)
return 1;
return;
n -= 8;
t += 8;
if(n < 8){
t -= 8 - n;
n = 8;
}
encrypt(key->des, t, 8);
encrypt(key, t, 8);
}
}
static void
passtoaeskey(uchar *key, char *p)
{
static char salt[] = "Plan 9 key derivation";
pbkdf2_hmac_sha1((uchar*)p, strlen(p), (uchar*)salt, sizeof(salt)-1, 9001, key, AESKEYLEN);
}
void
passtokey(Authkey *key, char *p)
{
memset(key, 0, sizeof(Authkey));
passtodeskey(key->des, p);
passtoaeskey(key->aes, p);
}

View file

@ -268,13 +268,22 @@ readnvram(Nvrsafe *safep, int flag)
/* verify data read */
err |= check(safe->machkey, DESKEYLEN, safe->machsum,
"bad nvram key");
// err |= check(safe->config, CONFIGLEN, safe->configsum,
// "bad secstore key");
"bad nvram des key");
err |= check(safe->authid, ANAMELEN, safe->authidsum,
"bad authentication id");
err |= check(safe->authdom, DOMLEN, safe->authdomsum,
"bad authentication domain");
if(0){
err |= check(safe->config, CONFIGLEN, safe->configsum,
"bad secstore key");
err |= check(safe->aesmachkey, AESKEYLEN, safe->aesmachsum,
"bad nvram aes key");
} else {
if(nvcsum(safe->config, CONFIGLEN) != safe->configsum)
memset(safe->config, 0, CONFIGLEN);
if(nvcsum(safe->aesmachkey, AESKEYLEN) != safe->aesmachsum)
memset(safe->aesmachkey, 0, AESKEYLEN);
}
if(err == 0)
if(safe->authid[0]==0 || safe->authdom[0]==0){
fprint(2, "empty nvram authid or authdom\n");
@ -296,18 +305,19 @@ readnvram(Nvrsafe *safep, int flag)
if(readcons("password", nil, 1, in, sizeof in) == nil)
goto Out;
if(passtokey(&k, in)){
memmove(safe->machkey, k.des, DESKEYLEN);
break;
}
passtokey(&k, in);
memmove(safe->machkey, k.des, DESKEYLEN);
memmove(safe->aesmachkey, k.aes, AESKEYLEN);
break;
}
}
// safe->authsum = nvcsum(safe->authkey, DESKEYLEN);
safe->machsum = nvcsum(safe->machkey, DESKEYLEN);
// safe->authsum = nvcsum(safe->authkey, DESKEYLEN);
safe->configsum = nvcsum(safe->config, CONFIGLEN);
safe->authidsum = nvcsum(safe->authid, sizeof safe->authid);
safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom);
safe->aesmachsum = nvcsum(safe->aesmachkey, AESKEYLEN);
*(Nvrsafe*)buf = *safe;
if(loc.fd < 0