18c2ecf20Sopenharmony_ci/* mpi-mul.c  -  MPI functions
28c2ecf20Sopenharmony_ci * Copyright (C) 1994, 1996, 1998, 2001, 2002,
38c2ecf20Sopenharmony_ci *               2003 Free Software Foundation, Inc.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This file is part of Libgcrypt.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Note: This code is heavily based on the GNU MP Library.
88c2ecf20Sopenharmony_ci *	 Actually it's the same code with only minor changes in the
98c2ecf20Sopenharmony_ci *	 way the data is stored; this is to support the abstraction
108c2ecf20Sopenharmony_ci *	 of an optional secure memory allocation which may be used
118c2ecf20Sopenharmony_ci *	 to avoid revealing of sensitive data due to paging etc.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "mpi-internal.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_civoid mpi_mul(MPI w, MPI u, MPI v)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	mpi_size_t usize, vsize, wsize;
198c2ecf20Sopenharmony_ci	mpi_ptr_t up, vp, wp;
208c2ecf20Sopenharmony_ci	mpi_limb_t cy;
218c2ecf20Sopenharmony_ci	int usign, vsign, sign_product;
228c2ecf20Sopenharmony_ci	int assign_wp = 0;
238c2ecf20Sopenharmony_ci	mpi_ptr_t tmp_limb = NULL;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	if (u->nlimbs < v->nlimbs) {
268c2ecf20Sopenharmony_ci		/* Swap U and V. */
278c2ecf20Sopenharmony_ci		usize = v->nlimbs;
288c2ecf20Sopenharmony_ci		usign = v->sign;
298c2ecf20Sopenharmony_ci		up    = v->d;
308c2ecf20Sopenharmony_ci		vsize = u->nlimbs;
318c2ecf20Sopenharmony_ci		vsign = u->sign;
328c2ecf20Sopenharmony_ci		vp    = u->d;
338c2ecf20Sopenharmony_ci	} else {
348c2ecf20Sopenharmony_ci		usize = u->nlimbs;
358c2ecf20Sopenharmony_ci		usign = u->sign;
368c2ecf20Sopenharmony_ci		up    = u->d;
378c2ecf20Sopenharmony_ci		vsize = v->nlimbs;
388c2ecf20Sopenharmony_ci		vsign = v->sign;
398c2ecf20Sopenharmony_ci		vp    = v->d;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci	sign_product = usign ^ vsign;
428c2ecf20Sopenharmony_ci	wp = w->d;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* Ensure W has space enough to store the result.  */
458c2ecf20Sopenharmony_ci	wsize = usize + vsize;
468c2ecf20Sopenharmony_ci	if (w->alloced < wsize) {
478c2ecf20Sopenharmony_ci		if (wp == up || wp == vp) {
488c2ecf20Sopenharmony_ci			wp = mpi_alloc_limb_space(wsize);
498c2ecf20Sopenharmony_ci			assign_wp = 1;
508c2ecf20Sopenharmony_ci		} else {
518c2ecf20Sopenharmony_ci			mpi_resize(w, wsize);
528c2ecf20Sopenharmony_ci			wp = w->d;
538c2ecf20Sopenharmony_ci		}
548c2ecf20Sopenharmony_ci	} else { /* Make U and V not overlap with W.	*/
558c2ecf20Sopenharmony_ci		if (wp == up) {
568c2ecf20Sopenharmony_ci			/* W and U are identical.  Allocate temporary space for U. */
578c2ecf20Sopenharmony_ci			up = tmp_limb = mpi_alloc_limb_space(usize);
588c2ecf20Sopenharmony_ci			/* Is V identical too?  Keep it identical with U.  */
598c2ecf20Sopenharmony_ci			if (wp == vp)
608c2ecf20Sopenharmony_ci				vp = up;
618c2ecf20Sopenharmony_ci			/* Copy to the temporary space.  */
628c2ecf20Sopenharmony_ci			MPN_COPY(up, wp, usize);
638c2ecf20Sopenharmony_ci		} else if (wp == vp) {
648c2ecf20Sopenharmony_ci			/* W and V are identical.  Allocate temporary space for V. */
658c2ecf20Sopenharmony_ci			vp = tmp_limb = mpi_alloc_limb_space(vsize);
668c2ecf20Sopenharmony_ci			/* Copy to the temporary space.  */
678c2ecf20Sopenharmony_ci			MPN_COPY(vp, wp, vsize);
688c2ecf20Sopenharmony_ci		}
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (!vsize)
728c2ecf20Sopenharmony_ci		wsize = 0;
738c2ecf20Sopenharmony_ci	else {
748c2ecf20Sopenharmony_ci		mpihelp_mul(wp, up, usize, vp, vsize, &cy);
758c2ecf20Sopenharmony_ci		wsize -= cy ? 0:1;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (assign_wp)
798c2ecf20Sopenharmony_ci		mpi_assign_limb_space(w, wp, wsize);
808c2ecf20Sopenharmony_ci	w->nlimbs = wsize;
818c2ecf20Sopenharmony_ci	w->sign = sign_product;
828c2ecf20Sopenharmony_ci	if (tmp_limb)
838c2ecf20Sopenharmony_ci		mpi_free_limb_space(tmp_limb);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_civoid mpi_mulm(MPI w, MPI u, MPI v, MPI m)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	mpi_mul(w, u, v);
898c2ecf20Sopenharmony_ci	mpi_tdiv_r(w, w, m);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mpi_mulm);
92