/* Store the MPI NEWVALUE into the context EC under NAME. */ gpg_err_code_t _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec) { gpg_err_code_t rc = 0; if (!*name) ; else if (!strcmp (name, "p")) { mpi_free (ec->p); ec->p = mpi_copy (newvalue); _gcry_mpi_ec_get_reset (ec); } else if (!strcmp (name, "a")) { mpi_free (ec->a); ec->a = mpi_copy (newvalue); _gcry_mpi_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, "h")) { mpi_free (ec->h); ec->h = mpi_copy (newvalue); } else if (*name == 'q' && (!name[1] || name[1] == '@')) { if (newvalue) { if (!ec->Q) ec->Q = mpi_point_new (0); if (ec->dialect == ECC_DIALECT_ED25519) rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL); else rc = _gcry_ecc_os2ec (ec->Q, newvalue); } if (rc || !newvalue) { _gcry_mpi_point_release (ec->Q); ec->Q = NULL; } /* Note: We assume that Q matches d and thus do not reset d. */ } else if (!strcmp (name, "d")) { mpi_free (ec->d); ec->d = mpi_copy (newvalue); if (ec->d) { /* We need to reset the public key because it may not anymore match. */ _gcry_mpi_point_release (ec->Q); ec->Q = NULL; } } else rc = GPG_ERR_UNKNOWN_NAME; return rc; }
/* Helper to extract a point from key parameters. If no parameter with NAME is found, the functions tries to find a non-encoded point by appending ".x", ".y" and ".z" to NAME. ".z" is in this case optional and defaults to 1. EC is the context which at this point may not be fully initialized. */ static gpg_err_code_t point_from_keyparam (gcry_mpi_point_t *r_a, gcry_sexp_t keyparam, const char *name, mpi_ec_t ec) { gcry_err_code_t rc; gcry_sexp_t l1; gcry_mpi_point_t point; l1 = sexp_find_token (keyparam, name, 0); if (l1) { gcry_mpi_t a; a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE); sexp_release (l1); if (!a) return GPG_ERR_INV_OBJ; point = mpi_point_new (0); if (ec && ec->dialect == ECC_DIALECT_ED25519) rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL); else rc = _gcry_ecc_os2ec (point, a); mpi_free (a); if (rc) { mpi_point_release (point); return rc; } } else { char *tmpname; gcry_mpi_t x = NULL; gcry_mpi_t y = NULL; gcry_mpi_t z = NULL; tmpname = xtrymalloc (strlen (name) + 2 + 1); if (!tmpname) return gpg_err_code_from_syserror (); strcpy (stpcpy (tmpname, name), ".x"); rc = mpi_from_keyparam (&x, keyparam, tmpname); if (rc) { xfree (tmpname); return rc; } strcpy (stpcpy (tmpname, name), ".y"); rc = mpi_from_keyparam (&y, keyparam, tmpname); if (rc) { mpi_free (x); xfree (tmpname); return rc; } strcpy (stpcpy (tmpname, name), ".z"); rc = mpi_from_keyparam (&z, keyparam, tmpname); if (rc) { mpi_free (y); mpi_free (x); xfree (tmpname); return rc; } if (!z) z = mpi_set_ui (NULL, 1); if (x && y) point = mpi_point_snatch_set (NULL, x, y, z); else { mpi_free (x); mpi_free (y); mpi_free (z); point = NULL; } xfree (tmpname); } if (point) *r_a = point; return 0; }