--- /n/sources/plan9/sys/include/authsrv.h Sat Feb 17 00:30:16 2007 +++ /sys/include/authsrv.h Sat Jun 22 18:24:29 2024 @@ -12,21 +12,38 @@ typedef struct OChapreply OChapreply; typedef struct OMSchapreply OMSchapreply; +typedef struct Authkey Authkey; + enum { ANAMELEN= 28, /* name max size in previous proto */ AERRLEN= 64, /* errstr max size in previous proto */ DOMLEN= 48, /* authentication domain name length */ DESKEYLEN= 7, /* encrypt/decrypt des key length */ + AESKEYLEN= 16, /* encrypt/decrypt aes key length */ + FORM1SIGLEN= 8, + FORM1CNTLEN= 4, + FORM1NONCELEN= FORM1SIGLEN + FORM1CNTLEN, CHALLEN= 8, /* plan9 sk1 challenge length */ NETCHLEN= 16, /* max network challenge length (used in AS protocol) */ CONFIGLEN= 14, SECRETLEN= 32, /* secret max size */ + NONCELEN= 32, + FORM1AUTHTAGLEN=16, + KEYDBOFF= 8, /* bytes of random data at key file's start */ OKEYDBLEN= ANAMELEN+DESKEYLEN+4+2, /* old key file entry length */ KEYDBLEN= OKEYDBLEN+SECRETLEN, /* key file entry length */ OMD5LEN= 16, + + /* AuthPAK constants */ + PAKKEYLEN= 32, + PAKSLEN= (448+7)/8, /* ed448 scalar */ + PAKPLEN= 4*PAKSLEN, /* point in extended format X,Y,Z,T */ + PAKHASHLEN= 2*PAKPLEN, /* hashed points PM,PN */ + PAKXLEN= PAKSLEN, /* random scalar secret key */ + PAKYLEN= PAKSLEN, /* decaf encoded public key */ }; /* encryption numberings (anti-replay) */ @@ -47,6 +64,7 @@ AuthVNC=14, /* VNC server login (deprecated) */ + AuthPAK=19, /* authenticated diffie hellman key agreement */ AuthTs=64, /* ticket encrypted with server's key */ AuthTc, /* ticket encrypted with client's key */ AuthAs, /* server generated authenticator */ @@ -72,17 +90,20 @@ char chal[CHALLEN]; /* server challenge */ char cuid[ANAMELEN]; /* uid on client */ char suid[ANAMELEN]; /* uid on server */ - char key[DESKEYLEN]; /* nonce DES key */ + char key[NONCELEN]; /* nonce DES key */ }; #define TICKETLEN (CHALLEN+2*ANAMELEN+DESKEYLEN+1) +#define TICKETLENFORM1 (FORM1NONCELEN+CHALLEN+2*ANAMELEN+NONCELEN+FORM1AUTHTAGLEN) struct Authenticator { char num; /* replay protection */ char chal[CHALLEN]; ulong id; /* authenticator id, ++'d with each auth */ + uchar rand[NONCELEN]; /* server/client nonce */ }; #define AUTHENTLEN (CHALLEN+4+1) +#define AUTHENTLENFORM1 (FORM1NONCELEN+CHALLEN+NONCELEN+FORM1AUTHTAGLEN) struct Passwordreq { @@ -108,6 +129,14 @@ char NTresp[24]; /* NT response */ }; +struct Authkey +{ + char des[DESKEYLEN]; /* DES key from password */ + uchar aes[AESKEYLEN]; /* AES key from password */ + uchar pakkey[PAKKEYLEN]; /* shared key from AuthPAK exchange (see authpak_finish()) */ + uchar pakhash[PAKHASHLEN]; /* secret hash from AES key and user name (see authpak_hash()) */ +}; + /* * convert to/from wire format */ @@ -122,12 +151,24 @@ extern void convM2PR(char*, Passwordreq*, char*); /* + * convert to/from form1 wire format + */ +extern void convM2Tform1(char*, Ticket*, char*); +extern int convA2Mform1(Authenticator*, char*, char*); +extern void convM2Aform1(char*, Authenticator*, char*); + +/* * convert ascii password to DES key */ extern int opasstokey(char*, char*); extern int passtokey(char*, char*); /* + * convert ascii password to AES key + */ +extern int passtoaeskey(char*, char*); + +/* * Nvram interface */ enum { @@ -171,3 +212,18 @@ extern int _asrdresp(int, char*, int); extern int sslnegotiate(int, Ticket*, char**, char**); extern int srvsslnegotiate(int, Ticket*, char**, char**); + +/* + * AuthPAK protocol + */ +typedef struct PAKpriv PAKpriv; +struct PAKpriv +{ + int isclient; + uchar x[PAKXLEN]; + uchar y[PAKYLEN]; +}; + +extern void authpak_hash(Authkey *k, char *u); +extern void authpak_new(PAKpriv *p, Authkey *k, uchar y[PAKYLEN], int isclient); +extern int authpak_finish(PAKpriv *p, Authkey *k, uchar y[PAKYLEN]); diff -Nru /n/sources/plan9/sys/src/libauthsrv/authpak.c /sys/src/libauthsrv/authpak.c --- /n/sources/plan9/sys/src/libauthsrv/authpak.c Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/authpak.c Sun Jun 30 01:50:55 2024 @@ -0,0 +1,340 @@ +#include +#include +#include +#include +#include + +#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; +}; + +void +mptober(mpint *b, uchar *buf, int len) +{ + int n; + + n = mptobe(b, buf, len, nil); + assert(n >= 0); + if(n < len){ + len -= n; + memmove(buf+len, buf, n); + memset(buf, 0, len); + } +} + +/* return uniform random [0..n-1] */ +mpint* +mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b) +{ + int bits; + + bits = mpsignif(n); + if(bits == 0) + abort(); + if(b == nil){ + b = mpnew(bits); + setmalloctag(b, getcallerpc(&n)); + } + do { + mprand(bits, gen, b); + } while(mpmagcmp(b, n) >= 0); + + return b; +} + +/* operands need to have m->top+1 digits of space and satisfy 0 ≤ a ≤ m-1 */ +static mpint* +modarg(mpint *a, mpint *m) +{ + if(a->size <= m->top || a->sign < 0 || mpmagcmp(a, m) >= 0){ + a = mpcopy(a); + mpmod(a, m, a); + mpbits(a, Dbits*(m->top+1)); + a->top = m->top; + } else if(a->top < m->top){ + memset(&a->p[a->top], 0, (m->top - a->top)*Dbytes); + } + return a; +} + +void +mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum) +{ + mpint *a, *b; + mpdigit d; + int i, j; + + a = modarg(b1, m); + b = modarg(b2, m); + + mpbits(sum, Dbits*2*(m->top+1)); + + mpvecadd(a->p, m->top, b->p, m->top, sum->p); + mpvecsub(sum->p, m->top+1, m->p, m->top, sum->p+m->top+1); + + d = sum->p[2*m->top+1]; + for(i = 0, j = m->top+1; i < m->top; i++, j++) + sum->p[i] = (sum->p[i] & d) | (sum->p[j] & ~d); + + sum->top = m->top; + sum->sign = 1; + mpnorm(sum); + + if(a != b1) + mpfree(a); + if(b != b2) + mpfree(b); +} + +void +mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff) +{ + mpint *a, *b; + mpdigit d; + int i, j; + + a = modarg(b1, m); + b = modarg(b2, m); + + mpbits(diff, Dbits*2*(m->top+1)); + + a->p[m->top] = 0; + mpvecsub(a->p, m->top+1, b->p, m->top, diff->p); + mpvecadd(diff->p, m->top, m->p, m->top, diff->p+m->top+1); + + d = ~diff->p[m->top]; + for(i = 0, j = m->top+1; i < m->top; i++, j++) + diff->p[i] = (diff->p[i] & d) | (diff->p[j] & ~d); + + diff->top = m->top; + diff->sign = 1; + mpnorm(diff); + + if(a != b1) + mpfree(a); + if(b != b2) + mpfree(b); +} + +void +mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod) +{ + mpint *a, *b; + + a = modarg(b1, m); + b = modarg(b2, m); + + mpmul(a, b, prod); + mpmod(prod, m, prod); + + if(a != b1) + mpfree(a); + if(b != b2) + mpfree(b); +} + +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; + int bits; + + 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 -Nru /n/sources/plan9/sys/src/libauthsrv/convA2Mform1.c /sys/src/libauthsrv/convA2Mform1.c --- /n/sources/plan9/sys/src/libauthsrv/convA2Mform1.c Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/convA2Mform1.c Sat Jun 22 13:33:35 2024 @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#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 VSTRING(s,n) memmove(p, s, n); p += n +#define STRING(x,n) VSTRING(f->x, n); + +int +convA2Mform1(Authenticator *f, char *ap, char *key) +{ + int n; + uchar *p; + static u32int counter; + Chachastate s; + + p = (uchar*)ap; + VSTRING("form1 As", FORM1SIGLEN); + VLONG(counter++); + STRING(chal, CHALLEN); + STRING(rand, NONCELEN); + n = p - (uchar*)ap; + if(key) { + setupChachastate(&s, (uchar *)key, ChachaKeylen, (uchar*)ap, ChachaIVlen, 0); + ap += FORM1NONCELEN; + n -= FORM1NONCELEN; + ccpoly_encrypt((uchar *)ap, n, nil, 0, (uchar *)ap+n, &s); + } + return n; +} diff -Nru /n/sources/plan9/sys/src/libauthsrv/convM2Aform1.c /sys/src/libauthsrv/convM2Aform1.c --- /n/sources/plan9/sys/src/libauthsrv/convM2Aform1.c Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/convM2Aform1.c Sat Jun 22 12:20:59 2024 @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +#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 + +void +convM2Aform1(char *ap, Authenticator *f, char *key) +{ + uchar *p; + Chachastate s; + + if(key) { + setupChachastate(&s, (uchar *)key, ChachaKeylen, (uchar*)ap, ChachaIVlen, 0); + ap += FORM1NONCELEN; + ccpoly_decrypt((uchar *)ap, CHALLEN+NONCELEN, nil, 0, (uchar *)ap+CHALLEN+NONCELEN, &s); + } + p = (uchar*)ap; +// CHAR(num); + f->num = AuthAc; //todo: actually parse; + STRING(chal, CHALLEN); + STRING(rand, NONCELEN); + LONG(id); + + USED(p); +} diff -Nru /n/sources/plan9/sys/src/libauthsrv/convM2Tform1.c /sys/src/libauthsrv/convM2Tform1.c --- /n/sources/plan9/sys/src/libauthsrv/convM2Tform1.c Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/convM2Tform1.c Mon Jun 24 14:32:31 2024 @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#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 + +void +convM2Tform1(char *ap, Ticket *f, char *key) +{ + Chachastate s; + uchar *p; + + if(key) { + setupChachastate(&s, (uchar *)key, ChachaKeylen, (uchar*)ap, ChachaIVlen, 0); + ap += FORM1NONCELEN; + ccpoly_decrypt((uchar *)ap, TICKETLENFORM1-FORM1NONCELEN-FORM1AUTHTAGLEN, nil, 0, (uchar *)ap+TICKETLENFORM1-FORM1NONCELEN-FORM1AUTHTAGLEN, &s); + } + p = (uchar*)ap; +// CHAR(num); + f->num = AuthTs; // todo: actually parse; + STRING(chal, CHALLEN); + STRING(cuid, ANAMELEN); + f->cuid[ANAMELEN-1] = 0; + STRING(suid, ANAMELEN); + f->suid[ANAMELEN-1] = 0; +print(f->suid); + STRING(key, NONCELEN); + USED(p); +} + diff -Nru /n/sources/plan9/sys/src/libauthsrv/decaf.mp /sys/src/libauthsrv/decaf.mp --- /n/sources/plan9/sys/src/libauthsrv/decaf.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/decaf.mp Fri Jun 28 01:22:48 2024 @@ -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 -Nru /n/sources/plan9/sys/src/libauthsrv/decaf.mpc /sys/src/libauthsrv/decaf.mpc --- /n/sources/plan9/sys/src/libauthsrv/decaf.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/decaf.mpc Sat Jun 29 17:52:43 2024 @@ -0,0 +1,131 @@ +void decaf_neg(mpint *p, mpint *n, mpint *r){ + mpint *m = mpnew(0); + mpmodsub(mpzero, r, p, m); + mpint *tmp1 = mpnew(0); + mpsub(p, mpone, tmp1); + mpright(tmp1, 1, tmp1); +// mpsel(-mpcmp(n, tmp1) >> (sizeof(int)*8-1), m, r, r); + mpassign(-mpcmp(n, tmp1) >> (sizeof(int)*8-1) ? m : r, r); + mpfree(tmp1); + mpfree(m); + } +void decaf_encode(mpint *p, mpint *a, mpint *d, mpint *X, mpint *Y, mpint *Z, mpint *T, mpint *s){ + mpint *u = mpnew(0); + mpint *r = mpnew(0); + mpint *tmp1 = mpnew(0); + mpint *tmp2 = mpnew(0); + mpint *tmp3 = mpnew(0); + mpmodsub(a, d, p, tmp3); + mpint *tmp4 = mpnew(0); + mpmodadd(Z, Y, p, tmp4); + mpmodmul(tmp3, tmp4, p, tmp2); + mpfree(tmp3); + mpfree(tmp4); + tmp4 = mpnew(0); + mpmodsub(Z, Y, p, tmp4); + mpmodmul(tmp2, tmp4, p, tmp1); + mpfree(tmp2); + mpfree(tmp4); + misqrt(tmp1, p, r); + mpfree(tmp1); + tmp1 = mpnew(0); + mpmodsub(a, d, p, tmp1); + mpmodmul(tmp1, r, p, u); + mpfree(tmp1); + tmp1 = mpnew(0); + tmp4 = mpnew(0); + mpmodadd(u, u, p, tmp4); // 2*u + mpmodmul(tmp4, Z, p, tmp1); + mpfree(tmp4); + mpmodsub(mpzero, tmp1, p, tmp1); + decaf_neg(p, tmp1, r); + mpfree(tmp1); + tmp1 = mpnew(0); + tmp4 = mpnew(0); + tmp2 = mpnew(0); + tmp3 = mpnew(0); + mpmodmul(a, Z, p, tmp3); + mpmodmul(tmp3, X, p, tmp2); + mpfree(tmp3); + tmp3 = mpnew(0); + mpint *tmp5 = mpnew(0); + mpmodmul(d, Y, p, tmp5); + mpmodmul(tmp5, T, p, tmp3); + mpfree(tmp5); + mpmodsub(tmp2, tmp3, p, tmp2); + mpfree(tmp3); + mpmodmul(r, tmp2, p, tmp4); + mpfree(tmp2); + mpmodadd(tmp4, Y, p, tmp4); + mpmodmul(u, tmp4, p, tmp1); + mpfree(tmp4); + tmp4 = mpnew(0); + mpinvert(a, p, tmp4); + mpmodmul(tmp1, tmp4, p, s); + mpfree(tmp4); + mpfree(tmp1); + decaf_neg(p, s, s); + mpfree(u); + mpfree(r); + } +void decaf_decode(mpint *p, mpint *a, mpint *d, mpint *s, mpint *ok, mpint *X, mpint *Y, mpint *Z, mpint *T){ + mpint *w = mpnew(0); + mpint *v = mpnew(0); + mpint *u = mpnew(0); + mpint *ss = mpnew(0); + mpint *tmp1 = mpnew(0); + mpsub(p, mpone, tmp1); + mpright(tmp1, 1, tmp1); + if(mpcmp(s, tmp1) > 0){ + mpassign(mpzero, ok); + }else{ + mpmodmul(s, s, p, ss); + mpmodmul(a, ss, p, Z); + mpmodadd(mpone, Z, p, Z); + mpmodmul(Z, Z, p, u); + mpint *tmp2 = mpnew(0); + mpint *tmp3 = mpnew(0); + mpint *tmp4 = mpnew(0); + uitomp(4UL, tmp4); + mpmodmul(tmp4, d, p, tmp3); + mpfree(tmp4); + mpmodmul(tmp3, ss, p, tmp2); + mpfree(tmp3); + mpmodsub(u, tmp2, p, u); + mpfree(tmp2); + mpmodmul(u, ss, p, v); + if(mpcmp(v, mpzero) == 0){ + mpassign(mpone, ok); + }else{ + msqrt(v, p, ok); + if(mpcmp(ok, mpzero) != 0){ + mpinvert(ok, p, v); + mpassign(mpone, ok); + } + } + if(mpcmp(ok, mpzero) != 0){ + mpint *tmp5 = mpnew(0); + mpmodmul(u, v, p, tmp5); + decaf_neg(p, tmp5, v); + mpfree(tmp5); + tmp5 = mpnew(0); + mpmodmul(v, s, p, tmp5); + mpint *tmp6 = mpnew(0); + mpmodsub(mptwo, Z, p, tmp6); + mpmodmul(tmp5, tmp6, p, w); + mpfree(tmp5); + mpfree(tmp6); + if(mpcmp(s, mpzero) == 0){ + mpmodadd(w, mpone, p, w); + } + mpmodadd(s, s, p, X); // 2*s + mpmodmul(w, Z, p, Y); + mpmodmul(w, X, p, T); + } + } + mpfree(tmp1); + mpfree(w); + mpfree(v); + mpfree(u); + mpfree(ss); + } diff -Nru /n/sources/plan9/sys/src/libauthsrv/ed448.mp /sys/src/libauthsrv/ed448.mp --- /n/sources/plan9/sys/src/libauthsrv/ed448.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/ed448.mp Fri Jun 28 01:22:48 2024 @@ -0,0 +1,10 @@ +# Edwards Curve Ed448-Goldilocks + +# x^2+y^2 = 1-39081x^2y^2 +ed448_curve(p,a,d,x,y) { + p = 2^448 - 2^224 - 1; + a = 1; + d = -39081; + x = 117812161263436946737282484343310064665180535357016373416879082147939404277809514858788439644911793978499419995990477371552926308078495; + y = 19; +} diff -Nru /n/sources/plan9/sys/src/libauthsrv/ed448.mpc /sys/src/libauthsrv/ed448.mpc --- /n/sources/plan9/sys/src/libauthsrv/ed448.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/ed448.mpc Fri Jun 28 04:21:48 2024 @@ -0,0 +1,8 @@ +void ed448_curve(mpint *p, mpint *a, mpint *d, mpint *x, mpint *y){ + strtomp("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", nil, 16, p); + mpassign(mpone, a); + uitomp(39081UL, d); + d->sign = -1; + strtomp("297EA0EA2692FF1B4FAFF46098453A6A26ADF733245F065C3C59D0709CECFA96147EAAF3932D94C63D96C170033F4BA0C7F0DE840AED939F", nil, 16, x); + uitomp(19UL, y); + } diff -Nru /n/sources/plan9/sys/src/libauthsrv/edwards.mp /sys/src/libauthsrv/edwards.mp --- /n/sources/plan9/sys/src/libauthsrv/edwards.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/edwards.mp Fri Jun 28 01:22:48 2024 @@ -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 -Nru /n/sources/plan9/sys/src/libauthsrv/edwards.mpc /sys/src/libauthsrv/edwards.mpc --- /n/sources/plan9/sys/src/libauthsrv/edwards.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/edwards.mpc Sat Jun 29 19:13:11 2024 @@ -0,0 +1,102 @@ +void edwards_add(mpint *p, mpint *a, mpint *d, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X2, mpint *Y2, mpint *Z2, mpint *T2, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){ + mpint *H = mpnew(0); + mpint *G = mpnew(0); + mpint *F = mpnew(0); + mpint *E = mpnew(0); + mpint *D = mpnew(0); + mpint *C = mpnew(0); + mpint *B = mpnew(0); + mpint *A = mpnew(0); + mpmodmul(X1, X2, p, A); + mpmodmul(Y1, Y2, p, B); + mpint *tmp1 = mpnew(0); + mpmodmul(d, T1, p, tmp1); + mpmodmul(tmp1, T2, p, C); + mpfree(tmp1); + mpmodmul(Z1, Z2, p, D); + tmp1 = mpnew(0); + mpmodadd(X1, Y1, p, tmp1); + mpint *tmp2 = mpnew(0); + mpmodadd(X2, Y2, p, tmp2); + mpmodmul(tmp1, tmp2, p, E); + mpfree(tmp1); + mpfree(tmp2); + mpmodsub(E, A, p, E); + mpmodsub(E, B, p, E); + mpmodsub(D, C, p, F); + mpmodadd(D, C, p, G); + mpmodmul(a, A, p, H); + mpmodsub(B, H, p, H); + mpmodmul(E, F, p, X3); + mpmodmul(G, H, p, Y3); + mpmodmul(F, G, p, Z3); + mpmodmul(E, H, p, T3); + mpfree(H); + mpfree(G); + mpfree(F); + mpfree(E); + mpfree(D); + mpfree(C); + mpfree(B); + mpfree(A); + } +void edwards_sel(mpint *s, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X2, mpint *Y2, mpint *Z2, mpint *T2, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){ +// mpsel(mpcmp(s, mpzero), X1, X2, X3); + mpassign(mpcmp(s, mpzero) ? X1 : X2, X3); +// mpsel(mpcmp(s, mpzero), Y1, Y2, Y3); + mpassign(mpcmp(s, mpzero) ? Y1 : Y2, Y3); +// mpsel(mpcmp(s, mpzero), Z1, Z2, Z3); + mpassign(mpcmp(s, mpzero) ? Z1 : Z2, Z3); +// mpsel(mpcmp(s, mpzero), T1, T2, T3); + mpassign(mpcmp(s, mpzero) ? T1 : T2, T3); + } +void edwards_new(mpint *x, mpint *y, mpint *z, mpint *t, mpint *X, mpint *Y, mpint *Z, mpint *T){ + mpassign(x, X); + mpassign(y, Y); + mpassign(z, Z); + mpassign(t, T); + } +void edwards_scale(mpint *p, mpint *a, mpint *d, mpint *s, mpint *X1, mpint *Y1, mpint *Z1, mpint *T1, mpint *X3, mpint *Y3, mpint *Z3, mpint *T3){ + mpint *j = mpnew(0); + mpint *k = mpnew(0); + mpint *T4 = mpnew(0); + mpint *Z4 = mpnew(0); + mpint *Y4 = mpnew(0); + mpint *X4 = mpnew(0); + mpint *T2 = mpnew(0); + mpint *Z2 = mpnew(0); + mpint *Y2 = mpnew(0); + mpint *X2 = mpnew(0); + edwards_new(X1, Y1, Z1, T1, X2, Y2, Z2, T2); + edwards_new(mpzero, mpone, mpone, mpzero, X4, Y4, Z4, T4); + mpint *tmp1 = mpnew(0); + mpmod(s, mptwo, tmp1); + edwards_sel(tmp1, X2, Y2, Z2, T2, X4, Y4, Z4, T4, X3, Y3, Z3, T3); + mpfree(tmp1); + mpright(s, 1, k); + mpright(p, 1, j); + for(;;){ + if(mpcmp(j, mpzero) != 0){ + edwards_add(p, a, d, X2, Y2, Z2, T2, X2, Y2, Z2, T2, X2, Y2, Z2, T2); + edwards_add(p, a, d, X2, Y2, Z2, T2, X3, Y3, Z3, T3, X4, Y4, Z4, T4); + mpint *tmp2 = mpnew(0); + mpmod(k, mptwo, tmp2); + edwards_sel(tmp2, X4, Y4, Z4, T4, X3, Y3, Z3, T3, X3, Y3, Z3, T3); + mpfree(tmp2); + mpright(k, 1, k); + mpright(j, 1, j); + }else{ + break; + } + } + mpfree(j); + mpfree(k); + mpfree(T4); + mpfree(Z4); + mpfree(Y4); + mpfree(X4); + mpfree(T2); + mpfree(Z2); + mpfree(Y2); + mpfree(X2); + } diff -Nru /n/sources/plan9/sys/src/libauthsrv/elligator2.mp /sys/src/libauthsrv/elligator2.mp --- /n/sources/plan9/sys/src/libauthsrv/elligator2.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/elligator2.mp Fri Jun 28 01:22:48 2024 @@ -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 -Nru /n/sources/plan9/sys/src/libauthsrv/elligator2.mpc /sys/src/libauthsrv/elligator2.mpc --- /n/sources/plan9/sys/src/libauthsrv/elligator2.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/elligator2.mpc Fri Jun 28 04:21:48 2024 @@ -0,0 +1,129 @@ +void elligator2(mpint *p, mpint *a, mpint *d, mpint *n, mpint *r0, mpint *X, mpint *Y, mpint *Z, mpint *T){ + mpint *t = mpnew(0); + mpint *s = mpnew(0); + mpint *e = mpnew(0); + mpint *c = mpnew(0); + mpint *ND = mpnew(0); + mpint *N = mpnew(0); + mpint *D = mpnew(0); + mpint *r = mpnew(0); + mpint *tmp1 = mpnew(0); + mpmodmul(n, r0, p, tmp1); + mpmodmul(tmp1, r0, p, r); + mpfree(tmp1); + tmp1 = mpnew(0); + mpmodmul(d, r, p, tmp1); + mpmodadd(tmp1, a, p, tmp1); + mpmodsub(tmp1, d, p, tmp1); + mpint *tmp2 = mpnew(0); + mpmodmul(d, r, p, tmp2); + mpint *tmp3 = mpnew(0); + mpmodmul(a, r, p, tmp3); + mpmodsub(tmp2, tmp3, p, tmp2); + mpfree(tmp3); + mpmodsub(tmp2, d, p, tmp2); + mpmodmul(tmp1, tmp2, p, D); + mpfree(tmp1); + mpfree(tmp2); + tmp2 = mpnew(0); + mpmodadd(r, mpone, p, tmp2); + tmp1 = mpnew(0); + mpmodadd(d, d, p, tmp1); // 2*d + mpmodsub(a, tmp1, p, tmp1); + mpmodmul(tmp2, tmp1, p, N); + mpfree(tmp2); + mpfree(tmp1); + mpmodmul(N, D, p, ND); + if(mpcmp(ND, mpzero) == 0){ + mpassign(mpone, c); + mpassign(mpzero, e); + }else{ + msqrt(ND, p, e); + if(mpcmp(e, mpzero) != 0){ + mpassign(mpone, c); + mpinvert(e, p, e); + }else{ + mpmodsub(mpzero, mpone, p, c); + mpint *tmp4 = mpnew(0); + mpmodmul(n, r0, p, tmp4); + mpint *tmp5 = mpnew(0); + mpint *tmp6 = mpnew(0); + mpmodmul(n, ND, p, tmp6); + misqrt(tmp6, p, tmp5); + mpfree(tmp6); + mpmodmul(tmp4, tmp5, p, e); + mpfree(tmp4); + mpfree(tmp5); + } + } + tmp1 = mpnew(0); + mpmodmul(c, N, p, tmp1); + mpmodmul(tmp1, e, p, s); + mpfree(tmp1); + tmp1 = mpnew(0); + tmp2 = mpnew(0); + mpmodmul(c, N, p, tmp2); + tmp3 = mpnew(0); + mpmodsub(r, mpone, p, tmp3); + mpmodmul(tmp2, tmp3, p, tmp1); + mpfree(tmp2); + mpfree(tmp3); + tmp3 = mpnew(0); + tmp2 = mpnew(0); + mpmodadd(d, d, p, tmp2); // 2*d + mpmodsub(a, tmp2, p, tmp2); + mpmodmul(tmp2, e, p, tmp3); + mpfree(tmp2); + mpmodmul(tmp3, tmp3, p, tmp3); + mpmodmul(tmp1, tmp3, p, t); + mpfree(tmp1); + mpfree(tmp3); + mpmodsub(mpzero, t, p, t); + mpmodsub(t, mpone, p, t); + tmp3 = mpnew(0); + mpmodadd(s, s, p, tmp3); // 2*s + mpmodmul(tmp3, t, p, X); + mpfree(tmp3); + tmp3 = mpnew(0); + tmp1 = mpnew(0); + mpmodmul(a, s, p, tmp1); + mpmodmul(tmp1, s, p, tmp3); + mpfree(tmp1); + mpmodsub(mpone, tmp3, p, tmp3); + tmp1 = mpnew(0); + tmp2 = mpnew(0); + mpmodmul(a, s, p, tmp2); + mpmodmul(tmp2, s, p, tmp1); + mpfree(tmp2); + mpmodadd(mpone, tmp1, p, tmp1); + mpmodmul(tmp3, tmp1, p, Y); + mpfree(tmp3); + mpfree(tmp1); + tmp1 = mpnew(0); + tmp3 = mpnew(0); + mpmodmul(a, s, p, tmp3); + mpmodmul(tmp3, s, p, tmp1); + mpfree(tmp3); + mpmodadd(mpone, tmp1, p, tmp1); + mpmodmul(tmp1, t, p, Z); + mpfree(tmp1); + tmp1 = mpnew(0); + mpmodadd(s, s, p, tmp1); // 2*s + tmp3 = mpnew(0); + tmp2 = mpnew(0); + mpmodmul(a, s, p, tmp2); + mpmodmul(tmp2, s, p, tmp3); + mpfree(tmp2); + mpmodsub(mpone, tmp3, p, tmp3); + mpmodmul(tmp1, tmp3, p, T); + mpfree(tmp1); + mpfree(tmp3); + mpfree(t); + mpfree(s); + mpfree(e); + mpfree(c); + mpfree(ND); + mpfree(N); + mpfree(D); + mpfree(r); + } diff -Nru /n/sources/plan9/sys/src/libauthsrv/mkfile /sys/src/libauthsrv/mkfile --- /n/sources/plan9/sys/src/libauthsrv/mkfile Wed Oct 23 12:16:16 2002 +++ /sys/src/libauthsrv/mkfile Fri Jun 28 04:20:50 2024 @@ -4,6 +4,7 @@ OFILES=\ _asgetticket.$O\ _asrdresp.$O\ + authpak.$O\ authdial.$O\ convA2M.$O\ convM2A.$O\ @@ -13,18 +14,38 @@ convPR2M.$O\ convT2M.$O\ convTR2M.$O\ + convM2Aform1.$O\ + convM2Tform1.$O\ + convA2Mform1.$O\ nvcsum.$O\ opasstokey.$O\ passtokey.$O\ + passtoaeskey.$O\ readnvram.$O\ HFILES=\ /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 + $target diff -Nru /n/sources/plan9/sys/src/libauthsrv/msqrt.mp /sys/src/libauthsrv/msqrt.mp --- /n/sources/plan9/sys/src/libauthsrv/msqrt.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/msqrt.mp Fri Jun 28 01:22:50 2024 @@ -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 -Nru /n/sources/plan9/sys/src/libauthsrv/msqrt.mpc /sys/src/libauthsrv/msqrt.mpc --- /n/sources/plan9/sys/src/libauthsrv/msqrt.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/msqrt.mpc Fri Jun 28 04:21:48 2024 @@ -0,0 +1,149 @@ +void legendresymbol(mpint *a, mpint *p, mpint *r){ + mpint *pm1 = mpnew(0); + mpsub(p, mpone, pm1); + mpright(pm1, 1, r); + mpexp(a, r, p, r); + if(mpcmp(r, pm1) == 0){ + mpassign(mpone, r); + r->sign = -1; + } + mpfree(pm1); + } +void msqrt(mpint *a, mpint *p, mpint *r){ + mpint *gs = mpnew(0); + mpint *m = mpnew(0); + mpint *t = mpnew(0); + mpint *g = mpnew(0); + mpint *b = mpnew(0); + mpint *x = mpnew(0); + mpint *n = mpnew(0); + mpint *s = mpnew(0); + mpint *e = mpnew(0); + mpint *tmp1 = mpnew(0); + legendresymbol(a, p, tmp1); + if(mpcmp(tmp1, mpone) != 0){ + mpassign(mpzero, r); + }else{ + if(mpcmp(a, mpzero) == 0){ + mpassign(mpzero, r); + }else{ + if(mpcmp(p, mptwo) == 0){ + mpassign(a, r); + }else{ + mpint *tmp2 = mpnew(0); + uitomp(4UL, tmp2); + mpmod(p, tmp2, tmp2); + mpint *tmp3 = mpnew(0); + uitomp(3UL, tmp3); + if(mpcmp(tmp2, tmp3) == 0){ + mpadd(p, mpone, e); + mpright(e, 2, e); + mpexp(a, e, p, r); + }else{ + mpsub(p, mpone, s); + mpassign(mpzero, e); + for(;;){ + mpint *tmp4 = mpnew(0); + mpmod(s, mptwo, tmp4); + if(mpcmp(tmp4, mpzero) == 0){ + mpright(s, 1, s); + mpadd(e, mpone, e); + }else{ + mpfree(tmp4); + break; + } + mpfree(tmp4); + } + mpassign(mptwo, n); + for(;;){ + mpint *tmp5 = mpnew(0); + legendresymbol(n, p, tmp5); + mpint *tmp6 = mpnew(0); + mpassign(mpone, tmp6); + tmp6->sign = -1; + if(mpcmp(tmp5, tmp6) != 0){ + mpadd(n, mpone, n); + }else{ + mpfree(tmp6); + mpfree(tmp5); + break; + } + mpfree(tmp5); + mpfree(tmp6); + } + mpmodadd(s, mpone, p, x); + mpright(x, 1, x); + mpexp(a, x, p, x); + mpexp(a, s, p, b); + mpexp(n, s, p, g); + for(;;){ + if(0 == 0){ + mpassign(b, t); + mpassign(mpzero, m); + for(;;){ + if(mpcmp(m, e) < 0){ + if(mpcmp(t, mpone) == 0){ + break; + } + mpmul(t, t, t); + mpmod(t, p, t); + mpadd(m, mpone, m); + }else{ + break; + } + } + if(mpcmp(m, mpzero) == 0){ + mpassign(x, r); + break; + } + mpsub(e, m, t); + mpsub(t, mpone, t); + mpexp(mptwo, t, nil, t); + mpexp(g, t, p, gs); + mpmodmul(gs, gs, p, g); + mpmodmul(x, gs, p, x); + mpmodmul(b, g, p, b); + mpassign(m, e); + }else{ + break; + } + } + } + mpfree(tmp2); + mpfree(tmp3); + } + } + } + mpfree(tmp1); + mpfree(gs); + mpfree(m); + mpfree(t); + mpfree(g); + mpfree(b); + mpfree(x); + mpfree(n); + mpfree(s); + mpfree(e); + } +void misqrt(mpint *a, mpint *p, mpint *r){ + mpint *e = mpnew(0); + mpint *tmp1 = mpnew(0); + uitomp(4UL, tmp1); + mpmod(p, tmp1, tmp1); + mpint *tmp2 = mpnew(0); + uitomp(3UL, tmp2); + if(mpcmp(tmp1, tmp2) == 0){ + uitomp(3UL, e); + mpsub(p, e, e); + mpright(e, 2, e); + mpexp(a, e, p, r); + }else{ + msqrt(a, p, r); + if(mpcmp(r, mpzero) != 0){ + mpinvert(r, p, r); + } + } + mpfree(tmp1); + mpfree(tmp2); + mpfree(e); + } diff -Nru /n/sources/plan9/sys/src/libauthsrv/passtoaeskey.c /sys/src/libauthsrv/passtoaeskey.c --- /n/sources/plan9/sys/src/libauthsrv/passtoaeskey.c Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/passtoaeskey.c Wed Jun 19 18:42:34 2024 @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +int +passtoaeskey(char *key, char *p) +{ + static char salt[] = "Plan 9 key derivation"; + pbkdf2_x((uchar*)p, strlen(p), (uchar*)salt, sizeof(salt)-1, 9001, (uchar *)key, AESKEYLEN, hmac_sha1, SHA1dlen); + return 0; +} diff -Nru /n/sources/plan9/sys/src/libauthsrv/spake2ee.mp /sys/src/libauthsrv/spake2ee.mp --- /n/sources/plan9/sys/src/libauthsrv/spake2ee.mp Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/spake2ee.mp Fri Jun 28 01:22:50 2024 @@ -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); + } +} diff -Nru /n/sources/plan9/sys/src/libauthsrv/spake2ee.mpc /sys/src/libauthsrv/spake2ee.mpc --- /n/sources/plan9/sys/src/libauthsrv/spake2ee.mpc Wed Dec 31 19:00:00 1969 +++ /sys/src/libauthsrv/spake2ee.mpc Fri Jun 28 04:21:48 2024 @@ -0,0 +1,63 @@ +void spake2ee_h2P(mpint *p, mpint *a, mpint *d, mpint *h, mpint *PX, mpint *PY, mpint *PZ, mpint *PT){ + mpint *n = mpnew(0); + mpassign(mptwo, n); + for(;;){ + mpint *tmp1 = mpnew(0); + legendresymbol(n, p, tmp1); + mpint *tmp2 = mpnew(0); + mpassign(mpone, tmp2); + tmp2->sign = -1; + if(mpcmp(tmp1, tmp2) != 0){ + mpadd(n, mpone, n); + }else{ + mpfree(tmp2); + mpfree(tmp1); + break; + } + mpfree(tmp1); + mpfree(tmp2); + } + mpint *tmp3 = mpnew(0); + mpmod(h, p, tmp3); + elligator2(p, a, d, n, tmp3, PX, PY, PZ, PT); + mpfree(tmp3); + mpfree(n); + } +void spake2ee_1(mpint *p, mpint *a, mpint *d, mpint *x, mpint *GX, mpint *GY, mpint *PX, mpint *PY, mpint *PZ, mpint *PT, mpint *y){ + mpint *T = mpnew(0); + mpint *Z = mpnew(0); + mpint *Y = mpnew(0); + mpint *X = mpnew(0); + mpint *tmp1 = mpnew(0); + mpmodmul(GX, GY, p, tmp1); + edwards_scale(p, a, d, x, GX, GY, mpone, tmp1, X, Y, Z, T); + mpfree(tmp1); + edwards_add(p, a, d, X, Y, Z, T, PX, PY, PZ, PT, X, Y, Z, T); + decaf_encode(p, a, d, X, Y, Z, T, y); + mpfree(T); + mpfree(Z); + mpfree(Y); + mpfree(X); + } +void spake2ee_2(mpint *p, mpint *a, mpint *d, mpint *PX, mpint *PY, mpint *PZ, mpint *PT, mpint *x, mpint *y, mpint *ok, mpint *z){ + mpint *T = mpnew(0); + mpint *Z = mpnew(0); + mpint *Y = mpnew(0); + mpint *X = mpnew(0); + decaf_decode(p, a, d, y, ok, X, Y, Z, T); + if(mpcmp(ok, mpzero) != 0){ + mpint *tmp1 = mpnew(0); + mpmodsub(mpzero, PX, p, tmp1); + mpint *tmp2 = mpnew(0); + mpmodsub(mpzero, PT, p, tmp2); + edwards_add(p, a, d, X, Y, Z, T, tmp1, PY, PZ, tmp2, X, Y, Z, T); + mpfree(tmp1); + mpfree(tmp2); + edwards_scale(p, a, d, x, X, Y, Z, T, X, Y, Z, T); + decaf_encode(p, a, d, X, Y, Z, T, z); + } + mpfree(T); + mpfree(Z); + mpfree(Y); + mpfree(X); + }