summaryrefslogtreecommitdiff
path: root/sys/src/libauthsrv
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-01-06 03:09:00 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2016-01-06 03:09:00 +0100
commit2dae1ed53a73d81bfb86778793a6bda265d5140d (patch)
treee037c4a663fc9d17906cc2045c488232ac223ece /sys/src/libauthsrv
parente064752dd476b7a2f76567f8cc15f9c2645e5d3d (diff)
auth: release dp9ik implementation and reentrant factotum
Diffstat (limited to 'sys/src/libauthsrv')
-rw-r--r--sys/src/libauthsrv/_asgetpakkey.c26
-rw-r--r--sys/src/libauthsrv/_asgetresp.c36
-rw-r--r--sys/src/libauthsrv/_asgetticket.c34
-rw-r--r--sys/src/libauthsrv/authpak.c214
-rw-r--r--sys/src/libauthsrv/convA2M.c33
-rw-r--r--sys/src/libauthsrv/convM2A.c43
-rw-r--r--sys/src/libauthsrv/convM2PR.c45
-rw-r--r--sys/src/libauthsrv/convM2T.c60
-rw-r--r--sys/src/libauthsrv/convM2TR.c20
-rw-r--r--sys/src/libauthsrv/convPR2M.c32
-rw-r--r--sys/src/libauthsrv/convT2M.c38
-rw-r--r--sys/src/libauthsrv/convTR2M.c19
-rw-r--r--sys/src/libauthsrv/decaf.mp49
-rw-r--r--sys/src/libauthsrv/ed448.mp11
-rw-r--r--sys/src/libauthsrv/edwards.mp40
-rw-r--r--sys/src/libauthsrv/elligator2.mp30
-rw-r--r--sys/src/libauthsrv/form1.c90
-rw-r--r--sys/src/libauthsrv/mkfile22
-rw-r--r--sys/src/libauthsrv/msqrt.mp100
-rw-r--r--sys/src/libauthsrv/passtokey.c14
-rw-r--r--sys/src/libauthsrv/spake2ee.mp35
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);
+ }
+}