libsec: implement elliptic curve group operations in jacobian coordinate system
This commit is contained in:
parent
2763229c00
commit
2fa4c8ef66
6 changed files with 140 additions and 26 deletions
|
@ -497,6 +497,7 @@ typedef struct ECpoint{
|
|||
int inf;
|
||||
mpint *x;
|
||||
mpint *y;
|
||||
mpint *z; /* nil when using affine coordinates */
|
||||
} ECpoint;
|
||||
|
||||
typedef ECpoint ECpub;
|
||||
|
|
|
@ -489,6 +489,7 @@ typedef struct ECpoint{
|
|||
int inf;
|
||||
mpint *x;
|
||||
mpint *y;
|
||||
mpint *z; /* nil when using affine coordinates */
|
||||
} ECpoint;
|
||||
|
||||
typedef ECpoint ECpub;
|
||||
|
|
|
@ -26,6 +26,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
|||
thumb.c readcert.c \
|
||||
aes_xts.c \
|
||||
ecc.c\
|
||||
jacobian.c\
|
||||
ripemd.c\
|
||||
dh.c\
|
||||
curve25519.c\
|
||||
|
@ -37,7 +38,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
|||
secp256r1.c\
|
||||
secp256k1.c\
|
||||
|
||||
CLEANFILES=secp256r1.c secp256k1.c
|
||||
CLEANFILES=secp256r1.c secp256k1.c jacobian.c
|
||||
|
||||
ALLOFILES=${CFILES:%.c=%.$O}
|
||||
|
||||
|
|
|
@ -3,12 +3,33 @@
|
|||
#include <libsec.h>
|
||||
#include <ctype.h>
|
||||
|
||||
extern void jacobian_affine(mpint *p,
|
||||
mpint *X, mpint *Y, mpint *Z);
|
||||
extern void jacobian_dbl(mpint *p, mpint *a,
|
||||
mpint *X1, mpint *Y1, mpint *Z1,
|
||||
mpint *X3, mpint *Y3, mpint *Z3);
|
||||
extern void jacobian_add(mpint *p, mpint *a,
|
||||
mpint *X1, mpint *Y1, mpint *Z1,
|
||||
mpint *X2, mpint *Y2, mpint *Z2,
|
||||
mpint *X3, mpint *Y3, mpint *Z3);
|
||||
|
||||
void
|
||||
ecassign(ECdomain *, ECpoint *a, ECpoint *b)
|
||||
ecassign(ECdomain *dom, ECpoint *a, ECpoint *b)
|
||||
{
|
||||
b->inf = a->inf;
|
||||
if((b->inf = a->inf) != 0)
|
||||
return;
|
||||
mpassign(a->x, b->x);
|
||||
mpassign(a->y, b->y);
|
||||
if(b->z != nil){
|
||||
mpassign(a->z != nil ? a->z : mpone, b->z);
|
||||
return;
|
||||
}
|
||||
if(a->z != nil){
|
||||
b->z = mpcopy(a->z);
|
||||
jacobian_affine(dom->p, b->x, b->y, b->z);
|
||||
mpfree(b->z);
|
||||
b->z = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -28,10 +49,26 @@ ecadd(ECdomain *dom, ECpoint *a, ECpoint *b, ECpoint *s)
|
|||
ecassign(dom, a, s);
|
||||
return;
|
||||
}
|
||||
|
||||
if(s->z != nil){
|
||||
if(a == b)
|
||||
jacobian_dbl(dom->p, dom->a,
|
||||
a->x, a->y, a->z != nil ? a->z : mpone,
|
||||
s->x, s->y, s->z);
|
||||
else
|
||||
jacobian_add(dom->p, dom->a,
|
||||
a->x, a->y, a->z != nil ? a->z : mpone,
|
||||
b->x, b->y, b->z != nil ? b->z : mpone,
|
||||
s->x, s->y, s->z);
|
||||
s->inf = mpcmp(s->z, mpzero) == 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(mpcmp(a->x, b->x) == 0 && (mpcmp(a->y, mpzero) == 0 || mpcmp(a->y, b->y) != 0)){
|
||||
s->inf = 1;
|
||||
return;
|
||||
}
|
||||
s->inf = 0;
|
||||
l = mpnew(0);
|
||||
k = mpnew(0);
|
||||
sx = mpnew(0);
|
||||
|
@ -103,8 +140,10 @@ ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
|
|||
ns.inf = 1;
|
||||
ns.x = mpnew(0);
|
||||
ns.y = mpnew(0);
|
||||
ns.z = mpnew(0);
|
||||
na.x = mpnew(0);
|
||||
na.y = mpnew(0);
|
||||
na.z = mpnew(0);
|
||||
ecassign(dom, a, &na);
|
||||
l = mpcopy(k);
|
||||
l->sign = 1;
|
||||
|
@ -114,15 +153,17 @@ ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s)
|
|||
ecadd(dom, &na, &na, &na);
|
||||
mpright(l, 1, l);
|
||||
}
|
||||
if(k->sign < 0){
|
||||
if(k->sign < 0 && !ns.inf){
|
||||
ns.y->sign = -1;
|
||||
mpmod(ns.y, dom->p, ns.y);
|
||||
}
|
||||
ecassign(dom, &ns, s);
|
||||
mpfree(ns.x);
|
||||
mpfree(ns.y);
|
||||
mpfree(ns.z);
|
||||
mpfree(na.x);
|
||||
mpfree(na.y);
|
||||
mpfree(na.z);
|
||||
mpfree(l);
|
||||
}
|
||||
|
||||
|
@ -132,18 +173,17 @@ ecverify(ECdomain *dom, ECpoint *a)
|
|||
mpint *p, *q;
|
||||
int r;
|
||||
|
||||
assert(a->z == nil); /* need affine coordinates */
|
||||
if(a->inf)
|
||||
return 1;
|
||||
|
||||
|
||||
p = mpnew(0);
|
||||
q = mpnew(0);
|
||||
mpmul(a->y, a->y, p);
|
||||
mpmod(p, dom->p, p);
|
||||
mpmul(a->x, a->x, q);
|
||||
mpadd(q, dom->a, q);
|
||||
mpmul(a->x, q, q);
|
||||
mpadd(q, dom->b, q);
|
||||
mpmod(q, dom->p, q);
|
||||
mpmodmul(a->y, a->y, dom->p, p);
|
||||
mpmodmul(a->x, a->x, dom->p, q);
|
||||
mpmodadd(q, dom->a, dom->p, q);
|
||||
mpmodmul(q, a->x, dom->p, q);
|
||||
mpmodadd(q, dom->b, dom->p, q);
|
||||
r = mpcmp(p, q);
|
||||
mpfree(p);
|
||||
mpfree(q);
|
||||
|
@ -162,10 +202,12 @@ ecpubverify(ECdomain *dom, ECpub *a)
|
|||
return 0;
|
||||
p.x = mpnew(0);
|
||||
p.y = mpnew(0);
|
||||
p.z = mpnew(0);
|
||||
ecmul(dom, a, dom->n, &p);
|
||||
r = p.inf;
|
||||
mpfree(p.x);
|
||||
mpfree(p.y);
|
||||
mpfree(p.z);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -272,8 +314,8 @@ mpsqrt(mpint *n, mpint *p, mpint *r)
|
|||
zq = mpnew(0);
|
||||
for(;;){
|
||||
for(;;){
|
||||
mprand(mpsignif(p), genrandom, a);
|
||||
if(mpcmp(a, mpzero) > 0 && mpcmp(a, p) < 0)
|
||||
mpnrand(p, genrandom, a);
|
||||
if(mpcmp(a, mpzero) > 0)
|
||||
break;
|
||||
}
|
||||
mpmul(a, a, t);
|
||||
|
@ -345,11 +387,12 @@ strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
|
|||
ret->x = mpnew(0);
|
||||
ret->y = mpnew(0);
|
||||
}
|
||||
ret->inf = 0;
|
||||
o = 0;
|
||||
switch(octet(&s)){
|
||||
case 0:
|
||||
ret->inf = 1;
|
||||
return ret;
|
||||
break;
|
||||
case 3:
|
||||
o = 1;
|
||||
case 2:
|
||||
|
@ -370,7 +413,7 @@ strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
|
|||
mpfree(r);
|
||||
if(!ecverify(dom, ret))
|
||||
goto err;
|
||||
return ret;
|
||||
break;
|
||||
case 4:
|
||||
if(halfpt(dom, s, &s, ret->x) == nil)
|
||||
goto err;
|
||||
|
@ -378,8 +421,12 @@ strtoec(ECdomain *dom, char *s, char **rptr, ECpoint *ret)
|
|||
goto err;
|
||||
if(!ecverify(dom, ret))
|
||||
goto err;
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
if(ret->z != nil && !ret->inf)
|
||||
mpassign(mpone, ret->z);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if(rptr)
|
||||
*rptr = s;
|
||||
|
@ -403,8 +450,8 @@ ecgen(ECdomain *dom, ECpriv *p)
|
|||
p->d = mpnew(0);
|
||||
}
|
||||
for(;;){
|
||||
mprand(mpsignif(dom->n), genrandom, p->d);
|
||||
if(mpcmp(p->d, mpzero) > 0 && mpcmp(p->d, dom->n) < 0)
|
||||
mpnrand(dom->n, genrandom, p->d);
|
||||
if(mpcmp(p->d, mpzero) > 0)
|
||||
break;
|
||||
}
|
||||
ecmul(dom, &dom->G, p->d, p);
|
||||
|
@ -419,6 +466,7 @@ ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
|
|||
|
||||
tmp.x = mpnew(0);
|
||||
tmp.y = mpnew(0);
|
||||
tmp.z = nil;
|
||||
tmp.d = mpnew(0);
|
||||
E = betomp(dig, len, nil);
|
||||
t = mpnew(0);
|
||||
|
@ -432,8 +480,7 @@ ecdsasign(ECdomain *dom, ECpriv *priv, uchar *dig, int len, mpint *r, mpint *s)
|
|||
mpmul(r, priv->d, s);
|
||||
mpadd(E, s, s);
|
||||
mpinvert(tmp.d, dom->n, t);
|
||||
mpmul(s, t, s);
|
||||
mpmod(s, dom->n, s);
|
||||
mpmodmul(s, t, dom->n, s);
|
||||
if(mpcmp(s, mpzero) != 0)
|
||||
break;
|
||||
}
|
||||
|
@ -461,18 +508,19 @@ ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
|
|||
u2 = mpnew(0);
|
||||
R.x = mpnew(0);
|
||||
R.y = mpnew(0);
|
||||
R.z = mpnew(0);
|
||||
S.x = mpnew(0);
|
||||
S.y = mpnew(0);
|
||||
S.z = mpnew(0);
|
||||
mpinvert(s, dom->n, t);
|
||||
mpmul(E, t, u1);
|
||||
mpmod(u1, dom->n, u1);
|
||||
mpmul(r, t, u2);
|
||||
mpmod(u2, dom->n, u2);
|
||||
mpmodmul(E, t, dom->n, u1);
|
||||
mpmodmul(r, t, dom->n, u2);
|
||||
ecmul(dom, &dom->G, u1, &R);
|
||||
ecmul(dom, pub, u2, &S);
|
||||
ecadd(dom, &R, &S, &R);
|
||||
ret = 0;
|
||||
if(!R.inf){
|
||||
jacobian_affine(dom->p, R.x, R.y, R.z);
|
||||
mpmod(R.x, dom->n, t);
|
||||
ret = mpcmp(r, t) == 0;
|
||||
}
|
||||
|
@ -482,8 +530,10 @@ ecdsaverify(ECdomain *dom, ECpub *pub, uchar *dig, int len, mpint *r, mpint *s)
|
|||
mpfree(u2);
|
||||
mpfree(R.x);
|
||||
mpfree(R.y);
|
||||
mpfree(R.z);
|
||||
mpfree(S.x);
|
||||
mpfree(S.y);
|
||||
mpfree(S.z);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
60
sys/src/libsec/port/jacobian.mp
Normal file
60
sys/src/libsec/port/jacobian.mp
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Elliptic curve group operations in jacobian coordinates:
|
||||
# x=X/Z^2
|
||||
# x=Y/Z^3
|
||||
|
||||
jacobian_new(x,y,z, X,Y,Z) {
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
jacobian_inf(X,Y,Z) {
|
||||
X,Y,Z = jacobian_new(0,1,0);
|
||||
}
|
||||
jacobian_affine(p, X,Y,Z) mod(p) {
|
||||
if(Z != 0) {
|
||||
ZZ = Z^2;
|
||||
ZZZ = ZZ*Z;
|
||||
X = X / ZZ;
|
||||
Y = Y / ZZZ;
|
||||
Z = 1;
|
||||
}
|
||||
}
|
||||
jacobian_dbl(p,a, X1,Y1,Z1, X3,Y3,Z3) mod(p) {
|
||||
if(Y1 == 0) {
|
||||
X3,Y3,Z3 = jacobian_inf();
|
||||
} else {
|
||||
XX = X1^2;
|
||||
YY = Y1^2;
|
||||
YYYY = YY^2;
|
||||
ZZ = Z1^2;
|
||||
S = 2*((X1+YY)^2-XX-YYYY);
|
||||
M = 3*XX+a*ZZ^2;
|
||||
Z3 = (Y1+Z1)^2-YY-ZZ;
|
||||
X3 = M^2-2*S;
|
||||
Y3 = M*(S-X3)-8*YYYY;
|
||||
}
|
||||
}
|
||||
jacobian_add(p,a, X1,Y1,Z1, X2,Y2,Z2, X3,Y3,Z3) mod(p) {
|
||||
Z1Z1 = Z1^2;
|
||||
Z2Z2 = Z2^2;
|
||||
U1 = X1*Z2Z2;
|
||||
U2 = X2*Z1Z1;
|
||||
S1 = Y1*Z2*Z2Z2;
|
||||
S2 = Y2*Z1*Z1Z1;
|
||||
if(U1 == U2) {
|
||||
if(S1 != S2) {
|
||||
X3,Y3,Z3 = jacobian_inf();
|
||||
} else {
|
||||
X3,Y3,Z3 = jacobian_dbl(p,a, X1,Y1,Z1);
|
||||
}
|
||||
} else {
|
||||
H = U2-U1;
|
||||
I = (2*H)^2;
|
||||
J = H*I;
|
||||
r = 2*(S2-S1);
|
||||
V = U1*I;
|
||||
X3 = r^2-J-2*V;
|
||||
Y3 = r*(V-X3)-2*S1*J;
|
||||
Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H;
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
|||
tlshand.c thumb.c readcert.c \
|
||||
aes_xts.c \
|
||||
ecc.c\
|
||||
jacobian.c\
|
||||
ripemd.c\
|
||||
dh.c\
|
||||
curve25519.c\
|
||||
|
@ -33,7 +34,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
|||
secp256r1.c\
|
||||
secp256k1.c\
|
||||
|
||||
CLEANFILES=secp256r1.c secp256k1.c
|
||||
CLEANFILES=secp256r1.c secp256k1.c jacobian.c
|
||||
|
||||
ALLOFILES=${CFILES:%.c=%.$O}
|
||||
|
||||
|
|
Loading…
Reference in a new issue