2016-11-25 17:18:40 +01:00
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#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;
|
|
|
|
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_lock(&a);
|
2016-11-25 17:18:40 +01:00
|
|
|
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);
|
|
|
|
}
|
2017-04-19 23:33:14 +02:00
|
|
|
jehanne_unlock(&a);
|
2016-11-25 17:18:40 +01:00
|
|
|
return &a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
authpak_hash(Authkey *k, char *u)
|
|
|
|
{
|
|
|
|
static char info[] = "Plan 9 AuthPAK hash";
|
|
|
|
uint8_t *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((uint8_t*)u, strlen(u), salt, nil);
|
|
|
|
|
|
|
|
hkdf_x( salt, SHA2_256dlen,
|
|
|
|
(uint8_t*)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, uint8_t y[PAKYLEN], int isclient)
|
|
|
|
{
|
|
|
|
mpint *PX,*PY,*PZ,*PT, *X, *Y;
|
|
|
|
PAKcurve *c;
|
|
|
|
uint8_t *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, uint8_t y[PAKYLEN])
|
|
|
|
{
|
|
|
|
static char info[] = "Plan 9 AuthPAK key";
|
|
|
|
uint8_t *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,
|
|
|
|
(uint8_t*)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;
|
|
|
|
}
|