ref: 63b18e79252845d09abbad44672eabd9233a911b
parent: e48a5832b26f817ab06db2d42f88288373b78fac
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Aug 20 22:43:31 EDT 2015
introduce AES key into nvram and keyfs
--- a/sys/include/authsrv.h
+++ b/sys/include/authsrv.h
@@ -20,6 +20,7 @@
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 Authkey
{
char des[DESKEYLEN];
+ uchar aes[AESKEYLEN];
};
/*
@@ -132,7 +134,7 @@
/*
* convert ascii password to DES key
*/
-extern int passtokey(Authkey*, char*);
+extern void passtokey(Authkey*, char*);
/*
* Nvram interface
@@ -147,7 +149,7 @@
/* 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 @@
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);
--- a/sys/man/2/authsrv
+++ b/sys/man/2/authsrv
@@ -15,7 +15,7 @@
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 @@
.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:
--- a/sys/man/4/keyfs
+++ b/sys/man/4/keyfs
@@ -41,7 +41,7 @@
.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 @@
.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 @@
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 @@
.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 @@
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
@@ -132,6 +143,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.
--- a/sys/man/8/auth
+++ b/sys/man/8/auth
@@ -7,7 +7,7 @@
.I user
.PP
.B auth/convkeys
-.RB [ -p ]
+.RB [ -pa ]
.I keyfile
.PP
.B auth/convkeys2
@@ -151,6 +151,9 @@
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
--- a/sys/src/cmd/auth/convkeys.c
+++ b/sys/src/cmd/auth/convkeys.c
@@ -7,11 +7,15 @@
#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
@@ -18,7 +22,6 @@
main(int argc, char *argv[])
{
Dir *d;
- Authkey key;
char *p, *file;
int fd, len;
@@ -29,6 +32,9 @@
case 'v':
verb = 1;
break;
+ case 'a':
+ convaes = 1;
+ break;
default:
usage();
}ARGEND
@@ -40,12 +46,13 @@
/* 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 @@
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 @@
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 @@
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,29 +106,96 @@
}
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)
+
+ 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])) {
- print("bad name %.30s... - aborting\n", &p[i]);
- return 0;
+ fprint(2, "%s: bad name %.30s... - aborting\n", argv0, &p[i]);
+ exits("bad name");
}
- if(verb)
- for(i = KEYDBOFF; i < len; i += KEYDBLEN)
+ nu++;
+ }
+
+ if(verb){
+ for(i = keydboff; i < len; i += keydblen)
print("%s\n", &p[i]);
+ exits(nil);
+ }
- randombytes((uchar*)p, 8);
- oldCBCencrypt(key->des, p, len);
+ 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;
}
@@ -157,6 +202,6 @@
void
usage(void)
{
- fprint(2, "usage: convkeys keyfile\n");
+ fprint(2, "usage: %s [-pva] keyfile\n", argv0);
exits("usage");
}
--- a/sys/src/cmd/auth/keyfs.c
+++ b/sys/src/cmd/auth/keyfs.c
@@ -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 @@
Qroot,
Quser,
Qkey,
+ Qaeskey,
Qsecret,
Qlog,
Qstatus,
@@ -52,6 +55,7 @@
struct User {
char *name;
char key[DESKEYLEN];
+ uchar aeskey[AESKEYLEN];
char secret[SECRETLEN];
ulong expire; /* 0 == never */
uchar status;
@@ -68,6 +72,7 @@
[Qroot] "keys",
[Quser] ".",
[Qkey] "key",
+ [Qaeskey] "aeskey",
[Qsecret] "secret",
[Qlog] "log",
[Qexpire] "expire",
@@ -85,8 +90,7 @@
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 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 @@
exits("usage");
}
+static int
+haveaeskey(void)
+{
+ return memcmp(authkey.aes, zeros, 16) != 0;
+}
+
void
main(int argc, char *argv[])
{
@@ -169,13 +180,24 @@
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)){
case 0:
close(p[0]);
@@ -209,7 +231,7 @@
{
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 @@
if(strcmp(name, "..") == 0)
goto Accept;
user = finduser(name);
- if(!user)
+ if(user == nil)
goto Out;
qtype = Quser;
@@ -283,7 +305,7 @@
case Quser:
if(strcmp(name, "..") == 0) {
qtype = Qroot;
- user = 0;
+ user = nil;
goto Accept;
}
max = Qmax;
@@ -314,14 +336,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,18 +696,7 @@
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)
{
@@ -713,57 +715,35 @@
}
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,11 +757,28 @@
*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);
if(fd < 0){
@@ -858,6 +855,7 @@
int
readusers(void)
{
+ int keydblen, keydboff;
int fd, i, n, nu;
uchar *p, *buf, *ep;
User *u;
@@ -872,12 +870,7 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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,13 +1015,13 @@
{
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;
}
@@ -1011,7 +1028,7 @@
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 @@
{
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
--- a/sys/src/cmd/auth/lib/getauthkey.c
+++ b/sys/src/cmd/auth/lib/getauthkey.c
@@ -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 @@
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);
--- a/sys/src/cmd/auth/lib/readln.c
+++ b/sys/src/cmd/auth/lib/readln.c
@@ -22,15 +22,12 @@
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;
}
}
--- a/sys/src/libauthsrv/passtokey.c
+++ b/sys/src/libauthsrv/passtokey.c
@@ -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,12 +16,12 @@
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){
@@ -27,6 +28,21 @@
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);
}
--- a/sys/src/libauthsrv/readnvram.c
+++ b/sys/src/libauthsrv/readnvram.c
@@ -268,13 +268,22 @@
/* 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 @@
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