diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-21 02:43:31 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-21 02:43:31 +0200 |
commit | 63b18e79252845d09abbad44672eabd9233a911b (patch) | |
tree | a71e5f93e01bf695bca43cc148ebf9a2c9a738c7 /sys | |
parent | e48a5832b26f817ab06db2d42f88288373b78fac (diff) |
introduce AES key into nvram and keyfs
Diffstat (limited to 'sys')
-rw-r--r-- | sys/include/authsrv.h | 11 | ||||
-rw-r--r-- | sys/man/2/authsrv | 6 | ||||
-rw-r--r-- | sys/man/4/keyfs | 35 | ||||
-rw-r--r-- | sys/man/8/auth | 5 | ||||
-rw-r--r-- | sys/src/cmd/auth/convkeys.c | 161 | ||||
-rw-r--r-- | sys/src/cmd/auth/keyfs.c | 321 | ||||
-rw-r--r-- | sys/src/cmd/auth/lib/getauthkey.c | 7 | ||||
-rw-r--r-- | sys/src/cmd/auth/lib/readln.c | 5 | ||||
-rw-r--r-- | sys/src/libauthsrv/passtokey.c | 28 | ||||
-rw-r--r-- | sys/src/libauthsrv/readnvram.c | 26 |
10 files changed, 363 insertions, 242 deletions
diff --git a/sys/include/authsrv.h b/sys/include/authsrv.h index d8fbf36bc..1808f1716 100644 --- a/sys/include/authsrv.h +++ b/sys/include/authsrv.h @@ -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); diff --git a/sys/man/2/authsrv b/sys/man/2/authsrv index 70b1e7057..095753b5b 100644 --- a/sys/man/2/authsrv +++ b/sys/man/2/authsrv @@ -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: diff --git a/sys/man/4/keyfs b/sys/man/4/keyfs index c78e31df4..cbb93beaf 100644 --- a/sys/man/4/keyfs +++ b/sys/man/4/keyfs @@ -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 diff --git a/sys/man/8/auth b/sys/man/8/auth index a73076672..72b370a35 100644 --- a/sys/man/8/auth +++ b/sys/man/8/auth @@ -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 diff --git a/sys/src/cmd/auth/convkeys.c b/sys/src/cmd/auth/convkeys.c index bb7d553b3..7886fa457 100644 --- a/sys/src/cmd/auth/convkeys.c +++ b/sys/src/cmd/auth/convkeys.c @@ -7,18 +7,21 @@ #include <bio.h> #include "authcmdlib.h" -Authkey authkey; +Authkey okey, nkey; + int verb; int usepass; +int convaes; + +uchar zeros[16]; -int convert(char*, Authkey*, int); +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; + + 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; + 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; - len -= KEYDBOFF; - if(len % KEYDBLEN){ - fprint(2, "convkeys: file odd length; not converting %d bytes\n", - len % KEYDBLEN); - len -= len % KEYDBLEN; + /* 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); } - len += KEYDBOFF; - oldCBCdecrypt(authkey.des, p, len); - for(i = KEYDBOFF; i < len; i += KEYDBLEN) + + 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); + } + + 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, 8); - oldCBCencrypt(key->des, p, len); + 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"); } diff --git a/sys/src/cmd/auth/keyfs.c b/sys/src/cmd/auth/keyfs.c index 8c6c01748..9ec02e0fb 100644 --- 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 @@ 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) @@ -713,57 +715,35 @@ randombytes(uchar *p, int len) } 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 diff --git a/sys/src/cmd/auth/lib/getauthkey.c b/sys/src/cmd/auth/lib/getauthkey.c index 84c3d1557..48437e808 100644 --- 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 @@ 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); diff --git a/sys/src/cmd/auth/lib/readln.c b/sys/src/cmd/auth/lib/readln.c index 38a712497..f5b8789f7 100644 --- a/sys/src/cmd/auth/lib/readln.c +++ b/sys/src/cmd/auth/lib/readln.c @@ -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; } } diff --git a/sys/src/libauthsrv/passtokey.c b/sys/src/libauthsrv/passtokey.c index 44963cec6..c829b374e 100644 --- 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,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); +} diff --git a/sys/src/libauthsrv/readnvram.c b/sys/src/libauthsrv/readnvram.c index 5d054725d..ae708acbc 100644 --- a/sys/src/libauthsrv/readnvram.c +++ b/sys/src/libauthsrv/readnvram.c @@ -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 |