Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /* ec.c -  Elliptic Curve functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * Copyright (C) 2007 Free Software Foundation, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Copyright (C) 2013 g10 Code GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * This file is part of Libgcrypt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Libgcrypt is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * it under the terms of the GNU Lesser General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * published by the Free Software Foundation; either version 2.1 of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * the License, or (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * Libgcrypt is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  * GNU Lesser General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * You should have received a copy of the GNU Lesser General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include "mpi-internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include "longlong.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #define point_init(a)  mpi_point_init((a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #define point_free(a)  mpi_point_free_parts((a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #define log_error(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #define log_fatal(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define DIM(v) (sizeof(v)/sizeof((v)[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) /* Create a new point option.  NBITS gives the size in bits of one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  * coordinate; it is only used to pre-allocate some resources and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  * might also be passed as 0 to use a default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) MPI_POINT mpi_point_new(unsigned int nbits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 	MPI_POINT p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 	(void)nbits;  /* Currently not used.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	p = kmalloc(sizeof(*p), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 		mpi_point_init(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) EXPORT_SYMBOL_GPL(mpi_point_new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) /* Release the point object P.  P may be NULL. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) void mpi_point_release(MPI_POINT p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 		mpi_point_free_parts(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) EXPORT_SYMBOL_GPL(mpi_point_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) /* Initialize the fields of a point object.  gcry_mpi_point_free_parts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  * may be used to release the fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) void mpi_point_init(MPI_POINT p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	p->x = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	p->y = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	p->z = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) EXPORT_SYMBOL_GPL(mpi_point_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) /* Release the parts of a point object. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) void mpi_point_free_parts(MPI_POINT p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	mpi_free(p->x); p->x = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	mpi_free(p->y); p->y = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	mpi_free(p->z); p->z = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) EXPORT_SYMBOL_GPL(mpi_point_free_parts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) /* Set the value from S into D.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) static void point_set(MPI_POINT d, MPI_POINT s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	mpi_set(d->x, s->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	mpi_set(d->y, s->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	mpi_set(d->z, s->z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) static void point_resize(MPI_POINT p, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	size_t nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	mpi_resize(p->x, nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	p->x->nlimbs = nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	mpi_resize(p->z, nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	p->z->nlimbs = nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	if (ctx->model != MPI_EC_MONTGOMERY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 		mpi_resize(p->y, nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 		p->y->nlimbs = nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) static void point_swap_cond(MPI_POINT d, MPI_POINT s, unsigned long swap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	mpi_swap_cond(d->x, s->x, swap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	if (ctx->model != MPI_EC_MONTGOMERY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 		mpi_swap_cond(d->y, s->y, swap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	mpi_swap_cond(d->z, s->z, swap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) /* W = W mod P.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) static void ec_mod(MPI w, struct mpi_ec_ctx *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	if (ec->t.p_barrett)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		mpi_mod_barrett(w, w, ec->t.p_barrett);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 		mpi_mod(w, w, ec->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) static void ec_addm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	mpi_add(w, u, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	ec_mod(w, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) static void ec_subm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	mpi_sub(w, u, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	while (w->sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		mpi_add(w, w, ec->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	/*ec_mod(w, ec);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) static void ec_mulm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	mpi_mul(w, u, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	ec_mod(w, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) /* W = 2 * U mod P.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) static void ec_mul2(MPI w, MPI u, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	mpi_lshift(w, u, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	ec_mod(w, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) static void ec_powm(MPI w, const MPI b, const MPI e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	mpi_powm(w, b, e, ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	/* mpi_abs(w); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) /* Shortcut for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157)  * ec_powm(B, B, mpi_const(MPI_C_TWO), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158)  * for easier optimization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) static void ec_pow2(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	/* Using mpi_mul is slightly faster (at least on amd64).  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	/* mpi_powm(w, b, mpi_const(MPI_C_TWO), ctx->p); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	ec_mulm(w, b, b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) /* Shortcut for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  * ec_powm(B, B, mpi_const(MPI_C_THREE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  * for easier optimization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) static void ec_pow3(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	mpi_powm(w, b, mpi_const(MPI_C_THREE), ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) static void ec_invm(MPI x, MPI a, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	if (!mpi_invm(x, a, ctx->p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		log_error("ec_invm: inverse does not exist:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) static void mpih_set_cond(mpi_ptr_t wp, mpi_ptr_t up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		mpi_size_t usize, unsigned long set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	mpi_size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	mpi_limb_t mask = ((mpi_limb_t)0) - set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	mpi_limb_t x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	for (i = 0; i < usize; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 		x = mask & (wp[i] ^ up[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 		wp[i] = wp[i] ^ x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) /* Routines for 2^255 - 19.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) #define LIMB_SIZE_25519 ((256+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) static void ec_addm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	mpi_size_t wsize = LIMB_SIZE_25519;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	mpi_limb_t n[LIMB_SIZE_25519];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	mpi_limb_t borrow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		log_bug("addm_25519: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	memset(n, 0, sizeof(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	mpihelp_add_n(wp, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	borrow = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	mpihelp_add_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) static void ec_subm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	mpi_size_t wsize = LIMB_SIZE_25519;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	mpi_limb_t n[LIMB_SIZE_25519];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	mpi_limb_t borrow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		log_bug("subm_25519: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	memset(n, 0, sizeof(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	borrow = mpihelp_sub_n(wp, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	mpihelp_add_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) static void ec_mulm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	mpi_size_t wsize = LIMB_SIZE_25519;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	mpi_limb_t n[LIMB_SIZE_25519*2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	mpi_limb_t m[LIMB_SIZE_25519+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	mpi_limb_t cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	int msb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	(void)ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 		log_bug("mulm_25519: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	mpihelp_mul_n(n, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	memcpy(wp, n, wsize * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	memcpy(m, n+LIMB_SIZE_25519-1, (wsize+1) * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	mpihelp_rshift(m, m, LIMB_SIZE_25519+1, (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	memcpy(n, m, wsize * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	cy = mpihelp_lshift(m, m, LIMB_SIZE_25519, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	m[LIMB_SIZE_25519] = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	cy = mpihelp_add_n(m, m, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	m[LIMB_SIZE_25519] += cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	cy = mpihelp_add_n(m, m, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	m[LIMB_SIZE_25519] += cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	cy = mpihelp_add_n(m, m, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	m[LIMB_SIZE_25519] += cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	cy = mpihelp_add_n(wp, wp, m, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	m[LIMB_SIZE_25519] += cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	memset(m, 0, wsize * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	m[0] = (m[LIMB_SIZE_25519] * 2 + msb) * 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	mpihelp_add_n(wp, wp, m, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	m[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	cy = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	mpih_set_cond(m, ctx->p->d, wsize, (cy != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	mpihelp_add_n(wp, wp, m, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) static void ec_mul2_25519(MPI w, MPI u, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	ec_addm_25519(w, u, u, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) static void ec_pow2_25519(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	ec_mulm_25519(w, b, b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) /* Routines for 2^448 - 2^224 - 1.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) #define LIMB_SIZE_448 ((448+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) #define LIMB_SIZE_HALF_448 ((LIMB_SIZE_448+1)/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) static void ec_addm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	mpi_size_t wsize = LIMB_SIZE_448;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	mpi_limb_t n[LIMB_SIZE_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	mpi_limb_t cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		log_bug("addm_448: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	memset(n, 0, sizeof(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	cy = mpihelp_add_n(wp, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	mpih_set_cond(n, ctx->p->d, wsize, (cy != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	mpihelp_sub_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) static void ec_subm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	mpi_size_t wsize = LIMB_SIZE_448;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	mpi_limb_t n[LIMB_SIZE_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	mpi_limb_t borrow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		log_bug("subm_448: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	memset(n, 0, sizeof(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	borrow = mpihelp_sub_n(wp, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	mpihelp_add_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) static void ec_mulm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	mpi_size_t wsize = LIMB_SIZE_448;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	mpi_limb_t n[LIMB_SIZE_448*2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	mpi_limb_t a2[LIMB_SIZE_HALF_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	mpi_limb_t a3[LIMB_SIZE_HALF_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	mpi_limb_t b0[LIMB_SIZE_HALF_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	mpi_limb_t b1[LIMB_SIZE_HALF_448];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	mpi_limb_t cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	mpi_limb_t b1_rest, a3_rest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		log_bug("mulm_448: different sizes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	mpihelp_mul_n(n, up, vp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	for (i = 0; i < (wsize + 1) / 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		b0[i] = n[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 		b1[i] = n[i+wsize/2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		a2[i] = n[i+wsize];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		a3[i] = n[i+wsize+wsize/2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	b0[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL << 32)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	a2[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL << 32)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	b1_rest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	a3_rest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	for (i = (wsize + 1) / 2 - 1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		mpi_limb_t b1v, a3v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		b1v = b1[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		a3v = a3[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		b1[i] = (b1_rest << 32) | (b1v >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		a3[i] = (a3_rest << 32) | (a3v >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		b1_rest = b1v & (((mpi_limb_t)1UL << 32)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		a3_rest = a3v & (((mpi_limb_t)1UL << 32)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	cy = mpihelp_add_n(b0, b0, a2, LIMB_SIZE_HALF_448);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	cy += mpihelp_add_n(b0, b0, a3, LIMB_SIZE_HALF_448);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	for (i = 0; i < (wsize + 1) / 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		wp[i] = b0[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	wp[LIMB_SIZE_HALF_448-1] &= (((mpi_limb_t)1UL << 32)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	cy = b0[LIMB_SIZE_HALF_448-1] >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	cy = mpihelp_add_1(b1, b1, LIMB_SIZE_HALF_448, cy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	cy += mpihelp_add_n(b1, b1, a2, LIMB_SIZE_HALF_448);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	cy += mpihelp_add_n(b1, b1, a3, LIMB_SIZE_HALF_448);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	cy += mpihelp_add_n(b1, b1, a3, LIMB_SIZE_HALF_448);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	b1_rest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	for (i = (wsize + 1) / 2 - 1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		mpi_limb_t b1v = b1[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		b1[i] = (b1_rest << 32) | (b1v >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		b1_rest = b1v & (((mpi_limb_t)1UL << 32)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	wp[LIMB_SIZE_HALF_448-1] |= (b1_rest << 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	for (i = 0; i < wsize / 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		wp[i+(wsize + 1) / 2] = b1[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	cy = b1[LIMB_SIZE_HALF_448-1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	memset(n, 0, wsize * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	n[LIMB_SIZE_HALF_448-1] = cy << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	n[LIMB_SIZE_HALF_448] = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	n[0] = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	mpihelp_add_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	memset(n, 0, wsize * BYTES_PER_MPI_LIMB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	cy = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	mpih_set_cond(n, ctx->p->d, wsize, (cy != 0UL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	mpihelp_add_n(wp, wp, n, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) static void ec_mul2_448(MPI w, MPI u, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	ec_addm_448(w, u, u, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) static void ec_pow2_448(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	ec_mulm_448(w, b, b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) struct field_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	/* computation routines for the field.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	void (*addm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	void (*subm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	void (*mulm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	void (*mul2)(MPI w, MPI u, struct mpi_ec_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	void (*pow2)(MPI w, const MPI b, struct mpi_ec_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) static const struct field_table field_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		ec_addm_25519,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		ec_subm_25519,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		ec_mulm_25519,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		ec_mul2_25519,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		ec_pow2_25519
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		ec_addm_448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		ec_subm_448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		ec_mulm_448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		ec_mul2_448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		ec_pow2_448
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	{ NULL, NULL, NULL, NULL, NULL, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) /* Force recomputation of all helper variables.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) static void mpi_ec_get_reset(struct mpi_ec_ctx *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	ec->t.valid.a_is_pminus3 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	ec->t.valid.two_inv_p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) /* Accessor for helper variable.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) static int ec_get_a_is_pminus3(struct mpi_ec_ctx *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	MPI tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	if (!ec->t.valid.a_is_pminus3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		ec->t.valid.a_is_pminus3 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		tmp = mpi_alloc_like(ec->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		mpi_sub_ui(tmp, ec->p, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		ec->t.a_is_pminus3 = !mpi_cmp(ec->a, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		mpi_free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	return ec->t.a_is_pminus3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) /* Accessor for helper variable.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) static MPI ec_get_two_inv_p(struct mpi_ec_ctx *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	if (!ec->t.valid.two_inv_p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		ec->t.valid.two_inv_p = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		if (!ec->t.two_inv_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			ec->t.two_inv_p = mpi_alloc(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 		ec_invm(ec->t.two_inv_p, mpi_const(MPI_C_TWO), ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	return ec->t.two_inv_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) static const char *const curve25519_bad_points[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	"0x0000000000000000000000000000000000000000000000000000000000000000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	"0x0000000000000000000000000000000000000000000000000000000000000001",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	"0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	"0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) static const char *const curve448_bad_points[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	"0x00000000000000000000000000000000000000000000000000000000"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	"00000000000000000000000000000000000000000000000000000000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	"0x00000000000000000000000000000000000000000000000000000000"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	"00000000000000000000000000000000000000000000000000000001",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	"fffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	"00000000000000000000000000000000000000000000000000000000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) static const char *const *bad_points_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	curve25519_bad_points,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	curve448_bad_points,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) static void mpi_ec_coefficient_normalize(MPI a, MPI p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	if (a->sign) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		mpi_resize(a, p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		mpihelp_sub_n(a->d, p->d, a->d, p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 		a->nlimbs = p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		a->sign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) /* This function initialized a context for elliptic curve based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  * field GF(p).  P is the prime specifying this field, A is the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  * coefficient.  CTX is expected to be zeroized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) void mpi_ec_init(struct mpi_ec_ctx *ctx, enum gcry_mpi_ec_models model,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 			enum ecc_dialects dialect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 			int flags, MPI p, MPI a, MPI b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	static int use_barrett = -1 /* TODO: 1 or -1 */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	mpi_ec_coefficient_normalize(a, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	mpi_ec_coefficient_normalize(b, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	/* Fixme: Do we want to check some constraints? e.g.  a < p  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	ctx->model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	ctx->dialect = dialect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	ctx->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	if (dialect == ECC_DIALECT_ED25519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		ctx->nbits = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		ctx->nbits = mpi_get_nbits(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	ctx->p = mpi_copy(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	ctx->a = mpi_copy(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	ctx->b = mpi_copy(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	ctx->t.p_barrett = use_barrett > 0 ? mpi_barrett_init(ctx->p, 0) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	mpi_ec_get_reset(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	if (model == MPI_EC_MONTGOMERY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		for (i = 0; i < DIM(bad_points_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			MPI p_candidate = mpi_scanval(bad_points_table[i][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 			int match_p = !mpi_cmp(ctx->p, p_candidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 			mpi_free(p_candidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 			if (!match_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			for (j = 0; i < DIM(ctx->t.scratch) && bad_points_table[i][j]; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 				ctx->t.scratch[j] = mpi_scanval(bad_points_table[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		/* Allocate scratch variables.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		for (i = 0; i < DIM(ctx->t.scratch); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 			ctx->t.scratch[i] = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	ctx->addm = ec_addm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	ctx->subm = ec_subm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	ctx->mulm = ec_mulm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	ctx->mul2 = ec_mul2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	ctx->pow2 = ec_pow2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	for (i = 0; field_table[i].p; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		MPI f_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		f_p = mpi_scanval(field_table[i].p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		if (!f_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		if (!mpi_cmp(p, f_p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 			ctx->addm = field_table[i].addm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 			ctx->subm = field_table[i].subm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 			ctx->mulm = field_table[i].mulm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 			ctx->mul2 = field_table[i].mul2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 			ctx->pow2 = field_table[i].pow2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 			mpi_free(f_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			mpi_resize(ctx->a, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 			ctx->a->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 			mpi_resize(ctx->b, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 			ctx->b->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 			for (i = 0; i < DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 				ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		mpi_free(f_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) EXPORT_SYMBOL_GPL(mpi_ec_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) void mpi_ec_deinit(struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	mpi_barrett_free(ctx->t.p_barrett);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	/* Domain parameter.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	mpi_free(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	mpi_free(ctx->a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	mpi_free(ctx->b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	mpi_point_release(ctx->G);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	mpi_free(ctx->n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	/* The key.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	mpi_point_release(ctx->Q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	mpi_free(ctx->d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	/* Private data of ec.c.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	mpi_free(ctx->t.two_inv_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	for (i = 0; i < DIM(ctx->t.scratch); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		mpi_free(ctx->t.scratch[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) EXPORT_SYMBOL_GPL(mpi_ec_deinit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) /* Compute the affine coordinates from the projective coordinates in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674)  * POINT.  Set them into X and Y.  If one coordinate is not required,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)  * X or Y may be passed as NULL.  CTX is the usual context. Returns: 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)  * on success or !0 if POINT is at infinity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) int mpi_ec_get_affine(MPI x, MPI y, MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	if (!mpi_cmp_ui(point->z, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	switch (ctx->model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	case MPI_EC_WEIERSTRASS: /* Using Jacobian coordinates.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 			MPI z1, z2, z3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 			z1 = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 			z2 = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 			ec_invm(z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 			ec_mulm(z2, z1, z1, ctx);    /* z2 = z^(-2) mod p  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 			if (x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 				ec_mulm(x, point->x, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 			if (y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 				z3 = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 				ec_mulm(z3, z2, z1, ctx);      /* z3 = z^(-3) mod p */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 				ec_mulm(y, point->y, z3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 				mpi_free(z3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			mpi_free(z2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 			mpi_free(z1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	case MPI_EC_MONTGOMERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 			if (x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 				mpi_set(x, point->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 			if (y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 				log_fatal("%s: Getting Y-coordinate on %s is not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 						"mpi_ec_get_affine", "Montgomery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	case MPI_EC_EDWARDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 			MPI z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 			z = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 			ec_invm(z, point->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 			mpi_resize(z, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 			z->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			if (x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 				mpi_resize(x, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 				x->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 				ctx->mulm(x, point->x, z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 			if (y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 				mpi_resize(y, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 				y->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 				ctx->mulm(y, point->y, z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 			mpi_free(z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) EXPORT_SYMBOL_GPL(mpi_ec_get_affine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) /*  RESULT = 2 * POINT  (Weierstrass version). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) static void dup_point_weierstrass(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) #define x3 (result->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) #define y3 (result->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) #define z3 (result->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) #define t1 (ctx->t.scratch[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) #define t2 (ctx->t.scratch[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) #define t3 (ctx->t.scratch[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) #define l1 (ctx->t.scratch[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) #define l2 (ctx->t.scratch[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) #define l3 (ctx->t.scratch[5])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	if (!mpi_cmp_ui(point->y, 0) || !mpi_cmp_ui(point->z, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 		/* P_y == 0 || P_z == 0 => [1:1:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 		mpi_set_ui(x3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		mpi_set_ui(y3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		mpi_set_ui(z3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 		if (ec_get_a_is_pminus3(ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 			/* Use the faster case.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 			/* L1 = 3(X - Z^2)(X + Z^2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 			/*                          T1: used for Z^2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 			/*                          T2: used for the right term. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 			ec_pow2(t1, point->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			ec_subm(l1, point->x, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			ec_mulm(l1, l1, mpi_const(MPI_C_THREE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			ec_addm(t2, point->x, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 			ec_mulm(l1, l1, t2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			/* Standard case. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			/* L1 = 3X^2 + aZ^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 			/*                          T1: used for aZ^4. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 			ec_pow2(l1, point->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			ec_mulm(l1, l1, mpi_const(MPI_C_THREE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 			ec_powm(t1, point->z, mpi_const(MPI_C_FOUR), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			ec_mulm(t1, t1, ctx->a, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 			ec_addm(l1, l1, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		/* Z3 = 2YZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		ec_mulm(z3, point->y, point->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		ec_mul2(z3, z3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 		/* L2 = 4XY^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		/*                              T2: used for Y2; required later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		ec_pow2(t2, point->y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		ec_mulm(l2, t2, point->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		ec_mulm(l2, l2, mpi_const(MPI_C_FOUR), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		/* X3 = L1^2 - 2L2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		/*                              T1: used for L2^2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		ec_pow2(x3, l1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		ec_mul2(t1, l2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		ec_subm(x3, x3, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		/* L3 = 8Y^4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		/*                              T2: taken from above. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		ec_pow2(t2, t2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 		ec_mulm(l3, t2, mpi_const(MPI_C_EIGHT), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		/* Y3 = L1(L2 - X3) - L3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		ec_subm(y3, l2, x3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		ec_mulm(y3, y3, l1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		ec_subm(y3, y3, l3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) #undef x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) #undef y3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) #undef z3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) #undef t1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) #undef t2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) #undef t3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) #undef l1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) #undef l2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) #undef l3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) /*  RESULT = 2 * POINT  (Montgomery version). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) static void dup_point_montgomery(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 				MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	(void)result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	(void)point;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	(void)ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	log_fatal("%s: %s not yet supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 			"mpi_ec_dup_point", "Montgomery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) /*  RESULT = 2 * POINT  (Twisted Edwards version). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) static void dup_point_edwards(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) #define X1 (point->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) #define Y1 (point->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) #define Z1 (point->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) #define X3 (result->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) #define Y3 (result->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) #define Z3 (result->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) #define B (ctx->t.scratch[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) #define C (ctx->t.scratch[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) #define D (ctx->t.scratch[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) #define E (ctx->t.scratch[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) #define F (ctx->t.scratch[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) #define H (ctx->t.scratch[5])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) #define J (ctx->t.scratch[6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	/* Compute: (X_3 : Y_3 : Z_3) = 2( X_1 : Y_1 : Z_1 ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	/* B = (X_1 + Y_1)^2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	ctx->addm(B, X1, Y1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	ctx->pow2(B, B, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	/* C = X_1^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	/* D = Y_1^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	ctx->pow2(C, X1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	ctx->pow2(D, Y1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	/* E = aC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	if (ctx->dialect == ECC_DIALECT_ED25519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		ctx->subm(E, ctx->p, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		ctx->mulm(E, ctx->a, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	/* F = E + D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	ctx->addm(F, E, D, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	/* H = Z_1^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	ctx->pow2(H, Z1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	/* J = F - 2H */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	ctx->mul2(J, H, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	ctx->subm(J, F, J, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	/* X_3 = (B - C - D) · J */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	ctx->subm(X3, B, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	ctx->subm(X3, X3, D, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	ctx->mulm(X3, X3, J, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	/* Y_3 = F · (E - D) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	ctx->subm(Y3, E, D, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	ctx->mulm(Y3, Y3, F, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	/* Z_3 = F · J */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	ctx->mulm(Z3, F, J, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) #undef X1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) #undef Y1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) #undef Z1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) #undef X3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) #undef Y3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) #undef Z3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) #undef B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) #undef C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) #undef D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) #undef E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) #undef F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) #undef H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) #undef J
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) /*  RESULT = 2 * POINT  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) mpi_ec_dup_point(MPI_POINT result, MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	switch (ctx->model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	case MPI_EC_WEIERSTRASS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		dup_point_weierstrass(result, point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	case MPI_EC_MONTGOMERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		dup_point_montgomery(result, point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	case MPI_EC_EDWARDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		dup_point_edwards(result, point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) /* RESULT = P1 + P2  (Weierstrass version).*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) static void add_points_weierstrass(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		MPI_POINT p1, MPI_POINT p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) #define x1 (p1->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) #define y1 (p1->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) #define z1 (p1->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) #define x2 (p2->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) #define y2 (p2->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) #define z2 (p2->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) #define x3 (result->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) #define y3 (result->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) #define z3 (result->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) #define l1 (ctx->t.scratch[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) #define l2 (ctx->t.scratch[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) #define l3 (ctx->t.scratch[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) #define l4 (ctx->t.scratch[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) #define l5 (ctx->t.scratch[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) #define l6 (ctx->t.scratch[5])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) #define l7 (ctx->t.scratch[6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) #define l8 (ctx->t.scratch[7])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) #define l9 (ctx->t.scratch[8])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) #define t1 (ctx->t.scratch[9])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) #define t2 (ctx->t.scratch[10])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	if ((!mpi_cmp(x1, x2)) && (!mpi_cmp(y1, y2)) && (!mpi_cmp(z1, z2))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		/* Same point; need to call the duplicate function.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		mpi_ec_dup_point(result, p1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	} else if (!mpi_cmp_ui(z1, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		/* P1 is at infinity.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		mpi_set(x3, p2->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		mpi_set(y3, p2->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		mpi_set(z3, p2->z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	} else if (!mpi_cmp_ui(z2, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		/* P2 is at infinity.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		mpi_set(x3, p1->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		mpi_set(y3, p1->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		mpi_set(z3, p1->z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		int z1_is_one = !mpi_cmp_ui(z1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		int z2_is_one = !mpi_cmp_ui(z2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		/* l1 = x1 z2^2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		/* l2 = x2 z1^2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		if (z2_is_one)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			mpi_set(l1, x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 			ec_pow2(l1, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			ec_mulm(l1, l1, x1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		if (z1_is_one)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 			mpi_set(l2, x2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 			ec_pow2(l2, z1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 			ec_mulm(l2, l2, x2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		/* l3 = l1 - l2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		ec_subm(l3, l1, l2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 		/* l4 = y1 z2^3  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		ec_powm(l4, z2, mpi_const(MPI_C_THREE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		ec_mulm(l4, l4, y1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		/* l5 = y2 z1^3  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		ec_powm(l5, z1, mpi_const(MPI_C_THREE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		ec_mulm(l5, l5, y2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		/* l6 = l4 - l5  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		ec_subm(l6, l4, l5, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		if (!mpi_cmp_ui(l3, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 			if (!mpi_cmp_ui(l6, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 				/* P1 and P2 are the same - use duplicate function. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 				mpi_ec_dup_point(result, p1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 				/* P1 is the inverse of P2.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 				mpi_set_ui(x3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 				mpi_set_ui(y3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 				mpi_set_ui(z3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 			/* l7 = l1 + l2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			ec_addm(l7, l1, l2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 			/* l8 = l4 + l5  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 			ec_addm(l8, l4, l5, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 			/* z3 = z1 z2 l3  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 			ec_mulm(z3, z1, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 			ec_mulm(z3, z3, l3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 			/* x3 = l6^2 - l7 l3^2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 			ec_pow2(t1, l6, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 			ec_pow2(t2, l3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 			ec_mulm(t2, t2, l7, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 			ec_subm(x3, t1, t2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			/* l9 = l7 l3^2 - 2 x3  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 			ec_mul2(t1, x3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 			ec_subm(l9, t2, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 			/* y3 = (l9 l6 - l8 l3^3)/2  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 			ec_mulm(l9, l9, l6, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			ec_powm(t1, l3, mpi_const(MPI_C_THREE), ctx); /* fixme: Use saved value*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 			ec_mulm(t1, t1, l8, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 			ec_subm(y3, l9, t1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 			ec_mulm(y3, y3, ec_get_two_inv_p(ctx), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) #undef x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) #undef y1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) #undef z1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) #undef x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) #undef y2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) #undef z2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) #undef x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) #undef y3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) #undef z3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #undef l1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) #undef l2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) #undef l3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) #undef l4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) #undef l5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) #undef l6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) #undef l7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) #undef l8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) #undef l9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) #undef t1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #undef t2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* RESULT = P1 + P2  (Montgomery version).*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static void add_points_montgomery(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		MPI_POINT p1, MPI_POINT p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	(void)result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	(void)p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	(void)p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	(void)ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	log_fatal("%s: %s not yet supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 			"mpi_ec_add_points", "Montgomery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /* RESULT = P1 + P2  (Twisted Edwards version).*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) static void add_points_edwards(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		MPI_POINT p1, MPI_POINT p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) #define X1 (p1->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) #define Y1 (p1->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) #define Z1 (p1->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) #define X2 (p2->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) #define Y2 (p2->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) #define Z2 (p2->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) #define X3 (result->x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) #define Y3 (result->y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) #define Z3 (result->z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) #define A (ctx->t.scratch[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) #define B (ctx->t.scratch[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) #define C (ctx->t.scratch[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) #define D (ctx->t.scratch[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) #define E (ctx->t.scratch[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) #define F (ctx->t.scratch[5])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) #define G (ctx->t.scratch[6])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) #define tmp (ctx->t.scratch[7])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	point_resize(result, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	/* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	/* A = Z1 · Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	ctx->mulm(A, Z1, Z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	/* B = A^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	ctx->pow2(B, A, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	/* C = X1 · X2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	ctx->mulm(C, X1, X2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	/* D = Y1 · Y2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	ctx->mulm(D, Y1, Y2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	/* E = d · C · D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	ctx->mulm(E, ctx->b, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	ctx->mulm(E, E, D, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 	/* F = B - E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	ctx->subm(F, B, E, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	/* G = B + E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	ctx->addm(G, B, E, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	/* X_3 = A · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	ctx->addm(tmp, X1, Y1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	ctx->addm(X3, X2, Y2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	ctx->mulm(X3, X3, tmp, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	ctx->subm(X3, X3, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	ctx->subm(X3, X3, D, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	ctx->mulm(X3, X3, F, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	ctx->mulm(X3, X3, A, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	/* Y_3 = A · G · (D - aC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	if (ctx->dialect == ECC_DIALECT_ED25519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		ctx->addm(Y3, D, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		ctx->mulm(Y3, ctx->a, C, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 		ctx->subm(Y3, D, Y3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	ctx->mulm(Y3, Y3, G, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	ctx->mulm(Y3, Y3, A, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	/* Z_3 = F · G */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	ctx->mulm(Z3, F, G, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) #undef X1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) #undef Y1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) #undef Z1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) #undef X2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) #undef Y2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) #undef Z2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) #undef X3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) #undef Y3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) #undef Z3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) #undef A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) #undef B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) #undef C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) #undef D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) #undef E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) #undef F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) #undef G
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) #undef tmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* Compute a step of Montgomery Ladder (only use X and Z in the point).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)  * Inputs:  P1, P2, and x-coordinate of DIF = P1 - P1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)  * Outputs: PRD = 2 * P1 and  SUM = P1 + P2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static void montgomery_ladder(MPI_POINT prd, MPI_POINT sum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		MPI_POINT p1, MPI_POINT p2, MPI dif_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	ctx->addm(sum->x, p2->x, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	ctx->subm(p2->z, p2->x, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	ctx->addm(prd->x, p1->x, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	ctx->subm(p1->z, p1->x, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	ctx->mulm(p2->x, p1->z, sum->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	ctx->mulm(p2->z, prd->x, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	ctx->pow2(p1->x, prd->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	ctx->pow2(p1->z, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	ctx->addm(sum->x, p2->x, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	ctx->subm(p2->z, p2->x, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	ctx->mulm(prd->x, p1->x, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	ctx->subm(p1->z, p1->x, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	ctx->pow2(sum->x, sum->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	ctx->pow2(sum->z, p2->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	ctx->mulm(prd->z, p1->z, ctx->a, ctx); /* CTX->A: (a-2)/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	ctx->mulm(sum->z, sum->z, dif_x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	ctx->addm(prd->z, p1->x, prd->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	ctx->mulm(prd->z, prd->z, p1->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* RESULT = P1 + P2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) void mpi_ec_add_points(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		MPI_POINT p1, MPI_POINT p2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	switch (ctx->model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	case MPI_EC_WEIERSTRASS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		add_points_weierstrass(result, p1, p2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	case MPI_EC_MONTGOMERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		add_points_montgomery(result, p1, p2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	case MPI_EC_EDWARDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		add_points_edwards(result, p1, p2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) EXPORT_SYMBOL_GPL(mpi_ec_add_points);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) /* Scalar point multiplication - the main function for ECC.  If takes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)  * an integer SCALAR and a POINT as well as the usual context CTX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)  * RESULT will be set to the resulting point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) void mpi_ec_mul_point(MPI_POINT result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 			MPI scalar, MPI_POINT point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 			struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	MPI x1, y1, z1, k, h, yy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	unsigned int i, loops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	struct gcry_mpi_point p1, p2, p1inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	if (ctx->model == MPI_EC_EDWARDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		/* Simple left to right binary method.  Algorithm 3.27 from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 		 * {author={Hankerson, Darrel and Menezes, Alfred J. and Vanstone, Scott},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		 *  title = {Guide to Elliptic Curve Cryptography},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 		 *  year = {2003}, isbn = {038795273X},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		 *  url = {http://www.cacr.math.uwaterloo.ca/ecc/},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		 *  publisher = {Springer-Verlag New York, Inc.}}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		unsigned int nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 		if (mpi_cmp(scalar, ctx->p) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 			nbits = mpi_get_nbits(scalar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 			nbits = mpi_get_nbits(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 		mpi_set_ui(result->x, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		mpi_set_ui(result->y, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 		mpi_set_ui(result->z, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		point_resize(point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		point_resize(result, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 		point_resize(point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		for (j = nbits-1; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 			mpi_ec_dup_point(result, result, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 			if (mpi_test_bit(scalar, j))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 				mpi_ec_add_points(result, result, point, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	} else if (ctx->model == MPI_EC_MONTGOMERY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		unsigned int nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		struct gcry_mpi_point p1_, p2_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		MPI_POINT q1, q2, prd, sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		unsigned long sw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		mpi_size_t rsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		int scalar_copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		/* Compute scalar point multiplication with Montgomery Ladder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		 * Note that we don't use Y-coordinate in the points at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		 * RESULT->Y will be filled by zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 		nbits = mpi_get_nbits(scalar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 		point_init(&p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		point_init(&p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 		point_init(&p1_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 		point_init(&p2_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		mpi_set_ui(p1.x, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 		mpi_free(p2.x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		p2.x = mpi_copy(point->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		mpi_set_ui(p2.z, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		point_resize(&p1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		point_resize(&p2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		point_resize(&p1_, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		point_resize(&p2_, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 		mpi_resize(point->x, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		point->x->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 		q1 = &p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 		q2 = &p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		prd = &p1_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		sum = &p2_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		for (j = nbits-1; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 			MPI_POINT t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 			sw = mpi_test_bit(scalar, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 			point_swap_cond(q1, q2, sw, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 			montgomery_ladder(prd, sum, q1, q2, point->x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 			point_swap_cond(prd, sum, sw, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 			t = q1;  q1 = prd;  prd = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 			t = q2;  q2 = sum;  sum = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 		mpi_clear(result->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 		sw = (nbits & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		point_swap_cond(&p1, &p1_, sw, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 		rsize = p1.z->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		MPN_NORMALIZE(p1.z->d, rsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 		if (rsize == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 			mpi_set_ui(result->x, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 			mpi_set_ui(result->z, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 			z1 = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 			ec_invm(z1, p1.z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 			ec_mulm(result->x, p1.x, z1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 			mpi_set_ui(result->z, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 			mpi_free(z1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		point_free(&p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 		point_free(&p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		point_free(&p1_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		point_free(&p2_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		if (scalar_copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 			mpi_free(scalar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	x1 = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	y1 = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	h  = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	k  = mpi_copy(scalar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	yy = mpi_copy(point->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	if (mpi_has_sign(k)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		k->sign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		ec_invm(yy, yy, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	if (!mpi_cmp_ui(point->z, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		mpi_set(x1, point->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 		mpi_set(y1, yy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		MPI z2, z3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		z2 = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		z3 = mpi_alloc_like(ctx->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		ec_mulm(z2, point->z, point->z, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		ec_mulm(z3, point->z, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		ec_invm(z2, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		ec_mulm(x1, point->x, z2, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 		ec_invm(z3, z3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		ec_mulm(y1, yy, z3, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		mpi_free(z2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		mpi_free(z3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 	z1 = mpi_copy(mpi_const(MPI_C_ONE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	mpi_mul(h, k, mpi_const(MPI_C_THREE)); /* h = 3k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 	loops = mpi_get_nbits(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	if (loops < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 		/* If SCALAR is zero, the above mpi_mul sets H to zero and thus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 		 * LOOPs will be zero.  To avoid an underflow of I in the main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		 * loop we set LOOP to 2 and the result to (0,0,0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		loops = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 		mpi_clear(result->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		mpi_clear(result->y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 		mpi_clear(result->z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		mpi_set(result->x, point->x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 		mpi_set(result->y, yy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 		mpi_set(result->z, point->z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	mpi_free(yy); yy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	p1.x = x1; x1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	p1.y = y1; y1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	p1.z = z1; z1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	point_init(&p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	point_init(&p1inv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	/* Invert point: y = p - y mod p  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 	point_set(&p1inv, &p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	ec_subm(p1inv.y, ctx->p, p1inv.y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 	for (i = loops-2; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 		mpi_ec_dup_point(result, result, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		if (mpi_test_bit(h, i) == 1 && mpi_test_bit(k, i) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 			point_set(&p2, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 			mpi_ec_add_points(result, &p2, &p1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 		if (mpi_test_bit(h, i) == 0 && mpi_test_bit(k, i) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 			point_set(&p2, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 			mpi_ec_add_points(result, &p2, &p1inv, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	point_free(&p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	point_free(&p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	point_free(&p1inv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	mpi_free(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	mpi_free(k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) EXPORT_SYMBOL_GPL(mpi_ec_mul_point);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) /* Return true if POINT is on the curve described by CTX.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) int mpi_ec_curve_point(MPI_POINT point, struct mpi_ec_ctx *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	MPI x, y, w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	x = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	y = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	w = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	/* Check that the point is in range.  This needs to be done here and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	 * not after conversion to affine coordinates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	if (mpi_cmpabs(point->x, ctx->p) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 		goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	if (mpi_cmpabs(point->y, ctx->p) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 		goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	if (mpi_cmpabs(point->z, ctx->p) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 		goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	switch (ctx->model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	case MPI_EC_WEIERSTRASS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 			MPI xxx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 			if (mpi_ec_get_affine(x, y, point, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 				goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			xxx = mpi_new(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 			/* y^2 == x^3 + a·x + b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			ec_pow2(y, y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 			ec_pow3(xxx, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 			ec_mulm(w, ctx->a, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 			ec_addm(w, w, ctx->b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			ec_addm(w, w, xxx, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 			if (!mpi_cmp(y, w))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 				res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 			mpi_free(xxx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	case MPI_EC_MONTGOMERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) #define xx y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 			/* With Montgomery curve, only X-coordinate is valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 			if (mpi_ec_get_affine(x, NULL, point, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 				goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 			/* The equation is: b * y^2 == x^3 + a · x^2 + x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 			/* We check if right hand is quadratic residue or not by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 			 * Euler's criterion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 			/* CTX->A has (a-2)/4 and CTX->B has b^-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 			ec_mulm(w, ctx->a, mpi_const(MPI_C_FOUR), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 			ec_addm(w, w, mpi_const(MPI_C_TWO), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 			ec_mulm(w, w, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 			ec_pow2(xx, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 			ec_addm(w, w, xx, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 			ec_addm(w, w, mpi_const(MPI_C_ONE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 			ec_mulm(w, w, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 			ec_mulm(w, w, ctx->b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) #undef xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 			/* Compute Euler's criterion: w^(p-1)/2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) #define p_minus1 y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 			ec_subm(p_minus1, ctx->p, mpi_const(MPI_C_ONE), ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 			mpi_rshift(p_minus1, p_minus1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 			ec_powm(w, w, p_minus1, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 			res = !mpi_cmp_ui(w, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) #undef p_minus1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	case MPI_EC_EDWARDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 			if (mpi_ec_get_affine(x, y, point, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 				goto leave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 			mpi_resize(w, ctx->p->nlimbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 			w->nlimbs = ctx->p->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 			/* a · x^2 + y^2 - 1 - b · x^2 · y^2 == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 			ctx->pow2(x, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 			ctx->pow2(y, y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 			if (ctx->dialect == ECC_DIALECT_ED25519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 				ctx->subm(w, ctx->p, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 				ctx->mulm(w, ctx->a, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 			ctx->addm(w, w, y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 			ctx->mulm(x, x, y, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 			ctx->mulm(x, x, ctx->b, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 			ctx->subm(w, w, x, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 			if (!mpi_cmp_ui(w, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 				res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) leave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	mpi_free(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	mpi_free(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	mpi_free(y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) EXPORT_SYMBOL_GPL(mpi_ec_curve_point);