diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-01-06 03:09:00 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-01-06 03:09:00 +0100 |
commit | 2dae1ed53a73d81bfb86778793a6bda265d5140d (patch) | |
tree | e037c4a663fc9d17906cc2045c488232ac223ece /sys/src/libauthsrv | |
parent | e064752dd476b7a2f76567f8cc15f9c2645e5d3d (diff) |
auth: release dp9ik implementation and reentrant factotum
Diffstat (limited to 'sys/src/libauthsrv')
-rw-r--r-- | sys/src/libauthsrv/_asgetpakkey.c | 26 | ||||
-rw-r--r-- | sys/src/libauthsrv/_asgetresp.c | 36 | ||||
-rw-r--r-- | sys/src/libauthsrv/_asgetticket.c | 34 | ||||
-rw-r--r-- | sys/src/libauthsrv/authpak.c | 214 | ||||
-rw-r--r-- | sys/src/libauthsrv/convA2M.c | 33 | ||||
-rw-r--r-- | sys/src/libauthsrv/convM2A.c | 43 | ||||
-rw-r--r-- | sys/src/libauthsrv/convM2PR.c | 45 | ||||
-rw-r--r-- | sys/src/libauthsrv/convM2T.c | 60 | ||||
-rw-r--r-- | sys/src/libauthsrv/convM2TR.c | 20 | ||||
-rw-r--r-- | sys/src/libauthsrv/convPR2M.c | 32 | ||||
-rw-r--r-- | sys/src/libauthsrv/convT2M.c | 38 | ||||
-rw-r--r-- | sys/src/libauthsrv/convTR2M.c | 19 | ||||
-rw-r--r-- | sys/src/libauthsrv/decaf.mp | 49 | ||||
-rw-r--r-- | sys/src/libauthsrv/ed448.mp | 11 | ||||
-rw-r--r-- | sys/src/libauthsrv/edwards.mp | 40 | ||||
-rw-r--r-- | sys/src/libauthsrv/elligator2.mp | 30 | ||||
-rw-r--r-- | sys/src/libauthsrv/form1.c | 90 | ||||
-rw-r--r-- | sys/src/libauthsrv/mkfile | 22 | ||||
-rw-r--r-- | sys/src/libauthsrv/msqrt.mp | 100 | ||||
-rw-r--r-- | sys/src/libauthsrv/passtokey.c | 14 | ||||
-rw-r--r-- | sys/src/libauthsrv/spake2ee.mp | 35 |
21 files changed, 838 insertions, 153 deletions
diff --git a/sys/src/libauthsrv/_asgetpakkey.c b/sys/src/libauthsrv/_asgetpakkey.c new file mode 100644 index 000000000..c30b16b84 --- /dev/null +++ b/sys/src/libauthsrv/_asgetpakkey.c @@ -0,0 +1,26 @@ +#include <u.h> +#include <libc.h> +#include <authsrv.h> + +int +_asgetpakkey(int fd, Ticketreq *tr, Authkey *a) +{ + uchar y[PAKYLEN]; + PAKpriv p; + int type; + + type = tr->type; + tr->type = AuthPAK; + if(_asrequest(fd, tr) != 0){ + tr->type = type; + return -1; + } + tr->type = type; + authpak_new(&p, a, y, 1); + if(write(fd, y, PAKYLEN) != PAKYLEN + || _asrdresp(fd, (char*)y, PAKYLEN) != PAKYLEN){ + memset(&p, 0, sizeof(p)); + return -1; + } + return authpak_finish(&p, a, y); +} diff --git a/sys/src/libauthsrv/_asgetresp.c b/sys/src/libauthsrv/_asgetresp.c index da0e2bd20..3f7cb5d4f 100644 --- a/sys/src/libauthsrv/_asgetresp.c +++ b/sys/src/libauthsrv/_asgetresp.c @@ -5,28 +5,40 @@ int _asgetresp(int fd, Ticket *t, Authenticator *a, Authkey *k) { - char tbuf[TICKETLEN+AUTHENTLEN]; + char buf[MAXTICKETLEN+MAXAUTHENTLEN], err[ERRMAX]; int n, m; - m = TICKETLEN; memset(t, 0, sizeof(Ticket)); - if(a != nil){ - m += AUTHENTLEN; + if(a != nil) memset(a, 0, sizeof(Authenticator)); - } - n = _asrdresp(fd, tbuf, m); - if(n <= 0) - return -1; + strcpy(err, "AS protocol botch"); + errstr(err, ERRMAX); - m = convM2T(tbuf, n, t, k); - if(m <= 0) + if(_asrdresp(fd, buf, 0) < 0) return -1; - if(a != nil){ - if(convM2A(tbuf+m, n-m, a, t) <= 0) + for(n = 0; (m = convM2T(buf, n, t, k)) <= 0; n += m){ + m = -m; + if(m <= n || m > sizeof(buf)) + return -1; + m -= n; + if(readn(fd, buf+n, m) != m) return -1; } + if(a != nil){ + for(n = 0; (m = convM2A(buf, n, a, t)) <= 0; n += m){ + m = -m; + if(m <= n || m > sizeof(buf)) + return -1; + m -= n; + if(readn(fd, buf+n, m) != m) + return -1; + } + } + + errstr(err, ERRMAX); + return 0; } diff --git a/sys/src/libauthsrv/_asgetticket.c b/sys/src/libauthsrv/_asgetticket.c index 11a344621..d7e30b2a8 100644 --- a/sys/src/libauthsrv/_asgetticket.c +++ b/sys/src/libauthsrv/_asgetticket.c @@ -2,16 +2,36 @@ #include <libc.h> #include <authsrv.h> -static char *pbmsg = "AS protocol botch"; - int _asgetticket(int fd, Ticketreq *tr, char *tbuf, int tbuflen) { - if(_asrequest(fd, tr) < 0){ - werrstr(pbmsg); + char err[ERRMAX]; + int i, n, m, r; + + strcpy(err, "AS protocol botch"); + errstr(err, ERRMAX); + + if(_asrequest(fd, tr) < 0) + return -1; + if(_asrdresp(fd, tbuf, 0) < 0) return -1; + + r = 0; + for(i = 0; i<2; i++){ + for(n=0; (m = convM2T(tbuf, n, nil, nil)) <= 0; n += m){ + m = -m; + if(m <= n || m > tbuflen) + return -1; + m -= n; + if(readn(fd, tbuf+n, m) != m) + return -1; + } + r += n; + tbuf += n; + tbuflen -= n; } - if(tbuflen > 2*TICKETLEN) - tbuflen = 2*TICKETLEN; - return _asrdresp(fd, tbuf, tbuflen); + + errstr(err, ERRMAX); + + return r; } diff --git a/sys/src/libauthsrv/authpak.c b/sys/src/libauthsrv/authpak.c new file mode 100644 index 000000000..50f7ee6d0 --- /dev/null +++ b/sys/src/libauthsrv/authpak.c @@ -0,0 +1,214 @@ +#include <u.h> +#include <libc.h> +#include <mp.h> +#include <libsec.h> +#include <authsrv.h> + +#include "msqrt.mpc" +#include "decaf.mpc" +#include "edwards.mpc" +#include "elligator2.mpc" +#include "spake2ee.mpc" +#include "ed448.mpc" + +typedef struct PAKcurve PAKcurve; +struct PAKcurve +{ + Lock; + mpint *P; + mpint *A; + mpint *D; + mpint *X; + mpint *Y; +}; + +static PAKcurve* +authpak_curve(void) +{ + static PAKcurve a; + + lock(&a); + if(a.P == nil){ + a.P = mpnew(0); + a.A = mpnew(0); + a.D = mpnew(0); + a.X = mpnew(0); + a.Y = mpnew(0); + ed448_curve(a.P, a.A, a.D, a.X, a.Y); + a.P = mpfield(a.P); + } + unlock(&a); + return &a; +} + +void +authpak_hash(Authkey *k, char *u) +{ + static char info[] = "Plan 9 AuthPAK hash"; + uchar *bp, salt[SHA2_256dlen], h[2*PAKSLEN]; + mpint *H, *PX,*PY,*PZ,*PT; + PAKcurve *c; + + H = mpnew(0); + PX = mpnew(0); + PY = mpnew(0); + PZ = mpnew(0); + PT = mpnew(0); + + sha2_256((uchar*)u, strlen(u), salt, nil); + + hkdf_x( salt, SHA2_256dlen, + (uchar*)info, sizeof(info)-1, + k->aes, AESKEYLEN, + h, sizeof(h), + hmac_sha2_256, SHA2_256dlen); + + c = authpak_curve(); + + betomp(h + 0*PAKSLEN, PAKSLEN, H); /* HM */ + spake2ee_h2P(c->P,c->A,c->D, H, PX,PY,PZ,PT); /* PM */ + + bp = k->pakhash; + mptober(PX, bp, PAKSLEN), bp += PAKSLEN; + mptober(PY, bp, PAKSLEN), bp += PAKSLEN; + mptober(PZ, bp, PAKSLEN), bp += PAKSLEN; + mptober(PT, bp, PAKSLEN), bp += PAKSLEN; + + betomp(h + 1*PAKSLEN, PAKSLEN, H); /* HN */ + spake2ee_h2P(c->P,c->A,c->D, H, PX,PY,PZ,PT); /* PN */ + + mptober(PX, bp, PAKSLEN), bp += PAKSLEN; + mptober(PY, bp, PAKSLEN), bp += PAKSLEN; + mptober(PZ, bp, PAKSLEN), bp += PAKSLEN; + mptober(PT, bp, PAKSLEN); + + mpfree(PX); + mpfree(PY); + mpfree(PZ); + mpfree(PT); + mpfree(H); +} + +void +authpak_new(PAKpriv *p, Authkey *k, uchar y[PAKYLEN], int isclient) +{ + mpint *PX,*PY,*PZ,*PT, *X, *Y; + PAKcurve *c; + uchar *bp; + + memset(p, 0, sizeof(PAKpriv)); + p->isclient = isclient != 0; + + X = mpnew(0); + Y = mpnew(0); + + PX = mpnew(0); + PY = mpnew(0); + PZ = mpnew(0); + PT = mpnew(0); + + PX->flags |= MPtimesafe; + PY->flags |= MPtimesafe; + PZ->flags |= MPtimesafe; + PT->flags |= MPtimesafe; + + bp = k->pakhash + PAKPLEN*(p->isclient == 0); + betomp(bp, PAKSLEN, PX), bp += PAKSLEN; + betomp(bp, PAKSLEN, PY), bp += PAKSLEN; + betomp(bp, PAKSLEN, PZ), bp += PAKSLEN; + betomp(bp, PAKSLEN, PT); + + c = authpak_curve(); + + X->flags |= MPtimesafe; + mpnrand(c->P, genrandom, X); + + spake2ee_1(c->P,c->A,c->D, X, c->X,c->Y, PX,PY,PZ,PT, Y); + + mptober(X, p->x, PAKXLEN); + mptober(Y, p->y, PAKYLEN); + + memmove(y, p->y, PAKYLEN); + + mpfree(PX); + mpfree(PY); + mpfree(PZ); + mpfree(PT); + + mpfree(X); + mpfree(Y); +} + +int +authpak_finish(PAKpriv *p, Authkey *k, uchar y[PAKYLEN]) +{ + static char info[] = "Plan 9 AuthPAK key"; + uchar *bp, z[PAKSLEN], salt[SHA2_256dlen]; + mpint *PX,*PY,*PZ,*PT, *X, *Y, *Z, *ok; + DigestState *s; + PAKcurve *c; + int ret; + + X = mpnew(0); + Y = mpnew(0); + Z = mpnew(0); + ok = mpnew(0); + + PX = mpnew(0); + PY = mpnew(0); + PZ = mpnew(0); + PT = mpnew(0); + + PX->flags |= MPtimesafe; + PY->flags |= MPtimesafe; + PZ->flags |= MPtimesafe; + PT->flags |= MPtimesafe; + + bp = k->pakhash + PAKPLEN*(p->isclient != 0); + betomp(bp, PAKSLEN, PX), bp += PAKSLEN; + betomp(bp, PAKSLEN, PY), bp += PAKSLEN; + betomp(bp, PAKSLEN, PZ), bp += PAKSLEN; + betomp(bp, PAKSLEN, PT); + + Z->flags |= MPtimesafe; + X->flags |= MPtimesafe; + betomp(p->x, PAKXLEN, X); + + betomp(y, PAKYLEN, Y); + + c = authpak_curve(); + spake2ee_2(c->P,c->A,c->D, PX,PY,PZ,PT, X, Y, ok, Z); + + if(mpcmp(ok, mpzero) == 0){ + ret = -1; + goto out; + } + + mptober(Z, z, sizeof(z)); + + s = sha2_256(p->isclient ? p->y : y, PAKYLEN, nil, nil); + sha2_256(p->isclient ? y : p->y, PAKYLEN, salt, s); + + hkdf_x( salt, SHA2_256dlen, + (uchar*)info, sizeof(info)-1, + z, sizeof(z), + k->pakkey, PAKKEYLEN, + hmac_sha2_256, SHA2_256dlen); + + ret = 0; +out: + memset(z, 0, sizeof(z)); + memset(p, 0, sizeof(PAKpriv)); + + mpfree(PX); + mpfree(PY); + mpfree(PZ); + mpfree(PT); + + mpfree(X); + mpfree(Y); + mpfree(Z); + mpfree(ok); + + return ret; +} diff --git a/sys/src/libauthsrv/convA2M.c b/sys/src/libauthsrv/convA2M.c index d285ad770..4db2df39e 100644 --- a/sys/src/libauthsrv/convA2M.c +++ b/sys/src/libauthsrv/convA2M.c @@ -2,26 +2,35 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) *p++ = f->x -#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 -#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(p, f->x, n); p += n +extern int form1B2M(char *ap, int n, uchar key[32]); int convA2M(Authenticator *f, char *ap, int n, Ticket *t) { uchar *p; - if(n < AUTHENTLEN) + if(n < 1+CHALLEN) return 0; p = (uchar*)ap; - CHAR(num); - STRING(chal, CHALLEN); - LONG(id); - n = p - (uchar*)ap; - if(t) + *p++ = f->num; + memmove(p, f->chal, CHALLEN), p += CHALLEN; + switch(t->form){ + case 0: + if(n < 1+CHALLEN+4) + return 0; + + memset(p, 0, 4), p += 4; /* unused id field */ + n = p - (uchar*)ap; encrypt(t->key, ap, n); - return n; + return n; + case 1: + if(n < 12+CHALLEN+NONCELEN+16) + return 0; + + memmove(p, f->rand, NONCELEN), p += NONCELEN; + return form1B2M(ap, (char*)p - ap, t->key); + } + + return 0; } diff --git a/sys/src/libauthsrv/convM2A.c b/sys/src/libauthsrv/convM2A.c index b0d6712ca..0da7865fe 100644 --- a/sys/src/libauthsrv/convM2A.c +++ b/sys/src/libauthsrv/convM2A.c @@ -2,30 +2,35 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) f->x = *p++ -#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 -#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(f->x, p, n); p += n +extern int form1M2B(char *ap, int n, uchar key[32]); int convM2A(char *ap, int n, Authenticator *f, Ticket *t) { - uchar *p, buf[AUTHENTLEN]; + uchar buf[MAXAUTHENTLEN], *p; + int m; memset(f, 0, sizeof(Authenticator)); - if(n < AUTHENTLEN) - return -AUTHENTLEN; - - if(t) { - memmove(buf, ap, AUTHENTLEN); - ap = (char*)buf; - decrypt(t->key, ap, AUTHENTLEN); + if(t->form == 0){ + m = 1+CHALLEN+4; + if(n < m) + return -m; + memmove(buf, ap, m); + decrypt(t->key, buf, m); + } else { + m = 12+CHALLEN+NONCELEN+16; + if(n < m) + return -m; + memmove(buf, ap, m); + if(form1M2B((char*)buf, m, t->key) < 0) + return m; } - p = (uchar*)ap; - CHAR(num); - STRING(chal, CHALLEN); - LONG(id); - n = p - (uchar*)ap; - return n; + p = buf; + f->num = *p++; + memmove(f->chal, p, CHALLEN); + p += CHALLEN; + if(t->form == 1) + memmove(f->rand, p, NONCELEN); + + return m; } diff --git a/sys/src/libauthsrv/convM2PR.c b/sys/src/libauthsrv/convM2PR.c index c7bd4974d..ecc46e649 100644 --- a/sys/src/libauthsrv/convM2PR.c +++ b/sys/src/libauthsrv/convM2PR.c @@ -2,35 +2,38 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) f->x = *p++ -#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 -#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(f->x, p, n); p += n +extern int form1M2B(char *ap, int n, uchar key[32]); int convM2PR(char *ap, int n, Passwordreq *f, Ticket *t) { - uchar *p, buf[PASSREQLEN]; + uchar *p, buf[MAXPASSREQLEN]; + int m; memset(f, 0, sizeof(Passwordreq)); - if(n < PASSREQLEN) - return -PASSREQLEN; - - if(t){ - memmove(buf, ap, PASSREQLEN); - ap = (char*)buf; - decrypt(t->key, ap, PASSREQLEN); + if(t->form == 0){ + m = 1+2*ANAMELEN+1+SECRETLEN; + if(n < m) + return -m; + memmove(buf, ap, m); + decrypt(t->key, buf, m); + } else { + m = 12+2*ANAMELEN+1+SECRETLEN+16; + if(n < m) + return -m; + memmove(buf, ap, m); + if(form1M2B((char*)buf, m, t->key) < 0) + return m; } - p = (uchar*)ap; - CHAR(num); - STRING(old, ANAMELEN); + p = buf; + f->num = *p++; + memmove(f->old, p, ANAMELEN), p += ANAMELEN; + memmove(f->new, p, ANAMELEN), p += ANAMELEN; + f->changesecret = *p++; + memmove(f->secret, p, SECRETLEN); f->old[ANAMELEN-1] = 0; - STRING(new, ANAMELEN); f->new[ANAMELEN-1] = 0; - CHAR(changesecret); - STRING(secret, SECRETLEN); f->secret[SECRETLEN-1] = 0; - n = p - (uchar*)ap; - return n; + + return m; } diff --git a/sys/src/libauthsrv/convM2T.c b/sys/src/libauthsrv/convM2T.c index 425ebefdd..cfe97b734 100644 --- a/sys/src/libauthsrv/convM2T.c +++ b/sys/src/libauthsrv/convM2T.c @@ -2,34 +2,50 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) f->x = *p++ -#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 -#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(f->x, p, n); p += n +extern int form1check(char *ap, int n); +extern int form1M2B(char *ap, int n, uchar key[32]); int -convM2T(char *ap, int n, Ticket *f, Authkey *key) +convM2T(char *ap, int n, Ticket *f, Authkey *k) { - uchar *p, buf[TICKETLEN]; + uchar buf[MAXTICKETLEN], *p; + int m; - memset(f, 0, sizeof(Ticket)); - if(n < TICKETLEN) - return -TICKETLEN; + if(f != nil) + memset(f, 0, sizeof(Ticket)); - if(key){ - memmove(buf, ap, TICKETLEN); - ap = (char*)buf; - decrypt(key->des, ap, TICKETLEN); + if(n < 8) + return -8; + + if(form1check(ap, n) < 0){ + m = 1+CHALLEN+2*ANAMELEN+DESKEYLEN; + if(n < m) + return -m; + if(f == nil || k == nil) + return m; + f->form = 0; + memmove(buf, ap, m); + decrypt(k->des, buf, m); + } else { + m = 12+CHALLEN+2*ANAMELEN+NONCELEN+16; + if(n < m) + return -m; + if(f == nil || k == nil) + return m; + f->form = 1; + memmove(buf, ap, m); + if(form1M2B((char*)buf, m, k->pakkey) < 0) + return m; } - p = (uchar*)ap; - CHAR(num); - STRING(chal, CHALLEN); - STRING(cuid, ANAMELEN); + p = buf; + f->num = *p++; + memmove(f->chal, p, CHALLEN), p += CHALLEN; + memmove(f->cuid, p, ANAMELEN), p += ANAMELEN; + memmove(f->suid, p, ANAMELEN), p += ANAMELEN; + memmove(f->key, p, f->form == 0 ? DESKEYLEN : NONCELEN); + f->cuid[ANAMELEN-1] = 0; - STRING(suid, ANAMELEN); f->suid[ANAMELEN-1] = 0; - STRING(key, DESKEYLEN); - n = p - (uchar*)ap; - return n; + + return m; } diff --git a/sys/src/libauthsrv/convM2TR.c b/sys/src/libauthsrv/convM2TR.c index d6491705b..79749873c 100644 --- a/sys/src/libauthsrv/convM2TR.c +++ b/sys/src/libauthsrv/convM2TR.c @@ -2,12 +2,6 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) f->x = *p++ -#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 -#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(f->x, p, n); p += n - int convM2TR(char *ap, int n, Ticketreq *f) { @@ -18,16 +12,18 @@ convM2TR(char *ap, int n, Ticketreq *f) return -TICKREQLEN; p = (uchar*)ap; - CHAR(type); - STRING(authid, ANAMELEN); + f->type = *p++; + memmove(f->authid, p, ANAMELEN), p += ANAMELEN; + memmove(f->authdom, p, DOMLEN), p += DOMLEN; + memmove(f->chal, p, CHALLEN), p += CHALLEN; + memmove(f->hostid, p, ANAMELEN), p += ANAMELEN; + memmove(f->uid, p, ANAMELEN), p += ANAMELEN; + f->authid[ANAMELEN-1] = 0; - STRING(authdom, DOMLEN); f->authdom[DOMLEN-1] = 0; - STRING(chal, CHALLEN); - STRING(hostid, ANAMELEN); f->hostid[ANAMELEN-1] = 0; - STRING(uid, ANAMELEN); f->uid[ANAMELEN-1] = 0; n = p - (uchar*)ap; + return n; } diff --git a/sys/src/libauthsrv/convPR2M.c b/sys/src/libauthsrv/convPR2M.c index d5c0ee7ac..0f3463ef2 100644 --- a/sys/src/libauthsrv/convPR2M.c +++ b/sys/src/libauthsrv/convPR2M.c @@ -2,29 +2,33 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) *p++ = f->x -#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 -#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(p, f->x, n); p += n +extern int form1B2M(char *ap, int n, uchar key[32]); int convPR2M(Passwordreq *f, char *ap, int n, Ticket *t) { uchar *p; - if(n < PASSREQLEN) + if(n < 1+2*ANAMELEN+1+SECRETLEN) return 0; p = (uchar*)ap; - CHAR(num); - STRING(old, ANAMELEN); - STRING(new, ANAMELEN); - CHAR(changesecret); - STRING(secret, SECRETLEN); - n = p - (uchar*)ap; - if(t) + *p++ = f->num; + memmove(p, f->old, ANAMELEN), p += ANAMELEN; + memmove(p, f->new, ANAMELEN), p += ANAMELEN; + *p++ = f->changesecret; + memmove(p, f->secret, SECRETLEN), p += SECRETLEN; + switch(t->form){ + case 0: + n = p - (uchar*)ap; encrypt(t->key, ap, n); - return n; + return n; + case 1: + if(n < 12+2*ANAMELEN+1+SECRETLEN+16) + return 0; + return form1B2M(ap, p - (uchar*)ap, t->key); + } + + return 0; } diff --git a/sys/src/libauthsrv/convT2M.c b/sys/src/libauthsrv/convT2M.c index 77edcef1f..5f1243498 100644 --- a/sys/src/libauthsrv/convT2M.c +++ b/sys/src/libauthsrv/convT2M.c @@ -1,29 +1,39 @@ #include <u.h> #include <libc.h> #include <authsrv.h> +#include <libsec.h> -#define CHAR(x) *p++ = f->x -#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 -#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(p, f->x, n); p += n +extern int form1B2M(char *ap, int n, uchar key[32]); int convT2M(Ticket *f, char *ap, int n, Authkey *key) { uchar *p; - if(n < TICKETLEN) + if(n < 1+CHALLEN+2*ANAMELEN) return 0; p = (uchar*)ap; - CHAR(num); - STRING(chal, CHALLEN); - STRING(cuid, ANAMELEN); - STRING(suid, ANAMELEN); - STRING(key, DESKEYLEN); - n = p - (uchar*)ap; - if(key) + *p++ = f->num; + memmove(p, f->chal, CHALLEN), p += CHALLEN; + memmove(p, f->cuid, ANAMELEN), p += ANAMELEN; + memmove(p, f->suid, ANAMELEN), p += ANAMELEN; + switch(f->form){ + case 0: + if(n < 1+CHALLEN+2*ANAMELEN+DESKEYLEN) + return 0; + + memmove(p, f->key, DESKEYLEN), p += DESKEYLEN; + n = p - (uchar*)ap; encrypt(key->des, ap, n); - return n; + return n; + case 1: + if(n < 12+CHALLEN+2*ANAMELEN+NONCELEN+16) + return 0; + + memmove(p, f->key, NONCELEN), p += NONCELEN; + return form1B2M(ap, p - (uchar*)ap, key->pakkey); + } + + return 0; } diff --git a/sys/src/libauthsrv/convTR2M.c b/sys/src/libauthsrv/convTR2M.c index 0bbe9cb6f..8664ed066 100644 --- a/sys/src/libauthsrv/convTR2M.c +++ b/sys/src/libauthsrv/convTR2M.c @@ -2,12 +2,6 @@ #include <libc.h> #include <authsrv.h> -#define CHAR(x) *p++ = f->x -#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 -#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 -#define LONG(x) VLONG(f->x) -#define STRING(x,n) memmove(p, f->x, n); p += n - int convTR2M(Ticketreq *f, char *ap, int n) { @@ -17,12 +11,13 @@ convTR2M(Ticketreq *f, char *ap, int n) return 0; p = (uchar*)ap; - CHAR(type); - STRING(authid, 28); /* BUG */ - STRING(authdom, DOMLEN); - STRING(chal, CHALLEN); - STRING(hostid, 28); /* BUG */ - STRING(uid, 28); /* BUG */ + *p++ = f->type; + memmove(p, f->authid, ANAMELEN), p += ANAMELEN; + memmove(p, f->authdom, DOMLEN), p += DOMLEN; + memmove(p, f->chal, CHALLEN), p += CHALLEN; + memmove(p, f->hostid, ANAMELEN), p += ANAMELEN; + memmove(p, f->uid, ANAMELEN), p += ANAMELEN; n = p - (uchar*)ap; + return n; } diff --git a/sys/src/libauthsrv/decaf.mp b/sys/src/libauthsrv/decaf.mp new file mode 100644 index 000000000..509e3edd7 --- /dev/null +++ b/sys/src/libauthsrv/decaf.mp @@ -0,0 +1,49 @@ +# negate r when n > (p-1)/2 +decaf_neg(p, n, r) { + mod(p) m = -r; + r = n > (p-1)>>1 ? m : r; +} + +# field F_p +# curve a*x**2+y**2==1+d*x**2*y**2 +# input X,Y,Z,T (extended coordinates) +decaf_encode(p,a,d, X,Y,Z,T, s) mod(p) { + r = misqrt((a-d)*(Z+Y)*(Z-Y), p); + u = (a-d)*r; + decaf_neg(p, -2*u*Z, r); + s = u*(r*(a*Z*X-d*Y*T)+Y)/a; + decaf_neg(p, s, s); +} + +# field F_p +# curve a*x**2+y**2==1+d*x**2*y**2 +# input s +# output in extended coordinates +decaf_decode(p,a,d, s, ok,X,Y,Z,T) { + if(s > (p-1)>>1){ + ok = 0; + } else mod(p) { + ss = s^2; + Z = 1+a*ss; + u = Z^2 - 4*d*ss; + v = u*ss; + if(v == 0) + ok = 1; + else { + ok = msqrt(v, p); + if(ok != 0){ + v = 1/ok; + ok = 1; + } + } + if(ok != 0) { + decaf_neg(p, u*v, v); + w = v * s * (2-Z); + if(s == 0) + w = w + 1; + X = 2*s; + Y = w * Z; + T = w * X; + } + } +} diff --git a/sys/src/libauthsrv/ed448.mp b/sys/src/libauthsrv/ed448.mp new file mode 100644 index 000000000..89c57727b --- /dev/null +++ b/sys/src/libauthsrv/ed448.mp @@ -0,0 +1,11 @@ +# Edwards Curve Ed448-Goldilocks + +# x^2+y^2 = 1-39081x^2y^2 +# modulo p = 2^448 - 1^224 - 1 +ed448_curve(p,a,d,x,y) { + p = (1<<448) - (1<<224) - 1; + a = 1; + d = -39081; + x = 117812161263436946737282484343310064665180535357016373416879082147939404277809514858788439644911793978499419995990477371552926308078495; + y = 19; +} diff --git a/sys/src/libauthsrv/edwards.mp b/sys/src/libauthsrv/edwards.mp new file mode 100644 index 000000000..33305b71a --- /dev/null +++ b/sys/src/libauthsrv/edwards.mp @@ -0,0 +1,40 @@ +# Edwards curve arithmetic +edwards_add(p,a,d, X1,Y1,Z1,T1, X2,Y2,Z2,T2, X3,Y3,Z3,T3) mod(p) { + A = X1*X2; + B = Y1*Y2; + C = d*T1*T2; + D = Z1*Z2; + E = (X1+Y1)*(X2+Y2); + E = E - A - B; + F = D - C; + G = D + C; + H = B - a*A; + X3 = E*F; + Y3 = G*H; + Z3 = F*G; + T3 = E*H; +} +edwards_sel(s, X1,Y1,Z1,T1, X2,Y2,Z2,T2, X3,Y3,Z3,T3){ + X3 = s != 0 ? X1 : X2; + Y3 = s != 0 ? Y1 : Y2; + Z3 = s != 0 ? Z1 : Z2; + T3 = s != 0 ? T1 : T2; +} +edwards_new(x,y,z,t, X,Y,Z,T) { + X = x; + Y = y; + Z = z; + T = t; +} +edwards_scale(p,a,d, s, X1,Y1,Z1,T1, X3,Y3,Z3,T3) { + X2,Y2,Z2,T2 = edwards_new(X1,Y1,Z1,T1); + X4,Y4,Z4,T4 = edwards_new( 0, 1, 1, 0); + X3,Y3,Z3,T3 = edwards_sel(s % 2, X2,Y2,Z2,T2, X4,Y4,Z4,T4); + k = s >> 1; j = p >> 1; + while(j != 0){ + X2,Y2,Z2,T2 = edwards_add(p,a,d, X2,Y2,Z2,T2, X2,Y2,Z2,T2); + X4,Y4,Z4,T4 = edwards_add(p,a,d, X2,Y2,Z2,T2, X3,Y3,Z3,T3); + X3,Y3,Z3,T3 = edwards_sel(k % 2, X4,Y4,Z4,T4, X3,Y3,Z3,T3); + k = k >> 1; j = j >> 1; + } +} diff --git a/sys/src/libauthsrv/elligator2.mp b/sys/src/libauthsrv/elligator2.mp new file mode 100644 index 000000000..820adc771 --- /dev/null +++ b/sys/src/libauthsrv/elligator2.mp @@ -0,0 +1,30 @@ +#elligator2: +# curve a*x^2+y^2==1+d*x^2*y^2 +# input r0 +# n is any non-square +# +elligator2(p,a,d, n, r0, X,Y,Z,T) mod(p) { + r = n*r0*r0; + D = (d*r+a-d)*(d*r-a*r-d); + N = (r+1)*(a-2*d); + ND = N*D; + if(ND == 0) { + c = 1; + e = 0; + } else { + e = msqrt(ND, p); + if(e != 0) { + c = 1; + e = 1/e; + } else { + c = -1; + e = n*r0*misqrt(n*ND, p); + } + } + s = c*N*e; + t = -c*N*(r-1)*((a-2*d)*e)^2-1; + X = 2*s*t; + Y = (1-a*s*s)*(1+a*s*s); + Z = (1+a*s*s)*t; + T = (2*s)*(1-a*s*s); +} diff --git a/sys/src/libauthsrv/form1.c b/sys/src/libauthsrv/form1.c new file mode 100644 index 000000000..9ff4a1fad --- /dev/null +++ b/sys/src/libauthsrv/form1.c @@ -0,0 +1,90 @@ +#include <u.h> +#include <libc.h> +#include <authsrv.h> +#include <libsec.h> + +/* + * new ticket format: the reply protector/type is replaced by a + * 8 byte signature and a 4 byte counter forming the 12 byte + * nonce for chacha20/poly1305 encryption. a 16 byte poly1305 + * authentication tag is appended for message authentication. + * the counter is needed for the AuthPass message which uses + * the same key for several messages. + */ + +static struct { + char num; + char sig[8]; +} form1sig[] = { + AuthPass, "form1 PR", /* password change request encrypted with ticket key */ + AuthTs, "form1 Ts", /* ticket encrypted with server's key */ + AuthTc, "form1 Tc", /* ticket encrypted with client's key */ + AuthAs, "form1 As", /* server generated authenticator */ + AuthAc, "form1 Ac", /* client generated authenticator */ + AuthTp, "form1 Tp", /* ticket encrypted with client's key for password change */ + AuthHr, "form1 Hr", /* http reply */ +}; + +int +form1check(char *ap, int n) +{ + if(n < 8) + return -1; + + for(n=0; n<nelem(form1sig); n++) + if(memcmp(form1sig[n].sig, ap, 8) == 0) + return form1sig[n].num; + + return -1; +} + +int +form1B2M(char *ap, int n, uchar key[32]) +{ + static u32int counter; + Chachastate s; + uchar *p; + int i; + + for(i=nelem(form1sig)-1; i>=0; i--) + if(form1sig[i].num == *ap) + break; + if(i < 0) + abort(); + + p = (uchar*)ap + 12; + memmove(p, ap+1, --n); + + /* nonce[12] = sig[8] | counter[4] */ + memmove(ap, form1sig[i].sig, 8); + i = counter++; + ap[8] = i, ap[9] = i>>8, ap[10] = i>>16, ap[11] = i>>24; + + setupChachastate(&s, key, 32, (uchar*)ap, 12, 20); + ccpoly_encrypt(p, n, nil, 0, p+n, &s); + return 12+16 + n; +} + +int +form1M2B(char *ap, int n, uchar key[32]) +{ + Chachastate s; + uchar *p; + int num; + + num = form1check(ap, n); + if(num < 0) + return -1; + n -= 12+16; + if(n <= 0) + return -1; + + p = (uchar*)ap + 12; + setupChachastate(&s, key, 32, (uchar*)ap, 12, 20); + if(ccpoly_decrypt(p, n, nil, 0, p+n, &s)) + return -1; + + memmove(ap+1, p, n); + ap[0] = num; + return n+1; +} diff --git a/sys/src/libauthsrv/mkfile b/sys/src/libauthsrv/mkfile index d46fa52d7..9a058b0a4 100644 --- a/sys/src/libauthsrv/mkfile +++ b/sys/src/libauthsrv/mkfile @@ -2,10 +2,12 @@ LIB=/$objtype/lib/libauthsrv.a OFILES=\ + _asgetpakkey.$O\ _asgetticket.$O\ _asgetresp.$O\ _asrequest.$O\ _asrdresp.$O\ + authpak.$O\ authdial.$O\ convA2M.$O\ convM2A.$O\ @@ -15,17 +17,35 @@ OFILES=\ convPR2M.$O\ convT2M.$O\ convTR2M.$O\ + form1.$O\ nvcsum.$O\ passtokey.$O\ readnvram.$O\ HFILES=\ - /sys/include/authsrv.h\ + /sys/include/authsrv.h + +MPCFILES=\ + msqrt.mpc\ + decaf.mpc\ + edwards.mpc\ + elligator2.mpc\ + spake2ee.mpc\ + ed448.mpc\ UPDATE=\ mkfile\ $HFILES\ ${OFILES:%.$O=%.c}\ + ${MPCFILES:.mpc=%.mp}\ ${LIB:/$objtype/%=/386/%}\ + +CLEANFILES=$MPCFILES + </sys/src/cmd/mksyslib + +authpak.$O: $MPCFILES + +%.mpc: %.mp + mpc $stem.mp > $target diff --git a/sys/src/libauthsrv/msqrt.mp b/sys/src/libauthsrv/msqrt.mp new file mode 100644 index 000000000..c34d5e480 --- /dev/null +++ b/sys/src/libauthsrv/msqrt.mp @@ -0,0 +1,100 @@ +# derived from: http://eli.thegreenplace.net/2009/03/07/computing-square-roots-in-python + +# Compute the Legendre symbol a|p using Euler's criterion. +# p is a prime, a is relatively prime to p (if p divides a, +# then a|p = 0) +legendresymbol(a, p, r) { + pm1 = p-1; + mod(p) r = a^(pm1>>1); + if(r == pm1) + r = -1; +} + +# Find a quadratic residue (mod p) of 'a'. p must be an +# odd prime. +# +# Solve the congruence of the form: +# x^2 = a (mod p) +# And returns x. Node that p - x is also a root. +# +# 0 is returned if no square root exists for these +# a and p. +# +# The Tonelli-Shanks algorithm is used (except +# for some simple cases in which the solution is known +# from an identity). +msqrt(a, p, r) { + if(legendresymbol(a, p) != 1) + r = 0; + else if(a == 0) + r = 0; + else if(p == 2) + r = a; + else if(p%4 == 3){ + e = p+1 >> 2; + mod(p) r = a^e; + } else { + # Partition p-1 to s * 2^e for an odd s (i.e. + # reduce all the powers of 2 from p-1) + s = p-1; + e = 0; + while(s%2 == 0){ + s = s >> 1; + e = e + 1; + } + + # Find some 'n' with a legendre symbol n|p = -1. + # Shouldn't take long. + n = 2; + while(legendresymbol(n, p) != -1) + n = n + 1; + + # x is a guess of the square root that gets better + # with each iteration. + # b is the "fudge factor" - by now much we're off + # with the guess. The invariant x^2 == a*b (mod p) + # is maintained throughout the loop. + # g is used for successive powers of n to update + # both a and b + # e is the exponent - decreases with each update + mod(p){ + x = a^(s+1 >> 1); + b = a^s; + g = n^s; + } + while(1==1){ + t = b; + m = 0; + while(m < e){ + if(t == 1) + break; + t = t*t % p; + m = m + 1; + } + if(m == 0){ + r = x; + break; + } + t = 2^(e-m-1); + mod(p){ + gs = g^t; + g = gs*gs; + x = x*gs; + b = b*g; + } + e = m; + } + } +} + +# modular inverse square-root +misqrt(a, p, r) { + if((p % 4) == 3){ + e = ((p-3)>>2); + mod(p) r = a^e; + } else { + r = msqrt(a, p); + if(r != 0) + mod(p) r = 1/r; + } +} diff --git a/sys/src/libauthsrv/passtokey.c b/sys/src/libauthsrv/passtokey.c index d2867da87..60742c49c 100644 --- a/sys/src/libauthsrv/passtokey.c +++ b/sys/src/libauthsrv/passtokey.c @@ -3,8 +3,8 @@ #include <authsrv.h> #include <libsec.h> -static void -passtodeskey(char *key, char *p) +void +passtodeskey(char key[DESKEYLEN], char *p) { uchar buf[ANAMELEN], *t; int i, n; @@ -32,17 +32,17 @@ passtodeskey(char *key, char *p) } } -static void -passtoaeskey(uchar *key, char *p) +void +passtoaeskey(uchar key[AESKEYLEN], char *p) { static char salt[] = "Plan 9 key derivation"; pbkdf2_x((uchar*)p, strlen(p), (uchar*)salt, sizeof(salt)-1, 9001, key, AESKEYLEN, hmac_sha1, SHA1dlen); } void -passtokey(Authkey *key, char *p) +passtokey(Authkey *key, char *pw) { memset(key, 0, sizeof(Authkey)); - passtodeskey(key->des, p); - passtoaeskey(key->aes, p); + passtodeskey(key->des, pw); + passtoaeskey(key->aes, pw); } diff --git a/sys/src/libauthsrv/spake2ee.mp b/sys/src/libauthsrv/spake2ee.mp new file mode 100644 index 000000000..dd8786988 --- /dev/null +++ b/sys/src/libauthsrv/spake2ee.mp @@ -0,0 +1,35 @@ +# +# this implements a variant of SPAKE2 Elligator edition described in: +# https://www.mail-archive.com/curves@moderncrypto.org/msg00412.html +# + +# derive points PM or PN from a (password) hash +spake2ee_h2P(p,a,d, h, PX,PY,PZ,PT){ + # find a small non-square for elligator + n = 2; + while(legendresymbol(n, p) != -1) + n = n + 1; + PX,PY,PZ,PT = elligator2(p,a,d, n, h%p); +} + +# Ya = xa*G+PM, Yb = xb*G+PN +spake2ee_1(p,a,d, x, GX,GY, PX,PY,PZ,PT, y){ + mod(p) X,Y,Z,T = edwards_scale(p,a,d, x, GX,GY,1,GX*GY); + X,Y,Z,T = edwards_add(p,a,d, X,Y,Z,T, PX,PY,PZ,PT); + y = decaf_encode(p,a,d, X,Y,Z,T); +} + +# Z = xa*(Yb-PN) +# = xa*(xb*G+PN-PN) +# = xa*xb*G +# = xb*xa*G +# = xb*(xa*G+PM-PM) +# = xb*(Ya-PM) +spake2ee_2(p,a,d, PX,PY,PZ,PT, x, y, ok, z){ + ok, X,Y,Z,T = decaf_decode(p,a,d, y); + if(ok != 0){ + mod(p) X,Y,Z,T = edwards_add(p,a,d, X,Y,Z,T, -PX,PY,PZ,-PT); + X,Y,Z,T = edwards_scale(p,a,d, x, X,Y,Z,T); + z = decaf_encode(p,a,d, X,Y,Z,T); + } +} |