jehanne/sys/src/lib/authsrv/authpak.c

215 lines
3.9 KiB
C

#include <u.h>
#include <lib9.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;
jehanne_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);
}
jehanne_unlock(&a);
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;
}