void gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u, gcry_ctx_t ctx) { _gcry_mpi_ec_mul_point (w, n, u, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); }
void gcry_mpi_ec_add (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx) { _gcry_mpi_ec_add_points (w, u, v, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); }
int gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point, gcry_ctx_t ctx) { return _gcry_mpi_ec_get_affine (x, y, point, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); }
void gcry_log_debugpnt (const char *text, mpi_point_t point, gcry_ctx_t ctx) { mpi_ec_t ec = ctx? _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC) : NULL; _gcry_mpi_point_log (text, point, ec); }
gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (!strcmp (name, "p") && ec->p) return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p); if (!strcmp (name, "a") && ec->a) return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a); if (!strcmp (name, "b") && ec->b) return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b); if (!strcmp (name, "n") && ec->n) return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n); if (!strcmp (name, "d") && ec->d) return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d); /* Return a requested point coordinate. */ if (!strcmp (name, "g.x") && ec->G && ec->G->x) return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x); if (!strcmp (name, "g.y") && ec->G && ec->G->y) return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y); if (!strcmp (name, "q.x") && ec->Q && ec->Q->x) return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x); if (!strcmp (name, "q.y") && ec->Q && ec->Q->y) return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y); /* If a point has been requested, return it in standard encoding. */ if (!strcmp (name, "g") && ec->G) return _gcry_mpi_ec_ec2os (ec->G, ec); if (!strcmp (name, "q")) { /* If only the private key is given, compute the public key. */ if (!ec->Q && ec->d && ec->G && ec->p && ec->a) { ec->Q = gcry_mpi_point_new (0); _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); } if (ec->Q) return _gcry_mpi_ec_ec2os (ec->Q, ec); } return NULL; }
/* This function returns a new context for elliptic curve operations based on the field GF(p). P is the prime specifying this field, A is the first coefficient. On success the new context is stored at R_CTX and 0 is returned; on error NULL is stored at R_CTX and an error code is returned. The context needs to be released using gcry_ctx_release. This is an internal fucntions. */ gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a) { gcry_ctx_t ctx; mpi_ec_t ec; *r_ctx = NULL; if (!p || !a || !mpi_cmp_ui (a, 0)) return GPG_ERR_EINVAL; ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit); if (!ctx) return gpg_err_code_from_syserror (); ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); ec_p_init (ec, p, a); *r_ctx = ctx; return 0; }
gpg_err_code_t _gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue, gcry_ctx_t ctx) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (!strcmp (name, "g")) { gcry_mpi_point_release (ec->G); ec->G = point_copy (newvalue); } else if (!strcmp (name, "q")) { gcry_mpi_point_release (ec->Q); ec->Q = point_copy (newvalue); } else return GPG_ERR_UNKNOWN_NAME; return 0; }
gpg_err_code_t _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue, gcry_ctx_t ctx) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (!strcmp (name, "p")) { mpi_free (ec->p); ec->p = mpi_copy (newvalue); ec_get_reset (ec); } else if (!strcmp (name, "a")) { mpi_free (ec->a); ec->a = mpi_copy (newvalue); ec_get_reset (ec); } else if (!strcmp (name, "b")) { mpi_free (ec->b); ec->b = mpi_copy (newvalue); } else if (!strcmp (name, "n")) { mpi_free (ec->n); ec->n = mpi_copy (newvalue); } else if (!strcmp (name, "d")) { mpi_free (ec->d); ec->d = mpi_copy (newvalue); } else return GPG_ERR_UNKNOWN_NAME; return 0; }
gcry_mpi_point_t _gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); (void)copy; /* Not used. */ if (!strcmp (name, "g") && ec->G) return point_copy (ec->G); if (!strcmp (name, "q")) { /* If only the private key is given, compute the public key. */ if (!ec->Q && ec->d && ec->G && ec->p && ec->a) { ec->Q = gcry_mpi_point_new (0); _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec); } if (ec->Q) return point_copy (ec->Q); } return NULL; }
int gcry_mpi_ec_curve_point (gcry_mpi_point_t point, gcry_ctx_t ctx) { return _gcry_mpi_ec_curve_point (point, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); }
void gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx) { _gcry_mpi_ec_dup_point (w, u, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC)); }
/* This function creates a new context for elliptic curve operations. Either KEYPARAM or CURVENAME must be given. If both are given and KEYPARAM has no curve parameter, CURVENAME is used to add missing parameters. On success 0 is returned and the new context stored at R_CTX. On error NULL is stored at R_CTX and an error code is returned. The context needs to be released using gcry_ctx_release. */ gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_sexp_t keyparam, const char *curvename) { gpg_err_code_t errc; gcry_ctx_t ctx = NULL; enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS; enum ecc_dialects dialect = ECC_DIALECT_STANDARD; gcry_mpi_t p = NULL; gcry_mpi_t a = NULL; gcry_mpi_t b = NULL; gcry_mpi_point_t G = NULL; gcry_mpi_t n = NULL; gcry_mpi_point_t Q = NULL; gcry_mpi_t d = NULL; int flags = 0; gcry_sexp_t l1; *r_ctx = NULL; if (keyparam) { /* Parse an optional flags list. */ l1 = sexp_find_token (keyparam, "flags", 0); if (l1) { errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL); sexp_release (l1); l1 = NULL; if (errc) goto leave; } /* Check whether a curve name was given. */ l1 = sexp_find_token (keyparam, "curve", 5); /* If we don't have a curve name or if override parameters have explicitly been requested, parse them. */ if (!l1 || (flags & PUBKEY_FLAG_PARAM)) { errc = mpi_from_keyparam (&p, keyparam, "p"); if (errc) goto leave; errc = mpi_from_keyparam (&a, keyparam, "a"); if (errc) goto leave; errc = mpi_from_keyparam (&b, keyparam, "b"); if (errc) goto leave; errc = point_from_keyparam (&G, keyparam, "g", NULL); if (errc) goto leave; errc = mpi_from_keyparam (&n, keyparam, "n"); if (errc) goto leave; } } else l1 = NULL; /* No curvename. */ /* Check whether a curve parameter is available and use that to fill in missing values. If no curve parameter is available try an optional provided curvename. If only the curvename has been given use that one. */ if (l1 || curvename) { char *name; elliptic_curve_t *E; if (l1) { name = sexp_nth_string (l1, 1); sexp_release (l1); if (!name) { errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ goto leave; } } else name = NULL; E = xtrycalloc (1, sizeof *E); if (!E) { errc = gpg_err_code_from_syserror (); xfree (name); goto leave; } errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL); xfree (name); if (errc) { xfree (E); goto leave; } model = E->model; dialect = E->dialect; if (!p) { p = E->p; E->p = NULL; } if (!a) { a = E->a; E->a = NULL; } if (!b) { b = E->b; E->b = NULL; } if (!G) { G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z); E->G.x = NULL; E->G.y = NULL; E->G.z = NULL; } if (!n) { n = E->n; E->n = NULL; } _gcry_ecc_curve_free (E); xfree (E); } errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b); if (!errc) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); if (b) { mpi_free (ec->b); ec->b = b; b = NULL; } if (G) { ec->G = G; G = NULL; } if (n) { ec->n = n; n = NULL; } /* Now that we know the curve name we can look for the public key Q. point_from_keyparam needs to know the curve parameters so that it is able to use the correct decompression. Parsing the private key D could have been done earlier but it is less surprising if we do it here as well. */ if (keyparam) { errc = point_from_keyparam (&Q, keyparam, "q", ec); if (errc) goto leave; errc = mpi_from_keyparam (&d, keyparam, "d"); if (errc) goto leave; } if (Q) { ec->Q = Q; Q = NULL; } if (d) { ec->d = d; d = NULL; } *r_ctx = ctx; ctx = NULL; } leave: _gcry_ctx_release (ctx); mpi_free (p); mpi_free (a); mpi_free (b); _gcry_mpi_point_release (G); mpi_free (n); _gcry_mpi_point_release (Q); mpi_free (d); return errc; }