jehanne/sys/src/lib/sec/port/dh.c

75 lines
1.2 KiB
C

#include "os.h"
#include <mp.h>
#include <libsec.h>
mpint*
dh_new(DHstate *dh, mpint *p, mpint *q, mpint *g)
{
mpint *pm1;
int n;
jehanne_memset(dh, 0, sizeof(*dh));
if(mpcmp(g, mpone) <= 0)
return nil;
n = mpsignif(p);
pm1 = mpnew(n);
mpsub(p, mpone, pm1);
dh->p = mpcopy(p);
dh->g = mpcopy(g);
dh->q = mpcopy(q != nil ? q : pm1);
dh->x = mpnew(mpsignif(dh->q));
dh->y = mpnew(n);
for(;;){
mpnrand(dh->q, genrandom, dh->x);
mpexp(dh->g, dh->x, dh->p, dh->y);
if(mpcmp(dh->y, mpone) > 0 && mpcmp(dh->y, pm1) < 0)
break;
}
mpfree(pm1);
return dh->y;
}
mpint*
dh_finish(DHstate *dh, mpint *y)
{
mpint *k = nil;
if(y == nil || dh->x == nil || dh->p == nil || dh->q == nil)
goto Out;
/* y > 1 */
if(mpcmp(y, mpone) <= 0)
goto Out;
k = mpnew(mpsignif(dh->p));
/* y < p-1 */
mpsub(dh->p, mpone, k);
if(mpcmp(y, k) >= 0){
Bad:
mpfree(k);
k = nil;
goto Out;
}
/* y**q % p == 1 if q < p-1 */
if(mpcmp(dh->q, k) < 0){
mpexp(y, dh->q, dh->p, k);
if(mpcmp(k, mpone) != 0)
goto Bad;
}
mpexp(y, dh->x, dh->p, k);
Out:
mpfree(dh->p);
mpfree(dh->q);
mpfree(dh->g);
mpfree(dh->x);
mpfree(dh->y);
jehanne_memset(dh, 0, sizeof(*dh));
return k;
}