brintos

brintos / linux-shallow public Read only

0
0
Text · 2.4 KiB · 7e6ff1c Raw
110 lines · c
1/* mpi-mul.c  -  MPI functions2 * Copyright (C) 1994, 1996, 1998, 2001, 2002,3 *               2003 Free Software Foundation, Inc.4 *5 * This file is part of Libgcrypt.6 *7 * Note: This code is heavily based on the GNU MP Library.8 *	 Actually it's the same code with only minor changes in the9 *	 way the data is stored; this is to support the abstraction10 *	 of an optional secure memory allocation which may be used11 *	 to avoid revealing of sensitive data due to paging etc.12 */13 14#include "mpi-internal.h"15 16int mpi_mul(MPI w, MPI u, MPI v)17{18	mpi_size_t usize, vsize, wsize;19	mpi_ptr_t up, vp, wp;20	mpi_limb_t cy;21	int usign, vsign, sign_product;22	int assign_wp = 0;23	mpi_ptr_t tmp_limb = NULL;24	int err = 0;25 26	if (u->nlimbs < v->nlimbs) {27		/* Swap U and V. */28		usize = v->nlimbs;29		usign = v->sign;30		up    = v->d;31		vsize = u->nlimbs;32		vsign = u->sign;33		vp    = u->d;34	} else {35		usize = u->nlimbs;36		usign = u->sign;37		up    = u->d;38		vsize = v->nlimbs;39		vsign = v->sign;40		vp    = v->d;41	}42	sign_product = usign ^ vsign;43	wp = w->d;44 45	/* Ensure W has space enough to store the result.  */46	wsize = usize + vsize;47	if (w->alloced < wsize) {48		if (wp == up || wp == vp) {49			wp = mpi_alloc_limb_space(wsize);50			if (!wp)51				return -ENOMEM;52			assign_wp = 1;53		} else {54			err = mpi_resize(w, wsize);55			if (err)56				return err;57			wp = w->d;58		}59	} else { /* Make U and V not overlap with W.	*/60		if (wp == up) {61			/* W and U are identical.  Allocate temporary space for U. */62			up = tmp_limb = mpi_alloc_limb_space(usize);63			if (!up)64				return -ENOMEM;65			/* Is V identical too?  Keep it identical with U.  */66			if (wp == vp)67				vp = up;68			/* Copy to the temporary space.  */69			MPN_COPY(up, wp, usize);70		} else if (wp == vp) {71			/* W and V are identical.  Allocate temporary space for V. */72			vp = tmp_limb = mpi_alloc_limb_space(vsize);73			if (!vp)74				return -ENOMEM;75			/* Copy to the temporary space.  */76			MPN_COPY(vp, wp, vsize);77		}78	}79 80	if (!vsize)81		wsize = 0;82	else {83		err = mpihelp_mul(wp, up, usize, vp, vsize, &cy);84		if (err) {85			if (assign_wp)86				mpi_free_limb_space(wp);87			goto free_tmp_limb;88		}89		wsize -= cy ? 0:1;90	}91 92	if (assign_wp)93		mpi_assign_limb_space(w, wp, wsize);94	w->nlimbs = wsize;95	w->sign = sign_product;96 97free_tmp_limb:98	if (tmp_limb)99		mpi_free_limb_space(tmp_limb);100	return err;101}102EXPORT_SYMBOL_GPL(mpi_mul);103 104int mpi_mulm(MPI w, MPI u, MPI v, MPI m)105{106	return mpi_mul(w, u, v) ?:107	       mpi_tdiv_r(w, w, m);108}109EXPORT_SYMBOL_GPL(mpi_mulm);110