void point_add(struct affine_point *p1, const struct affine_point *p2, const struct domain_params *dp) { if (! point_is_zero(p2)) { if (! point_is_zero(p1)) { if (! gcry_mpi_cmp(p1->x, p2->x)) { if (! gcry_mpi_cmp(p1->y, p2->y)) point_double(p1, dp); else point_load_zero(p1); } else { gcry_mpi_t t; t = gcry_mpi_snew(0); gcry_mpi_subm(t, p1->y, p2->y, dp->m); gcry_mpi_subm(p1->y, p1->x, p2->x, dp->m); gcry_mpi_invm(p1->y, p1->y, dp->m); gcry_mpi_mulm(p1->y, t, p1->y, dp->m); gcry_mpi_mulm(t, p1->y, p1->y, dp->m); gcry_mpi_addm(p1->x, p1->x, p2->x, dp->m); gcry_mpi_subm(p1->x, t, p1->x, dp->m); gcry_mpi_subm(t, p2->x, p1->x, dp->m); gcry_mpi_mulm(p1->y, p1->y, t, dp->m); gcry_mpi_subm(p1->y, p1->y, p2->y, dp->m); gcry_mpi_release(t); } } else point_set(p1, p2); } }
static void point_add(struct point *r, struct point *p, struct point *q) { u8 s[20], t[20], u[20]; u8 *px, *py, *qx, *qy, *rx, *ry; struct point pp, qq; pp = *p; qq = *q; px = pp.x; py = pp.y; qx = qq.x; qy = qq.y; rx = r->x; ry = r->y; if (point_is_zero(&pp)) { elt_copy(rx, qx); elt_copy(ry, qy); return; } if (point_is_zero(&qq)) { elt_copy(rx, px); elt_copy(ry, py); return; } elt_sub(u, qx, px); if (elt_is_zero(u)) { elt_sub(u, qy, py); if (elt_is_zero(u)) point_double(r, &pp); else point_zero(r); return; } elt_inv(t, u); // t = 1/(qx-px) elt_sub(u, qy, py); // u = qy-py elt_mul(s, t, u); // s = (qy-py)/(qx-px) elt_square(rx, s); // rx = s*s elt_add(t, px, qx); // t = px+qx elt_sub(rx, rx, t); // rx = s*s - (px+qx) elt_sub(t, px, rx); // t = -(rx-px) elt_mul(ry, s, t); // ry = -s*(rx-px) elt_sub(ry, ry, py); // ry = -s*(rx-px) - py }
int ECDSA_verify(const char *msg, const struct affine_point *Q, const gcry_mpi_t sig, const struct curve_params *cp) { gcry_mpi_t e, r, s; struct affine_point X1, X2; int res = 0; r = gcry_mpi_new(0); s = gcry_mpi_new(0); gcry_mpi_div(s, r, sig, cp->dp.order, 0); if (gcry_mpi_cmp_ui(s, 0) <= 0 || gcry_mpi_cmp(s, cp->dp.order) >= 0 || gcry_mpi_cmp_ui(r, 0) <= 0 || gcry_mpi_cmp(r, cp->dp.order) >= 0) goto end; gcry_mpi_scan(&e, GCRYMPI_FMT_USG, msg, 64, NULL); gcry_mpi_mod(e, e, cp->dp.order); gcry_mpi_invm(s, s, cp->dp.order); gcry_mpi_mulm(e, e, s, cp->dp.order); X1 = pointmul(&cp->dp.base, e, &cp->dp); gcry_mpi_mulm(e, r, s, cp->dp.order); X2 = pointmul(Q, e, &cp->dp); point_add(&X1, &X2, &cp->dp); gcry_mpi_release(e); if (! point_is_zero(&X1)) { gcry_mpi_mod(s, X1.x, cp->dp.order); res = ! gcry_mpi_cmp(s, r); } point_release(&X1); point_release(&X2); end: gcry_mpi_release(r); gcry_mpi_release(s); return res; }
/* Algorithm 4.26 in the "Guide to Elliptic Curve Cryptography" */ int embedded_key_validation(const struct affine_point *p, const struct domain_params *dp) { if (gcry_mpi_cmp_ui(p->x, 0) < 0 || gcry_mpi_cmp(p->x, dp->m) >= 0 || gcry_mpi_cmp_ui(p->y, 0) < 0 || gcry_mpi_cmp(p->y, dp->m) >= 0) return 0; return ! point_is_zero(p) && point_on_curve(p, dp); }
void jacobian_load_affine(struct jacobian_point *p1, const struct affine_point *p2) { if (! point_is_zero(p2)) { gcry_mpi_set(p1->x, p2->x); gcry_mpi_set(p1->y, p2->y); gcry_mpi_set_ui(p1->z, 1); } else gcry_mpi_set_ui(p1->z, 0); }
/* Algorithm 4.25 in the "Guide to Elliptic Curve Cryptography" */ int full_key_validation(const struct affine_point *p, const struct domain_params *dp) { if (! embedded_key_validation(p, dp)) return 0; if (dp->cofactor != 1) { struct affine_point bp; int res; bp = pointmul(p, dp->order, dp); res = point_is_zero(&bp); point_release(&bp); return res; } else return 1; }
int ECIES_decryption(char *key, const struct affine_point *R, const gcry_mpi_t d, const struct curve_params *cp) { struct affine_point Z; gcry_mpi_t e; int res = 0; if (! embedded_key_validation(R, &cp->dp)) return 0; e = gcry_mpi_snew(0); gcry_mpi_mul_ui(e, d, cp->dp.cofactor); Z = pointmul(R, e, &cp->dp); gcry_mpi_release(e); if ((res = ! point_is_zero(&Z))) ECIES_KDF(key, Z.x, R, cp->elem_len_bin); point_release(&Z); return res; }
int point_on_curve(const struct affine_point *p, const struct domain_params *dp) { int res; if (! (res = point_is_zero(p))) { gcry_mpi_t h1, h2; h1 = gcry_mpi_snew(0); h2 = gcry_mpi_snew(0); gcry_mpi_mulm(h1, p->x, p->x, dp->m); gcry_mpi_addm(h1, h1, dp->a, dp->m); gcry_mpi_mulm(h1, h1, p->x, dp->m); gcry_mpi_addm(h1, h1, dp->b, dp->m); gcry_mpi_mulm(h2, p->y, p->y, dp->m); res = ! gcry_mpi_cmp(h1, h2); gcry_mpi_release(h1); gcry_mpi_release(h2); } return res; }
void jacobian_affine_point_add(struct jacobian_point *p1, const struct affine_point *p2, const struct domain_params *dp) { if (! point_is_zero(p2)) { if (gcry_mpi_cmp_ui(p1->z, 0)) { gcry_mpi_t t1, t2, t3; t1 = gcry_mpi_snew(0); t2 = gcry_mpi_snew(0); gcry_mpi_mulm(t1, p1->z, p1->z, dp->m); gcry_mpi_mulm(t2, t1, p2->x, dp->m); gcry_mpi_mulm(t1, t1, p1->z, dp->m); gcry_mpi_mulm(t1, t1, p2->y, dp->m); if (! gcry_mpi_cmp(p1->x, t2)) { if (! gcry_mpi_cmp(p1->y, t1)) jacobian_double(p1, dp); else jacobian_load_zero(p1); } else { t3 = gcry_mpi_snew(0); gcry_mpi_subm(p1->x, p1->x, t2, dp->m); gcry_mpi_subm(p1->y, p1->y, t1, dp->m); gcry_mpi_mulm(p1->z, p1->z, p1->x, dp->m); gcry_mpi_mulm(t3, p1->x, p1->x, dp->m); gcry_mpi_mulm(t2, t2, t3, dp->m); gcry_mpi_mulm(t3, t3, p1->x, dp->m); gcry_mpi_mulm(t1, t1, t3, dp->m); gcry_mpi_mulm(p1->x, p1->y, p1->y, dp->m); gcry_mpi_subm(p1->x, p1->x, t3, dp->m); gcry_mpi_subm(p1->x, p1->x, t2, dp->m); gcry_mpi_subm(p1->x, p1->x, t2, dp->m); gcry_mpi_subm(t2, t2, p1->x, dp->m); gcry_mpi_mulm(p1->y, p1->y, t2, dp->m); gcry_mpi_subm(p1->y, p1->y, t1, dp->m); gcry_mpi_release(t3); } gcry_mpi_release(t1); gcry_mpi_release(t2); } else jacobian_load_affine(p1, p2); } }
struct affine_point ECIES_encryption(char *key, const struct affine_point *Q, const struct curve_params *cp) { struct affine_point Z, R; gcry_mpi_t k; Step1: k = get_random_exponent(cp); R = pointmul(&cp->dp.base, k, &cp->dp); gcry_mpi_mul_ui(k, k, cp->dp.cofactor); Z = pointmul(Q, k, &cp->dp); gcry_mpi_release(k); if (point_is_zero(&Z)) { point_release(&R); point_release(&Z); goto Step1; } ECIES_KDF(key, Z.x, &R, cp->elem_len_bin); point_release(&Z); return R; }